https://git.reactos.org/?p=reactos.git;a=commitdiff;h=66ef31494e4a9da8a1bd688a631f4a02f2fcf1da

commit 66ef31494e4a9da8a1bd688a631f4a02f2fcf1da
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Mon Oct 4 07:33:15 2021 +0900
Commit:     GitHub <[email protected]>
CommitDate: Mon Oct 4 07:33:15 2021 +0900

    [IMM32] Implement ImmActivateLayout (#3987)
    
    - Add IME_STATE and IME_SUBSTATE structures.
    - Modify INPUTCONTEXTDX structure.
    - Implement ImmActivateLayout function.
    - Improve ImmDestroyContext function by using newly-defined 
Imm32FreeImeStates.
    - Add Imm32FetchImeState, Imm32FetchImeSubState, Imm32LoadImeStateSentence, 
Imm32SaveImeStateSentence, and Imm32SelectLayout helper functions.
    - Modify NtUserSetThreadLayoutHandles prototype.
    CORE-11700
---
 dll/win32/imm32/ime.c              |   8 -
 dll/win32/imm32/imm.c              | 332 ++++++++++++++++++++++++++++++++++++-
 dll/win32/imm32/imm32.spec         |   2 +-
 dll/win32/imm32/precomp.h          |   9 +
 dll/win32/imm32/utils.c            |  74 +++++++++
 sdk/include/psdk/imm.h             |   2 +
 sdk/include/reactos/wine/ddk/imm.h |  40 ++++-
 win32ss/include/ntuser.h           |   4 +-
 win32ss/user/ntuser/ntstubs.c      |   4 +-
 9 files changed, 453 insertions(+), 22 deletions(-)

diff --git a/dll/win32/imm32/ime.c b/dll/win32/imm32/ime.c
index e831a81fcee..02b47bd1b88 100644
--- a/dll/win32/imm32/ime.c
+++ b/dll/win32/imm32/ime.c
@@ -533,14 +533,6 @@ BOOL WINAPI ImmDisableLegacyIME(void)
     return TRUE;
 }
 
-/***********************************************************************
- *             CtfImmIsTextFrameServiceDisabled(IMM32.@)
- */
-BOOL WINAPI CtfImmIsTextFrameServiceDisabled(VOID)
-{
-    return !!(GetWin32ClientInfo()->CI_flags & CI_TFSDISABLED);
-}
-
 /***********************************************************************
  *              ImmGetImeInfoEx (IMM32.@)
  */
diff --git a/dll/win32/imm32/imm.c b/dll/win32/imm32/imm.c
index f458685e0ec..c840cdf3ee7 100644
--- a/dll/win32/imm32/imm.c
+++ b/dll/win32/imm32/imm.c
@@ -168,6 +168,314 @@ Retry:
     return TRUE;
 }
 
