mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Added patch to limit cross thread access to ImmSet* functions.
This commit is contained in:
parent
ed22aea5bd
commit
acacbd588d
@ -35,12 +35,13 @@ Wine. All those differences are also documented on the
|
||||
Included bugfixes and improvements
|
||||
==================================
|
||||
|
||||
**Bugfixes and features included in the next upcoming release [8]:**
|
||||
**Bugfixes and features included in the next upcoming release [9]:**
|
||||
|
||||
* Correctly treat '.' when checking for empty directories ([Wine Bug #26272](http://bugs.winehq.org/show_bug.cgi?id=26272))
|
||||
* Do not fail when a used context is passed to wglShareLists ([Wine Bug #11436](http://bugs.winehq.org/show_bug.cgi?id=11436))
|
||||
* Export ?_BADOFF@std@@3_JB on both i386 and win64 ([Wine Bug #37198](http://bugs.winehq.org/show_bug.cgi?id=37198))
|
||||
* Fix issues when driver dispatch routine returns different status codes ([Wine Bug #30155](http://bugs.winehq.org/show_bug.cgi?id=30155))
|
||||
* Limit cross thread access to ImmSet* functions ([Wine Bug #35361](http://bugs.winehq.org/show_bug.cgi?id=35361))
|
||||
* Send WM_PAINT event during dialog creation ([Wine Bug #35652](http://bugs.winehq.org/show_bug.cgi?id=35652))
|
||||
* Support for FIND_FIRST_EX_CASE_SENSITIVE flag in FindFirstFileExW
|
||||
* Unity3D Editor requires ProductId registry value ([Wine Bug #36964](http://bugs.winehq.org/show_bug.cgi?id=36964))
|
||||
|
1
debian/changelog
vendored
1
debian/changelog
vendored
@ -8,6 +8,7 @@ wine-compholio (1.7.28) UNRELEASED; urgency=low
|
||||
* Added several patches for Unity3D Editor.
|
||||
* Added patch to fix differences between exception handling behaviour in Wine and Windows.
|
||||
* Added patch to export ?_BADOFF@std@@3_JB on both i386 and win64.
|
||||
* Added patch to limit cross thread access to ImmSet* functions.
|
||||
-- Sebastian Lackner <sebastian@fds-team.de> Sun, 21 Sep 2014 01:44:14 +0200
|
||||
|
||||
wine-compholio (1.7.27) unstable; urgency=low
|
||||
|
@ -29,6 +29,7 @@ PATCHLIST := \
|
||||
dbghelp-KdHelp.ok \
|
||||
dsound-Fast_Mixer.ok \
|
||||
fonts-Missing_Fonts.ok \
|
||||
imm32-Cross_Thread_Access.ok \
|
||||
iphlpapi-TCP_Table.ok \
|
||||
kernel32-FindFirstFile.ok \
|
||||
kernel32-GetFinalPathNameByHandle.ok \
|
||||
@ -339,6 +340,28 @@ fonts-Missing_Fonts.ok:
|
||||
echo '+ { "fonts-Missing_Fonts", "Torsten Kurbad / Erich E. Hoover", "Implement missing fonts expected by Silverlight. [rev 2]" },'; \
|
||||
) > fonts-Missing_Fonts.ok
|
||||
|
||||
# Patchset imm32-Cross_Thread_Access
|
||||
# |
|
||||
# | Included patches:
|
||||
# | * Limit cross thread access to ImmSet* functions. [by Aric Stewart]
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#35361] Limit cross thread access to ImmSet* functions
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/imm32/imm.c, dlls/imm32/tests/imm32.c
|
||||
# |
|
||||
.INTERMEDIATE: imm32-Cross_Thread_Access.ok
|
||||
imm32-Cross_Thread_Access.ok:
|
||||
$(call APPLY_FILE,imm32-Cross_Thread_Access/0001-imm32-Move-thread-data-from-TLSEntry-to-an-internal-.patch)
|
||||
$(call APPLY_FILE,imm32-Cross_Thread_Access/0002-imm32-Do-not-let-ImmDestroyContext-destroy-any-defau.patch)
|
||||
$(call APPLY_FILE,imm32-Cross_Thread_Access/0003-imm32-Use-thread-data-from-target-HWND.patch)
|
||||
$(call APPLY_FILE,imm32-Cross_Thread_Access/0004-imm32-Restrict-crossthread-Association-and-destructi.patch)
|
||||
$(call APPLY_FILE,imm32-Cross_Thread_Access/0005-imm32-Limit-cross-thread-access-to-ImmSet-functions.patch)
|
||||
@( \
|
||||
echo '+ { "imm32-Cross_Thread_Access", "Aric Stewart", "Limit cross thread access to ImmSet* functions." },'; \
|
||||
) > imm32-Cross_Thread_Access.ok
|
||||
|
||||
# Patchset iphlpapi-TCP_Table
|
||||
# |
|
||||
# | Included patches:
|
||||
|
@ -0,0 +1,327 @@
|
||||
From d6e9673ae62469399560736a43368ce7f4ff5a8e Mon Sep 17 00:00:00 2001
|
||||
From: Aric Stewart <aric@codeweavers.com>
|
||||
Date: Mon, 8 Sep 2014 21:05:31 -0500
|
||||
Subject: imm32: Move thread data from TLSEntry to an internal list.
|
||||
|
||||
Changes by Sebastian Lackner <sebastian@fds-team.de>:
|
||||
* Remove ugly logic in IMM_FreeThreadData (id not used at all, avoid unnecessary variables)
|
||||
* IMM_GetInitializedThreadData shouldn't hold the CS while destroying the context in case of a race-condition
|
||||
* ImmGetDefaultIMEWnd shouldn't hold the CS while creating a window
|
||||
---
|
||||
dlls/imm32/imm.c | 160 ++++++++++++++++++++++++++++++++++++++++++-------------
|
||||
1 file changed, 124 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c
|
||||
index 2fa31ac..b617f5a 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,50 @@ static DWORD convert_candidatelist_AtoW(
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static IMMThreadData* IMM_GetThreadData(void)
|
||||
+static IMMThreadData* IMM_GetThreadData(DWORD tid)
|
||||
{
|
||||
- IMMThreadData* data = TlsGetValue(tlsIndex);
|
||||
- if (!data)
|
||||
+ IMMThreadData *data;
|
||||
+
|
||||
+ if (!tid) tid = 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 == tid)
|
||||
+ return data;
|
||||
}
|
||||
+
|
||||
+ data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
+ sizeof(IMMThreadData));
|
||||
+ data->threadID = tid;
|
||||
+ list_add_head(&ImmThreadDataList, &data->entry);
|
||||
+ TRACE("Thread Data Created (%x)\n", tid);
|
||||
+
|
||||
return data;
|
||||
}
|
||||
|
||||
static void IMM_FreeThreadData(void)
|
||||
{
|
||||
- IMMThreadData* data = TlsGetValue(tlsIndex);
|
||||
- if (data)
|
||||
+ IMMThreadData *data;
|
||||
+ DWORD tid = GetCurrentThreadId();
|
||||
+
|
||||
+ EnterCriticalSection(&threaddata_cs);
|
||||
+ LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
|
||||
{
|
||||
- IMM_DestroyContext(data->defaultContext);
|
||||
- DestroyWindow(data->hwndDefault);
|
||||
- HeapFree(GetProcessHeap(),0,data);
|
||||
- TRACE("Thread Data Destroyed\n");
|
||||
+ if (data->threadID == tid)
|
||||
+ {
|
||||
+ list_remove(&data->entry);
|
||||
+ LeaveCriticalSection(&threaddata_cs);
|
||||
+
|
||||
+ IMM_DestroyContext(data->defaultContext);
|
||||
+ DestroyWindow(data->hwndDefault);
|
||||
+ HeapFree(GetProcessHeap(),0,data);
|
||||
+ TRACE("Thread Data Destroyed\n");
|
||||
+
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
+ LeaveCriticalSection(&threaddata_cs);
|
||||
}
|
||||
|
||||
static HMODULE load_graphics_driver(void)
|
||||
@@ -398,9 +430,6 @@ 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:
|
||||
@@ -412,7 +441,6 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
|
||||
if (lpReserved) break;
|
||||
IMM_FreeThreadData();
|
||||
IMM_FreeAllImmHkl();
|
||||
- TlsFree(tlsIndex);
|
||||
UnregisterClassW(szwIME, NULL);
|
||||
break;
|
||||
}
|
||||
@@ -469,6 +497,34 @@ static InputContextData* get_imc_data(HIMC hIMC)
|
||||
return data;
|
||||
}
|
||||
|
||||
+static IMMThreadData* IMM_GetInitializedThreadData(void)
|
||||
+{
|
||||
+ IMMThreadData* thread_data;
|
||||
+ HIMC defaultContext;
|
||||
+
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ thread_data = IMM_GetThreadData(0);
|
||||
+ if (thread_data->defaultContext)
|
||||
+ return thread_data;
|
||||
+ LeaveCriticalSection(&threaddata_cs);
|
||||
+
|
||||
+ /* don't hold the CS while creating the context */
|
||||
+ defaultContext = ImmCreateContext();
|
||||
+
|
||||
+ thread_data = IMM_GetThreadData(0);
|
||||
+ if (!thread_data->defaultContext)
|
||||
+ {
|
||||
+ thread_data->defaultContext = defaultContext;
|
||||
+ return thread_data;
|
||||
+ }
|
||||
+
|
||||
+ /* someone beat us */
|
||||
+ LeaveCriticalSection(&threaddata_cs);
|
||||
+ IMM_DestroyContext(defaultContext);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/***********************************************************************
|
||||
* ImmAssociateContext (IMM32.@)
|
||||
*/
|
||||
@@ -476,31 +532,30 @@ 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 (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 +570,7 @@ HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
|
||||
old_data->IMC.hWnd = NULL;
|
||||
}
|
||||
}
|
||||
+ LeaveCriticalSection(&threaddata_cs);
|
||||
|
||||
if (!hIMC)
|
||||
return old;
|
||||
@@ -556,12 +612,17 @@ 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();
|
||||
+ defaultContext = thread_data->defaultContext;
|
||||
+ LeaveCriticalSection(&threaddata_cs);
|
||||
|
||||
- if (!hWnd) return FALSE;
|
||||
+ if (!hWnd)
|
||||
+ return FALSE;
|
||||
|
||||
switch (dwFlags)
|
||||
{
|
||||
@@ -569,7 +630,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 +805,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 +1475,7 @@ BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
|
||||
HIMC WINAPI ImmGetContext(HWND hWnd)
|
||||
{
|
||||
HIMC rc;
|
||||
+ IMMThreadData* thread_data;
|
||||
|
||||
TRACE("%p\n", hWnd);
|
||||
|
||||
@@ -1418,20 +1484,21 @@ HIMC WINAPI ImmGetContext(HWND hWnd)
|
||||
SetLastError(ERROR_INVALID_WINDOW_HANDLE);
|
||||
return NULL;
|
||||
}
|
||||
- if (!IMM_GetThreadData()->defaultContext)
|
||||
- IMM_GetThreadData()->defaultContext = ImmCreateContext();
|
||||
|
||||
+ thread_data = IMM_GetInitializedThreadData();
|
||||
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 +1606,32 @@ BOOL WINAPI ImmGetConversionStatus(
|
||||
*/
|
||||
HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
|
||||
{
|
||||
- if (IMM_GetThreadData()->hwndDefault == NULL)
|
||||
- IMM_GetThreadData()->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;
|
||||
+ IMMThreadData* thread_data;
|
||||
+ HWND ret;
|
||||
+
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ thread_data = IMM_GetThreadData(0);
|
||||
+ ret = thread_data->hwndDefault;
|
||||
+ LeaveCriticalSection(&threaddata_cs);
|
||||
+ if (ret) return ret;
|
||||
+
|
||||
+ /* don't hold the CS while creating the window */
|
||||
+ ret = CreateWindowExW( WS_EX_TOOLWINDOW,
|
||||
+ szwIME, NULL, WS_POPUP, 0, 0, 1, 1, 0, 0, 0, 0);
|
||||
+
|
||||
+ thread_data = IMM_GetThreadData(0);
|
||||
+ if (!thread_data->hwndDefault)
|
||||
+ {
|
||||
+ thread_data->hwndDefault = ret;
|
||||
+ LeaveCriticalSection(&threaddata_cs);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* someone beat us */
|
||||
+ LeaveCriticalSection(&threaddata_cs);
|
||||
+ DestroyWindow(ret);
|
||||
+ }
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
--
|
||||
2.1.1
|
||||
|
@ -0,0 +1,72 @@
|
||||
From bf064c6ac3f0124810e2afadff7b0cdcbf032765 Mon Sep 17 00:00:00 2001
|
||||
From: Aric Stewart <aric@codeweavers.com>
|
||||
Date: Mon, 29 Sep 2014 02:28:32 +0200
|
||||
Subject: imm32: Do not let ImmDestroyContext destroy any default contexts.
|
||||
|
||||
optimization suggested by Nikolay Sivov
|
||||
---
|
||||
dlls/imm32/imm.c | 20 +++++++++++++++-----
|
||||
1 file changed, 15 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c
|
||||
index b617f5a..ec03c62 100644
|
||||
--- a/dlls/imm32/imm.c
|
||||
+++ b/dlls/imm32/imm.c
|
||||
@@ -74,6 +74,7 @@ typedef struct tagInputContextData
|
||||
|
||||
ImmHkl *immKbd;
|
||||
UINT lastVK;
|
||||
+ BOOL threadDefault;
|
||||
DWORD magic;
|
||||
} InputContextData;
|
||||
|
||||
@@ -128,6 +129,7 @@ static LRESULT WINAPI DefIME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
||||
#define is_kbd_ime_unicode(p) (p->imeInfo.fdwProperty & IME_PROP_UNICODE)
|
||||
|
||||
static BOOL IMM_DestroyContext(HIMC hIMC);
|
||||
+static InputContextData* get_imc_data(HIMC hIMC);
|
||||
|
||||
static inline WCHAR *strdupAtoW( const char *str )
|
||||
{
|
||||
@@ -253,6 +255,16 @@ static IMMThreadData* IMM_GetThreadData(DWORD tid)
|
||||
return data;
|
||||
}
|
||||
|
||||
+static BOOL IMM_IsDefaultContext(HIMC imc)
|
||||
+{
|
||||
+ InputContextData *data = get_imc_data(imc);
|
||||
+
|
||||
+ if (!data)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ return data->threadDefault;
|
||||
+}
|
||||
+
|
||||
static void IMM_FreeThreadData(void)
|
||||
{
|
||||
IMMThreadData *data;
|
||||
@@ -511,6 +523,8 @@ static IMMThreadData* IMM_GetInitializedThreadData(void)
|
||||
|
||||
/* don't hold the CS while creating the context */
|
||||
defaultContext = ImmCreateContext();
|
||||
+ if (defaultContext)
|
||||
+ ((InputContextData*)defaultContext)->threadDefault = TRUE;
|
||||
|
||||
thread_data = IMM_GetThreadData(0);
|
||||
if (!thread_data->defaultContext)
|
||||
@@ -805,11 +819,7 @@ static BOOL IMM_DestroyContext(HIMC hIMC)
|
||||
*/
|
||||
BOOL WINAPI ImmDestroyContext(HIMC hIMC)
|
||||
{
|
||||
- IMMThreadData* thread_data = IMM_GetThreadData(0);
|
||||
- HIMC defaultContext = thread_data->defaultContext;
|
||||
- LeaveCriticalSection(&threaddata_cs);
|
||||
-
|
||||
- if (hIMC != defaultContext)
|
||||
+ if (!IMM_IsDefaultContext(hIMC))
|
||||
return IMM_DestroyContext(hIMC);
|
||||
else
|
||||
return FALSE;
|
||||
--
|
||||
2.1.1
|
||||
|
@ -0,0 +1,210 @@
|
||||
From e900bc5a15f15278dc22dbc447ab5f7d18e0ce14 Mon Sep 17 00:00:00 2001
|
||||
From: Aric Stewart <aric@codeweavers.com>
|
||||
Date: Mon, 29 Sep 2014 02:42:05 +0200
|
||||
Subject: imm32: Use thread data from target HWND.
|
||||
|
||||
---
|
||||
dlls/imm32/imm.c | 61 +++++++++++++++++++++++++++++++++++++++++-------
|
||||
dlls/imm32/tests/imm32.c | 21 +++++++++++------
|
||||
2 files changed, 66 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c
|
||||
index ec03c62..f7fca3f 100644
|
||||
--- a/dlls/imm32/imm.c
|
||||
+++ b/dlls/imm32/imm.c
|
||||
@@ -255,6 +255,21 @@ static IMMThreadData* IMM_GetThreadData(DWORD tid)
|
||||
return data;
|
||||
}
|
||||
|
||||
+static IMMThreadData* IMM_GetThreadDataForWindow(HWND hwnd)
|
||||
+{
|
||||
+ DWORD process;
|
||||
+ DWORD thread = 0;
|
||||
+
|
||||
+ if (hwnd)
|
||||
+ {
|
||||
+ thread = GetWindowThreadProcessId(hwnd, &process);
|
||||
+ if (process != GetCurrentProcessId())
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ return IMM_GetThreadData(thread);
|
||||
+}
|
||||
+
|
||||
static BOOL IMM_IsDefaultContext(HIMC imc)
|
||||
{
|
||||
InputContextData *data = get_imc_data(imc);
|
||||
@@ -509,14 +524,16 @@ static InputContextData* get_imc_data(HIMC hIMC)
|
||||
return data;
|
||||
}
|
||||
|
||||
-static IMMThreadData* IMM_GetInitializedThreadData(void)
|
||||
+static IMMThreadData* IMM_GetInitializedThreadData(HWND hWnd)
|
||||
{
|
||||
IMMThreadData* thread_data;
|
||||
HIMC defaultContext;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
- thread_data = IMM_GetThreadData(0);
|
||||
+ thread_data = IMM_GetThreadDataForWindow(hWnd);
|
||||
+ if (!thread_data)
|
||||
+ return NULL;
|
||||
if (thread_data->defaultContext)
|
||||
return thread_data;
|
||||
LeaveCriticalSection(&threaddata_cs);
|
||||
@@ -526,7 +543,12 @@ static IMMThreadData* IMM_GetInitializedThreadData(void)
|
||||
if (defaultContext)
|
||||
((InputContextData*)defaultContext)->threadDefault = TRUE;
|
||||
|
||||
- thread_data = IMM_GetThreadData(0);
|
||||
+ thread_data = IMM_GetThreadDataForWindow(hWnd);
|
||||
+ if (!thread_data)
|
||||
+ {
|
||||
+ IMM_DestroyContext(defaultContext);
|
||||
+ return NULL;
|
||||
+ }
|
||||
if (!thread_data->defaultContext)
|
||||
{
|
||||
thread_data->defaultContext = defaultContext;
|
||||
@@ -559,7 +581,10 @@ HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
|
||||
if (hIMC && data->IMC.hWnd == hWnd)
|
||||
return hIMC;
|
||||
|
||||
- thread_data = IMM_GetInitializedThreadData();
|
||||
+ thread_data = IMM_GetInitializedThreadData(hWnd);
|
||||
+ if (!thread_data)
|
||||
+ return NULL;
|
||||
+
|
||||
if (hWnd)
|
||||
{
|
||||
old = RemovePropW(hWnd,szwWineIMCProperty);
|
||||
@@ -631,7 +656,10 @@ BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
|
||||
|
||||
TRACE("(%p, %p, 0x%x):\n", hWnd, hIMC, dwFlags);
|
||||
|
||||
- thread_data = IMM_GetInitializedThreadData();
|
||||
+ thread_data = IMM_GetInitializedThreadData(hWnd);
|
||||
+ if (!thread_data)
|
||||
+ return FALSE;
|
||||
+
|
||||
defaultContext = thread_data->defaultContext;
|
||||
LeaveCriticalSection(&threaddata_cs);
|
||||
|
||||
@@ -1495,7 +1523,10 @@ HIMC WINAPI ImmGetContext(HWND hWnd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- thread_data = IMM_GetInitializedThreadData();
|
||||
+ thread_data = IMM_GetInitializedThreadData(hWnd);
|
||||
+ if (!thread_data)
|
||||
+ return NULL;
|
||||
+
|
||||
rc = GetPropW(hWnd,szwWineIMCProperty);
|
||||
if (rc == (HIMC)-1)
|
||||
rc = NULL;
|
||||
@@ -1618,19 +1649,31 @@ HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
|
||||
{
|
||||
IMMThreadData* thread_data;
|
||||
HWND ret;
|
||||
+ DWORD tid;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
- thread_data = IMM_GetThreadData(0);
|
||||
+ thread_data = IMM_GetThreadDataForWindow(hWnd);
|
||||
+ if (!thread_data)
|
||||
+ return NULL;
|
||||
ret = thread_data->hwndDefault;
|
||||
+ tid = thread_data->threadID;
|
||||
LeaveCriticalSection(&threaddata_cs);
|
||||
- if (ret) return ret;
|
||||
+
|
||||
+ /* don't create windows for other threads */
|
||||
+ if (ret || tid != GetCurrentThreadId())
|
||||
+ return ret;
|
||||
|
||||
/* don't hold the CS while creating the window */
|
||||
ret = CreateWindowExW( WS_EX_TOOLWINDOW,
|
||||
szwIME, NULL, WS_POPUP, 0, 0, 1, 1, 0, 0, 0, 0);
|
||||
|
||||
- thread_data = IMM_GetThreadData(0);
|
||||
+ thread_data = IMM_GetThreadDataForWindow(hWnd);
|
||||
+ if (!thread_data)
|
||||
+ {
|
||||
+ DestroyWindow(ret);
|
||||
+ return NULL;
|
||||
+ }
|
||||
if (!thread_data->hwndDefault)
|
||||
{
|
||||
thread_data->hwndDefault = ret;
|
||||
diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c
|
||||
index 4c0a888..2471634 100644
|
||||
--- a/dlls/imm32/tests/imm32.c
|
||||
+++ b/dlls/imm32/tests/imm32.c
|
||||
@@ -425,15 +425,17 @@ static DWORD WINAPI ImmGetContextThreadFunc( LPVOID lpParam)
|
||||
HWND hwnd2;
|
||||
COMPOSITIONFORM cf;
|
||||
POINT pt;
|
||||
+ MSG msg;
|
||||
+
|
||||
igc_threadinfo *info= (igc_threadinfo*)lpParam;
|
||||
info->hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
|
||||
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
|
||||
|
||||
h1 = ImmGetContext(hwnd);
|
||||
- todo_wine ok(info->himc == h1, "hwnd context changed in new thread\n");
|
||||
+ ok(info->himc == h1, "hwnd context changed in new thread\n");
|
||||
h2 = ImmGetContext(info->hwnd);
|
||||
- todo_wine ok(h2 != h1, "new hwnd in new thread should have different context\n");
|
||||
+ ok(h2 != h1, "new hwnd in new thread should have different context\n");
|
||||
info->himc = h2;
|
||||
ImmReleaseContext(hwnd,h1);
|
||||
|
||||
@@ -452,7 +454,12 @@ static DWORD WINAPI ImmGetContextThreadFunc( LPVOID lpParam)
|
||||
ImmSetStatusWindowPos(h1, &pt);
|
||||
|
||||
SetEvent(info->event);
|
||||
- Sleep(INFINITE);
|
||||
+
|
||||
+ while(GetMessageW(&msg, 0, 0, 0))
|
||||
+ {
|
||||
+ TranslateMessage(&msg);
|
||||
+ DispatchMessageW(&msg);
|
||||
+ }
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -477,8 +484,8 @@ static void test_ImmThreads(void)
|
||||
|
||||
otherHimc = ImmGetContext(threadinfo.hwnd);
|
||||
|
||||
- todo_wine ok(himc != otherHimc, "Windows from other threads should have different himc\n");
|
||||
- todo_wine ok(otherHimc == threadinfo.himc, "Context from other thread should not change in main thread\n");
|
||||
+ ok(himc != otherHimc, "Windows from other threads should have different himc\n");
|
||||
+ ok(otherHimc == threadinfo.himc, "Context from other thread should not change in main thread\n");
|
||||
|
||||
if (0) /* FIXME: Causes wine to hang */
|
||||
{
|
||||
@@ -566,7 +573,7 @@ static void test_ImmThreads(void)
|
||||
ok (rc == 1, "ImmGetCandidateWindow should succeed\n");
|
||||
|
||||
rc = ImmGetCandidateWindow(otherHimc, 0, &cdf);
|
||||
- todo_wine ok (rc == 0, "ImmGetCandidateWindow should fail\n");
|
||||
+ ok (rc == 0, "ImmGetCandidateWindow should fail\n");
|
||||
rc = ImmSetCandidateWindow(otherHimc, &cdf);
|
||||
todo_wine ok (rc == 0, "ImmSetCandidateWindow should fail\n");
|
||||
|
||||
@@ -577,7 +584,7 @@ static void test_ImmThreads(void)
|
||||
TerminateThread(hThread, 1);
|
||||
|
||||
himc = ImmGetContext(GetDesktopWindow());
|
||||
- todo_wine ok(himc == NULL, "Should not be able to get himc from other process window\n");
|
||||
+ ok(himc == NULL, "Should not be able to get himc from other process window\n");
|
||||
}
|
||||
|
||||
static void test_ImmIsUIMessage(void)
|
||||
--
|
||||
2.1.1
|
||||
|
@ -0,0 +1,227 @@
|
||||
From f5b7d0ea864e0ab6fb28f8ff492730a4d748b356 Mon Sep 17 00:00:00 2001
|
||||
From: Aric Stewart <aric@codeweavers.com>
|
||||
Date: Mon, 29 Sep 2014 02:48:08 +0200
|
||||
Subject: imm32: Restrict crossthread Association and destruction.
|
||||
|
||||
---
|
||||
dlls/imm32/imm.c | 26 ++++++++++++++++++++-
|
||||
dlls/imm32/tests/imm32.c | 59 +++++++++++++++++++++++++++++++++++++++++++++---
|
||||
2 files changed, 81 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c
|
||||
index f7fca3f..efbd623 100644
|
||||
--- a/dlls/imm32/imm.c
|
||||
+++ b/dlls/imm32/imm.c
|
||||
@@ -71,6 +71,7 @@ typedef struct tagInputContextData
|
||||
{
|
||||
DWORD dwLock;
|
||||
INPUTCONTEXT IMC;
|
||||
+ DWORD threadID;
|
||||
|
||||
ImmHkl *immKbd;
|
||||
UINT lastVK;
|
||||
@@ -561,6 +562,25 @@ static IMMThreadData* IMM_GetInitializedThreadData(HWND hWnd)
|
||||
}
|
||||
}
|
||||
|
||||
+static BOOL IMM_IsCrossThreadAccess(HWND hWnd, HIMC hIMC)
|
||||
+{
|
||||
+ DWORD tid = GetCurrentThreadId();
|
||||
+ InputContextData *data;
|
||||
+
|
||||
+ if (hWnd)
|
||||
+ {
|
||||
+ DWORD process;
|
||||
+ DWORD thread;
|
||||
+
|
||||
+ thread = GetWindowThreadProcessId(hWnd, &process);
|
||||
+ if (thread != tid || process != GetCurrentProcessId())
|
||||
+ return TRUE;
|
||||
+ }
|
||||
+
|
||||
+ data = get_imc_data(hIMC);
|
||||
+ return (data && data->threadID != tid);
|
||||
+}
|
||||
+
|
||||
/***********************************************************************
|
||||
* ImmAssociateContext (IMM32.@)
|
||||
*/
|
||||
@@ -581,6 +601,9 @@ HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
|
||||
if (hIMC && data->IMC.hWnd == hWnd)
|
||||
return hIMC;
|
||||
|
||||
+ if (hIMC && IMM_IsCrossThreadAccess(hWnd, hIMC))
|
||||
+ return NULL;
|
||||
+
|
||||
thread_data = IMM_GetInitializedThreadData(hWnd);
|
||||
if (!thread_data)
|
||||
return NULL;
|
||||
@@ -808,6 +831,7 @@ HIMC WINAPI ImmCreateContext(void)
|
||||
IMM_DestroyContext(new_context);
|
||||
return 0;
|
||||
}
|
||||
+ new_context->threadID = GetCurrentThreadId();
|
||||
SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)GetKeyboardLayout(0));
|
||||
|
||||
new_context->immKbd->uSelected++;
|
||||
@@ -847,7 +871,7 @@ static BOOL IMM_DestroyContext(HIMC hIMC)
|
||||
*/
|
||||
BOOL WINAPI ImmDestroyContext(HIMC hIMC)
|
||||
{
|
||||
- if (!IMM_IsDefaultContext(hIMC))
|
||||
+ if (!IMM_IsDefaultContext(hIMC) && !IMM_IsCrossThreadAccess(NULL, hIMC))
|
||||
return IMM_DestroyContext(hIMC);
|
||||
else
|
||||
return FALSE;
|
||||
diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c
|
||||
index 2471634..a64f9da 100644
|
||||
--- a/dlls/imm32/tests/imm32.c
|
||||
+++ b/dlls/imm32/tests/imm32.c
|
||||
@@ -416,6 +416,7 @@ typedef struct _igc_threadinfo {
|
||||
HWND hwnd;
|
||||
HANDLE event;
|
||||
HIMC himc;
|
||||
+ HIMC u_himc;
|
||||
} igc_threadinfo;
|
||||
|
||||
|
||||
@@ -424,6 +425,7 @@ static DWORD WINAPI ImmGetContextThreadFunc( LPVOID lpParam)
|
||||
HIMC h1,h2;
|
||||
HWND hwnd2;
|
||||
COMPOSITIONFORM cf;
|
||||
+ CANDIDATEFORM cdf;
|
||||
POINT pt;
|
||||
MSG msg;
|
||||
|
||||
@@ -452,6 +454,13 @@ static DWORD WINAPI ImmGetContextThreadFunc( LPVOID lpParam)
|
||||
/* priming for later tests */
|
||||
ImmSetCompositionWindow(h1, &cf);
|
||||
ImmSetStatusWindowPos(h1, &pt);
|
||||
+ info->u_himc = ImmCreateContext();
|
||||
+ ImmSetOpenStatus(info->u_himc, TRUE);
|
||||
+ cdf.dwIndex = 0;
|
||||
+ cdf.dwStyle = CFS_CANDIDATEPOS;
|
||||
+ cdf.ptCurrentPos.x = 0;
|
||||
+ cdf.ptCurrentPos.y = 0;
|
||||
+ ImmSetCandidateWindow(info->u_himc, &cdf);
|
||||
|
||||
SetEvent(info->event);
|
||||
|
||||
@@ -487,15 +496,23 @@ static void test_ImmThreads(void)
|
||||
ok(himc != otherHimc, "Windows from other threads should have different himc\n");
|
||||
ok(otherHimc == threadinfo.himc, "Context from other thread should not change in main thread\n");
|
||||
|
||||
- if (0) /* FIXME: Causes wine to hang */
|
||||
- {
|
||||
h1 = ImmAssociateContext(hwnd,otherHimc);
|
||||
ok(h1 == NULL, "Should fail to be able to Associate a default context from a different thread\n");
|
||||
h1 = ImmGetContext(hwnd);
|
||||
ok(h1 == himc, "Context for window should remain unchanged\n");
|
||||
ImmReleaseContext(hwnd,h1);
|
||||
- }
|
||||
|
||||
+ h1 = ImmAssociateContext(hwnd, threadinfo.u_himc);
|
||||
+ ok (h1 == NULL, "Should fail to associate a context from a different thread\n");
|
||||
+ h1 = ImmGetContext(hwnd);
|
||||
+ ok(h1 == himc, "Context for window should remain unchanged\n");
|
||||
+ ImmReleaseContext(hwnd,h1);
|
||||
+
|
||||
+ h1 = ImmAssociateContext(threadinfo.hwnd, threadinfo.u_himc);
|
||||
+ ok (h1 == NULL, "Should fail to associate a context from a different thread into a window from that thread.\n");
|
||||
+ h1 = ImmGetContext(threadinfo.hwnd);
|
||||
+ ok(h1 == threadinfo.himc, "Context for window should remain unchanged\n");
|
||||
+ ImmReleaseContext(threadinfo.hwnd,h1);
|
||||
|
||||
/* OpenStatus */
|
||||
rc = ImmSetOpenStatus(himc, TRUE);
|
||||
@@ -509,8 +526,12 @@ static void test_ImmThreads(void)
|
||||
|
||||
rc = ImmSetOpenStatus(otherHimc, TRUE);
|
||||
todo_wine ok(rc == 0, "ImmSetOpenStatus should fail\n");
|
||||
+ rc = ImmSetOpenStatus(threadinfo.u_himc, TRUE);
|
||||
+ todo_wine ok(rc == 0, "ImmSetOpenStatus should fail\n");
|
||||
rc = ImmGetOpenStatus(otherHimc);
|
||||
todo_wine ok(rc == 0, "ImmGetOpenStatus failed\n");
|
||||
+ rc = ImmGetOpenStatus(threadinfo.u_himc);
|
||||
+ ok (rc == 1 || broken(rc == 0), "ImmGetOpenStatus should return 1\n");
|
||||
rc = ImmSetOpenStatus(otherHimc, FALSE);
|
||||
todo_wine ok(rc == 0, "ImmSetOpenStatus should fail\n");
|
||||
rc = ImmGetOpenStatus(otherHimc);
|
||||
@@ -524,8 +545,12 @@ static void test_ImmThreads(void)
|
||||
|
||||
rc = ImmGetCompositionFontA(otherHimc, &lf);
|
||||
ok(rc != 0 || broken(rc == 0), "ImmGetCompositionFont failed\n");
|
||||
+ rc = ImmGetCompositionFontA(threadinfo.u_himc, &lf);
|
||||
+ ok(rc != 0 || broken(rc == 0), "ImmGetCompositionFont user himc failed\n");
|
||||
rc = ImmSetCompositionFontA(otherHimc, &lf);
|
||||
todo_wine ok(rc == 0, "ImmSetCompositionFont should fail\n");
|
||||
+ rc = ImmSetCompositionFontA(threadinfo.u_himc, &lf);
|
||||
+ todo_wine ok(rc == 0, "ImmSetCompositionFont should fail\n");
|
||||
|
||||
/* CompositionWindow */
|
||||
rc = ImmSetCompositionWindow(himc, &cf);
|
||||
@@ -535,8 +560,12 @@ static void test_ImmThreads(void)
|
||||
|
||||
rc = ImmSetCompositionWindow(otherHimc, &cf);
|
||||
todo_wine ok(rc == 0, "ImmSetCompositionWindow should fail\n");
|
||||
+ rc = ImmSetCompositionWindow(threadinfo.u_himc, &cf);
|
||||
+ todo_wine ok(rc == 0, "ImmSetCompositionWindow should fail\n");
|
||||
rc = ImmGetCompositionWindow(otherHimc, &cf);
|
||||
ok(rc != 0 || broken(rc == 0), "ImmGetCompositionWindow failed\n");
|
||||
+ rc = ImmGetCompositionWindow(threadinfo.u_himc, &cf);
|
||||
+ ok(rc != 0 || broken(rc == 0), "ImmGetCompositionWindow failed\n");
|
||||
|
||||
/* ConversionStatus */
|
||||
rc = ImmGetConversionStatus(himc, &status, &sentence);
|
||||
@@ -546,8 +575,12 @@ static void test_ImmThreads(void)
|
||||
|
||||
rc = ImmGetConversionStatus(otherHimc, &status, &sentence);
|
||||
ok(rc != 0 || broken(rc == 0), "ImmGetConversionStatus failed\n");
|
||||
+ rc = ImmGetConversionStatus(threadinfo.u_himc, &status, &sentence);
|
||||
+ ok(rc != 0 || broken(rc == 0), "ImmGetConversionStatus failed\n");
|
||||
rc = ImmSetConversionStatus(otherHimc, status, sentence);
|
||||
todo_wine ok(rc == 0, "ImmSetConversionStatus should fail\n");
|
||||
+ rc = ImmSetConversionStatus(threadinfo.u_himc, status, sentence);
|
||||
+ todo_wine ok(rc == 0, "ImmSetConversionStatus should fail\n");
|
||||
|
||||
/* StatusWindowPos */
|
||||
rc = ImmSetStatusWindowPos(himc, &pt);
|
||||
@@ -557,8 +590,24 @@ static void test_ImmThreads(void)
|
||||
|
||||
rc = ImmSetStatusWindowPos(otherHimc, &pt);
|
||||
todo_wine ok(rc == 0, "ImmSetStatusWindowPos should fail\n");
|
||||
+ rc = ImmSetStatusWindowPos(threadinfo.u_himc, &pt);
|
||||
+ todo_wine ok(rc == 0, "ImmSetStatusWindowPos should fail\n");
|
||||
rc = ImmGetStatusWindowPos(otherHimc, &pt);
|
||||
ok(rc != 0 || broken(rc == 0), "ImmGetStatusWindowPos failed\n");
|
||||
+ rc = ImmGetStatusWindowPos(threadinfo.u_himc, &pt);
|
||||
+ ok(rc != 0 || broken(rc == 0), "ImmGetStatusWindowPos failed\n");
|
||||
+
|
||||
+ h1 = ImmAssociateContext(threadinfo.hwnd, NULL);
|
||||
+ ok (h1 == otherHimc, "ImmAssociateContext cross thread with NULL should work\n");
|
||||
+ h1 = ImmGetContext(threadinfo.hwnd);
|
||||
+ ok (h1 == NULL, "CrossThread window context should be NULL\n");
|
||||
+ h1 = ImmAssociateContext(threadinfo.hwnd, h1);
|
||||
+ ok (h1 == NULL, "Resetting cross thread context should fail\n");
|
||||
+ h1 = ImmGetContext(threadinfo.hwnd);
|
||||
+ ok (h1 == NULL, "CrossThread window context should still be NULL\n");
|
||||
+
|
||||
+ rc = ImmDestroyContext(threadinfo.u_himc);
|
||||
+ ok (rc == 0, "ImmDestroyContext Cross Thread should fail\n");
|
||||
|
||||
/* Candidate Window */
|
||||
rc = ImmGetCandidateWindow(himc, 0, &cdf);
|
||||
@@ -576,6 +625,10 @@ static void test_ImmThreads(void)
|
||||
ok (rc == 0, "ImmGetCandidateWindow should fail\n");
|
||||
rc = ImmSetCandidateWindow(otherHimc, &cdf);
|
||||
todo_wine ok (rc == 0, "ImmSetCandidateWindow should fail\n");
|
||||
+ rc = ImmGetCandidateWindow(threadinfo.u_himc, 0, &cdf);
|
||||
+ ok (rc == 1 || broken( rc == 0), "ImmGetCandidateWindow should succeed\n");
|
||||
+ rc = ImmSetCandidateWindow(threadinfo.u_himc, &cdf);
|
||||
+ todo_wine ok (rc == 0, "ImmSetCandidateWindow should fail\n");
|
||||
|
||||
ImmReleaseContext(threadinfo.hwnd,otherHimc);
|
||||
ImmReleaseContext(hwnd,himc);
|
||||
--
|
||||
2.1.1
|
||||
|
@ -0,0 +1,173 @@
|
||||
From e76b9bfb0d47f7df14256e62a57585660adcf8c0 Mon Sep 17 00:00:00 2001
|
||||
From: Aric Stewart <aric@codeweavers.com>
|
||||
Date: Mon, 8 Sep 2014 21:06:13 -0500
|
||||
Subject: imm32: Limit cross thread access to ImmSet* functions.
|
||||
|
||||
---
|
||||
dlls/imm32/imm.c | 21 +++++++++++++++++++++
|
||||
dlls/imm32/tests/imm32.c | 28 ++++++++++++++--------------
|
||||
2 files changed, 35 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c
|
||||
index efbd623..222c86e 100644
|
||||
--- a/dlls/imm32/imm.c
|
||||
+++ b/dlls/imm32/imm.c
|
||||
@@ -2311,6 +2311,9 @@ BOOL WINAPI ImmSetCandidateWindow(
|
||||
if (!data || !lpCandidate)
|
||||
return FALSE;
|
||||
|
||||
+ if (IMM_IsCrossThreadAccess(NULL, hIMC))
|
||||
+ return FALSE;
|
||||
+
|
||||
TRACE("\t%x, %x, (%i,%i), (%i,%i - %i,%i)\n",
|
||||
lpCandidate->dwIndex, lpCandidate->dwStyle,
|
||||
lpCandidate->ptCurrentPos.x, lpCandidate->ptCurrentPos.y,
|
||||
@@ -2341,6 +2344,9 @@ BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
+ if (IMM_IsCrossThreadAccess(NULL, hIMC))
|
||||
+ return FALSE;
|
||||
+
|
||||
memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
|
||||
MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
|
||||
LF_FACESIZE);
|
||||
@@ -2364,6 +2370,9 @@ BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
+ if (IMM_IsCrossThreadAccess(NULL, hIMC))
|
||||
+ return FALSE;
|
||||
+
|
||||
data->IMC.lfFont.W = *lplf;
|
||||
ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
|
||||
ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
|
||||
@@ -2505,6 +2514,9 @@ BOOL WINAPI ImmSetCompositionWindow(
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
+ if (IMM_IsCrossThreadAccess(NULL, hIMC))
|
||||
+ return FALSE;
|
||||
+
|
||||
data->IMC.cfCompForm = *lpCompForm;
|
||||
|
||||
if (IsWindowVisible(data->immKbd->UIWnd))
|
||||
@@ -2539,6 +2551,9 @@ BOOL WINAPI ImmSetConversionStatus(
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
+ if (IMM_IsCrossThreadAccess(NULL, hIMC))
|
||||
+ return FALSE;
|
||||
+
|
||||
if ( fdwConversion != data->IMC.fdwConversion )
|
||||
{
|
||||
oldConversion = data->IMC.fdwConversion;
|
||||
@@ -2572,6 +2587,9 @@ BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
+ if (IMM_IsCrossThreadAccess(NULL, hIMC))
|
||||
+ return FALSE;
|
||||
+
|
||||
if (data->immKbd->UIWnd == NULL)
|
||||
{
|
||||
/* create the ime window */
|
||||
@@ -2608,6 +2626,9 @@ BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
+ if (IMM_IsCrossThreadAccess(NULL, hIMC))
|
||||
+ return FALSE;
|
||||
+
|
||||
TRACE("\t(%i,%i)\n", lpptPos->x, lpptPos->y);
|
||||
|
||||
data->IMC.ptStatusWndPos = *lpptPos;
|
||||
diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c
|
||||
index a64f9da..d7eec44 100644
|
||||
--- a/dlls/imm32/tests/imm32.c
|
||||
+++ b/dlls/imm32/tests/imm32.c
|
||||
@@ -525,15 +525,15 @@ static void test_ImmThreads(void)
|
||||
ok(rc == 0, "ImmGetOpenStatus failed\n");
|
||||
|
||||
rc = ImmSetOpenStatus(otherHimc, TRUE);
|
||||
- todo_wine ok(rc == 0, "ImmSetOpenStatus should fail\n");
|
||||
+ ok(rc == 0, "ImmSetOpenStatus should fail\n");
|
||||
rc = ImmSetOpenStatus(threadinfo.u_himc, TRUE);
|
||||
- todo_wine ok(rc == 0, "ImmSetOpenStatus should fail\n");
|
||||
+ ok(rc == 0, "ImmSetOpenStatus should fail\n");
|
||||
rc = ImmGetOpenStatus(otherHimc);
|
||||
- todo_wine ok(rc == 0, "ImmGetOpenStatus failed\n");
|
||||
+ ok(rc == 0, "ImmGetOpenStatus failed\n");
|
||||
rc = ImmGetOpenStatus(threadinfo.u_himc);
|
||||
ok (rc == 1 || broken(rc == 0), "ImmGetOpenStatus should return 1\n");
|
||||
rc = ImmSetOpenStatus(otherHimc, FALSE);
|
||||
- todo_wine ok(rc == 0, "ImmSetOpenStatus should fail\n");
|
||||
+ ok(rc == 0, "ImmSetOpenStatus should fail\n");
|
||||
rc = ImmGetOpenStatus(otherHimc);
|
||||
ok(rc == 0, "ImmGetOpenStatus failed\n");
|
||||
|
||||
@@ -548,9 +548,9 @@ static void test_ImmThreads(void)
|
||||
rc = ImmGetCompositionFontA(threadinfo.u_himc, &lf);
|
||||
ok(rc != 0 || broken(rc == 0), "ImmGetCompositionFont user himc failed\n");
|
||||
rc = ImmSetCompositionFontA(otherHimc, &lf);
|
||||
- todo_wine ok(rc == 0, "ImmSetCompositionFont should fail\n");
|
||||
+ ok(rc == 0, "ImmSetCompositionFont should fail\n");
|
||||
rc = ImmSetCompositionFontA(threadinfo.u_himc, &lf);
|
||||
- todo_wine ok(rc == 0, "ImmSetCompositionFont should fail\n");
|
||||
+ ok(rc == 0, "ImmSetCompositionFont should fail\n");
|
||||
|
||||
/* CompositionWindow */
|
||||
rc = ImmSetCompositionWindow(himc, &cf);
|
||||
@@ -559,9 +559,9 @@ static void test_ImmThreads(void)
|
||||
ok(rc != 0, "ImmGetCompositionWindow failed\n");
|
||||
|
||||
rc = ImmSetCompositionWindow(otherHimc, &cf);
|
||||
- todo_wine ok(rc == 0, "ImmSetCompositionWindow should fail\n");
|
||||
+ ok(rc == 0, "ImmSetCompositionWindow should fail\n");
|
||||
rc = ImmSetCompositionWindow(threadinfo.u_himc, &cf);
|
||||
- todo_wine ok(rc == 0, "ImmSetCompositionWindow should fail\n");
|
||||
+ ok(rc == 0, "ImmSetCompositionWindow should fail\n");
|
||||
rc = ImmGetCompositionWindow(otherHimc, &cf);
|
||||
ok(rc != 0 || broken(rc == 0), "ImmGetCompositionWindow failed\n");
|
||||
rc = ImmGetCompositionWindow(threadinfo.u_himc, &cf);
|
||||
@@ -578,9 +578,9 @@ static void test_ImmThreads(void)
|
||||
rc = ImmGetConversionStatus(threadinfo.u_himc, &status, &sentence);
|
||||
ok(rc != 0 || broken(rc == 0), "ImmGetConversionStatus failed\n");
|
||||
rc = ImmSetConversionStatus(otherHimc, status, sentence);
|
||||
- todo_wine ok(rc == 0, "ImmSetConversionStatus should fail\n");
|
||||
+ ok(rc == 0, "ImmSetConversionStatus should fail\n");
|
||||
rc = ImmSetConversionStatus(threadinfo.u_himc, status, sentence);
|
||||
- todo_wine ok(rc == 0, "ImmSetConversionStatus should fail\n");
|
||||
+ ok(rc == 0, "ImmSetConversionStatus should fail\n");
|
||||
|
||||
/* StatusWindowPos */
|
||||
rc = ImmSetStatusWindowPos(himc, &pt);
|
||||
@@ -589,9 +589,9 @@ static void test_ImmThreads(void)
|
||||
ok(rc != 0, "ImmGetStatusWindowPos failed\n");
|
||||
|
||||
rc = ImmSetStatusWindowPos(otherHimc, &pt);
|
||||
- todo_wine ok(rc == 0, "ImmSetStatusWindowPos should fail\n");
|
||||
+ ok(rc == 0, "ImmSetStatusWindowPos should fail\n");
|
||||
rc = ImmSetStatusWindowPos(threadinfo.u_himc, &pt);
|
||||
- todo_wine ok(rc == 0, "ImmSetStatusWindowPos should fail\n");
|
||||
+ ok(rc == 0, "ImmSetStatusWindowPos should fail\n");
|
||||
rc = ImmGetStatusWindowPos(otherHimc, &pt);
|
||||
ok(rc != 0 || broken(rc == 0), "ImmGetStatusWindowPos failed\n");
|
||||
rc = ImmGetStatusWindowPos(threadinfo.u_himc, &pt);
|
||||
@@ -624,11 +624,11 @@ static void test_ImmThreads(void)
|
||||
rc = ImmGetCandidateWindow(otherHimc, 0, &cdf);
|
||||
ok (rc == 0, "ImmGetCandidateWindow should fail\n");
|
||||
rc = ImmSetCandidateWindow(otherHimc, &cdf);
|
||||
- todo_wine ok (rc == 0, "ImmSetCandidateWindow should fail\n");
|
||||
+ ok (rc == 0, "ImmSetCandidateWindow should fail\n");
|
||||
rc = ImmGetCandidateWindow(threadinfo.u_himc, 0, &cdf);
|
||||
ok (rc == 1 || broken( rc == 0), "ImmGetCandidateWindow should succeed\n");
|
||||
rc = ImmSetCandidateWindow(threadinfo.u_himc, &cdf);
|
||||
- todo_wine ok (rc == 0, "ImmSetCandidateWindow should fail\n");
|
||||
+ ok (rc == 0, "ImmSetCandidateWindow should fail\n");
|
||||
|
||||
ImmReleaseContext(threadinfo.hwnd,otherHimc);
|
||||
ImmReleaseContext(hwnd,himc);
|
||||
--
|
||||
2.1.1
|
||||
|
4
patches/imm32-Cross_Thread_Access/definition
Normal file
4
patches/imm32-Cross_Thread_Access/definition
Normal file
@ -0,0 +1,4 @@
|
||||
Author: Aric Stewart
|
||||
Subject: Limit cross thread access to ImmSet* functions.
|
||||
Revision: 1
|
||||
Fixes: [35361] Limit cross thread access to ImmSet* functions
|
Loading…
Reference in New Issue
Block a user