https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b3382d8d24ac7f9e098ed…
commit b3382d8d24ac7f9e098ed77ec1ce1f2f42d167a8
Author:     Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Mon Sep 27 09:32:24 2021 +0900
Commit:     GitHub <noreply(a)github.com>
CommitDate: Mon Sep 27 09:32:24 2021 +0900
    [IMM32] Rewrite ImmLockIMC (#3975)
    - Add Imm32InitContext and Imm32LockIMCEx helper functions.
    - Re-implement ImmLockIMC function.
    - Modify CLIENTIMC and INPUTCONTEXTDX structures.
    CORE-11700
---
 dll/win32/imm32/imm.c                       | 216 +++++++++++++++++++++++++---
 dll/win32/imm32/utils.c                     |   8 +-
 modules/rostests/apitests/imm32/clientimc.c |   8 +-
 sdk/include/reactos/wine/ddk/imm.h          |  10 +-
 win32ss/include/ntuser.h                    |   7 +-
 5 files changed, 212 insertions(+), 37 deletions(-)
diff --git a/dll/win32/imm32/imm.c b/dll/win32/imm32/imm.c
index 9fecb94c183..383a395f15e 100644
--- a/dll/win32/imm32/imm.c
+++ b/dll/win32/imm32/imm.c
@@ -354,7 +354,7 @@ BOOL APIENTRY Imm32CleanupContext(HIMC hIMC, HKL hKL, BOOL bKeep)
     if (!pClientImc)
         return FALSE;
-    if (pClientImc->hImc == NULL)
+    if (pClientImc->hInputContext == NULL)
     {
         pClientImc->dwFlags |= CLIENTIMC_UNKNOWN1;
         ImmUnlockClientImc(pClientImc);
@@ -390,11 +390,11 @@ BOOL APIENTRY Imm32CleanupContext(HIMC hIMC, HKL hKL, BOOL bKeep)
         pClientImc->hKL = NULL;
     }
-    ImmDestroyIMCC(pIC->hPrivate);
-    ImmDestroyIMCC(pIC->hMsgBuf);
-    ImmDestroyIMCC(pIC->hGuideLine);
-    ImmDestroyIMCC(pIC->hCandInfo);
-    ImmDestroyIMCC(pIC->hCompStr);
+    pIC->hPrivate = ImmDestroyIMCC(pIC->hPrivate);
+    pIC->hMsgBuf = ImmDestroyIMCC(pIC->hMsgBuf);
+    pIC->hGuideLine = ImmDestroyIMCC(pIC->hGuideLine);
+    pIC->hCandInfo = ImmDestroyIMCC(pIC->hCandInfo);
+    pIC->hCompStr = ImmDestroyIMCC(pIC->hCompStr);
     Imm32CleanupContextExtra(pIC);
@@ -409,6 +409,182 @@ BOOL APIENTRY Imm32CleanupContext(HIMC hIMC, HKL hKL, BOOL bKeep)
     return TRUE;
 }