+VOID APIENTRY Imm32SelectLayout(HKL hNewKL, HKL hOldKL, HIMC hIMC)
+{
+    PCLIENTIMC pClientImc;
+    LPINPUTCONTEXTDX pIC;
+    LPGUIDELINE pGL;
+    LPCANDIDATEINFO pCI;
+    LPCOMPOSITIONSTRING pCS;
+    LOGFONTA LogFontA;
+    LOGFONTW LogFontW;
+    BOOL fOpen, bIsNewHKLIme = TRUE, bIsOldHKLIme = TRUE, bClientWide, 
bNewDpiWide;
+    DWORD cbNewPrivate = 0, cbOldPrivate = 0, dwConversion, dwSentence, 
dwSize, dwNewSize;
+    PIMEDPI pNewImeDpi = NULL, pOldImeDpi = NULL;
+    HANDLE hPrivate;
+    PIME_STATE pNewState = NULL, pOldState = NULL;
+
+    pClientImc = ImmLockClientImc(hIMC);
+    if (!pClientImc)
+        return;
+
+    pNewImeDpi = ImmLockImeDpi(hNewKL);
+
+    if (hNewKL != hOldKL)
+        pOldImeDpi = ImmLockImeDpi(hOldKL);
+
+    if (pNewImeDpi)
+    {
+        cbNewPrivate = pNewImeDpi->ImeInfo.dwPrivateDataSize;
+        pClientImc->uCodePage = pNewImeDpi->uCodePage;
+    }
+    else
+    {
+        pClientImc->uCodePage = CP_ACP;
+    }
+
+    if (cbNewPrivate < 4)
+        cbNewPrivate = 4;
+
+    if (pOldImeDpi)
+        cbOldPrivate = pOldImeDpi->ImeInfo.dwPrivateDataSize;
+
+    if (cbOldPrivate < 4)
+        cbOldPrivate = 4;
+
+    if (pClientImc->hKL == hOldKL)
+    {
+        if (pOldImeDpi)
+        {
+            if (IS_IME_HKL(hOldKL))
+                pOldImeDpi->ImeSelect(hIMC, FALSE);
+            else if (Imm32IsCiceroMode() && !Imm32Is16BitMode() && 
pOldImeDpi->CtfImeSelectEx)
+                pOldImeDpi->CtfImeSelectEx(hIMC, FALSE, hOldKL);
+        }
+        pClientImc->hKL = NULL;
+    }
+
+    if (CtfImmIsTextFrameServiceDisabled())
+    {
+        if (Imm32IsImmMode() && !Imm32IsCiceroMode())
+        {
+            bIsNewHKLIme = IS_IME_HKL(hNewKL);
+            bIsOldHKLIme = IS_IME_HKL(hOldKL);
+        }
+    }
+
+    pIC = (LPINPUTCONTEXTDX)Imm32LockIMCEx(hIMC, FALSE);
+    if (!pIC)
+    {
+        if (pNewImeDpi)
+        {
+            if (IS_IME_HKL(hNewKL))
+                pNewImeDpi->ImeSelect(hIMC, TRUE);
+            else if (Imm32IsCiceroMode() && !Imm32Is16BitMode() && 
pNewImeDpi->CtfImeSelectEx)
+                pNewImeDpi->CtfImeSelectEx(hIMC, TRUE, hNewKL);
+
+            pClientImc->hKL = hNewKL;
+        }
+    }
+    else
+    {
+        dwConversion = pIC->fdwConversion;
+        dwSentence = pIC->fdwSentence;
+        fOpen = pIC->fOpen;
+
+        if (pNewImeDpi)
+        {
+            bClientWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
+            bNewDpiWide = ImeDpi_IsUnicode(pNewImeDpi);
+            if (bClientWide && !bNewDpiWide)
+            {
+                if (pIC->fdwInit & INIT_LOGFONT)
+                {
+                    LogFontWideToAnsi(&pIC->lfFont.W, &LogFontA);
+                    pIC->lfFont.A = LogFontA;
+                }
+                pClientImc->dwFlags &= ~CLIENTIMC_WIDE;
+            }
+            else if (!bClientWide && bNewDpiWide)
+            {
+                if (pIC->fdwInit & INIT_LOGFONT)
+                {
+                    LogFontAnsiToWide(&pIC->lfFont.A, &LogFontW);
+                    pIC->lfFont.W = LogFontW;
+                }
+                pClientImc->dwFlags |= CLIENTIMC_WIDE;
+            }
+        }
+
+        if (cbOldPrivate != cbNewPrivate)
+        {
+            hPrivate = ImmReSizeIMCC(pIC->hPrivate, cbNewPrivate);
+            if (!hPrivate)
+            {
+                ImmDestroyIMCC(pIC->hPrivate);
+                hPrivate = ImmCreateIMCC(cbNewPrivate);
+            }
+            pIC->hPrivate = hPrivate;
+        }
+
+#define MAX_IMCC_SIZE 0x1000
+        dwSize = ImmGetIMCCSize(pIC->hMsgBuf);
+        if (ImmGetIMCCLockCount(pIC->hMsgBuf) || dwSize > MAX_IMCC_SIZE)
+        {
+            ImmDestroyIMCC(pIC->hMsgBuf);
+            pIC->hMsgBuf = ImmCreateIMCC(sizeof(UINT));
+            pIC->dwNumMsgBuf = 0;
+        }
+
+        dwSize = ImmGetIMCCSize(pIC->hGuideLine);
+        dwNewSize = sizeof(GUIDELINE);
+        if (ImmGetIMCCLockCount(pIC->hGuideLine) ||
+            dwSize < dwNewSize || dwSize > MAX_IMCC_SIZE)
+        {
+            ImmDestroyIMCC(pIC->hGuideLine);
+            pIC->hGuideLine = ImmCreateIMCC(dwNewSize);
+            pGL = ImmLockIMCC(pIC->hGuideLine);
+            if (pGL)
+            {
+                pGL->dwSize = dwNewSize;
+                ImmUnlockIMCC(pIC->hGuideLine);
+            }
+        }
+
+        dwSize = ImmGetIMCCSize(pIC->hCandInfo);
+        dwNewSize = sizeof(CANDIDATEINFO);
+        if (ImmGetIMCCLockCount(pIC->hCandInfo) ||
+            dwSize < dwNewSize || dwSize > MAX_IMCC_SIZE)
+        {
+            ImmDestroyIMCC(pIC->hCandInfo);
+            pIC->hCandInfo = ImmCreateIMCC(dwNewSize);
+            pCI = ImmLockIMCC(pIC->hCandInfo);
+            if (pCI)
+            {
+                pCI->dwSize = dwNewSize;
+                ImmUnlockIMCC(pIC->hCandInfo);
+            }
+        }
+
+        dwSize = ImmGetIMCCSize(pIC->hCompStr);
+        dwNewSize = sizeof(COMPOSITIONSTRING);
+        if (ImmGetIMCCLockCount(pIC->hCompStr) ||
+            dwSize < dwNewSize || dwSize > MAX_IMCC_SIZE)
+        {
+            ImmDestroyIMCC(pIC->hCompStr);
+            pIC->hCompStr = ImmCreateIMCC(dwNewSize);
+            pCS = ImmLockIMCC(pIC->hCompStr);
+            if (pCS)
+            {
+                pCS->dwSize = dwNewSize;
+                ImmUnlockIMCC(pIC->hCompStr);
+            }
+        }
+#undef MAX_IMCC_SIZE
+
+        if (pOldImeDpi && bIsOldHKLIme)
+        {
+            pOldState = Imm32FetchImeState(pIC, hOldKL);
+            if (pOldState)
+                Imm32SaveImeStateSentence(pIC, pOldState, hOldKL);
+        }
+
+        if (pNewImeDpi && bIsNewHKLIme)
+            pNewState = Imm32FetchImeState(pIC, hNewKL);
+
+        if (pOldState != pNewState)
+        {
+            if (pOldState)
+            {
+                pOldState->fOpen = !!pIC->fOpen;
+                pOldState->dwConversion = (pIC->fdwConversion & 
~IME_CMODE_EUDC);
+                pOldState->dwSentence = pIC->fdwSentence;
+                pOldState->dwInit = pIC->fdwInit;
+            }
+
+            if (pNewState)
+            {
+                if (pIC->dwChange & INPUTCONTEXTDX_CHANGE_FORCE_OPEN)
+                {
+                    pIC->dwChange &= ~INPUTCONTEXTDX_CHANGE_FORCE_OPEN;
+                    pIC->fOpen = TRUE;
+                }
+                else
+                {
+                    pIC->fOpen = pNewState->fOpen;
+                }
+
+                pIC->fdwConversion = (pNewState->dwConversion & 
~IME_CMODE_EUDC);
+                pIC->fdwSentence = pNewState->dwSentence;
+                pIC->fdwInit = pNewState->dwInit;
+            }
+        }
+
+        if (pNewState)
+            Imm32LoadImeStateSentence(pIC, pNewState, hNewKL);
+
+        if (pNewImeDpi)
+        {
+            if (IS_IME_HKL(hNewKL))
+                pNewImeDpi->ImeSelect(hIMC, TRUE);
+            else if (Imm32IsCiceroMode() && !Imm32Is16BitMode() && 
pNewImeDpi->CtfImeSelectEx)
+                pNewImeDpi->CtfImeSelectEx(hIMC, TRUE, hNewKL);
+
+            pClientImc->hKL = hNewKL;
+        }
+
+        pIC->dwChange = 0;
+        if (pIC->fOpen != fOpen)
+            pIC->dwChange |= INPUTCONTEXTDX_CHANGE_OPEN;
+        if (pIC->fdwConversion != dwConversion)
+            pIC->dwChange |= INPUTCONTEXTDX_CHANGE_CONVERSION;
+        if (pIC->fdwSentence != dwSentence)
+            pIC->dwChange |= INPUTCONTEXTDX_CHANGE_SENTENCE;
+
+        ImmUnlockIMC(hIMC);
+    }
+
+    ImmUnlockImeDpi(pOldImeDpi);
+    ImmUnlockImeDpi(pNewImeDpi);
+    ImmUnlockClientImc(pClientImc);
+}
+
+typedef struct SELECT_LAYOUT
+{
+    HKL hNewKL;
+    HKL hOldKL;
+} SELECT_LAYOUT, *LPSELECT_LAYOUT;
+
+static BOOL CALLBACK Imm32SelectLayoutProc(HIMC hIMC, LPARAM lParam)
+{
+    LPSELECT_LAYOUT pSelect = (LPSELECT_LAYOUT)lParam;
+    Imm32SelectLayout(pSelect->hNewKL, pSelect->hOldKL, hIMC);
+    return TRUE;
+}
+
+static BOOL CALLBACK Imm32NotifyCompStrProc(HIMC hIMC, LPARAM lParam)
+{
+    ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, (DWORD)lParam, 0);
+    return TRUE;
+}
+
+/***********************************************************************
+ *             ImmActivateLayout (IMM32.@)
+ */
+BOOL WINAPI ImmActivateLayout(HKL hKL)
+{
+    PIMEDPI pImeDpi;
+    HKL hOldKL;
+    LPARAM lParam;
+    HWND hwndDefIME = NULL;
+    SELECT_LAYOUT SelectLayout;
+
+    hOldKL = GetKeyboardLayout(0);
+
+    if (hOldKL == hKL && !(GetWin32ClientInfo()->CI_flags & CI_IMMACTIVATE))
+        return TRUE;
+
+    ImmLoadIME(hKL);
+
+    if (hOldKL != hKL)
+    {
+        pImeDpi = ImmLockImeDpi(hOldKL);
+        if (pImeDpi)
+        {
+            if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_COMPLETE_ON_UNSELECT)
+                lParam = CPS_COMPLETE;
+            else
+                lParam = CPS_CANCEL;
+            ImmUnlockImeDpi(pImeDpi);
+
+            ImmEnumInputContext(0, Imm32NotifyCompStrProc, lParam);
+        }
+
+        hwndDefIME = ImmGetDefaultIMEWnd(NULL);
+        if (IsWindow(hwndDefIME))
+            SendMessageW(hwndDefIME, WM_IME_SELECT, FALSE, (LPARAM)hOldKL);
+
+        NtUserSetThreadLayoutHandles(hKL, hOldKL);
+    }
+
+    SelectLayout.hNewKL = hKL;
+    SelectLayout.hOldKL = hOldKL;
+    ImmEnumInputContext(0, Imm32SelectLayoutProc, (LPARAM)&SelectLayout);
+
+    if (IsWindow(hwndDefIME))
+        SendMessageW(hwndDefIME, WM_IME_SELECT, TRUE, (LPARAM)hKL);
+
+    return TRUE;
+}
+
 typedef struct _tagImmHkl
 {
     struct list entry;
@@ -362,15 +670,29 @@ HIMC WINAPI ImmCreateContext(void)
     return hIMC;
 }
 
