Draft: improve IMC/IMCC related functions

Qian Hong fracting at gmail.com
Mon Aug 5 13:14:36 CDT 2013


Hello,

This is a follow up of
http://www.winehq.org/pipermail/wine-devel/2013-July/100459.html (
[PATCH] imm32: Fixed crashing in ImmGetIMCCSize. )

I believe the attached patchset is the correct fix for the Office
crashing bug, how ever, I'm looking for a more graceful way to improve
ImmCreateContext and other IMC functions, I appreciate to any feedback
on the patches especially Patch 6/6.

My tests show that Windows return a HGLOBAL hmem for ImmCreateIMCC()
as the returned HIMCC, so it is easy to re-implement ImmCreateIMCC in
a graceful way. However, Windows return a magic number for
ImmCreateContext, (for instance, have a look at 000B01D9 in the test
show in https://testbot.winehq.org/JobDetails.pl?Key=26619&log_207=1#k207)

I have no idea how that magic number comes, while I understand there
is no need to re-implement ImmCreateContext in the same way as Windows
does, I'm still interesting in a more beautiful implementation like my
ImmCreateIMCC reached, get rid of casting InputContextData to HIMC if
possible. Thanks in advance for any suggestions!

If there is no better way, I'll send this series to wine-patches.


-- 
Regards,
Qian Hong

-
http://www.winehq.org
-------------- next part --------------
From 8ef24f0fc1c962aa69ac2a1baec197abe3523068 Mon Sep 17 00:00:00 2001
From: Qian Hong <qhong at codeweavers.com>
Date: Mon, 5 Aug 2013 23:17:38 +0800
Subject: [PATCH 1/6] imm32/tests: Added more IMCC lock count tests.
To: wine-patches <wine-patches at winehq.org>
Reply-To: wine-devel <wine-devel at winehq.org>
Cc: Qian Hong<qhong at codeweavers.com>

---
 dlls/imm32/tests/imm32.c |   25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c
index 26101a4..2cdc662 100644
--- a/dlls/imm32/tests/imm32.c
+++ b/dlls/imm32/tests/imm32.c
@@ -715,7 +715,8 @@ static void test_ImmGetIMCLockCount(void)
 static void test_ImmGetIMCCLockCount(void)
 {
     HIMCC imcc;
-    DWORD count, ret;
+    DWORD count, g_count, ret, i;
+    VOID *p;
 
     imcc = ImmCreateIMCC(sizeof(CANDIDATEINFO));
     count = ImmGetIMCCLockCount(imcc);
@@ -731,6 +732,28 @@ static void test_ImmGetIMCCLockCount(void)
     ok(ret == FALSE, "expect FALSE, ret %d\n", ret);
     count = ImmGetIMCCLockCount(imcc);
     ok(count == 0, "expect 0, returned %d\n", count);
+
+    p = ImmLockIMCC(imcc);
+    todo_wine ok(GlobalHandle(p) == imcc, "expect %p, returned %p\n", imcc, GlobalHandle(p));
+
+    for (i = 0; i < GMEM_LOCKCOUNT * 2; i++)
+    {
+        ImmLockIMCC(imcc);
+        count = ImmGetIMCCLockCount(imcc);
+        g_count = GlobalFlags(imcc) & GMEM_LOCKCOUNT;
+        todo_wine ok(count == g_count, "count %d, g_count %d\n", count, g_count);
+    }
+    count = ImmGetIMCCLockCount(imcc);
+    todo_wine ok(count == GMEM_LOCKCOUNT, "expect GMEM_LOCKCOUNT, returned %d\n", count);
+
+    for (i = 0; i < GMEM_LOCKCOUNT - 1; i++)
+        GlobalUnlock(imcc);
+    count = ImmGetIMCCLockCount(imcc);
+    todo_wine ok(count == 1, "expect 1, returned %d\n", count);
+    GlobalUnlock(imcc);
+    count = ImmGetIMCCLockCount(imcc);
+    todo_wine ok(count == 0, "expect 0, returned %d\n", count);
+
     ImmDestroyIMCC(imcc);
 }
 
-- 
1.7.9.5
-------------- next part --------------
From 45a80c8cd1d0cb2dfa3d5afaadbfd22f41ee5cef Mon Sep 17 00:00:00 2001
From: Qian Hong <qhong at codeweavers.com>
Date: Mon, 5 Aug 2013 23:56:37 +0800
Subject: [PATCH 2/6] imm32/tests: Added tests for ImmDestroyIMCC.
To: wine-patches <wine-patches at winehq.org>
Reply-To: wine-devel <wine-devel at winehq.org>
Cc: Qian Hong<qhong at codeweavers.com>

---
 dlls/imm32/tests/imm32.c |   33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c
index 2cdc662..6965d5f 100644
--- a/dlls/imm32/tests/imm32.c
+++ b/dlls/imm32/tests/imm32.c
@@ -757,6 +757,38 @@ static void test_ImmGetIMCCLockCount(void)
     ImmDestroyIMCC(imcc);
 }
 