+BOOL APIENTRY
+Imm32InitContext(HIMC hIMC, LPINPUTCONTEXT pIC, PCLIENTIMC pClientImc, HKL hKL, BOOL
fSelect)
+{
+    DWORD dwIndex, cbPrivate;
+    PIMEDPI pImeDpi = NULL;
+    LPCOMPOSITIONSTRING pCS;
+    LPCANDIDATEINFO pCI;
+    LPGUIDELINE pGL;
+    /* NOTE: Windows does recursive call ImmLockIMC here but we don't do so. */
+
+    /* Create IC components */
+    pIC->hCompStr = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
+    pIC->hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
+    pIC->hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
+    pIC->hMsgBuf = ImmCreateIMCC(sizeof(UINT));
+    if (!pIC->hCompStr || !pIC->hCandInfo || !pIC->hGuideLine ||
!pIC->hMsgBuf)
+        goto Fail;
+
+    /* Initialize IC components */
+    pCS = ImmLockIMCC(pIC->hCompStr);
+    if (!pCS)
+        goto Fail;
+    pCS->dwSize = sizeof(COMPOSITIONSTRING);
+    ImmUnlockIMCC(pIC->hCompStr);
+
+    pCI = ImmLockIMCC(pIC->hCandInfo);
+    if (!pCI)
+        goto Fail;
+    pCI->dwSize = sizeof(CANDIDATEINFO);
+    ImmUnlockIMCC(pIC->hCandInfo);
+
+    pGL = ImmLockIMCC(pIC->hGuideLine);
+    if (!pGL)
+        goto Fail;
+    pGL->dwSize = sizeof(GUIDELINE);
+    ImmUnlockIMCC(pIC->hGuideLine);
+
+    pIC->dwNumMsgBuf = 0;
+    pIC->fOpen = FALSE;
+    pIC->fdwConversion = pIC->fdwSentence = 0;
+
+    for (dwIndex = 0; dwIndex < MAX_CANDIDATEFORM; ++dwIndex)
+        pIC->cfCandForm[dwIndex].dwIndex = IMM_INVALID_CANDFORM;
+
+    /* Get private data size */
+    pImeDpi = ImmLockImeDpi(hKL);
+    if (!pImeDpi)
+    {
+        cbPrivate = sizeof(DWORD);
+    }
+    else
+    {
+        /* Update CLIENTIMC */
+        pClientImc->uCodePage = pImeDpi->uCodePage;
+        if (ImeDpi_IsUnicode(pImeDpi))
+            pClientImc->dwFlags |= CLIENTIMC_WIDE;
+
+        cbPrivate = pImeDpi->ImeInfo.dwPrivateDataSize;
+    }
+
+    /* Create private data */
+    pIC->hPrivate = ImmCreateIMCC(cbPrivate);
+    if (!pIC->hPrivate)
+        goto Fail;
+
+    if (pImeDpi)
+    {
+        /* Select the IME */
+        if (fSelect)
+        {
+            if (IS_IME_HKL(hKL))
+                pImeDpi->ImeSelect(hIMC, TRUE);
+            else if (Imm32IsCiceroMode() && !Imm32Is16BitMode() &&
pImeDpi->CtfImeSelectEx)
+                pImeDpi->CtfImeSelectEx(hIMC, TRUE, hKL);
+        }
+
+        /* Set HKL */
+        pClientImc->hKL = hKL;
+
+        ImmUnlockImeDpi(pImeDpi);
+    }
+
+    return TRUE;
+
+Fail:
+    if (pImeDpi)
+        ImmUnlockImeDpi(pImeDpi);
+
+    pIC->hMsgBuf = ImmDestroyIMCC(pIC->hMsgBuf);
+    pIC->hGuideLine = ImmDestroyIMCC(pIC->hGuideLine);
+    pIC->hCandInfo = ImmDestroyIMCC(pIC->hCandInfo);
+    pIC->hCompStr = ImmDestroyIMCC(pIC->hCompStr);
+    return FALSE;
+}
+
+LPINPUTCONTEXT APIENTRY Imm32LockIMCEx(HIMC hIMC, BOOL fSelect)
+{
+    HANDLE hIC;
+    LPINPUTCONTEXT pIC = NULL;
+    PCLIENTIMC pClientImc;
+    WORD Word;
+    DWORD dwThreadId;
+    HKL hKL, hNewKL;
+    PIMEDPI pImeDpi = NULL;
+    BOOL bInited;
+
+    pClientImc = ImmLockClientImc(hIMC);
+    if (!pClientImc)
+        return NULL;
+
+    RtlEnterCriticalSection(&pClientImc->cs);
+
+    if (!pClientImc->hInputContext)
+    {
+        dwThreadId = (DWORD)NtUserQueryInputContext(hIMC, 1);
+
+        if (dwThreadId == GetCurrentThreadId() && Imm32IsCiceroMode() &&
!Imm32Is16BitMode())
+        {
+            hKL = GetKeyboardLayout(0);
+            Word = LOWORD(hKL);
+            hNewKL = (HKL)(DWORD_PTR)MAKELONG(Word, Word);
+
+            pImeDpi = ImmLockOrLoadImeDpi(hNewKL);
+            if (pImeDpi)
+            {
+                FIXME("We have to do something here\n");
+            }
+        }
+
+        if (!NtUserQueryInputContext(hIMC, 2))
+        {
+            RtlLeaveCriticalSection(&pClientImc->cs);
+            goto Quit;
+        }
+
+        hIC = LocalAlloc(LHND, sizeof(INPUTCONTEXTDX));
+        if (!hIC)
+        {
+            RtlLeaveCriticalSection(&pClientImc->cs);
+            goto Quit;
+        }
+        pClientImc->hInputContext = hIC;
+
+        pIC = LocalLock(pClientImc->hInputContext);
+        if (!pIC)
+        {
+            pClientImc->hInputContext = LocalFree(pClientImc->hInputContext);
+            RtlLeaveCriticalSection(&pClientImc->cs);
+            goto Quit;
+        }
+
+        hKL = GetKeyboardLayout(dwThreadId);
+        // bInited = Imm32InitContext(hIMC, hKL, fSelect);
+        bInited = Imm32InitContext(hIMC, pIC, pClientImc, hKL, fSelect);
+        LocalUnlock(pClientImc->hInputContext);
+
+        if (!bInited)
+        {
+            pIC = NULL;
+            pClientImc->hInputContext = LocalFree(pClientImc->hInputContext);
+            RtlLeaveCriticalSection(&pClientImc->cs);
+            goto Quit;
+        }
+    }
+
+    FIXME("We have to do something here\n");
+
+    RtlLeaveCriticalSection(&pClientImc->cs);
+    pIC = LocalLock(pClientImc->hInputContext);
+    InterlockedIncrement(&pClientImc->cLockObj);
+
+Quit:
+    ImmUnlockClientImc(pClientImc);
+    return pIC;
+}
+
 /***********************************************************************
  *             ImmDestroyContext (IMM32.@)
  */