-static VOID APIENTRY Imm32CleanupContextExtra(LPINPUTCONTEXT pIC)
+static VOID APIENTRY Imm32FreeImeStates(LPINPUTCONTEXTDX pIC)
 {
-    FIXME("We have to do something do here");
+    PIME_STATE pState, pStateNext;
+    PIME_SUBSTATE pSubState, pSubStateNext;
+
+    pState = pIC->pState;
+    pIC->pState = NULL;
+    for (; pState; pState = pStateNext)
+    {
+        pStateNext = pState->pNext;
+        for (pSubState = pState->pSubState; pSubState; pSubState = 
pSubStateNext)
+        {
+            pSubStateNext = pSubState->pNext;
+            Imm32HeapFree(pSubState);
+        }
+        Imm32HeapFree(pState);
+    }
 }
 
 BOOL APIENTRY Imm32CleanupContext(HIMC hIMC, HKL hKL, BOOL bKeep)
 {
     PIMEDPI pImeDpi;
-    LPINPUTCONTEXT pIC;
+    LPINPUTCONTEXTDX pIC;
     PCLIENTIMC pClientImc;
     PIMC pIMC;
 
@@ -394,7 +716,7 @@ BOOL APIENTRY Imm32CleanupContext(HIMC hIMC, HKL hKL, BOOL 
bKeep)
         return TRUE;
     }
 