+static void test_ImmDestroyIMCC(void)
+{
+    HIMCC imcc;
+    DWORD ret, count, size;
+    VOID *p;
+
+    imcc = ImmCreateIMCC(sizeof(CANDIDATEINFO));
+    count = ImmGetIMCCLockCount(imcc);
+    ok(count == 0, "expect 0, returned %d\n", count);
+    p = ImmLockIMCC(imcc);
+    ok(p != NULL, "ImmLockIMCC failed!\n");
+    count = ImmGetIMCCLockCount(imcc);
+    ok(count == 1, "expect 1, returned %d\n", count);
+    size = ImmGetIMCCSize(imcc);
+    ok(size == sizeof(CANDIDATEINFO), "expect %d, returned %d\n", sizeof(CANDIDATEINFO), size);
+    p = ImmDestroyIMCC(imcc);
+    ok(p == NULL, "Destroy an locked IMCC should success!\n");
+    p = ImmLockIMCC(imcc);
+    todo_wine ok(p == NULL, "Lock a destroyed IMCC should fail!\n");
+    ret = ImmUnlockIMCC(imcc);
+    todo_wine ok(ret == FALSE, "Unlock a destroyed IMCC should return FALSE!\n");
+    count = ImmGetIMCCLockCount(imcc);
+    todo_wine ok(count == 0, "Get lock count of a destroyed IMCC should return 0!\n");
+    size = ImmGetIMCCSize(imcc);
+    todo_wine ok(size == 0, "Get size of a destroyed IMCC should return 0!\n");
+    SetLastError(0xdeadbeef);
+    p = ImmDestroyIMCC(imcc);
+    todo_wine ok(p != NULL, "returned NULL\n");
+    ret = GetLastError();
+    todo_wine ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
+}
+
 static void test_ImmMessages(void)
 {
     CANDIDATEFORM cf;
@@ -918,6 +950,7 @@ START_TEST(imm32) {
         test_ImmDefaultHwnd();
         test_ImmGetIMCLockCount();
         test_ImmGetIMCCLockCount();
+        test_ImmDestroyIMCC();
         msg_spy_cleanup();
         /* Reinitialize the hooks to capture all windows */
         msg_spy_init(NULL);
-- 
1.7.9.5
-------------- next part --------------
From 5343cc57be7ea86ee0efc238d6609a60a98c4621 Mon Sep 17 00:00:00 2001
From: Qian Hong <qhong at codeweavers.com>
Date: Tue, 6 Aug 2013 00:08:36 +0800
Subject: [PATCH 3/6] imm32: Fixed IMCC implementation.
To: wine-patches <wine-patches at winehq.org>
Reply-To: wine-devel <wine-devel at winehq.org>
Cc: Qian Hong<qhong at codeweavers.com>

---
 dlls/imm32/imm.c         |   52 +++++++---------------------------------------
 dlls/imm32/tests/imm32.c |   22 ++++++++++----------
 2 files changed, 18 insertions(+), 56 deletions(-)

diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c
index 5aee6ea..bc7caba 100644
--- a/dlls/imm32/imm.c
+++ b/dlls/imm32/imm.c
@@ -37,12 +37,6 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(imm);
 
-typedef struct tagIMCCInternal
-{
-    DWORD dwLock;
-    DWORD dwSize;
-} IMCCInternal;
-
 #define MAKE_FUNCPTR(f) typeof(f) * p##f
 typedef struct _tagImmHkl{
     struct list entry;
@@ -2625,15 +2619,7 @@ DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
 */
 HIMCC  WINAPI ImmCreateIMCC(DWORD size)
 {
-    IMCCInternal *internal;
-    int real_size = size + sizeof(IMCCInternal);
-
-    internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
-    if (internal == NULL)
-        return NULL;
-
-    internal->dwSize = size;
-    return  internal;
+    return GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE, size);
 }
 
 /***********************************************************************
@@ -2641,8 +2627,7 @@ HIMCC  WINAPI ImmCreateIMCC(DWORD size)
 */
 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
 {
-    HeapFree(GetProcessHeap(),0,block);
-    return NULL;
+    return GlobalFree(block);
 }
 
 /***********************************************************************
@@ -2650,11 +2635,7 @@ HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
 */
 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
 {
-    IMCCInternal *internal;
-    internal = imcc;
-
-    internal->dwLock ++;
-    return internal + 1;
+    return GlobalLock(imcc);
 }
 
 /***********************************************************************
@@ -2662,12 +2643,7 @@ LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
 */
 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
 {
-    IMCCInternal *internal;
-    internal = imcc;
-
-    if (internal->dwLock)
-        internal->dwLock --;
-    return (internal->dwLock!=0);
+    return GlobalUnlock(imcc);
 }
 
 /***********************************************************************
@@ -2675,10 +2651,7 @@ BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
 */
 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
 {
-    IMCCInternal *internal;
-    internal = imcc;
-
-    return internal->dwLock;
+    return GlobalFlags(imcc) & GMEM_LOCKCOUNT;
 }
 
 /***********************************************************************
@@ -2686,15 +2659,7 @@ DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
 */
 HIMCC  WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
 {
-    IMCCInternal *internal,*newone;
-    int real_size = size + sizeof(IMCCInternal);
-
-    internal = imcc;
-
-    newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
-    newone->dwSize = size;
-
-    return newone;
+    return GlobalReAlloc(imcc, size, GMEM_ZEROINIT | GMEM_MOVEABLE);
 }
 
 /***********************************************************************
@@ -2702,10 +2667,7 @@ HIMCC  WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
 */
 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
 {
-    IMCCInternal *internal;
-    internal = imcc;
-
-    return internal->dwSize;
+    return GlobalSize(imcc);
 }
 
 /***********************************************************************
diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c
index 6965d5f..e6bb68a 100644
--- a/dlls/imm32/tests/imm32.c
+++ b/dlls/imm32/tests/imm32.c
@@ -734,25 +734,25 @@ static void test_ImmGetIMCCLockCount(void)
     ok(count == 0, "expect 0, returned %d\n", count);
 
     p = ImmLockIMCC(imcc);
-    todo_wine ok(GlobalHandle(p) == imcc, "expect %p, returned %p\n", imcc, GlobalHandle(p));
+    ok(GlobalHandle(p) == imcc, "expect %p, returned %p\n", imcc, GlobalHandle(p));
 
     for (i = 0; i < GMEM_LOCKCOUNT * 2; i++)
     {
         ImmLockIMCC(imcc);
         count = ImmGetIMCCLockCount(imcc);
         g_count = GlobalFlags(imcc) & GMEM_LOCKCOUNT;
-        todo_wine ok(count == g_count, "count %d, g_count %d\n", count, g_count);
+        ok(count == g_count, "count %d, g_count %d\n", count, g_count);
     }
     count = ImmGetIMCCLockCount(imcc);
-    todo_wine ok(count == GMEM_LOCKCOUNT, "expect GMEM_LOCKCOUNT, returned %d\n", count);
+    ok(count == GMEM_LOCKCOUNT, "expect GMEM_LOCKCOUNT, returned %d\n", count);
 
     for (i = 0; i < GMEM_LOCKCOUNT - 1; i++)
         GlobalUnlock(imcc);
     count = ImmGetIMCCLockCount(imcc);
-    todo_wine ok(count == 1, "expect 1, returned %d\n", count);
+    ok(count == 1, "expect 1, returned %d\n", count);
     GlobalUnlock(imcc);
     count = ImmGetIMCCLockCount(imcc);
-    todo_wine ok(count == 0, "expect 0, returned %d\n", count);
+    ok(count == 0, "expect 0, returned %d\n", count);
 
     ImmDestroyIMCC(imcc);
 }
@@ -775,18 +775,18 @@ static void test_ImmDestroyIMCC(void)
     p = ImmDestroyIMCC(imcc);
     ok(p == NULL, "Destroy an locked IMCC should success!\n");
     p = ImmLockIMCC(imcc);
-    todo_wine ok(p == NULL, "Lock a destroyed IMCC should fail!\n");
+    ok(p == NULL, "Lock a destroyed IMCC should fail!\n");
     ret = ImmUnlockIMCC(imcc);
-    todo_wine ok(ret == FALSE, "Unlock a destroyed IMCC should return FALSE!\n");
+    ok(ret == FALSE, "Unlock a destroyed IMCC should return FALSE!\n");
     count = ImmGetIMCCLockCount(imcc);
-    todo_wine ok(count == 0, "Get lock count of a destroyed IMCC should return 0!\n");
+    ok(count == 0, "Get lock count of a destroyed IMCC should return 0!\n");
     size = ImmGetIMCCSize(imcc);
-    todo_wine ok(size == 0, "Get size of a destroyed IMCC should return 0!\n");
+    ok(size == 0, "Get size of a destroyed IMCC should return 0!\n");
     SetLastError(0xdeadbeef);
     p = ImmDestroyIMCC(imcc);
-    todo_wine ok(p != NULL, "returned NULL\n");
+    ok(p != NULL, "returned NULL\n");
     ret = GetLastError();
-    todo_wine ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
+    ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
 }
 
 static void test_ImmMessages(void)
-- 
1.7.9.5
-------------- next part --------------
From 2d2e2d7387816145c7d1ef30a6ac18ea713fcc90 Mon Sep 17 00:00:00 2001
From: Qian Hong <qhong at codeweavers.com>
Date: Mon, 5 Aug 2013 23:21:44 +0800
Subject: [PATCH 4/6] imm32/tests: Added more IMC lock count tests.
To: wine-patches <wine-patches at winehq.org>
Reply-To: wine-devel <wine-devel at winehq.org>
Cc: Qian Hong<qhong at codeweavers.com>

---
 dlls/imm32/tests/imm32.c |   19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c
index e6bb68a..2d446d8 100644
--- a/dlls/imm32/tests/imm32.c
+++ b/dlls/imm32/tests/imm32.c
@@ -691,7 +691,7 @@ static void test_ImmDefaultHwnd(void)
 static void test_ImmGetIMCLockCount(void)
 {
     HIMC imc;
-    DWORD count, ret;
+    DWORD count, ret, i;
     INPUTCONTEXT *ic;
 
     imc = ImmCreateContext();
@@ -709,6 +709,23 @@ static void test_ImmGetIMCLockCount(void)
     ok(ret == TRUE, "expect TRUE, ret %d\n", ret);
     count = ImmGetIMCLockCount(imc);
     ok(count == 0, "expect 0, returned %d\n", count);
+
+    for (i = 0; i < GMEM_LOCKCOUNT * 2; i++)
+    {
+        ic = ImmLockIMC(imc);
+        ok(ic != NULL, "ImmLockIMC failed!\n");
+    }
+    count = ImmGetIMCLockCount(imc);
+    todo_wine ok(count == GMEM_LOCKCOUNT, "expect GMEM_LOCKCOUNT, returned %d\n", count);
+
+    for (i = 0; i < GMEM_LOCKCOUNT - 1; i++)
+        ImmUnlockIMC(imc);
+    count = ImmGetIMCLockCount(imc);
+    todo_wine ok(count == 1, "expect 1, returned %d\n", count);
+    ImmUnlockIMC(imc);
+    count = ImmGetIMCLockCount(imc);
+    todo_wine ok(count == 0, "expect 0, returned %d\n", count);
+
     ImmDestroyContext(imc);
 }
 
-- 
1.7.9.5
-------------- next part --------------
From f26c1a6c5609519cce532758d8d7e524395fe224 Mon Sep 17 00:00:00 2001
From: Qian Hong <qhong at codeweavers.com>
Date: Tue, 6 Aug 2013 00:34:56 +0800
Subject: [PATCH 5/6] imm32/tests: Added tests for ImmDestroyContext.
To: wine-patches <wine-patches at winehq.org>
Reply-To: wine-devel <wine-devel at winehq.org>
Cc: Qian Hong<qhong at codeweavers.com>

---
 dlls/imm32/tests/imm32.c |   29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c
index 2d446d8..9b2aede 100644
--- a/dlls/imm32/tests/imm32.c
+++ b/dlls/imm32/tests/imm32.c
@@ -774,6 +774,34 @@ static void test_ImmGetIMCCLockCount(void)
     ImmDestroyIMCC(imcc);
 }
 
+static void test_ImmDestroyContext(void)
+{
+    HIMC imc;
+    DWORD ret, count;
+    INPUTCONTEXT *ic;
+
+    imc = ImmCreateContext();
+    count = ImmGetIMCLockCount(imc);
+    ok(count == 0, "expect 0, returned %d\n", count);
+    ic = ImmLockIMC(imc);
+    ok(ic != NULL, "ImmLockIMC failed!\n");
+    count = ImmGetIMCLockCount(imc);
+    ok(count == 1, "expect 1, returned %d\n", count);
+    ret = ImmDestroyContext(imc);
+    ok(ret == TRUE, "Destroy an locked IMC should success!\n");
+    ic = ImmLockIMC(imc);
+    todo_wine ok(ic == NULL, "Lock a destroyed IMC should fail!\n");
+    ret = ImmUnlockIMC(imc);
+    todo_wine ok(ret == FALSE, "Unlock a destroyed IMC should fail!\n");
+    count = ImmGetIMCLockCount(imc);
+    todo_wine ok(count == 0, "Get lock count of a destroyed IMC should return 0!\n");
+    SetLastError(0xdeadbeef);
+    ret = ImmDestroyContext(imc);
+    todo_wine ok(ret == FALSE, "Destroy a destroyed IMC should fail!\n");
+    ret = GetLastError();
+    todo_wine ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
+}
+
 static void test_ImmDestroyIMCC(void)
 {
     HIMCC imcc;
@@ -967,6 +995,7 @@ START_TEST(imm32) {
         test_ImmDefaultHwnd();
         test_ImmGetIMCLockCount();
         test_ImmGetIMCCLockCount();
+        test_ImmDestroyContext();
         test_ImmDestroyIMCC();
         msg_spy_cleanup();
         /* Reinitialize the hooks to capture all windows */
-- 
1.7.9.5
-------------- next part --------------
From 0ffa7576938bcc6adf6674f46d6bf3174fff0745 Mon Sep 17 00:00:00 2001
From: Qian Hong <qhong at codeweavers.com>
Date: Tue, 6 Aug 2013 01:39:27 +0800
Subject: [PATCH 6/6] imm32: Improved IMC implementation.
To: wine-patches <wine-patches at winehq.org>
Reply-To: wine-devel <wine-devel at winehq.org>
Cc: Qian Hong<qhong at codeweavers.com>

---
 dlls/imm32/imm.c         |   46 ++++++++++++++++++++++++----------------------
 dlls/imm32/tests/imm32.c |   16 ++++++++--------
 2 files changed, 32 insertions(+), 30 deletions(-)

diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c
index bc7caba..d3f2167 100644
--- a/dlls/imm32/imm.c
+++ b/dlls/imm32/imm.c
@@ -69,7 +69,6 @@ typedef struct _tagImmHkl{
 
 typedef struct tagInputContextData
 {
-        DWORD           dwLock;
         INPUTCONTEXT    IMC;
 
         ImmHkl          *immKbd;
@@ -615,8 +614,11 @@ HIMC WINAPI ImmCreateContext(void)
     InputContextData *new_context;
     LPGUIDELINE gl;
     LPCANDIDATEINFO ci;
+    HGLOBAL hmem;
 
-    new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
+    hmem = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE, sizeof(InputContextData));
+    new_context = GlobalLock(hmem);
+    GlobalUnlock(hmem);
 
     /* Load the IME */
     new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
@@ -662,24 +664,24 @@ HIMC WINAPI ImmCreateContext(void)
 static BOOL IMM_DestroyContext(HIMC hIMC)
 {
     InputContextData *data = hIMC;
+    HGLOBAL hmem = GlobalHandle(data);
 
-    TRACE("Destroying %p\n",hIMC);
+    TRACE("Destroying %p\n", hIMC);
 
-    if (hIMC)
-    {
-        data->immKbd->uSelected --;
-        data->immKbd->pImeSelect(hIMC, FALSE);
-        SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)GetKeyboardLayout(0));
+    if (!hmem)
+        return FALSE;
 
-        ImmDestroyIMCC(data->IMC.hCompStr);
-        ImmDestroyIMCC(data->IMC.hCandInfo);
-        ImmDestroyIMCC(data->IMC.hGuideLine);
-        ImmDestroyIMCC(data->IMC.hPrivate);
-        ImmDestroyIMCC(data->IMC.hMsgBuf);
+    data->immKbd->uSelected --;
+    data->immKbd->pImeSelect(hIMC, FALSE);
+    SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)GetKeyboardLayout(0));
 
-        HeapFree(GetProcessHeap(),0,data);
-    }
-    return TRUE;
+    ImmDestroyIMCC(data->IMC.hCompStr);
+    ImmDestroyIMCC(data->IMC.hCandInfo);
+    ImmDestroyIMCC(data->IMC.hGuideLine);
+    ImmDestroyIMCC(data->IMC.hPrivate);
+    ImmDestroyIMCC(data->IMC.hMsgBuf);
+
+    return (GlobalFree(hmem) == NULL);
 }
 
 /***********************************************************************
@@ -2587,10 +2589,8 @@ DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
 {
     InputContextData *data = hIMC;
-
-    if (!data)
+    if (!GlobalLock(GlobalHandle(data)))
         return NULL;
-    data->dwLock++;
     return &data->IMC;
 }
 
@@ -2600,8 +2600,10 @@ LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
 {
     InputContextData *data = hIMC;
-    if (data->dwLock)
-        data->dwLock--;
+    HGLOBAL hmem = GlobalHandle(data);
+    if (!hmem)
+        return FALSE;
+    GlobalUnlock(hmem);
     return TRUE;
 }
 
@@ -2611,7 +2613,7 @@ BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
 {
     InputContextData *data = hIMC;
-    return data->dwLock;
+    return GlobalFlags(GlobalHandle(data)) & GMEM_LOCKCOUNT;
 }
 
 /***********************************************************************
diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c
index 9b2aede..f82632b 100644
--- a/dlls/imm32/tests/imm32.c
+++ b/dlls/imm32/tests/imm32.c
@@ -716,15 +716,15 @@ static void test_ImmGetIMCLockCount(void)
         ok(ic != NULL, "ImmLockIMC failed!\n");
     }
     count = ImmGetIMCLockCount(imc);
-    todo_wine ok(count == GMEM_LOCKCOUNT, "expect GMEM_LOCKCOUNT, returned %d\n", count);
+    ok(count == GMEM_LOCKCOUNT, "expect GMEM_LOCKCOUNT, returned %d\n", count);
 
     for (i = 0; i < GMEM_LOCKCOUNT - 1; i++)
         ImmUnlockIMC(imc);
     count = ImmGetIMCLockCount(imc);
-    todo_wine ok(count == 1, "expect 1, returned %d\n", count);
+    ok(count == 1, "expect 1, returned %d\n", count);
     ImmUnlockIMC(imc);
     count = ImmGetIMCLockCount(imc);
-    todo_wine ok(count == 0, "expect 0, returned %d\n", count);
+    ok(count == 0, "expect 0, returned %d\n", count);
 
     ImmDestroyContext(imc);
 }
@@ -790,16 +790,16 @@ static void test_ImmDestroyContext(void)
     ret = ImmDestroyContext(imc);
     ok(ret == TRUE, "Destroy an locked IMC should success!\n");
     ic = ImmLockIMC(imc);
-    todo_wine ok(ic == NULL, "Lock a destroyed IMC should fail!\n");
+    ok(ic == NULL, "Lock a destroyed IMC should fail!\n");
     ret = ImmUnlockIMC(imc);
-    todo_wine ok(ret == FALSE, "Unlock a destroyed IMC should fail!\n");
+    ok(ret == FALSE, "Unlock a destroyed IMC should fail!\n");
     count = ImmGetIMCLockCount(imc);
-    todo_wine ok(count == 0, "Get lock count of a destroyed IMC should return 0!\n");
+    ok(count == 0, "Get lock count of a destroyed IMC should return 0!\n");
     SetLastError(0xdeadbeef);
     ret = ImmDestroyContext(imc);
-    todo_wine ok(ret == FALSE, "Destroy a destroyed IMC should fail!\n");
+    ok(ret == FALSE, "Destroy a destroyed IMC should fail!\n");
     ret = GetLastError();
-    todo_wine ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
+    ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
 }
 
 static void test_ImmDestroyIMCC(void)
-- 
1.7.9.5


More information about the wine-devel mailing list