@@ -481,7 +657,7 @@ PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc)
 VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc)
 {
     LONG cLocks;
-    HIMC hImc;
+    HANDLE hInputContext;
     TRACE("(%p)\n", pClientImc);
@@ -489,9 +665,9 @@ VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc)
     if (cLocks != 0 || !(pClientImc->dwFlags & CLIENTIMC_UNKNOWN1))
         return;
-    hImc = pClientImc->hImc;
-    if (hImc)
-        LocalFree(hImc);
+    hInputContext = pClientImc->hInputContext;
+    if (hInputContext)
+        LocalFree(hInputContext);
     RtlDeleteCriticalSection(&pClientImc->cs);
     Imm32HeapFree(pClientImc);
@@ -925,16 +1101,14 @@ HKL WINAPI ImmInstallIMEW(LPCWSTR lpszIMEFileName, LPCWSTR
lpszLayoutText)
 }
 /***********************************************************************
-*              ImmLockIMC(IMM32.@)
-*/
+ *             ImmLockIMC(IMM32.@)
+ *
+ * NOTE: This is not ImmLockIMCC. Don't confuse.
+ */
 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
 {
-    InputContextData *data = get_imc_data(hIMC);
-
-    if (!data)
-        return NULL;
-    data->dwLock++;
-    return &data->IMC;
+    TRACE("(%p)\n", hIMC);
+    return Imm32LockIMCEx(hIMC, TRUE);
 }
 /***********************************************************************
@@ -943,15 +1117,13 @@ LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
 {
     PCLIENTIMC pClientImc;
-    HIMC hClientImc;
     pClientImc = ImmLockClientImc(hIMC);
     if (pClientImc == NULL)
         return FALSE;
-    hClientImc = pClientImc->hImc;
-    if (hClientImc)
-        LocalUnlock(hClientImc);
+    if (pClientImc->hInputContext)
+        LocalUnlock(pClientImc->hInputContext);
     InterlockedDecrement(&pClientImc->cLockObj);
     ImmUnlockClientImc(pClientImc);
diff --git a/dll/win32/imm32/utils.c b/dll/win32/imm32/utils.c
index 17a7efb5179..64bd3d158be 100644
--- a/dll/win32/imm32/utils.c
+++ b/dll/win32/imm32/utils.c
@@ -276,7 +276,7 @@ DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
 {
     DWORD ret;
-    HIMC hClientImc;
+    HANDLE hInputContext;
     PCLIENTIMC pClientImc;
     pClientImc = ImmLockClientImc(hIMC);
@@ -284,9 +284,9 @@ DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
         return 0;
     ret = 0;
-    hClientImc = pClientImc->hImc;
-    if (hClientImc)
-        ret = (LocalFlags(hClientImc) & LMEM_LOCKCOUNT);
+    hInputContext = pClientImc->hInputContext;
+    if (hInputContext)
+        ret = (LocalFlags(hInputContext) & LMEM_LOCKCOUNT);
     ImmUnlockClientImc(pClientImc);
     return ret;
diff --git a/modules/rostests/apitests/imm32/clientimc.c
b/modules/rostests/apitests/imm32/clientimc.c
index 0f43024efd0..f0080c8112e 100644
--- a/modules/rostests/apitests/imm32/clientimc.c
+++ b/modules/rostests/apitests/imm32/clientimc.c
@@ -24,15 +24,15 @@ START_TEST(clientimc)
     DWORD dwCode;
     CLIENTIMC *pClientImc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(CLIENTIMC));
-    pClientImc->hImc = (HIMC)ImmCreateIMCC(4);
+    pClientImc->hInputContext = (HANDLE)ImmCreateIMCC(4);
     pClientImc->cLockObj = 2;
     pClientImc->dwFlags = 0x40;
     RtlInitializeCriticalSection(&pClientImc->cs);
-    ok_long(ImmGetIMCCSize((HIMCC)pClientImc->hImc), 4);
+    ok_long(ImmGetIMCCSize((HIMCC)pClientImc->hInputContext), 4);
     ImmUnlockClientImc(pClientImc);
     ok_long(pClientImc->cLockObj, 1);
-    ok_long(ImmGetIMCCSize((HIMCC)pClientImc->hImc), 4);
+    ok_long(ImmGetIMCCSize((HIMCC)pClientImc->hInputContext), 4);
     dwCode = 0;
     _SEH2_TRY
@@ -47,7 +47,7 @@ START_TEST(clientimc)
     ok_long(dwCode, STATUS_ACCESS_VIOLATION);
     ok_long(pClientImc->cLockObj, 0);
-    ok_long(ImmGetIMCCSize((HIMCC)pClientImc->hImc), 0);
+    ok_long(ImmGetIMCCSize((HIMCC)pClientImc->hInputContext), 0);
     HeapFree(GetProcessHeap(), 0, pClientImc);
 }
diff --git a/sdk/include/reactos/wine/ddk/imm.h b/sdk/include/reactos/wine/ddk/imm.h
index f5b45fc6d1a..842c7cac015 100644
--- a/sdk/include/reactos/wine/ddk/imm.h
+++ b/sdk/include/reactos/wine/ddk/imm.h
@@ -92,17 +92,19 @@ typedef struct INPUTCONTEXTDX /* unconfirmed */
     INPUTCONTEXT;
     UINT nVKey;
     BOOL bNeedsTrans;