-    pIC = ImmLockIMC(hIMC);
+    pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
     if (pIC == NULL)
     {
         ImmUnlockClientImc(pClientImc);
@@ -427,7 +749,7 @@ BOOL APIENTRY Imm32CleanupContext(HIMC hIMC, HKL hKL, BOOL 
bKeep)
     pIC->hCandInfo = ImmDestroyIMCC(pIC->hCandInfo);
     pIC->hCompStr = ImmDestroyIMCC(pIC->hCompStr);
 
-    Imm32CleanupContextExtra(pIC);
+    Imm32FreeImeStates(pIC);
 
     ImmUnlockIMC(hIMC);
 
diff --git a/dll/win32/imm32/imm32.spec b/dll/win32/imm32/imm32.spec
index 221c8a85e80..162d3d0c4ff 100644
--- a/dll/win32/imm32/imm32.spec
+++ b/dll/win32/imm32/imm32.spec
@@ -4,7 +4,7 @@
 @ stdcall -stub CtfImmRestoreToolbarWnd(long)
 @ stdcall -stub CtfImmHideToolbarWnd()
 @ stdcall -stub CtfImmDispatchDefImeMessage(ptr long ptr ptr)
-@ stdcall -stub ImmActivateLayout(long)
+@ stdcall ImmActivateLayout(ptr)
 @ stdcall ImmAssociateContext(ptr ptr)
 @ stdcall ImmAssociateContextEx(ptr ptr long)
 @ stdcall ImmConfigureIMEA(ptr ptr long ptr)
diff --git a/dll/win32/imm32/precomp.h b/dll/win32/imm32/precomp.h
index c5522127cc3..caaf30c1c09 100644
--- a/dll/win32/imm32/precomp.h
+++ b/dll/win32/imm32/precomp.h
@@ -81,6 +81,7 @@ LPVOID APIENTRY Imm32HeapAlloc(DWORD dwFlags, DWORD dwBytes);
 LPWSTR APIENTRY Imm32WideFromAnsi(LPCSTR pszA);
 LPSTR APIENTRY Imm32AnsiFromWide(LPCWSTR pszW);
 PIMEDPI APIENTRY ImmLockOrLoadImeDpi(HKL hKL);
+LPINPUTCONTEXT APIENTRY Imm32LockIMCEx(HIMC hIMC, BOOL fSelect);
 BOOL APIENTRY Imm32ReleaseIME(HKL hKL);
 
 static inline BOOL Imm32IsCrossThreadAccess(HIMC hIMC)
@@ -122,3 +123,11 @@ Imm32ImeMenuAnsiToWide(const IMEMENUITEMINFOA *pItemA, 
LPIMEMENUITEMINFOW pItemW
 INT APIENTRY
 Imm32ImeMenuWideToAnsi(const IMEMENUITEMINFOW *pItemW, LPIMEMENUITEMINFOA 
pItemA,
                        UINT uCodePage);
+
+PIME_STATE APIENTRY Imm32FetchImeState(LPINPUTCONTEXTDX pIC, HKL hKL);
+PIME_SUBSTATE APIENTRY Imm32FetchImeSubState(PIME_STATE pState, HKL hKL);
+
+BOOL APIENTRY
+Imm32LoadImeStateSentence(LPINPUTCONTEXTDX pIC, PIME_STATE pState, HKL hKL);
+BOOL APIENTRY
+Imm32SaveImeStateSentence(LPINPUTCONTEXTDX pIC, PIME_STATE pState, HKL hKL);
diff --git a/dll/win32/imm32/utils.c b/dll/win32/imm32/utils.c
index 40512338d22..5be74913595 100644
--- a/dll/win32/imm32/utils.c
+++ b/dll/win32/imm32/utils.c
@@ -262,6 +262,80 @@ Imm32ImeMenuWideToAnsi(const IMEMENUITEMINFOW *pItemW, 
LPIMEMENUITEMINFOA pItemA
     return ret;
 }
 
+PIME_STATE APIENTRY
+Imm32FetchImeState(LPINPUTCONTEXTDX pIC, HKL hKL)
+{
+    PIME_STATE pState;
+    WORD Lang = PRIMARYLANGID(LOWORD(hKL));
+    for (pState = pIC->pState; pState; pState = pState->pNext)
+    {
+        if (pState->wLang == Lang)
+            break;
+    }
+    if (!pState)
+    {
+        pState = Imm32HeapAlloc(HEAP_ZERO_MEMORY, sizeof(IME_STATE));
+        if (pState)
+        {
+            pState->wLang = Lang;
+            pState->pNext = pIC->pState;
+            pIC->pState = pState;
+        }
+    }
+    return pState;
+}
+
+PIME_SUBSTATE APIENTRY
+Imm32FetchImeSubState(PIME_STATE pState, HKL hKL)
+{
+    PIME_SUBSTATE pSubState;
+    for (pSubState = pState->pSubState; pSubState; pSubState = 
pSubState->pNext)
+    {
+        if (pSubState->hKL == hKL)
+            return pSubState;
+    }
+    pSubState = Imm32HeapAlloc(0, sizeof(IME_SUBSTATE));
+    if (!pSubState)
+        return NULL;
+    pSubState->dwValue = 0;
+    pSubState->hKL = hKL;
+    pSubState->pNext = pState->pSubState;
+    pState->pSubState = pSubState;
+    return pSubState;
+}
+
+BOOL APIENTRY
+Imm32LoadImeStateSentence(LPINPUTCONTEXTDX pIC, PIME_STATE pState, HKL hKL)
+{
+    PIME_SUBSTATE pSubState = Imm32FetchImeSubState(pState, hKL);
+    if (pSubState)
+    {
+        pIC->fdwSentence |= pSubState->dwValue;
+        return TRUE;
+    }
+    return FALSE;
+}
+
+BOOL APIENTRY
+Imm32SaveImeStateSentence(LPINPUTCONTEXTDX pIC, PIME_STATE pState, HKL hKL)
+{
+    PIME_SUBSTATE pSubState = Imm32FetchImeSubState(pState, hKL);
+    if (pSubState)
+    {
+        pSubState->dwValue = (pIC->fdwSentence & 0xffff0000);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/***********************************************************************
+ *             CtfImmIsTextFrameServiceDisabled(IMM32.@)
+ */
+BOOL WINAPI CtfImmIsTextFrameServiceDisabled(VOID)
+{
+    return !!(GetWin32ClientInfo()->CI_flags & CI_TFSDISABLED);
+}
+
 /***********************************************************************
  *             ImmCreateIMCC(IMM32.@)
  */
diff --git a/sdk/include/psdk/imm.h b/sdk/include/psdk/imm.h
index 14458e26203..fb7032181a7 100644
--- a/sdk/include/psdk/imm.h
+++ b/sdk/include/psdk/imm.h
@@ -635,6 +635,8 @@ BOOL WINAPI ImmSetActiveContext(HWND hwnd, HIMC hIMC, BOOL 
fFlag);
 BOOL WINAPI ImmDestroyContext(_In_ HIMC hIMC);
 BOOL WINAPI ImmDisableIME(_In_ DWORD idThread);
 BOOL WINAPI ImmEnumInputContext(_In_ DWORD, _In_ IMCENUMPROC, _In_ LPARAM);
+BOOL WINAPI ImmLoadIME(HKL hKL);
+BOOL WINAPI CtfImmIsTextFrameServiceDisabled(VOID);
 
 UINT
 WINAPI
diff --git a/sdk/include/reactos/wine/ddk/imm.h 
b/sdk/include/reactos/wine/ddk/imm.h
index 842c7cac015..33ed8e49a82 100644
--- a/sdk/include/reactos/wine/ddk/imm.h
+++ b/sdk/include/reactos/wine/ddk/imm.h
@@ -87,6 +87,8 @@ C_ASSERT(offsetof(INPUTCONTEXT, dwReserve) == 0x134);
 C_ASSERT(sizeof(INPUTCONTEXT) == 0x140);
 #endif
 
+struct IME_STATE;
+
 typedef struct INPUTCONTEXTDX /* unconfirmed */
 {
     INPUTCONTEXT;
@@ -95,8 +97,8 @@ typedef struct INPUTCONTEXTDX /* unconfirmed */
     DWORD dwUnknown1;
     DWORD dwUIFlags;
     DWORD dwUnknown2;
-    void *pUnknown3;
-    DWORD dwUnknown4;
+    struct IME_STATE *pState;
+    DWORD dwChange;
     DWORD dwUnknown5;
 } INPUTCONTEXTDX, *LPINPUTCONTEXTDX;
 
@@ -104,6 +106,8 @@ typedef struct INPUTCONTEXTDX /* unconfirmed */
 C_ASSERT(offsetof(INPUTCONTEXTDX, nVKey) == 0x140);
 C_ASSERT(offsetof(INPUTCONTEXTDX, bNeedsTrans) == 0x144);
 C_ASSERT(offsetof(INPUTCONTEXTDX, dwUIFlags) == 0x14c);
+C_ASSERT(offsetof(INPUTCONTEXTDX, pState) == 0x154);
+C_ASSERT(offsetof(INPUTCONTEXTDX, dwChange) == 0x158);
 C_ASSERT(sizeof(INPUTCONTEXTDX) == 0x160);
 #endif
 
@@ -115,6 +119,12 @@ C_ASSERT(sizeof(INPUTCONTEXTDX) == 0x160);
 #define INIT_COMPFORM                   0x00000010
 #define INIT_SOFTKBDPOS                 0x00000020
 
+// bits for INPUTCONTEXTDX.dwChange
+#define INPUTCONTEXTDX_CHANGE_OPEN          0x1
+#define INPUTCONTEXTDX_CHANGE_CONVERSION    0x2
+#define INPUTCONTEXTDX_CHANGE_SENTENCE      0x4
+#define INPUTCONTEXTDX_CHANGE_FORCE_OPEN    0x100
+
 #ifndef WM_IME_REPORT
     #define WM_IME_REPORT 0x280
 #endif
@@ -154,4 +164,30 @@ typedef struct tagUNDETERMINESTRUCT
 
 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC);
 
+typedef struct IME_SUBSTATE
+{
+    struct IME_SUBSTATE *pNext;
+    HKL hKL;
+    DWORD dwValue;
+} IME_SUBSTATE, *PIME_SUBSTATE;
+
+#ifndef _WIN64
+C_ASSERT(sizeof(IME_SUBSTATE) == 0xc);
+#endif
+
+typedef struct IME_STATE
+{
+    struct IME_STATE *pNext;
+    WORD wLang;
+    WORD fOpen;
+    DWORD dwConversion;
+    DWORD dwSentence;
+    DWORD dwInit;
+    PIME_SUBSTATE pSubState;
+} IME_STATE, *PIME_STATE;
+
+#ifndef _WIN64
+C_ASSERT(sizeof(IME_STATE) == 0x18);
+#endif
+
 #endif /* _WINE_IMM_H_ */
diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h
index a6a45af167b..eb5fb285a79 100644
--- a/win32ss/include/ntuser.h
+++ b/win32ss/include/ntuser.h
@@ -3314,9 +3314,7 @@ NtUserSetSystemTimer(
 
 DWORD
 NTAPI
-NtUserSetThreadLayoutHandles(
-    DWORD dwUnknown1,
-    DWORD dwUnknown2);
+NtUserSetThreadLayoutHandles(HKL hNewKL, HKL hOldKL);
 
 UINT_PTR
 NTAPI
diff --git a/win32ss/user/ntuser/ntstubs.c b/win32ss/user/ntuser/ntstubs.c
index 6a1b3c4673e..e3de96b1d51 100644
--- a/win32ss/user/ntuser/ntstubs.c
+++ b/win32ss/user/ntuser/ntstubs.c
@@ -894,9 +894,7 @@ Quit:
 
 DWORD
 APIENTRY
-NtUserSetThreadLayoutHandles(
-    DWORD dwUnknown1,
-    DWORD dwUnknown2)
+NtUserSetThreadLayoutHandles(HKL hNewKL, HKL hOldKL)
 {
     STUB;
     return 0;

Reply via email to