From: Aric Stewart Subject: (try 7)[1/5] imm32: Move thread data from TLSEntry to an internal list Message-Id: <540E606B.4090604@codeweavers.com> Date: Mon, 08 Sep 2014 21:05:31 -0500 --- dlls/imm32/imm.c | 158 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 120 insertions(+), 38 deletions(-) diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c index 2fa31ac..7bd283e 100644 --- a/dlls/imm32/imm.c +++ b/dlls/imm32/imm.c @@ -86,12 +86,14 @@ typedef struct _tagTRANSMSG { } TRANSMSG, *LPTRANSMSG; typedef struct _tagIMMThreadData { + struct list entry; + DWORD threadID; HIMC defaultContext; HWND hwndDefault; } IMMThreadData; -static DWORD tlsIndex = 0; static struct list ImmHklList = LIST_INIT(ImmHklList); +static struct list ImmThreadDataList = LIST_INIT(ImmThreadDataList); /* MSIME messages */ static UINT WM_MSIME_SERVICE; @@ -110,6 +112,15 @@ static const WCHAR szImeRegFmt[] = {'S','y','s','t','e','m','\\','C','u','r','r' static const WCHAR szwIME[] = {'I','M','E',0}; +static CRITICAL_SECTION threaddata_cs; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &threaddata_cs, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") } +}; +static CRITICAL_SECTION threaddata_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; + static LRESULT WINAPI DefIME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); @@ -220,29 +231,52 @@ static DWORD convert_candidatelist_AtoW( return ret; } -static IMMThreadData* IMM_GetThreadData(void) +static IMMThreadData* IMM_GetThreadData(DWORD id) { - IMMThreadData* data = TlsGetValue(tlsIndex); - if (!data) + IMMThreadData *data; + + if (!id) id = GetCurrentThreadId(); + + EnterCriticalSection(&threaddata_cs); + LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry) { - data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(IMMThreadData)); - TlsSetValue(tlsIndex,data); - TRACE("Thread Data Created\n"); + if (data->threadID == id) + return data; } + + data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(IMMThreadData)); + data->threadID = id; + list_add_head(&ImmThreadDataList,&data->entry); + TRACE("Thread Data Created (%x)\n",id); + return data; } -static void IMM_FreeThreadData(void) +static void IMM_FreeThreadData(DWORD id) { - IMMThreadData* data = TlsGetValue(tlsIndex); - if (data) + BOOL found = FALSE; + IMMThreadData *data,*cursor2; + + if (!id) id = GetCurrentThreadId(); + + EnterCriticalSection(&threaddata_cs); + LIST_FOR_EACH_ENTRY_SAFE(data, cursor2, &ImmThreadDataList, IMMThreadData, entry) { - IMM_DestroyContext(data->defaultContext); - DestroyWindow(data->hwndDefault); - HeapFree(GetProcessHeap(),0,data); - TRACE("Thread Data Destroyed\n"); + if (data->threadID == id) + { + list_remove(&data->entry); + LeaveCriticalSection(&threaddata_cs); + IMM_DestroyContext(data->defaultContext); + DestroyWindow(data->hwndDefault); + HeapFree(GetProcessHeap(),0,data); + TRACE("Thread Data Destroyed\n"); + found = TRUE; + break; + } } + if (!found) + LeaveCriticalSection(&threaddata_cs); } static HMODULE load_graphics_driver(void) @@ -398,21 +432,17 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved) { case DLL_PROCESS_ATTACH: IMM_RegisterMessages(); - tlsIndex = TlsAlloc(); - if (tlsIndex == TLS_OUT_OF_INDEXES) - return FALSE; IMM_RegisterIMEClass(); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: - IMM_FreeThreadData(); + IMM_FreeThreadData(0); break; case DLL_PROCESS_DETACH: if (lpReserved) break; - IMM_FreeThreadData(); + IMM_FreeThreadData(0); IMM_FreeAllImmHkl(); - TlsFree(tlsIndex); UnregisterClassW(szwIME, NULL); break; } @@ -469,6 +499,34 @@ static InputContextData* get_imc_data(HIMC hIMC) return data; } +static IMMThreadData* IMM_GetInitializedThreadData(void) +{ + IMMThreadData* thread_data = IMM_GetThreadData(0); + + if (!thread_data) + return NULL; + + if (!thread_data->defaultContext) + { + HIMC defaultContext; + LeaveCriticalSection(&threaddata_cs); + defaultContext = ImmCreateContext(); + thread_data = IMM_GetThreadData(0); + if (!thread_data) + { + IMM_DestroyContext(defaultContext); + return NULL; + } + + if (thread_data->defaultContext) /* someone beat us */ + IMM_DestroyContext(defaultContext); + else + thread_data->defaultContext = defaultContext; + } + + return thread_data; +} + /*********************************************************************** * ImmAssociateContext (IMM32.@) */ @@ -476,31 +534,33 @@ HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC) { HIMC old = NULL; InputContextData *data = get_imc_data(hIMC); + IMMThreadData* thread_data = NULL; TRACE("(%p, %p):\n", hWnd, hIMC); if(hIMC && !data) return NULL; - if (!IMM_GetThreadData()->defaultContext) - IMM_GetThreadData()->defaultContext = ImmCreateContext(); - /* * If already associated just return */ if (hIMC && data->IMC.hWnd == hWnd) return hIMC; + thread_data = IMM_GetInitializedThreadData(); + if (!thread_data) + return NULL; + if (hWnd) { old = RemovePropW(hWnd,szwWineIMCProperty); if (old == NULL) - old = IMM_GetThreadData()->defaultContext; + old = thread_data->defaultContext; else if (old == (HIMC)-1) old = NULL; - if (hIMC != IMM_GetThreadData()->defaultContext) + if (hIMC != thread_data->defaultContext) { if (hIMC == NULL) /* Meaning disable imm for that window*/ SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1); @@ -515,6 +575,7 @@ HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC) old_data->IMC.hWnd = NULL; } } + LeaveCriticalSection(&threaddata_cs); if (!hIMC) return old; @@ -556,12 +617,20 @@ static BOOL CALLBACK _ImmAssociateContextExEnumProc(HWND hwnd, LPARAM lParam) */ BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags) { + IMMThreadData* thread_data = NULL; + HIMC defaultContext = NULL; + TRACE("(%p, %p, 0x%x):\n", hWnd, hIMC, dwFlags); - if (!IMM_GetThreadData()->defaultContext) - IMM_GetThreadData()->defaultContext = ImmCreateContext(); + thread_data = IMM_GetInitializedThreadData(); + if (!thread_data) + return FALSE; - if (!hWnd) return FALSE; + defaultContext = thread_data->defaultContext; + LeaveCriticalSection(&threaddata_cs); + + if (!hWnd) + return FALSE; switch (dwFlags) { @@ -569,7 +638,7 @@ BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags) ImmAssociateContext(hWnd,hIMC); return TRUE; case IACE_DEFAULT: - ImmAssociateContext(hWnd,IMM_GetThreadData()->defaultContext); + ImmAssociateContext(hWnd,defaultContext); return TRUE; case IACE_IGNORENOCONTEXT: if (GetPropW(hWnd,szwWineIMCProperty)) @@ -744,7 +813,11 @@ static BOOL IMM_DestroyContext(HIMC hIMC) */ BOOL WINAPI ImmDestroyContext(HIMC hIMC) { - if (hIMC != IMM_GetThreadData()->defaultContext) + IMMThreadData* thread_data = IMM_GetThreadData(0); + HIMC defaultContext = thread_data->defaultContext; + LeaveCriticalSection(&threaddata_cs); + + if (hIMC != defaultContext) return IMM_DestroyContext(hIMC); else return FALSE; @@ -1410,6 +1483,7 @@ BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) HIMC WINAPI ImmGetContext(HWND hWnd) { HIMC rc; + IMMThreadData* thread_data; TRACE("%p\n", hWnd); @@ -1418,20 +1492,24 @@ HIMC WINAPI ImmGetContext(HWND hWnd) SetLastError(ERROR_INVALID_WINDOW_HANDLE); return NULL; } - if (!IMM_GetThreadData()->defaultContext) - IMM_GetThreadData()->defaultContext = ImmCreateContext(); + + thread_data = IMM_GetInitializedThreadData(); + if (!thread_data) + return NULL; rc = GetPropW(hWnd,szwWineIMCProperty); if (rc == (HIMC)-1) rc = NULL; else if (rc == NULL) - rc = IMM_GetThreadData()->defaultContext; + rc = thread_data->defaultContext; if (rc) { InputContextData *data = rc; data->IMC.hWnd = hWnd; } + LeaveCriticalSection(&threaddata_cs); + TRACE("returning %p\n", rc); return rc; @@ -1539,11 +1617,15 @@ BOOL WINAPI ImmGetConversionStatus( */ HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd) { - if (IMM_GetThreadData()->hwndDefault == NULL) - IMM_GetThreadData()->hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW, + HWND ret; + IMMThreadData* thread_data = IMM_GetThreadData(0); + if (thread_data->hwndDefault == NULL) + thread_data->hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW, szwIME, NULL, WS_POPUP, 0, 0, 1, 1, 0, 0, 0, 0); - TRACE("Default is %p\n",IMM_GetThreadData()->hwndDefault); - return IMM_GetThreadData()->hwndDefault; + ret = thread_data->hwndDefault; + LeaveCriticalSection(&threaddata_cs); + TRACE("Default is %p\n",ret); + return ret; } /***********************************************************************