-    DWORD dwUnknownCat;
+    DWORD dwUnknown1;
     DWORD dwUIFlags;
-    DWORD dwUnknownDog;
-    void *pUnknownFox;
-    /* ... */
+    DWORD dwUnknown2;
+    void *pUnknown3;
+    DWORD dwUnknown4;
+    DWORD dwUnknown5;
 } INPUTCONTEXTDX, *LPINPUTCONTEXTDX;
 #ifndef _WIN64
 C_ASSERT(offsetof(INPUTCONTEXTDX, nVKey) == 0x140);
 C_ASSERT(offsetof(INPUTCONTEXTDX, bNeedsTrans) == 0x144);
 C_ASSERT(offsetof(INPUTCONTEXTDX, dwUIFlags) == 0x14c);
+C_ASSERT(sizeof(INPUTCONTEXTDX) == 0x160);
 #endif
 // bits of fdwInit of INPUTCONTEXT
diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h
index 6d463ddb69a..482ea232926 100644
--- a/win32ss/include/ntuser.h
+++ b/win32ss/include/ntuser.h
@@ -1290,21 +1290,22 @@ C_ASSERT(sizeof(IMEDPI) == 0xa8);
 /* unconfirmed */
 typedef struct tagCLIENTIMC
 {
-    HIMC hImc;
+    HANDLE hInputContext;   /* LocalAlloc'ed LHND */
     LONG cLockObj;
     DWORD dwFlags;
     DWORD unknown;
     RTL_CRITICAL_SECTION cs;
-    DWORD unknown2;
+    UINT uCodePage;
     HKL hKL;
     BOOL bUnknown4;
 } CLIENTIMC, *PCLIENTIMC;
 #ifndef _WIN64
-C_ASSERT(offsetof(CLIENTIMC, hImc) == 0x0);
+C_ASSERT(offsetof(CLIENTIMC, hInputContext) == 0x0);
 C_ASSERT(offsetof(CLIENTIMC, cLockObj) == 0x4);
 C_ASSERT(offsetof(CLIENTIMC, dwFlags) == 0x8);
 C_ASSERT(offsetof(CLIENTIMC, cs) == 0x10);
+C_ASSERT(offsetof(CLIENTIMC, uCodePage) == 0x28);
 C_ASSERT(offsetof(CLIENTIMC, hKL) == 0x2c);
 C_ASSERT(sizeof(CLIENTIMC) == 0x34);
 #endif