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

commit b4557a60a98b4d188c058388395177b36994572e
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Fri Sep 10 23:39:15 2021 +0900
Commit:     GitHub <[email protected]>
CommitDate: Fri Sep 10 23:39:15 2021 +0900

    [IMM32] Restructure! (Retry) (#3952)
    
    The imm.c file became big and bloated, so we split the source file. 
CORE-11700
    - Split the IMM32 code and do formatting.
---
 dll/win32/imm32/CMakeLists.txt |   15 +-
 dll/win32/imm32/candidate.c    |  406 ++++
 dll/win32/imm32/guideline.c    |  198 ++
 dll/win32/imm32/ime.c          | 1201 +++++++++++
 dll/win32/imm32/imm.c          | 4507 +++++-----------------------------------
 dll/win32/imm32/keymsg.c       |  688 ++++++
 dll/win32/imm32/nt3.c          |  205 ++
 dll/win32/imm32/precomp.h      |  103 +
 dll/win32/imm32/regword.c      |  520 +++++
 dll/win32/imm32/utils.c        |  276 +++
 10 files changed, 4103 insertions(+), 4016 deletions(-)

diff --git a/dll/win32/imm32/CMakeLists.txt b/dll/win32/imm32/CMakeLists.txt
index 9ccdcd26f20..bb50a71ab63 100644
--- a/dll/win32/imm32/CMakeLists.txt
+++ b/dll/win32/imm32/CMakeLists.txt
@@ -1,14 +1,21 @@
 
-include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine)
-add_definitions(-D__WINESRC__)
+include_directories(
+    ${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine
+    ${REACTOS_SOURCE_DIR}/win32ss/include)
 
-remove_definitions(-D_WIN32_WINNT=0x502)
-add_definitions(-D_WIN32_WINNT=0x600)
+add_definitions(-D__WINESRC__)
 
 spec2def(imm32.dll imm32.spec ADD_IMPORTLIB)
 
 list(APPEND SOURCE
+    candidate.c
+    guideline.c
+    ime.c
     imm.c
+    keymsg.c
+    nt3.c
+    regword.c
+    utils.c
     ${CMAKE_CURRENT_BINARY_DIR}/imm32_stubs.c
     ${CMAKE_CURRENT_BINARY_DIR}/imm32.def)
 
diff --git a/dll/win32/imm32/candidate.c b/dll/win32/imm32/candidate.c
new file mode 100644
index 00000000000..43f4e8d03c1
--- /dev/null
+++ b/dll/win32/imm32/candidate.c
@@ -0,0 +1,406 @@
+/*
+ * PROJECT:     ReactOS IMM32
+ * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
+ * PURPOSE:     Implementing IMM32 candidate lists
+ * COPYRIGHT:   Copyright 2020-2021 Katayama Hirofumi MZ 
<[email protected]>
+ */
+
+#include "precomp.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(imm);
+
+DWORD APIENTRY
+CandidateListWideToAnsi(const CANDIDATELIST *pWideCL, LPCANDIDATELIST pAnsiCL, 
DWORD dwBufLen,
+                        UINT uCodePage)
+{
+    BOOL bUsedDefault;
+    DWORD dwSize, dwIndex, cbGot, cbLeft;
+    const BYTE *pbWide;
+    LPBYTE pbAnsi;
+    LPDWORD pibOffsets;
+
+    /* calculate total ansi size */
+    if (pWideCL->dwCount > 0)
+    {
+        dwSize = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * 
sizeof(DWORD));
+        for (dwIndex = 0; dwIndex < pWideCL->dwCount; ++dwIndex)
+        {
+            pbWide = (const BYTE *)pWideCL + pWideCL->dwOffset[dwIndex];
+            cbGot = WideCharToMultiByte(uCodePage, 0, (LPCWSTR)pbWide, -1, 
NULL, 0,
+                                        NULL, &bUsedDefault);
+            dwSize += cbGot;
+        }
+    }
+    else
+    {
+        dwSize = sizeof(CANDIDATELIST);
+    }
+
+    dwSize = ROUNDUP4(dwSize);
+    if (dwBufLen == 0)
+        return dwSize;
+    if (dwBufLen < dwSize)
+        return 0;
+
+    /* store to ansi */
+    pAnsiCL->dwSize = dwBufLen;
+    pAnsiCL->dwStyle = pWideCL->dwStyle;
+    pAnsiCL->dwCount = pWideCL->dwCount;
+    pAnsiCL->dwSelection = pWideCL->dwSelection;
+    pAnsiCL->dwPageStart = pWideCL->dwPageStart;
+    pAnsiCL->dwPageSize = pWideCL->dwPageSize;
+
+    pibOffsets = pAnsiCL->dwOffset;
+    if (pWideCL->dwCount > 0)
+    {
+        pibOffsets[0] = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * 
sizeof(DWORD));
+        cbLeft = dwBufLen - pibOffsets[0];
+
+        for (dwIndex = 0; dwIndex < pWideCL->dwCount; ++dwIndex)
+        {
+            pbWide = (const BYTE *)pWideCL + pWideCL->dwOffset[dwIndex];
+            pbAnsi = (LPBYTE)pAnsiCL + pibOffsets[dwIndex];
+
+            /* convert to ansi */
+            cbGot = WideCharToMultiByte(uCodePage, 0, (LPCWSTR)pbWide, -1,
+                                        (LPSTR)pbAnsi, cbLeft, NULL, 
&bUsedDefault);
+            cbLeft -= cbGot;
+
+            if (dwIndex < pWideCL->dwCount - 1)
+                pibOffsets[dwIndex + 1] = pibOffsets[dwIndex] + cbGot;
+        }
+    }
+    else
+    {
+        pibOffsets[0] = sizeof(CANDIDATELIST);
+    }
+
+    return dwBufLen;
+}
+
+DWORD APIENTRY
+CandidateListAnsiToWide(const CANDIDATELIST *pAnsiCL, LPCANDIDATELIST pWideCL, 
DWORD dwBufLen,
+                        UINT uCodePage)
+{
+    DWORD dwSize, dwIndex, cchGot, cbGot, cbLeft;
+    const BYTE *pbAnsi;
+    LPBYTE pbWide;
+    LPDWORD pibOffsets;
+
+    /* calculate total wide size */
+    if (pAnsiCL->dwCount > 0)
+    {
+        dwSize = sizeof(CANDIDATELIST) + ((pAnsiCL->dwCount - 1) * 
sizeof(DWORD));
+        for (dwIndex = 0; dwIndex < pAnsiCL->dwCount; ++dwIndex)
+        {
+            pbAnsi = (const BYTE *)pAnsiCL + pAnsiCL->dwOffset[dwIndex];
+            cchGot = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, 
(LPCSTR)pbAnsi, -1, NULL, 0);
+            dwSize += cchGot * sizeof(WCHAR);
+        }
+    }
+    else
+    {
+        dwSize = sizeof(CANDIDATELIST);
+    }
+
+    dwSize = ROUNDUP4(dwSize);
+    if (dwBufLen == 0)
+        return dwSize;
+    if (dwBufLen < dwSize)
+        return 0;
+
+    /* store to wide */
+    pWideCL->dwSize = dwBufLen;
+    pWideCL->dwStyle = pAnsiCL->dwStyle;
+    pWideCL->dwCount = pAnsiCL->dwCount;
+    pWideCL->dwSelection = pAnsiCL->dwSelection;
+    pWideCL->dwPageStart = pAnsiCL->dwPageStart;
+    pWideCL->dwPageSize = pAnsiCL->dwPageSize;
+
+    pibOffsets = pWideCL->dwOffset;
+    if (pAnsiCL->dwCount > 0)
+    {
+        pibOffsets[0] = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * 
sizeof(DWORD));
+        cbLeft = dwBufLen - pibOffsets[0];
+
+        for (dwIndex = 0; dwIndex < pAnsiCL->dwCount; ++dwIndex)
+        {
+            pbAnsi = (const BYTE *)pAnsiCL + pAnsiCL->dwOffset[dwIndex];
+            pbWide = (LPBYTE)pWideCL + pibOffsets[dwIndex];
+
+            /* convert to wide */
+            cchGot = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, 
(LPCSTR)pbAnsi, -1,
+                                         (LPWSTR)pbWide, cbLeft / 
sizeof(WCHAR));
+            cbGot = cchGot * sizeof(WCHAR);
+            cbLeft -= cbGot;
+
+            if (dwIndex + 1 < pAnsiCL->dwCount)
+                pibOffsets[dwIndex + 1] = pibOffsets[dwIndex] + cbGot;
+        }
+    }
+    else
+    {
+        pibOffsets[0] = sizeof(CANDIDATELIST);
+    }
+
+    return dwBufLen;
+}
+
+static DWORD APIENTRY
+ImmGetCandidateListAW(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, 
DWORD dwBufLen,
+                      BOOL bAnsi)
+{
+    DWORD ret = 0;
+    LPINPUTCONTEXT pIC;
+    PCLIENTIMC pClientImc;
+    LPCANDIDATEINFO pCI;
+    LPCANDIDATELIST pCL;
+    DWORD dwSize;
+
+    pClientImc = ImmLockClientImc(hIMC);
+    if (!pClientImc)
+        return 0;
+
+    pIC = ImmLockIMC(hIMC);
+    if (pIC == NULL)
+    {
+        ImmUnlockClientImc(pClientImc);
+        return 0;
+    }
+
+    pCI = ImmLockIMCC(pIC->hCandInfo);
+    if (pCI == NULL)
+    {
+        ImmUnlockIMC(hIMC);
+        ImmUnlockClientImc(pClientImc);
+        return 0;
+    }
+
+    if (pCI->dwSize < sizeof(CANDIDATEINFO) || pCI->dwCount <= dwIndex)
+        goto Quit;
+
+    /* get required size */
+    pCL = (LPCANDIDATELIST)((LPBYTE)pCI + pCI->dwOffset[dwIndex]);
+    if (bAnsi)
+    {
+        if (pClientImc->dwFlags & CLIENTIMC_WIDE)
+            dwSize = CandidateListAnsiToWide(pCL, NULL, 0, CP_ACP);
+        else
+            dwSize = pCL->dwSize;
+    }
+    else
+    {
+        if (pClientImc->dwFlags & CLIENTIMC_WIDE)
+            dwSize = pCL->dwSize;
+        else
+            dwSize = CandidateListWideToAnsi(pCL, NULL, 0, CP_ACP);
+    }
+
+    if (dwBufLen != 0 && dwSize != 0)
+    {
+        if (lpCandList == NULL || dwBufLen < dwSize)
+            goto Quit;
+
+        /* store */
+        if (bAnsi)
+        {
+            if (pClientImc->dwFlags & CLIENTIMC_WIDE)
+                CandidateListAnsiToWide(pCL, lpCandList, dwSize, CP_ACP);
+            else
+                RtlCopyMemory(lpCandList, pCL, dwSize);
+        }
+        else
+        {
+            if (pClientImc->dwFlags & CLIENTIMC_WIDE)
+                RtlCopyMemory(lpCandList, pCL, dwSize);
+            else
+                CandidateListWideToAnsi(pCL, lpCandList, dwSize, CP_ACP);
+        }
+    }
+
+    ret = dwSize;
+
+Quit:
+    ImmUnlockIMCC(pIC->hCandInfo);
+    ImmUnlockIMC(hIMC);
+    ImmUnlockClientImc(pClientImc);
+    return ret;
+}
+
+DWORD APIENTRY
+ImmGetCandidateListCountAW(HIMC hIMC, LPDWORD lpdwListCount, BOOL bAnsi)
+{
+    DWORD ret = 0, cbGot, dwIndex;
+    PCLIENTIMC pClientImc;
+    LPINPUTCONTEXT pIC;
+    const CANDIDATEINFO *pCI;
+    const BYTE *pb;
+    const CANDIDATELIST *pCL;
+    const DWORD *pdwOffsets;
+
+    if (lpdwListCount == NULL)
+        return 0;
+
+    *lpdwListCount = 0;
+
+    pClientImc = ImmLockClientImc(hIMC);
+    if (pClientImc == NULL)
+        return 0;
+
+    pIC = ImmLockIMC(hIMC);
+    if (pIC == NULL)
+    {
+        ImmUnlockClientImc(pClientImc);
+        return 0;
+    }
+
+    pCI = ImmLockIMCC(pIC->hCandInfo);
+    if (pCI == NULL)
+    {
+        ImmUnlockIMC(hIMC);
+        ImmUnlockClientImc(pClientImc);
+        return 0;
+    }
+
+    if (pCI->dwSize < sizeof(CANDIDATEINFO))
+        goto Quit;
+
+    *lpdwListCount = pCI->dwCount; /* the number of candidate lists */
+
+    /* calculate total size of candidate lists */
+    if (bAnsi)
+    {
+        if (pClientImc->dwFlags & CLIENTIMC_WIDE)
+        {
+            ret = ROUNDUP4(pCI->dwPrivateSize);
+            pdwOffsets = pCI->dwOffset;
+            for (dwIndex = 0; dwIndex < pCI->dwCount; ++dwIndex)
+            {
+                pb = (const BYTE *)pCI + pdwOffsets[dwIndex];
+                pCL = (const CANDIDATELIST *)pb;
+                cbGot = CandidateListWideToAnsi(pCL, NULL, 0, CP_ACP);
+                ret += cbGot;
+            }
+        }
+        else
+        {
+            ret = pCI->dwSize;
+        }
+    }
+    else
+    {
+        if (pClientImc->dwFlags & CLIENTIMC_WIDE)
+        {
+            ret = pCI->dwSize;
+        }
+        else
+        {
+            ret = ROUNDUP4(pCI->dwPrivateSize);
+            pdwOffsets = pCI->dwOffset;
+            for (dwIndex = 0; dwIndex < pCI->dwCount; ++dwIndex)
+            {
+                pb = (const BYTE *)pCI + pdwOffsets[dwIndex];
+                pCL = (const CANDIDATELIST *)pb;
+                cbGot = CandidateListAnsiToWide(pCL, NULL, 0, CP_ACP);
+                ret += cbGot;
+            }
+        }
+    }
+
+Quit:
+    ImmUnlockIMCC(pIC->hCandInfo);
+    ImmUnlockIMC(hIMC);
+    ImmUnlockClientImc(pClientImc);
+    return ret;
+}
+
+/***********************************************************************
+ *             ImmGetCandidateListA (IMM32.@)
+ */
+DWORD WINAPI
+ImmGetCandidateListA(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, 
DWORD dwBufLen)
+{
+    return ImmGetCandidateListAW(hIMC, dwIndex, lpCandList, dwBufLen, TRUE);
+}
+
+/***********************************************************************
+ *             ImmGetCandidateListCountA (IMM32.@)
+ */
+DWORD WINAPI ImmGetCandidateListCountA(HIMC hIMC, LPDWORD lpdwListCount)
+{
+    return ImmGetCandidateListCountAW(hIMC, lpdwListCount, TRUE);
+}
+
+/***********************************************************************
+ *             ImmGetCandidateListCountW (IMM32.@)
+ */
+DWORD WINAPI ImmGetCandidateListCountW(HIMC hIMC, LPDWORD lpdwListCount)
+{
+    return ImmGetCandidateListCountAW(hIMC, lpdwListCount, FALSE);
+}
+
+/***********************************************************************
+ *             ImmGetCandidateListW (IMM32.@)
+ */
+DWORD WINAPI
+ImmGetCandidateListW(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, 
DWORD dwBufLen)
+{
+    return ImmGetCandidateListAW(hIMC, dwIndex, lpCandList, dwBufLen, FALSE);
+}
+
+/***********************************************************************
+ *             ImmGetCandidateWindow (IMM32.@)
+ */
+BOOL WINAPI
+ImmGetCandidateWindow(HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
+{
+    BOOL ret = FALSE;
+    LPINPUTCONTEXT pIC;
+    LPCANDIDATEFORM pCF;
+
+    TRACE("(%p, %lu, %p)\n", hIMC, dwIndex, lpCandidate);
+
+    pIC = ImmLockIMC(hIMC);
+    if (pIC  == NULL)
+        return FALSE;
+
+    pCF = &pIC->cfCandForm[dwIndex];
+    if (pCF->dwIndex != IMM_INVALID_CANDFORM)
+    {
+        *lpCandidate = *pCF;
+        ret = TRUE;
+    }
+
+    ImmUnlockIMC(hIMC);
+    return ret;
+}
+
+/***********************************************************************
+ *             ImmSetCandidateWindow (IMM32.@)
+ */
+BOOL WINAPI ImmSetCandidateWindow(HIMC hIMC, LPCANDIDATEFORM lpCandidate)
+{
+    HWND hWnd;
+    LPINPUTCONTEXT pIC;
+
+    TRACE("(%p, %p)\n", hIMC, lpCandidate);
+
+    if (lpCandidate->dwIndex >= MAX_CANDIDATEFORM)
+        return FALSE;
+
+    if (Imm32IsCrossThreadAccess(hIMC))
+        return FALSE;
+
+    pIC = ImmLockIMC(hIMC);
+    if (pIC == NULL)
+        return FALSE;
+
+    hWnd = pIC->hWnd;
+    pIC->cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
+
+    ImmUnlockIMC(hIMC);
+
+    Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS,
+                      IMN_SETCANDIDATEPOS, (1 << (BYTE)lpCandidate->dwIndex));
+    return TRUE;
+}
diff --git a/dll/win32/imm32/guideline.c b/dll/win32/imm32/guideline.c
new file mode 100644
index 00000000000..3a9a3c6bae1
--- /dev/null
+++ b/dll/win32/imm32/guideline.c
@@ -0,0 +1,198 @@
+/*
+ * PROJECT:     ReactOS IMM32
+ * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
+ * PURPOSE:     Implementing IMM32 guidelines
+ * COPYRIGHT:   Copyright 2020-2021 Katayama Hirofumi MZ 
<[email protected]>
+ */
+
+#include "precomp.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(imm);
+
+DWORD APIENTRY
+ImmGetGuideLineAW(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen, BOOL 
bAnsi)
+{
+    PCLIENTIMC pClientImc;
+    LPINPUTCONTEXT pIC;
+    LPGUIDELINE pGuideLine;
+    DWORD cb, ret = 0;
+    LPVOID pvStr, pvPrivate;
+    BOOL bUsedDefault;
+
+    pClientImc = ImmLockClientImc(hIMC);
+    if (!pClientImc)
+        return 0;
+
+    pIC = ImmLockIMC(hIMC);
+    if (!pIC)
+    {
+        ImmUnlockClientImc(pClientImc);
+        return 0;
+    }
+
+    pGuideLine = ImmLockIMCC(pIC->hGuideLine);
+    if (!pGuideLine)
+    {
+        ImmUnlockIMC(hIMC);
+        ImmUnlockClientImc(pClientImc);
+        return 0;
+    }
+
+    if (dwIndex == GGL_LEVEL)
+    {
+        ret = pGuideLine->dwLevel;
+        goto Quit;
+    }
+
+    if (dwIndex == GGL_INDEX)
+    {
+        ret = pGuideLine->dwIndex;
+        goto Quit;
+    }
+
+    if (dwIndex == GGL_STRING)
+    {
+        pvStr = (LPBYTE)pGuideLine + pGuideLine->dwStrOffset;
+
+        /* get size */
+        if (bAnsi)
+        {
+            if (pClientImc->dwFlags & CLIENTIMC_WIDE)
+            {
+                cb = WideCharToMultiByte(CP_ACP, 0, pvStr, 
pGuideLine->dwStrLen,
+                                         NULL, 0, NULL, &bUsedDefault);
+            }
+            else
+            {
+                cb = pGuideLine->dwStrLen * sizeof(CHAR);
+            }
+        }
+        else
+        {
+            if (pClientImc->dwFlags & CLIENTIMC_WIDE)
+            {
+                cb = pGuideLine->dwStrLen * sizeof(WCHAR);
+            }
+            else
+            {
+                cb = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pvStr, 
pGuideLine->dwStrLen,
+                                         NULL, 0) * sizeof(WCHAR);
+            }
+        }
+
+        if (dwBufLen == 0 || cb == 0 || lpBuf == NULL || dwBufLen < cb)
+        {
+            ret = cb;
+            goto Quit;
+        }
+
+        /* store to buffer */
+        if (bAnsi)
+        {
+            if (pClientImc->dwFlags & CLIENTIMC_WIDE)
+            {
+                ret = WideCharToMultiByte(CP_ACP, 0, pvStr, 
pGuideLine->dwStrLen,
+                                          lpBuf, dwBufLen, NULL, 
&bUsedDefault);
+                goto Quit;
+            }
+        }
+        else
+        {
+            if (!(pClientImc->dwFlags & CLIENTIMC_WIDE))
+            {
+                ret = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pvStr, 
pGuideLine->dwStrLen,
+                                          lpBuf, dwBufLen) * sizeof(WCHAR);
+                goto Quit;
+            }
+        }
+
+        RtlCopyMemory(lpBuf, pvStr, cb);
+        ret = cb;
+        goto Quit;
+    }
+
+    if (dwIndex == GGL_PRIVATE)
+    {
+        pvPrivate = (LPBYTE)pGuideLine + pGuideLine->dwPrivateOffset;
+
+        /* get size */
+        if (bAnsi)
+        {
+            if ((pClientImc->dwFlags & CLIENTIMC_WIDE) &&
+                pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
+            {
+                cb = CandidateListWideToAnsi(pvPrivate, NULL, 0, CP_ACP);
+            }
+            else
+            {
+                cb = pGuideLine->dwPrivateSize;
+            }
+        }
+        else
+        {
+            if (!(pClientImc->dwFlags & CLIENTIMC_WIDE) &&
+                pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
+            {
+                cb = CandidateListAnsiToWide(pvPrivate, NULL, 0, CP_ACP);
+            }
+            else
+            {
+                cb = pGuideLine->dwPrivateSize;
+            }
+        }
+
+        if (dwBufLen == 0 || cb == 0 || lpBuf == NULL || dwBufLen < cb)
+        {
+            ret = cb;
+            goto Quit;
+        }
+
+        /* store to buffer */
+        if (bAnsi)
+        {
+            if ((pClientImc->dwFlags & CLIENTIMC_WIDE) &&
+                pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
+            {
+                ret = CandidateListWideToAnsi(pvPrivate, lpBuf, cb, CP_ACP);
+                goto Quit;
+            }
+        }
+        else
+        {
+            if (!(pClientImc->dwFlags & CLIENTIMC_WIDE) &&
+                pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
+            {
+                ret = CandidateListAnsiToWide(pvPrivate, lpBuf, cb, CP_ACP);
+                goto Quit;
+            }
+        }
+
+        RtlCopyMemory(lpBuf, pvPrivate, cb);
+        ret = cb;
+        goto Quit;
+    }
+
+Quit:
+    ImmUnlockIMCC(pIC->hGuideLine);
+    ImmUnlockIMC(hIMC);
+    ImmUnlockClientImc(pClientImc);
+    return ret;
+}
+
+/***********************************************************************
+ *             ImmGetGuideLineA (IMM32.@)
+ */
+DWORD WINAPI ImmGetGuideLineA(HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD 
dwBufLen)
+{
+    TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen);
+    return ImmGetGuideLineAW(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
+}
+
+/***********************************************************************
+ *             ImmGetGuideLineW (IMM32.@)
+ */
+DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD 
dwBufLen)
+{
+    TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen);
+    return ImmGetGuideLineAW(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
+}
diff --git a/dll/win32/imm32/ime.c b/dll/win32/imm32/ime.c
new file mode 100644
index 00000000000..ba68a9ab3d1
--- /dev/null
+++ b/dll/win32/imm32/ime.c
@@ -0,0 +1,1201 @@
+/*
+ * PROJECT:     ReactOS IMM32
+ * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
+ * PURPOSE:     Implementing IME manipulation of IMM32
+ * COPYRIGHT:   Copyright 1998 Patrik Stridvall
+ *              Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
+ *              Copyright 2017 James Tabor <[email protected]>
+ *              Copyright 2018 Amine Khaldi <[email protected]>
+ *              Copyright 2020 Oleg Dubinskiy <[email protected]>
+ *              Copyright 2020-2021 Katayama Hirofumi MZ 
<[email protected]>
+ */
+
+#include "precomp.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(imm);
+
+RTL_CRITICAL_SECTION g_csImeDpi;
+PIMEDPI g_pImeDpiList = NULL;
+
+PIMEDPI APIENTRY Imm32FindImeDpi(HKL hKL)
+{
+    PIMEDPI pImeDpi;
+
+    RtlEnterCriticalSection(&g_csImeDpi);
+    for (pImeDpi = g_pImeDpiList; pImeDpi != NULL; pImeDpi = pImeDpi->pNext)
+    {
+        if (pImeDpi->hKL == hKL)
+            break;
+    }
+    RtlLeaveCriticalSection(&g_csImeDpi);
+
+    return pImeDpi;
+}
+
+VOID APIENTRY Imm32FreeImeDpi(PIMEDPI pImeDpi, BOOL bDestroy)
+{
+    if (pImeDpi->hInst == NULL)
+        return;
+    if (bDestroy)
+        pImeDpi->ImeDestroy(0);
+    FreeLibrary(pImeDpi->hInst);
+    pImeDpi->hInst = NULL;
+}
+
+BOOL APIENTRY Imm32InquireIme(PIMEDPI pImeDpi)
+{
+    WCHAR szUIClass[64];
+    WNDCLASSW wcW;
+    DWORD dwSysInfoFlags = 0; // TODO: ???
+    LPIMEINFO pImeInfo = &pImeDpi->ImeInfo;
+
+    // TODO: NtUserGetThreadState(16);
+
+    if (!IS_IME_HKL(pImeDpi->hKL))
+    {
+        if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED) &&
+            pImeDpi->CtfImeInquireExW)
+        {
+            // TODO:
+            return FALSE;
+        }
+    }
+
+    if (!pImeDpi->ImeInquire(pImeInfo, szUIClass, dwSysInfoFlags))
+        return FALSE;
+
+    szUIClass[_countof(szUIClass) - 1] = 0;
+
+    if (pImeInfo->dwPrivateDataSize == 0)
+        pImeInfo->dwPrivateDataSize = 4;
+
+#define VALID_IME_PROP (IME_PROP_AT_CARET              | \
+                        IME_PROP_SPECIAL_UI            | \
+                        IME_PROP_CANDLIST_START_FROM_1 | \
+                        IME_PROP_UNICODE               | \
+                        IME_PROP_COMPLETE_ON_UNSELECT  | \
+                        IME_PROP_END_UNLOAD            | \
+                        IME_PROP_KBD_CHAR_FIRST        | \
+                        IME_PROP_IGNORE_UPKEYS         | \
+                        IME_PROP_NEED_ALTKEY           | \
+                        IME_PROP_NO_KEYS_ON_CLOSE      | \
+                        IME_PROP_ACCEPT_WIDE_VKEY)
+#define VALID_CMODE_CAPS (IME_CMODE_ALPHANUMERIC | \
+                          IME_CMODE_NATIVE       | \
+                          IME_CMODE_KATAKANA     | \
+                          IME_CMODE_LANGUAGE     | \
+                          IME_CMODE_FULLSHAPE    | \
+                          IME_CMODE_ROMAN        | \
+                          IME_CMODE_CHARCODE     | \
+                          IME_CMODE_HANJACONVERT | \
+                          IME_CMODE_SOFTKBD      | \
+                          IME_CMODE_NOCONVERSION | \
+                          IME_CMODE_EUDC         | \
+                          IME_CMODE_SYMBOL       | \
+                          IME_CMODE_FIXED)
+#define VALID_SMODE_CAPS (IME_SMODE_NONE          | \
+                          IME_SMODE_PLAURALCLAUSE | \
+                          IME_SMODE_SINGLECONVERT | \
+                          IME_SMODE_AUTOMATIC     | \
+                          IME_SMODE_PHRASEPREDICT | \
+                          IME_SMODE_CONVERSATION)
+#define VALID_UI_CAPS (UI_CAP_2700    | \
+                       UI_CAP_ROT90   | \
+                       UI_CAP_ROTANY  | \
+                       UI_CAP_SOFTKBD)
+#define VALID_SCS_CAPS (SCS_CAP_COMPSTR            | \
+                        SCS_CAP_MAKEREAD           | \
+                        SCS_CAP_SETRECONVERTSTRING)
+#define VALID_SELECT_CAPS (SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE)
+
+    if (pImeInfo->fdwProperty & ~VALID_IME_PROP)
+        return FALSE;
+    if (pImeInfo->fdwConversionCaps & ~VALID_CMODE_CAPS)
+        return FALSE;
+    if (pImeInfo->fdwSentenceCaps & ~VALID_SMODE_CAPS)
+        return FALSE;
+    if (pImeInfo->fdwUICaps & ~VALID_UI_CAPS)
+        return FALSE;
+    if (pImeInfo->fdwSCSCaps & ~VALID_SCS_CAPS)
+        return FALSE;
+    if (pImeInfo->fdwSelectCaps & ~VALID_SELECT_CAPS)
+        return FALSE;
+
+#undef VALID_IME_PROP
+#undef VALID_CMODE_CAPS
+#undef VALID_SMODE_CAPS
+#undef VALID_UI_CAPS
+#undef VALID_SCS_CAPS
+#undef VALID_SELECT_CAPS
+
+    if (pImeInfo->fdwProperty & IME_PROP_UNICODE)
+    {
+        StringCchCopyW(pImeDpi->szUIClass, _countof(pImeDpi->szUIClass), 
szUIClass);
+    }
+    else
+    {
+        if (pImeDpi->uCodePage != GetACP() && pImeDpi->uCodePage)
+            return FALSE;
+
+        MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPSTR)szUIClass, -1,
+                            pImeDpi->szUIClass, _countof(pImeDpi->szUIClass));
+    }
+
+    return GetClassInfoW(pImeDpi->hInst, pImeDpi->szUIClass, &wcW);
+}
+
+BOOL APIENTRY Imm32LoadImeInfo(PIMEINFOEX pImeInfoEx, PIMEDPI pImeDpi)
+{
+    WCHAR szPath[MAX_PATH];
+    HINSTANCE hIME;
+    FARPROC fn;
+
+    if (!Imm32GetSystemLibraryPath(szPath, _countof(szPath), 
pImeInfoEx->wszImeFile))
+        return FALSE;
+
+    hIME = GetModuleHandleW(szPath);
+    if (hIME == NULL)
+    {
+        hIME = LoadLibraryW(szPath);
+        if (hIME == NULL)
+        {
+            ERR("Imm32LoadImeInfo: LoadLibraryW(%S) failed\n", szPath);
+            return FALSE;
+        }
+    }
+    pImeDpi->hInst = hIME;
+
+#define DEFINE_IME_ENTRY(type, name, params, extended) \
+    do { \
+        fn = GetProcAddress(hIME, #name); \
+        if (fn) pImeDpi->name = (FN_##name)fn; \
+        else if (!extended) goto Failed; \
+    } while (0);
+#include "../../../win32ss/include/imetable.h"
+#undef DEFINE_IME_ENTRY
+
+    if (!Imm32InquireIme(pImeDpi))
+    {
+        ERR("Imm32LoadImeInfo: Imm32InquireIme failed\n");
+        goto Failed;
+    }
+
+    if (pImeInfoEx->fLoadFlag)
+        return TRUE;
+
+    NtUserSetImeOwnerWindow(pImeInfoEx, TRUE);
+    return TRUE;
+
+Failed:
+    FreeLibrary(pImeDpi->hInst);
+    pImeDpi->hInst = NULL;
+    return FALSE;
+}
+
+PIMEDPI APIENTRY Ime32LoadImeDpi(HKL hKL, BOOL bLock)
+{
+    IMEINFOEX ImeInfoEx;
+    CHARSETINFO ci;
+    PIMEDPI pImeDpiNew, pImeDpiFound;
+    UINT uCodePage;
+    LCID lcid;
+
+    if (!ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExKeyboardLayout, &hKL) ||
+        ImeInfoEx.fLoadFlag == 1)
+    {
+        return NULL;
+    }
+
+    pImeDpiNew = Imm32HeapAlloc(HEAP_ZERO_MEMORY, sizeof(IMEDPI));
+    if (pImeDpiNew == NULL)
+        return NULL;
+
+    pImeDpiNew->hKL = hKL;
+
+    lcid = LOWORD(hKL);
+    if (TranslateCharsetInfo((LPDWORD)(DWORD_PTR)lcid, &ci, TCI_SRCLOCALE))
+        uCodePage = ci.ciACP;
+    else
+        uCodePage = CP_ACP;
+    pImeDpiNew->uCodePage = uCodePage;
+
+    if (!Imm32LoadImeInfo(&ImeInfoEx, pImeDpiNew))
+    {
+        HeapFree(g_hImm32Heap, 0, pImeDpiNew);
+        return FALSE;
+    }
+
+    RtlEnterCriticalSection(&g_csImeDpi);
+
+    pImeDpiFound = Imm32FindImeDpi(hKL);
+    if (pImeDpiFound)
+    {
+        if (!bLock)
+            pImeDpiFound->dwFlags &= ~IMEDPI_FLAG_LOCKED;
+
+        RtlLeaveCriticalSection(&g_csImeDpi);
+
+        Imm32FreeImeDpi(pImeDpiNew, FALSE);
+        HeapFree(g_hImm32Heap, 0, pImeDpiNew);
+        return pImeDpiFound;
+    }
+    else
+    {
+        if (bLock)
+        {
+            pImeDpiNew->dwFlags |= IMEDPI_FLAG_LOCKED;
+            pImeDpiNew->cLockObj = 1;
+        }
+
+        pImeDpiNew->pNext = g_pImeDpiList;
+        g_pImeDpiList = pImeDpiNew;
+
+        RtlLeaveCriticalSection(&g_csImeDpi);
+        return pImeDpiNew;
+    }
+}
+
+PIMEDPI APIENTRY ImmLockOrLoadImeDpi(HKL hKL)
+{
+    PW32CLIENTINFO pInfo;
+    PIMEDPI pImeDpi;
+
+    if (!IS_IME_HKL(hKL))
+    {
+        if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
+            return NULL;
+
+        pInfo = (PW32CLIENTINFO)(NtCurrentTeb()->Win32ClientInfo);
+        if ((pInfo->W32ClientInfo[0] & 2))
+            return NULL;
+    }
+
+    pImeDpi = ImmLockImeDpi(hKL);
+    if (pImeDpi == NULL)
+        pImeDpi = Ime32LoadImeDpi(hKL, TRUE);
+    return pImeDpi;
+}
+
+/***********************************************************************
+ *             ImmIsIME (IMM32.@)
+ */
+BOOL WINAPI ImmIsIME(HKL hKL)
+{
+    IMEINFOEX info;
+    TRACE("(%p)\n", hKL);
+    return !!ImmGetImeInfoEx(&info, ImeInfoExImeWindow, &hKL);
+}
+
+/***********************************************************************
+ *             ImmGetDefaultIMEWnd (IMM32.@)
+ */
+HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
+{
+    if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
+        return NULL;
+
+    // FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
+    if (hWnd == NULL)
+        return (HWND)NtUserGetThreadState(3);
+
+    return (HWND)NtUserQueryWindow(hWnd, QUERY_WINDOW_DEFAULT_IME);
+}
+
+/***********************************************************************
+ *             ImmNotifyIME (IMM32.@)
+ */
+BOOL WINAPI ImmNotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD 
dwValue)
+{
+    HKL hKL;
+    PIMEDPI pImeDpi;
+    BOOL ret;
+
+    TRACE("(%p, %lu, %lu, %lu)\n", hIMC, dwAction, dwIndex, dwValue);
+
+    if (hIMC && Imm32IsCrossThreadAccess(hIMC))
+        return FALSE;
+
+    hKL = GetKeyboardLayout(0);
+    pImeDpi = ImmLockImeDpi(hKL);
+    if (pImeDpi == NULL)
+        return FALSE;
+
+    ret = pImeDpi->NotifyIME(hIMC, dwAction, dwIndex, dwValue);
+    ImmUnlockImeDpi(pImeDpi);
+    return ret;
+}
+
+/***********************************************************************
+ *              ImmDisableLegacyIME(IMM32.@)
+ */
+BOOL WINAPI ImmDisableLegacyIME(void)
+{
+    FIXME("stub\n");
+    return TRUE;
+}
+
+/***********************************************************************
+ *             CtfImmIsTextFrameServiceDisabled(IMM32.@)
+ */
+BOOL WINAPI CtfImmIsTextFrameServiceDisabled(VOID)
+{
+    PTEB pTeb = NtCurrentTeb();
+    if (((PW32CLIENTINFO)pTeb->Win32ClientInfo)->CI_flags & CI_TFSDISABLED)
+        return TRUE;
+    return FALSE;
+}
+
+/***********************************************************************
+ *              ImmGetImeInfoEx (IMM32.@)
+ */
+BOOL WINAPI
+ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx, IMEINFOEXCLASS SearchType, PVOID 
pvSearchKey)
+{
+    BOOL bDisabled = FALSE;
+    HKL hKL;
+    PTEB pTeb;
+
+    switch (SearchType)
+    {
+        case ImeInfoExKeyboardLayout:
+            break;
+
+        case ImeInfoExImeWindow:
+            bDisabled = CtfImmIsTextFrameServiceDisabled();
+            SearchType = ImeInfoExKeyboardLayout;
+            break;
+
+        case ImeInfoExImeFileName:
+            StringCchCopyW(pImeInfoEx->wszImeFile, 
_countof(pImeInfoEx->wszImeFile),
+                           pvSearchKey);
+            goto Quit;
+    }
+
+    hKL = *(HKL*)pvSearchKey;
+    pImeInfoEx->hkl = hKL;
+
+    if (!IS_IME_HKL(hKL))
+    {
+        if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
+        {
+            pTeb = NtCurrentTeb();
+            if (((PW32CLIENTINFO)pTeb->Win32ClientInfo)->W32ClientInfo[0] & 2)
+                return FALSE;
+            if (!bDisabled)
+                goto Quit;
+        }
+        return FALSE;
+    }
+
+Quit:
+    return NtUserGetImeInfoEx(pImeInfoEx, SearchType);
+}
+
+/***********************************************************************
+ *             ImmLockImeDpi (IMM32.@)
+ */
+PIMEDPI WINAPI ImmLockImeDpi(HKL hKL)
+{
+    PIMEDPI pImeDpi = NULL;
+
+    TRACE("(%p)\n", hKL);
+
+    RtlEnterCriticalSection(&g_csImeDpi);
+
+    /* Find by hKL */
+    for (pImeDpi = g_pImeDpiList; pImeDpi; pImeDpi = pImeDpi->pNext)
+    {
+        if (pImeDpi->hKL == hKL) /* found */
+        {
+            /* lock if possible */
+            if (pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN)
+                pImeDpi = NULL;
+            else
+                ++(pImeDpi->cLockObj);
+            break;
+        }
+    }
+
+    RtlLeaveCriticalSection(&g_csImeDpi);
+    return pImeDpi;
+}
+
+/***********************************************************************
+ *             ImmUnlockImeDpi (IMM32.@)
+ */
+VOID WINAPI ImmUnlockImeDpi(PIMEDPI pImeDpi)
+{
+    PIMEDPI *ppEntry;
+
+    TRACE("(%p)\n", pImeDpi);
+
+    if (pImeDpi == NULL)
+        return;
+
+    RtlEnterCriticalSection(&g_csImeDpi);
+
+    /* unlock */
+    --(pImeDpi->cLockObj);
+    if (pImeDpi->cLockObj != 0)
+    {
+        RtlLeaveCriticalSection(&g_csImeDpi);
+        return;
+    }
+
+    if ((pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN) == 0)
+    {
+        if ((pImeDpi->dwFlags & IMEDPI_FLAG_LOCKED) == 0 ||
+            (pImeDpi->ImeInfo.fdwProperty & IME_PROP_END_UNLOAD) == 0)
+        {
+            RtlLeaveCriticalSection(&g_csImeDpi);
+            return;
+        }
+    }
+
+    /* Remove from list */
+    for (ppEntry = &g_pImeDpiList; *ppEntry; ppEntry = &((*ppEntry)->pNext))
+    {
+        if (*ppEntry == pImeDpi) /* found */
+        {
+            *ppEntry = pImeDpi->pNext;
+            break;
+        }
+    }
+
+    Imm32FreeImeDpi(pImeDpi, TRUE);
+    HeapFree(g_hImm32Heap, 0, pImeDpi);
+
+    RtlLeaveCriticalSection(&g_csImeDpi);
+}
+
+/***********************************************************************
+ *             ImmLoadIME (IMM32.@)
+ */
+BOOL WINAPI ImmLoadIME(HKL hKL)
+{
+    PW32CLIENTINFO pInfo;
+    PIMEDPI pImeDpi;
+
+    if (!IS_IME_HKL(hKL))
+    {
+        if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
+            return FALSE;
+
+        pInfo = (PW32CLIENTINFO)(NtCurrentTeb()->Win32ClientInfo);
+        if ((pInfo->W32ClientInfo[0] & 2))
+            return FALSE;
+    }
+
+    pImeDpi = Imm32FindImeDpi(hKL);
+    if (pImeDpi == NULL)
+        pImeDpi = Ime32LoadImeDpi(hKL, FALSE);
+    return (pImeDpi != NULL);
+}
+
+/***********************************************************************
+ *             ImmDisableIME (IMM32.@)
+ */
+BOOL WINAPI ImmDisableIME(DWORD dwThreadId)
+{
+    return NtUserDisableThreadIme(dwThreadId);
+}
+
+/***********************************************************************
+ *             ImmGetDescriptionA (IMM32.@)
+ */
+UINT WINAPI ImmGetDescriptionA(HKL hKL, LPSTR lpszDescription, UINT uBufLen)
+{
+    IMEINFOEX info;
+    size_t cch;
+
+    TRACE("(%p,%p,%d)\n", hKL, lpszDescription, uBufLen);
+
+    if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || 
!IS_IME_HKL(hKL))
+        return 0;
+
+    StringCchLengthW(info.wszImeDescription, _countof(info.wszImeDescription), 
&cch);
+    cch = WideCharToMultiByte(CP_ACP, 0, info.wszImeDescription, (INT)cch,
+                              lpszDescription, uBufLen, NULL, NULL);
+    if (uBufLen)
+        lpszDescription[cch] = 0;
+    return (UINT)cch;
+}
+
+/***********************************************************************
+ *             ImmGetDescriptionW (IMM32.@)
+ */
+UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
+{
+    IMEINFOEX info;
+    size_t cch;
+
+    TRACE("(%p, %p, %d)\n", hKL, lpszDescription, uBufLen);
+
+    if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || 
!IS_IME_HKL(hKL))
+        return 0;
+
+    if (uBufLen != 0)
+        StringCchCopyW(lpszDescription, uBufLen, info.wszImeDescription);
+
+    StringCchLengthW(info.wszImeDescription, _countof(info.wszImeDescription), 
&cch);
+    return (UINT)cch;
+}
+
+/***********************************************************************
+ *             ImmGetIMEFileNameA (IMM32.@)
+ */
+UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
+{
+    BOOL bDefUsed;
+    IMEINFOEX info;
+    size_t cch;
+
+    TRACE("(%p, %p, %u)\n", hKL, lpszFileName, uBufLen);
+
+    if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || 
!IS_IME_HKL(hKL))
+    {
+        if (uBufLen > 0)
+            lpszFileName[0] = 0;
+        return 0;
+    }
+
+    StringCchLengthW(info.wszImeFile, _countof(info.wszImeFile), &cch);
+
+    cch = WideCharToMultiByte(CP_ACP, 0, info.wszImeFile, (INT)cch,
+                              lpszFileName, uBufLen, NULL, &bDefUsed);
+    if (uBufLen == 0)
+        return (UINT)cch;
+
+    if (cch > uBufLen - 1)
+        cch = uBufLen - 1;
+
+    lpszFileName[cch] = 0;
+    return (UINT)cch;
+}
+
+/***********************************************************************
+ *             ImmGetIMEFileNameW (IMM32.@)
+ */
+UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
+{
+    IMEINFOEX info;
+    size_t cch;
+
+    TRACE("(%p, %p, %u)\n", hKL, lpszFileName, uBufLen);
+
+    if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || 
!IS_IME_HKL(hKL))
+    {
+        if (uBufLen > 0)
+            lpszFileName[0] = 0;
+        return 0;
+    }
+
+    StringCchLengthW(info.wszImeFile, _countof(info.wszImeFile), &cch);
+    if (uBufLen == 0)
+        return (UINT)cch;
+
+    StringCchCopyNW(lpszFileName, uBufLen, info.wszImeFile, cch);
+
+    if (cch > uBufLen - 1)
+        cch = uBufLen - 1;
+
+    lpszFileName[cch] = 0;
+    return (UINT)cch;
+}
+
+/***********************************************************************
+ *             ImmGetProperty (IMM32.@)
+ */
+DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
+{
+    IMEINFOEX ImeInfoEx;
+    LPIMEINFO pImeInfo;
+    DWORD dwValue;
+    PIMEDPI pImeDpi = NULL;
+
+    TRACE("(%p, %lu)\n", hKL, fdwIndex);
+
+    if (!ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExKeyboardLayout, &hKL))
+        return FALSE;
+
+    if (fdwIndex == IGP_GETIMEVERSION)
+        return ImeInfoEx.dwImeWinVersion;
+
+    if (ImeInfoEx.fLoadFlag != 2)
+    {
+        pImeDpi = ImmLockOrLoadImeDpi(hKL);
+        if (pImeDpi == NULL)
+            return FALSE;
+
+        pImeInfo = &pImeDpi->ImeInfo;
+    }
+    else
+    {
+        pImeInfo = &ImeInfoEx.ImeInfo;
+    }
+
+    switch (fdwIndex)
+    {
+        case IGP_PROPERTY:      dwValue = pImeInfo->fdwProperty; break;
+        case IGP_CONVERSION:    dwValue = pImeInfo->fdwConversionCaps; break;
+        case IGP_SENTENCE:      dwValue = pImeInfo->fdwSentenceCaps; break;
+        case IGP_UI:            dwValue = pImeInfo->fdwUICaps; break;
+        case IGP_SETCOMPSTR:    dwValue = pImeInfo->fdwSCSCaps; break;
+        case IGP_SELECT:        dwValue = pImeInfo->fdwSelectCaps; break;
+        default:                dwValue = 0; break;
+    }
+
+    if (pImeDpi)
+        ImmUnlockImeDpi(pImeDpi);
+    return dwValue;
+}
+
+/***********************************************************************
+ *             ImmGetOpenStatus (IMM32.@)
+ */
+BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
+{
+    BOOL ret;
+    LPINPUTCONTEXT pIC;
+
+    TRACE("(%p)\n", hIMC);
+
+    if (!hIMC)
+        return FALSE;
+
+    pIC = ImmLockIMC(hIMC);
+    if (!pIC)
+        return FALSE;
+
+    ret = pIC->fOpen;
+
+    ImmUnlockIMC(hIMC);
+    return ret;
+}
+
+/***********************************************************************
+ *             ImmSetOpenStatus (IMM32.@)
+ */
+BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
+{
+    DWORD dwConversion;
+    LPINPUTCONTEXT pIC;
+    HWND hWnd;
+    BOOL bHasChange = FALSE;
+
+    TRACE("(%p, %d)\n", hIMC, fOpen);
+
+    if (Imm32IsCrossThreadAccess(hIMC))
+        return FALSE;
+
+    pIC = ImmLockIMC(hIMC);
+    if (pIC == NULL)
+        return FALSE;
+
+    if (pIC->fOpen != fOpen)
+    {
+        pIC->fOpen = fOpen;
+        hWnd = pIC->hWnd;
+        dwConversion = pIC->fdwConversion;
+        bHasChange = TRUE;
+    }
+
+    ImmUnlockIMC(hIMC);
+
+    if (bHasChange)
+    {
+        Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0,
+                          IMC_SETOPENSTATUS, IMN_SETOPENSTATUS, 0);
+        NtUserNotifyIMEStatus(hWnd, hIMC, dwConversion);
+    }
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *             ImmGetStatusWindowPos (IMM32.@)
+ */
+BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
+{
+    LPINPUTCONTEXT pIC;
+    BOOL ret;
+
+    TRACE("(%p, %p)\n", hIMC, lpptPos);
+
+    pIC = ImmLockIMC(hIMC);
+    if (pIC == NULL)
+        return FALSE;
+
+    ret = !!(pIC->fdwInit & INIT_STATUSWNDPOS);
+    if (ret)
+        *lpptPos = pIC->ptStatusWndPos;
+
+    ImmUnlockIMC(hIMC);
+    return ret;
+}
+
+/***********************************************************************
+ *             ImmSetStatusWindowPos (IMM32.@)
+ */
+BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
+{
+    LPINPUTCONTEXT pIC;
+    HWND hWnd;
+
+    TRACE("(%p, {%ld, %ld})\n", hIMC, lpptPos->x, lpptPos->y);
+
+    if (Imm32IsCrossThreadAccess(hIMC))
+        return FALSE;
+
+    pIC = ImmLockIMC(hIMC);
+    if (!pIC)
+        return FALSE;
+
+    hWnd = pIC->hWnd;
+    pIC->ptStatusWndPos = *lpptPos;
+    pIC->fdwInit |= INIT_STATUSWNDPOS;
+
+    ImmUnlockIMC(hIMC);
+
+    Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0,
+                      IMC_SETSTATUSWINDOWPOS, IMN_SETSTATUSWINDOWPOS, 0);
+    return TRUE;
+}
+
+/***********************************************************************
+ *             ImmGetCompositionWindow (IMM32.@)
+ */
+BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
+{
+    LPINPUTCONTEXT pIC;
+    BOOL ret = FALSE;
+
+    TRACE("(%p, %p)\n", hIMC, lpCompForm);
+
+    pIC = ImmLockIMC(hIMC);
+    if (!pIC)
+        return FALSE;
+
+    if (pIC->fdwInit & INIT_COMPFORM)
+    {
+        *lpCompForm = pIC->cfCompForm;
+        ret = TRUE;
+    }
+
+    ImmUnlockIMC(hIMC);
+    return ret;
+}
+
+/***********************************************************************
+ *             ImmSetCompositionWindow (IMM32.@)
+ */
+BOOL WINAPI ImmSetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
+{
+    LPINPUTCONTEXT pIC;
+    HWND hWnd;
+
+    if (Imm32IsCrossThreadAccess(hIMC))
+        return FALSE;
+
+    pIC = ImmLockIMC(hIMC);
+    if (pIC == NULL)
+        return FALSE;
+
+    pIC->cfCompForm = *lpCompForm;
+    pIC->fdwInit |= INIT_COMPFORM;
+
+    hWnd = pIC->hWnd;
+
+    ImmUnlockIMC(hIMC);
+
+    Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0,
+                      IMC_SETCOMPOSITIONWINDOW, IMN_SETCOMPOSITIONWINDOW, 0);
+    return TRUE;
+}
+
+/***********************************************************************
+ *             ImmGetCompositionFontA (IMM32.@)
+ */
+BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
+{
+    PCLIENTIMC pClientImc;
+    BOOL ret = FALSE, bWide;
+    LPINPUTCONTEXT pIC;
+
+    TRACE("(%p, %p)\n", hIMC, lplf);
+
+    pClientImc = ImmLockClientImc(hIMC);
+    if (pClientImc == NULL)
+        return FALSE;
+
+    bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
+    ImmUnlockClientImc(pClientImc);
+
+    pIC = ImmLockIMC(hIMC);
+    if (pIC == NULL)
+        return FALSE;
+
+    if (pIC->fdwInit & INIT_LOGFONT)
+    {
+        if (bWide)
+            LogFontWideToAnsi(&pIC->lfFont.W, lplf);
+        else
+            *lplf = pIC->lfFont.A;
+
+        ret = TRUE;
+    }
+
+    ImmUnlockIMC(hIMC);
+    return ret;
+}
+
+/***********************************************************************
+ *             ImmGetCompositionFontW (IMM32.@)
+ */
+BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
+{
+    PCLIENTIMC pClientImc;
+    BOOL bWide;
+    LPINPUTCONTEXT pIC;
+    BOOL ret = FALSE;
+
+    TRACE("(%p, %p)\n", hIMC, lplf);
+
+    pClientImc = ImmLockClientImc(hIMC);
+    if (pClientImc == NULL)
+        return FALSE;
+
+    bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
+    ImmUnlockClientImc(pClientImc);
+
+    pIC = ImmLockIMC(hIMC);
+    if (pIC == NULL)
+        return FALSE;
+
+    if (pIC->fdwInit & INIT_LOGFONT)
+    {
+        if (bWide)
+            *lplf = pIC->lfFont.W;
+        else
+            LogFontAnsiToWide(&pIC->lfFont.A, lplf);
+
+        ret = TRUE;
+    }
+
+    ImmUnlockIMC(hIMC);
+    return ret;
+}
+
+/***********************************************************************
+ *             ImmSetCompositionFontA (IMM32.@)
+ */
+BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
+{
+    LOGFONTW lfW;
+    PCLIENTIMC pClientImc;
+    BOOL bWide;
+    LPINPUTCONTEXTDX pIC;
+    LCID lcid;
+    HWND hWnd;
+    PTEB pTeb;
+
+    TRACE("(%p, %p)\n", hIMC, lplf);
+
+    if (Imm32IsCrossThreadAccess(hIMC))
+        return FALSE;
+
+    pClientImc = ImmLockClientImc(hIMC);
+    if (pClientImc == NULL)
+        return FALSE;
+
+    bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
+    ImmUnlockClientImc(pClientImc);
+
+    if (bWide)
+    {
+        LogFontAnsiToWide(lplf, &lfW);
+        return ImmSetCompositionFontW(hIMC, &lfW);
+    }
+
+    pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
+    if (pIC == NULL)
+        return FALSE;
+
+    pTeb = NtCurrentTeb();
+    if (pTeb->Win32ClientInfo[2] < 0x400)
+    {
+        lcid = GetSystemDefaultLCID();
+        if (PRIMARYLANGID(lcid) == LANG_JAPANESE && !(pIC->dwUIFlags & 2) &&
+            pIC->cfCompForm.dwStyle != CFS_DEFAULT)
+        {
+            PostMessageA(pIC->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0);
+        }
+    }
+
+    pIC->lfFont.A = *lplf;
+    pIC->fdwInit |= INIT_LOGFONT;
+    hWnd = pIC->hWnd;
+
+    ImmUnlockIMC(hIMC);
+
+    Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT,
+                      IMN_SETCOMPOSITIONFONT, 0);
+    return TRUE;
+}
+
+/***********************************************************************
+ *             ImmSetCompositionFontW (IMM32.@)
+ */
+BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
+{
+    LOGFONTA lfA;
+    PCLIENTIMC pClientImc;
+    BOOL bWide;
+    HWND hWnd;
+    LPINPUTCONTEXTDX pIC;
+    PTEB pTeb;
+    LCID lcid;
+
+    TRACE("(%p, %p)\n", hIMC, lplf);
+
+    if (Imm32IsCrossThreadAccess(hIMC))
+        return FALSE;
+
+    pClientImc = ImmLockClientImc(hIMC);
+    if (pClientImc == NULL)
+        return FALSE;
+
+    bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
+    ImmUnlockClientImc(pClientImc);
+
+    if (!bWide)
+    {
+        LogFontWideToAnsi(lplf, &lfA);
+        return ImmSetCompositionFontA(hIMC, &lfA);
+    }
+
+    pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
+    if (pIC == NULL)
+        return FALSE;
+
+    pTeb = NtCurrentTeb();
+    if (pTeb->Win32ClientInfo[2] < 0x400)
+    {
+        lcid = GetSystemDefaultLCID();
+        if (PRIMARYLANGID(lcid) == LANG_JAPANESE &&
+            !(pIC->dwUIFlags & 2) &&
+            pIC->cfCompForm.dwStyle != CFS_DEFAULT)
+        {
+            PostMessageW(pIC->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0);
+        }
+    }
+
+    pIC->lfFont.W = *lplf;
+    pIC->fdwInit |= INIT_LOGFONT;
+    hWnd = pIC->hWnd;
+
+    ImmUnlockIMC(hIMC);
+
+    Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT,
+                      IMN_SETCOMPOSITIONFONT, 0);
+    return TRUE;
+}
+
+/***********************************************************************
+ *             ImmGetConversionListA (IMM32.@)
+ */
+DWORD WINAPI
+ImmGetConversionListA(HKL hKL, HIMC hIMC, LPCSTR pSrc, LPCANDIDATELIST lpDst,
+                      DWORD dwBufLen, UINT uFlag)
+{
+    DWORD ret = 0;
+    UINT cb;
+    LPWSTR pszSrcW = NULL;
+    LPCANDIDATELIST pCL = NULL;
+    PIMEDPI pImeDpi;
+
+    TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL, hIMC, debugstr_a(pSrc),
+          lpDst, dwBufLen, uFlag);
+
+    pImeDpi = ImmLockOrLoadImeDpi(hKL);
+    if (pImeDpi == NULL)
+        return 0;
+
+    if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))
+    {
+        ret = pImeDpi->ImeConversionList(hIMC, pSrc, lpDst, dwBufLen, uFlag);
+        ImmUnlockImeDpi(pImeDpi);
+        return ret;
+    }
+
+    if (pSrc)
+    {
+        pszSrcW = Imm32WideFromAnsi(pSrc);
+        if (pszSrcW == NULL)
+            goto Quit;
+    }
+
+    cb = pImeDpi->ImeConversionList(hIMC, pszSrcW, NULL, 0, uFlag);
+    if (cb == 0)
+        goto Quit;
+
+    pCL = Imm32HeapAlloc(0, cb);
+    if (pCL == NULL)
+        goto Quit;
+
+    cb = pImeDpi->ImeConversionList(hIMC, pszSrcW, pCL, cb, uFlag);
+    if (cb == 0)
+        goto Quit;
+
+    ret = CandidateListWideToAnsi(pCL, lpDst, dwBufLen, CP_ACP);
+
+Quit:
+    if (pszSrcW)
+        HeapFree(g_hImm32Heap, 0, pszSrcW);
+    if (pCL)
+        HeapFree(g_hImm32Heap, 0, pCL);
+    ImmUnlockImeDpi(pImeDpi);
+    return ret;
+}
+
+/***********************************************************************
+ *             ImmGetConversionListW (IMM32.@)
+ */
+DWORD WINAPI
+ImmGetConversionListW(HKL hKL, HIMC hIMC, LPCWSTR pSrc, LPCANDIDATELIST lpDst,
+                      DWORD dwBufLen, UINT uFlag)
+{
+    DWORD ret = 0;
+    INT cb;
+    PIMEDPI pImeDpi;
+    LPCANDIDATELIST pCL = NULL;
+    LPSTR pszSrcA = NULL;
+
+    TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL, hIMC, debugstr_w(pSrc),
+          lpDst, dwBufLen, uFlag);
+
+    pImeDpi = ImmLockOrLoadImeDpi(hKL);
+    if (!pImeDpi)
+        return 0;
+
+    if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
+    {
+        ret = pImeDpi->ImeConversionList(hIMC, pSrc, lpDst, dwBufLen, uFlag);
+        ImmUnlockImeDpi(pImeDpi);
+        return ret;
+    }
+
+    if (pSrc)
+    {
+        pszSrcA = Imm32AnsiFromWide(pSrc);
+        if (pszSrcA == NULL)
+            goto Quit;
+    }
+
+    cb = pImeDpi->ImeConversionList(hIMC, pszSrcA, NULL, 0, uFlag);
+    if (cb == 0)
+        goto Quit;
+
+    pCL = Imm32HeapAlloc(0, cb);
+    if (!pCL)
+        goto Quit;
+
+    cb = pImeDpi->ImeConversionList(hIMC, pszSrcA, pCL, cb, uFlag);
+    if (!cb)
+        goto Quit;
+
+    ret = CandidateListAnsiToWide(pCL, lpDst, dwBufLen, CP_ACP);
+
+Quit:
+    if (pszSrcA)
+        HeapFree(g_hImm32Heap, 0, pszSrcA);
+    if (pCL)
+        HeapFree(g_hImm32Heap, 0, pCL);
+    ImmUnlockImeDpi(pImeDpi);
+    return ret;
+}
+
+/***********************************************************************
+ *             ImmGetConversionStatus (IMM32.@)
+ */
+BOOL WINAPI ImmGetConversionStatus(HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD 
lpfdwSentence)
+{
+    LPINPUTCONTEXT pIC;
+
+    TRACE("(%p %p %p)\n", hIMC, lpfdwConversion, lpfdwSentence);
+
+    pIC = ImmLockIMC(hIMC);
+    if (!pIC)
+        return FALSE;
+
+    if (lpfdwConversion)
+        *lpfdwConversion = pIC->fdwConversion;
+    if (lpfdwSentence)
+        *lpfdwSentence = pIC->fdwSentence;
+
+    ImmUnlockIMC(hIMC);
+    return TRUE;
+}
+
+/***********************************************************************
+ *             ImmSetConversionStatus (IMM32.@)
+ */
+BOOL WINAPI ImmSetConversionStatus(HIMC hIMC, DWORD fdwConversion, DWORD 
fdwSentence)
+{
+    HKL hKL;
+    LPINPUTCONTEXT pIC;
+    DWORD dwOldConversion, dwOldSentence;
+    BOOL fConversionChange = FALSE, fSentenceChange = FALSE;
+    HWND hWnd;
+
+    TRACE("(%p, 0x%lX, 0x%lX)\n", hIMC, fdwConversion, fdwSentence);
+
+    hKL = GetKeyboardLayout(0);
+    if (!IS_IME_HKL(hKL))
+    {
+        if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
+        {
+            FIXME("Cicero\n");
+            return FALSE;
+        }
+    }
+
+    if (Imm32IsCrossThreadAccess(hIMC))
+        return FALSE;
+
+    pIC = ImmLockIMC(hIMC);
+    if (pIC == NULL)
+        return FALSE;
+
+    if (pIC->fdwConversion != fdwConversion)
+    {
+        dwOldConversion = pIC->fdwConversion;
+        pIC->fdwConversion = fdwConversion;
+        fConversionChange = TRUE;
+    }
+
+    if (pIC->fdwSentence != fdwSentence)
+    {
+        dwOldSentence = pIC->fdwSentence;
+        pIC->fdwSentence = fdwSentence;
+        fSentenceChange = TRUE;
+    }
+
+    hWnd = pIC->hWnd;
+    ImmUnlockIMC(hIMC);
+
+    if (fConversionChange)
+    {
+        Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, dwOldConversion,
+                          IMC_SETCONVERSIONMODE, IMN_SETCONVERSIONMODE, 0);
+        NtUserNotifyIMEStatus(hWnd, hIMC, fdwConversion);
+    }
+
+    if (fSentenceChange)
+    {
+        Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, dwOldSentence,
+                          IMC_SETSENTENCEMODE, IMN_SETSENTENCEMODE, 0);
+    }
+
+    return TRUE;
+}
diff --git a/dll/win32/imm32/imm.c b/dll/win32/imm32/imm.c
index 1dc41f8e362..38dd4b55b57 100644
--- a/dll/win32/imm32/imm.c
+++ b/dll/win32/imm32/imm.c
@@ -10,88 +10,14 @@
  *              Copyright 2020-2021 Katayama Hirofumi MZ 
<[email protected]>
  */
 
-#include <stdarg.h>
-#include <stdio.h>
-
-#define WIN32_NO_STATUS
-#include <windef.h>
-#include <winbase.h>
-#include <wingdi.h>
-#include <winuser.h>
-#include <winerror.h>
-#include <wine/debug.h>
-#include <imm.h>
-#include <ddk/imm.h>
-#include <winnls.h>
-#include <winreg.h>
-#include <wine/list.h>
-#include <stdlib.h>
-#include <ndk/umtypes.h>
-#include <ndk/pstypes.h>
-#include <ndk/rtlfuncs.h>
-#include "../../../win32ss/include/ntuser.h"
-#include "../../../win32ss/include/ntwin32.h"
-#include <undocuser.h>
-#include <imm32_undoc.h>
-#include <strsafe.h>
+#include "precomp.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(imm);
 
-#define IMM_INIT_MAGIC 0x19650412
-#define IMM_INVALID_CANDFORM ULONG_MAX
-#define INVALID_HOTKEY_ID 0xFFFFFFFF
-#define MAX_CANDIDATEFORM 4
-
-#define LANGID_CHINESE_SIMPLIFIED MAKELANGID(LANG_CHINESE, 
SUBLANG_CHINESE_SIMPLIFIED)
-#define LANGID_CHINESE_TRADITIONAL MAKELANGID(LANG_CHINESE, 
SUBLANG_CHINESE_TRADITIONAL)
-#define LANGID_JAPANESE MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT)
-
-#define REGKEY_KEYBOARD_LAYOUTS \
-    L"System\\CurrentControlSet\\Control\\Keyboard Layouts"
-#define REGKEY_IMM \
-    L"Software\\Microsoft\\Windows NT\\CurrentVersion\\IMM"
-
-#define ROUNDUP4(n) (((n) + 3) & ~3)  /* DWORD alignment */
-
 HMODULE g_hImm32Inst = NULL;
-RTL_CRITICAL_SECTION g_csImeDpi;
-PIMEDPI g_pImeDpiList = NULL;
 PSERVERINFO g_psi = NULL;
 SHAREDINFO g_SharedInfo = { NULL };
 BYTE g_bClientRegd = FALSE;
-HANDLE g_hImm32Heap = NULL;
-
-static PWND FASTCALL ValidateHwndNoErr(HWND hwnd)
-{
-    PCLIENTINFO ClientInfo = GetWin32ClientInfo();
-    INT index;
-    PUSER_HANDLE_TABLE ht;
-    PUSER_HANDLE_ENTRY he;
-    WORD generation;
-
-    /* See if the window is cached */
-    if (hwnd == ClientInfo->CallbackWnd.hWnd)
-        return ClientInfo->CallbackWnd.pWnd;
-
-    if (!NtUserValidateHandleSecure(hwnd))
-        return NULL;
-
-    ht = g_SharedInfo.aheList; /* handle table */
-    ASSERT(ht);
-    /* ReactOS-Specific! */
-    ASSERT(g_SharedInfo.ulSharedDelta != 0);
-    he = (PUSER_HANDLE_ENTRY)((ULONG_PTR)ht->handles - 
g_SharedInfo.ulSharedDelta);
-
-    index = (LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1;
-    if (index < 0 || index >= ht->nb_handles || he[index].type != TYPE_WINDOW)
-        return NULL;
-
-    generation = HIWORD(hwnd);
-    if (generation != he[index].generation && generation && generation != 
0xFFFF)
-        return NULL;
-
-    return (PWND)&he[index];
-}
 
 static BOOL APIENTRY Imm32InitInstance(HMODULE hMod)
 {
@@ -111,568 +37,15 @@ static BOOL APIENTRY Imm32InitInstance(HMODULE hMod)
     return TRUE;
 }
 
-LPVOID APIENTRY Imm32HeapAlloc(DWORD dwFlags, DWORD dwBytes)
-{
-    if (!g_hImm32Heap)
-    {
-        g_hImm32Heap = RtlGetProcessHeap();
-        if (g_hImm32Heap == NULL)
-            return NULL;
-    }
-    return HeapAlloc(g_hImm32Heap, dwFlags, dwBytes);
-}
-
-static LPWSTR APIENTRY Imm32WideFromAnsi(LPCSTR pszA)
-{
-    INT cch = lstrlenA(pszA);
-    LPWSTR pszW = Imm32HeapAlloc(0, (cch + 1) * sizeof(WCHAR));
-    if (pszW == NULL)
-        return NULL;
-    cch = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszA, cch, pszW, cch + 
1);
-    pszW[cch] = 0;
-    return pszW;
-}
-
-static LPSTR APIENTRY Imm32AnsiFromWide(LPCWSTR pszW)
-{
-    INT cchW = lstrlenW(pszW);
-    INT cchA = (cchW + 1) * sizeof(WCHAR);
-    LPSTR pszA = Imm32HeapAlloc(0, cchA);
-    if (!pszA)
-        return NULL;
-    cchA = WideCharToMultiByte(CP_ACP, 0, pszW, cchW, pszA, cchA, NULL, NULL);
-    pszA[cchA] = 0;
-    return pszA;
-}
-
-static inline BOOL Imm32IsCrossThreadAccess(HIMC hIMC)
-{
-    DWORD dwImeThreadId = NtUserQueryInputContext(hIMC, 1);
-    DWORD dwThreadId = GetCurrentThreadId();
-    return (dwImeThreadId != dwThreadId);
-}
-
-static BOOL Imm32IsCrossProcessAccess(HWND hWnd)
-{
-    return (NtUserQueryWindow(hWnd, QUERY_WINDOW_UNIQUE_PROCESS_ID) !=
-            (DWORD_PTR)NtCurrentTeb()->ClientId.UniqueProcess);
-}
-
-static VOID APIENTRY Imm32FreeImeDpi(PIMEDPI pImeDpi, BOOL bDestroy)
-{
-    if (pImeDpi->hInst == NULL)
-        return;
-    if (bDestroy)
-        pImeDpi->ImeDestroy(0);
-    FreeLibrary(pImeDpi->hInst);
-    pImeDpi->hInst = NULL;
-}
-
-static BOOL APIENTRY
-Imm32NotifyAction(HIMC hIMC, HWND hwnd, DWORD dwAction, DWORD_PTR dwIndex, 
DWORD_PTR dwValue,
-                  DWORD_PTR dwCommand, DWORD_PTR dwData)
-{
-    DWORD dwLayout;
-    HKL hKL;
-    PIMEDPI pImeDpi;
-
-    if (dwAction)
-    {
-        dwLayout = NtUserQueryInputContext(hIMC, 1);
-        if (dwLayout)
-        {
-            /* find keyboard layout and lock it */
-            hKL = GetKeyboardLayout(dwLayout);
-            pImeDpi = ImmLockImeDpi(hKL);
-            if (pImeDpi)
-            {
-                /* do notify */
-                pImeDpi->NotifyIME(hIMC, dwAction, dwIndex, dwValue);
-
-                ImmUnlockImeDpi(pImeDpi); /* unlock */
-            }
-        }
-    }
-
-    if (hwnd && dwCommand)
-        SendMessageW(hwnd, WM_IME_NOTIFY, dwCommand, dwData);
-
-    return TRUE;
-}
-
-static PIMEDPI APIENTRY Imm32FindImeDpi(HKL hKL)
-{
-    PIMEDPI pImeDpi;
-
-    RtlEnterCriticalSection(&g_csImeDpi);
-    for (pImeDpi = g_pImeDpiList; pImeDpi != NULL; pImeDpi = pImeDpi->pNext)
-    {
-        if (pImeDpi->hKL == hKL)
-            break;
-    }
-    RtlLeaveCriticalSection(&g_csImeDpi);
-
-    return pImeDpi;
-}
-
-static BOOL Imm32GetSystemLibraryPath(LPWSTR pszPath, DWORD cchPath, LPCWSTR 
pszFileName)
-{
-    if (!pszFileName[0] || !GetSystemDirectoryW(pszPath, cchPath))
-        return FALSE;
-    StringCchCatW(pszPath, cchPath, L"\\");
-    StringCchCatW(pszPath, cchPath, pszFileName);
-    return TRUE;
-}
-
-static BOOL APIENTRY Imm32InquireIme(PIMEDPI pImeDpi)
-{
-    WCHAR szUIClass[64];
-    WNDCLASSW wcW;
-    DWORD dwSysInfoFlags = 0; // TODO: ???
-    LPIMEINFO pImeInfo = &pImeDpi->ImeInfo;
-
-    // TODO: NtUserGetThreadState(16);
-
-    if (!IS_IME_HKL(pImeDpi->hKL))
-    {
-        if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED) &&
-            pImeDpi->CtfImeInquireExW)
-        {
-            // TODO:
-            return FALSE;
-        }
-    }
-
-    if (!pImeDpi->ImeInquire(pImeInfo, szUIClass, dwSysInfoFlags))
-        return FALSE;
-
-    szUIClass[_countof(szUIClass) - 1] = 0;
-
-    if (pImeInfo->dwPrivateDataSize == 0)
-        pImeInfo->dwPrivateDataSize = 4;
-
-#define VALID_IME_PROP (IME_PROP_AT_CARET              | \
-                        IME_PROP_SPECIAL_UI            | \
-                        IME_PROP_CANDLIST_START_FROM_1 | \
-                        IME_PROP_UNICODE               | \
-                        IME_PROP_COMPLETE_ON_UNSELECT  | \
-                        IME_PROP_END_UNLOAD            | \
-                        IME_PROP_KBD_CHAR_FIRST        | \
-                        IME_PROP_IGNORE_UPKEYS         | \
-                        IME_PROP_NEED_ALTKEY           | \
-                        IME_PROP_NO_KEYS_ON_CLOSE      | \
-                        IME_PROP_ACCEPT_WIDE_VKEY)
-#define VALID_CMODE_CAPS (IME_CMODE_ALPHANUMERIC | \
-                          IME_CMODE_NATIVE       | \
-                          IME_CMODE_KATAKANA     | \
-                          IME_CMODE_LANGUAGE     | \
-                          IME_CMODE_FULLSHAPE    | \
-                          IME_CMODE_ROMAN        | \
-                          IME_CMODE_CHARCODE     | \
-                          IME_CMODE_HANJACONVERT | \
-                          IME_CMODE_SOFTKBD      | \
-                          IME_CMODE_NOCONVERSION | \
-                          IME_CMODE_EUDC         | \
-                          IME_CMODE_SYMBOL       | \
-                          IME_CMODE_FIXED)
-#define VALID_SMODE_CAPS (IME_SMODE_NONE          | \
-                          IME_SMODE_PLAURALCLAUSE | \
-                          IME_SMODE_SINGLECONVERT | \
-                          IME_SMODE_AUTOMATIC     | \
-                          IME_SMODE_PHRASEPREDICT | \
-                          IME_SMODE_CONVERSATION)
-#define VALID_UI_CAPS (UI_CAP_2700    | \
-                       UI_CAP_ROT90   | \
-                       UI_CAP_ROTANY  | \
-                       UI_CAP_SOFTKBD)
-#define VALID_SCS_CAPS (SCS_CAP_COMPSTR            | \
-                        SCS_CAP_MAKEREAD           | \
-                        SCS_CAP_SETRECONVERTSTRING)
-#define VALID_SELECT_CAPS (SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE)
-
-    if (pImeInfo->fdwProperty & ~VALID_IME_PROP)
-        return FALSE;
-    if (pImeInfo->fdwConversionCaps & ~VALID_CMODE_CAPS)
-        return FALSE;
-    if (pImeInfo->fdwSentenceCaps & ~VALID_SMODE_CAPS)
-        return FALSE;
-    if (pImeInfo->fdwUICaps & ~VALID_UI_CAPS)
-        return FALSE;
-    if (pImeInfo->fdwSCSCaps & ~VALID_SCS_CAPS)
-        return FALSE;
-    if (pImeInfo->fdwSelectCaps & ~VALID_SELECT_CAPS)
-        return FALSE;
-
-#undef VALID_IME_PROP
-#undef VALID_CMODE_CAPS
-#undef VALID_SMODE_CAPS
-#undef VALID_UI_CAPS
-#undef VALID_SCS_CAPS
-#undef VALID_SELECT_CAPS
-
-    if (pImeInfo->fdwProperty & IME_PROP_UNICODE)
-    {
-        StringCchCopyW(pImeDpi->szUIClass, _countof(pImeDpi->szUIClass), 
szUIClass);
-    }
-    else
-    {
-        if (pImeDpi->uCodePage != GetACP() && pImeDpi->uCodePage)
-            return FALSE;
-
-        MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPSTR)szUIClass, -1,
-                            pImeDpi->szUIClass, _countof(pImeDpi->szUIClass));
-    }
-
-    return GetClassInfoW(pImeDpi->hInst, pImeDpi->szUIClass, &wcW);
-}
-
-static BOOL APIENTRY Imm32LoadImeInfo(PIMEINFOEX pImeInfoEx, PIMEDPI pImeDpi)
-{
-    WCHAR szPath[MAX_PATH];
-    HINSTANCE hIME;
-    FARPROC fn;
-
-    if (!Imm32GetSystemLibraryPath(szPath, _countof(szPath), 
pImeInfoEx->wszImeFile))
-        return FALSE;
-
-    hIME = GetModuleHandleW(szPath);
-    if (hIME == NULL)
-    {
-        hIME = LoadLibraryW(szPath);
-        if (hIME == NULL)
-        {
-            ERR("Imm32LoadImeInfo: LoadLibraryW(%S) failed\n", szPath);
-            return FALSE;
-        }
-    }
-    pImeDpi->hInst = hIME;
-
-#define DEFINE_IME_ENTRY(type, name, params, extended) \
-    do { \
-        fn = GetProcAddress(hIME, #name); \
-        if (fn) pImeDpi->name = (FN_##name)fn; \
-        else if (!extended) goto Failed; \
-    } while (0);
-#include "../../../win32ss/include/imetable.h"
-#undef DEFINE_IME_ENTRY
-
-    if (!Imm32InquireIme(pImeDpi))
-    {
-        ERR("Imm32LoadImeInfo: Imm32InquireIme failed\n");
-        goto Failed;
-    }
-
-    if (pImeInfoEx->fLoadFlag)
-        return TRUE;
-
-    NtUserSetImeOwnerWindow(pImeInfoEx, TRUE);
-    return TRUE;
-
-Failed:
-    FreeLibrary(pImeDpi->hInst);
-    pImeDpi->hInst = NULL;
-    return FALSE;
-}
-
-#ifdef IMP_SUPPORT /* 3.x support */
-static DWORD APIENTRY
-ImpJTransCompA(LPINPUTCONTEXTDX pIC, LPCOMPOSITIONSTRING pCS,
-               const TRANSMSG *pSrc, LPTRANSMSG pDest)
-{
-    // FIXME
-    *pDest = *pSrc;
-    return 1;
-}
-
-static DWORD APIENTRY
-ImpJTransCompW(LPINPUTCONTEXTDX pIC, LPCOMPOSITIONSTRING pCS,
-               const TRANSMSG *pSrc, LPTRANSMSG pDest)
-{
-    // FIXME
-    *pDest = *pSrc;
-    return 1;
-}
-
-typedef LRESULT (WINAPI *FN_SendMessage)(HWND, UINT, WPARAM, LPARAM);
-
-static DWORD APIENTRY
-ImpJTrans(DWORD dwCount, LPTRANSMSG pTrans, LPINPUTCONTEXTDX pIC,
-          LPCOMPOSITIONSTRING pCS, BOOL bAnsi)
-{
-    DWORD ret = 0;
-    HWND hWnd, hwndDefIME;
-    LPTRANSMSG pTempList, pEntry, pNext;
-    DWORD dwIndex, iCandForm, dwNumber, cbTempList;
-    HGLOBAL hGlobal;
-    CANDIDATEFORM CandForm;
-    FN_SendMessage pSendMessage;
-
-    hWnd = pIC->hWnd;
-    hwndDefIME = ImmGetDefaultIMEWnd(hWnd);
-    pSendMessage = (IsWindowUnicode(hWnd) ? SendMessageW : SendMessageA);
-
-    // clone the message list
-    cbTempList = (dwCount + 1) * sizeof(TRANSMSG);
-    pTempList = Imm32HeapAlloc(HEAP_ZERO_MEMORY, cbTempList);
-    if (pTempList == NULL)
-        return 0;
-    RtlCopyMemory(pTempList, pTrans, dwCount * sizeof(TRANSMSG));
-
-    if (pIC->dwUIFlags & 0x2)
-    {
-        // find WM_IME_ENDCOMPOSITION
-        pEntry = pTempList;
-        for (dwIndex = 0; dwIndex < dwCount; ++dwIndex, ++pEntry)
-        {
-            if (pEntry->message == WM_IME_ENDCOMPOSITION)
-                break;
-        }
-
-        if (pEntry->message == WM_IME_ENDCOMPOSITION) // if found
-        {
-            // move WM_IME_ENDCOMPOSITION to the end of the list
-            for (pNext = pEntry + 1; pNext->message != 0; ++pEntry, ++pNext)
-                *pEntry = *pNext;
-
-            pEntry->message = WM_IME_ENDCOMPOSITION;
-            pEntry->wParam = 0;
-            pEntry->lParam = 0;
-        }
-    }
-
-    for (pEntry = pTempList; pEntry->message != 0; ++pEntry)
-    {
-        switch (pEntry->message)
-        {
-            case WM_IME_STARTCOMPOSITION:
-                if (!(pIC->dwUIFlags & 0x2))
-                {
-                    // send IR_OPENCONVERT
-                    if (pIC->cfCompForm.dwStyle != CFS_DEFAULT)
-                        pSendMessage(hWnd, WM_IME_REPORT, IR_OPENCONVERT, 0);
-
-                    goto DoDefault;
-                }
-                break;
-
-            case WM_IME_ENDCOMPOSITION:
-                if (pIC->dwUIFlags & 0x2)
-                {
-                    // send IR_UNDETERMINE
-                    hGlobal = GlobalAlloc(GHND | GMEM_SHARE, 
sizeof(UNDETERMINESTRUCT));
-                    if (hGlobal)
-                    {
-                        pSendMessage(hWnd, WM_IME_REPORT, IR_UNDETERMINE, 
(LPARAM)hGlobal);
-                        GlobalFree(hGlobal);
-                    }
-                }
-                else
-                {
-                    // send IR_CLOSECONVERT
-                    if (pIC->cfCompForm.dwStyle != CFS_DEFAULT)
-                        pSendMessage(hWnd, WM_IME_REPORT, IR_CLOSECONVERT, 0);
-
-                    goto DoDefault;
-                }
-                break;
-
-            case WM_IME_COMPOSITION:
-                if (bAnsi)
-                    dwNumber = ImpJTransCompA(pIC, pCS, pEntry, pTrans);
-                else
-                    dwNumber = ImpJTransCompW(pIC, pCS, pEntry, pTrans);
-
-                ret += dwNumber;
-                pTrans += dwNumber;
-
-                // send IR_CHANGECONVERT
-                if (!(pIC->dwUIFlags & 0x2))
-                {
-                    if (pIC->cfCompForm.dwStyle != CFS_DEFAULT)
-                        pSendMessage(hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0);
-                }
-                break;
-
-            case WM_IME_NOTIFY:
-                if (pEntry->wParam == IMN_OPENCANDIDATE)
-                {
-                    if (IsWindow(hWnd) && (pIC->dwUIFlags & 0x2))
-                    {
-                        // send IMC_SETCANDIDATEPOS
-                        for (iCandForm = 0; iCandForm < MAX_CANDIDATEFORM; 
++iCandForm)
-                        {
-                            if (!(pEntry->lParam & (1 << iCandForm)))
-                                continue;
-
-                            CandForm.dwIndex = iCandForm;
-                            CandForm.dwStyle = CFS_EXCLUDE;
-                            CandForm.ptCurrentPos = 
pIC->cfCompForm.ptCurrentPos;
-                            CandForm.rcArea = pIC->cfCompForm.rcArea;
-                            pSendMessage(hwndDefIME, WM_IME_CONTROL, 
IMC_SETCANDIDATEPOS,
-                                         (LPARAM)&CandForm);
-                        }
-                    }
-                }
-
-                if (!(pIC->dwUIFlags & 0x2))
-                    goto DoDefault;
-
-                // send a WM_IME_NOTIFY notification to the default ime window
-                pSendMessage(hwndDefIME, pEntry->message, pEntry->wParam, 
pEntry->lParam);
-                break;
-
-DoDefault:
-            default:
-                // default processing
-                *pTrans++ = *pEntry;
-                ++ret;
-                break;
-        }
-    }
-
-    HeapFree(g_hImm32Heap, 0, pTempList);
-    return ret;
-}
-
-static DWORD APIENTRY
-ImpKTrans(DWORD dwCount, LPTRANSMSG pEntries, LPINPUTCONTEXTDX pIC,
-          LPCOMPOSITIONSTRING pCS, BOOL bAnsi)
-{
-    return dwCount; // FIXME
-}
-
-static DWORD APIENTRY
-ImpTrans(DWORD dwCount, LPTRANSMSG pEntries, HIMC hIMC, BOOL bAnsi, WORD wLang)
-{
-    BOOL ret = FALSE;
-    LPINPUTCONTEXTDX pIC;
-    LPCOMPOSITIONSTRING pCS;
-
-    pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
-    if (pIC == NULL)
-        return 0;
-
-    pCS = ImmLockIMCC(pIC->hCompStr);
-    if (pCS)
-    {
-        if (wLang == LANG_JAPANESE)
-            ret = ImpJTrans(dwCount, pEntries, pIC, pCS, bAnsi);
-        else if (wLang == LANG_KOREAN)
-            ret = ImpKTrans(dwCount, pEntries, pIC, pCS, bAnsi);
-        ImmUnlockIMCC(pIC->hCompStr);
-    }
-
-    ImmUnlockIMC(hIMC);
-    return ret;
-}
-#endif  /* def IMP_SUPPORT */
-
-static PIMEDPI APIENTRY Ime32LoadImeDpi(HKL hKL, BOOL bLock)
-{
-    IMEINFOEX ImeInfoEx;
-    CHARSETINFO ci;
-    PIMEDPI pImeDpiNew, pImeDpiFound;
-    UINT uCodePage;
-    LCID lcid;
-
-    if (!ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExKeyboardLayout, &hKL) ||
-        ImeInfoEx.fLoadFlag == 1)
-    {
-        return NULL;
-    }
-
-    pImeDpiNew = Imm32HeapAlloc(HEAP_ZERO_MEMORY, sizeof(IMEDPI));
-    if (pImeDpiNew == NULL)
-        return NULL;
-
-    pImeDpiNew->hKL = hKL;
-
-    lcid = LOWORD(hKL);
-    if (TranslateCharsetInfo((LPDWORD)(DWORD_PTR)lcid, &ci, TCI_SRCLOCALE))
-        uCodePage = ci.ciACP;
-    else
-        uCodePage = CP_ACP;
-    pImeDpiNew->uCodePage = uCodePage;
-
-    if (!Imm32LoadImeInfo(&ImeInfoEx, pImeDpiNew))
-    {
-        HeapFree(g_hImm32Heap, 0, pImeDpiNew);
-        return FALSE;
-    }
-
-    RtlEnterCriticalSection(&g_csImeDpi);
-
-    pImeDpiFound = Imm32FindImeDpi(hKL);
-    if (pImeDpiFound)
-    {
-        if (!bLock)
-            pImeDpiFound->dwFlags &= ~IMEDPI_FLAG_LOCKED;
-
-        RtlLeaveCriticalSection(&g_csImeDpi);
-
-        Imm32FreeImeDpi(pImeDpiNew, FALSE);
-        HeapFree(g_hImm32Heap, 0, pImeDpiNew);
-        return pImeDpiFound;
-    }
-    else
-    {
-        if (bLock)
-        {
-            pImeDpiNew->dwFlags |= IMEDPI_FLAG_LOCKED;
-            pImeDpiNew->cLockObj = 1;
-        }
-
-        pImeDpiNew->pNext = g_pImeDpiList;
-        g_pImeDpiList = pImeDpiNew;
-
-        RtlLeaveCriticalSection(&g_csImeDpi);
-        return pImeDpiNew;
-    }
-}
-
 /***********************************************************************
- *             ImmLoadIME (IMM32.@)
+ *             ImmRegisterClient(IMM32.@)
+ *       ( Undocumented, called from user32.dll )
  */
-BOOL WINAPI ImmLoadIME(HKL hKL)
-{
-    PW32CLIENTINFO pInfo;
-    PIMEDPI pImeDpi;
-
-    if (!IS_IME_HKL(hKL))
-    {
-        if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
-            return FALSE;
-
-        pInfo = (PW32CLIENTINFO)(NtCurrentTeb()->Win32ClientInfo);
-        if ((pInfo->W32ClientInfo[0] & 2))
-            return FALSE;
-    }
-
-    pImeDpi = Imm32FindImeDpi(hKL);
-    if (pImeDpi == NULL)
-        pImeDpi = Ime32LoadImeDpi(hKL, FALSE);
-    return (pImeDpi != NULL);
-}
-
-PIMEDPI APIENTRY ImmLockOrLoadImeDpi(HKL hKL)
+BOOL WINAPI ImmRegisterClient(PSHAREDINFO ptr, HINSTANCE hMod)
 {
-    PW32CLIENTINFO pInfo;
-    PIMEDPI pImeDpi;
-
-    if (!IS_IME_HKL(hKL))
-    {
-        if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
-            return NULL;
-
-        pInfo = (PW32CLIENTINFO)(NtCurrentTeb()->Win32ClientInfo);
-        if ((pInfo->W32ClientInfo[0] & 2))
-            return NULL;
-    }
-
-    pImeDpi = ImmLockImeDpi(hKL);
-    if (pImeDpi == NULL)
-        pImeDpi = Ime32LoadImeDpi(hKL, TRUE);
-    return pImeDpi;
+    g_SharedInfo = *ptr;
+    g_psi = g_SharedInfo.psi;
+    return Imm32InitInstance(hMod);
 }
 
 /***********************************************************************
@@ -730,7 +103,8 @@ HKL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx)
     return hKL;
 }
 
-typedef struct _tagImmHkl{
+typedef struct _tagImmHkl
+{
     struct list entry;
     HKL         hkl;
     HMODULE     hIME;
@@ -760,19 +134,20 @@ typedef struct _tagImmHkl{
 
 typedef struct tagInputContextData
 {
-        DWORD           dwLock;
-        INPUTCONTEXT    IMC;
-        DWORD           threadID;
-
-        ImmHkl          *immKbd;
-        UINT            lastVK;
-        BOOL            threadDefault;
-        DWORD           magic;
+    DWORD           dwLock;
+    INPUTCONTEXT    IMC;
+    DWORD           threadID;
+
+    ImmHkl          *immKbd;
+    UINT            lastVK;
+    BOOL            threadDefault;
+    DWORD           magic;
 } InputContextData;
 
 #define WINE_IMC_VALID_MAGIC 0x56434D49
 
-typedef struct _tagIMMThreadData {
+typedef struct _tagIMMThreadData
+{
     struct list entry;
     DWORD threadID;
     HIMC defaultContext;
@@ -790,18 +165,6 @@ static const WCHAR szImeFileW[] = {'I','m','e',' 
','F','i','l','e',0};
 static const WCHAR szLayoutTextW[] = {'L','a','y','o','u','t',' 
','T','e','x','t',0};
 static const WCHAR szImeRegFmt[] = 
{'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','K','e','y','b','o','a','r','d','
 ','L','a','y','o','u','t','s','\\','%','0','8','l','x',0};
 
-static const WCHAR szwIME[] = {'I','M','E',0};
-static const WCHAR szwDefaultIME[] = {'D','e','f','a','u','l','t',' 
','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 inline BOOL is_himc_ime_unicode(const InputContextData *data)
 {
     return !!(data->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE);
@@ -1038,7 +401,6 @@ HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
     return old;
 }
 
-
 /*
  * Helper function for ImmAssociateContextEx
  */
@@ -1087,8 +449,7 @@ BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, 
DWORD dwFlags)
 /***********************************************************************
  *             ImmConfigureIMEA (IMM32.@)
  */
-BOOL WINAPI ImmConfigureIMEA(
-  HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
+BOOL WINAPI ImmConfigureIMEA(HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
 {
     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
 
@@ -1122,8 +483,7 @@ BOOL WINAPI ImmConfigureIMEA(
 /***********************************************************************
  *             ImmConfigureIMEW (IMM32.@)
  */
-BOOL WINAPI ImmConfigureIMEW(
-  HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
+BOOL WINAPI ImmConfigureIMEW(HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
 {
     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
 
@@ -1285,232 +645,25 @@ BOOL WINAPI ImmDestroyContext(HIMC hIMC)
     return Imm32CleanupContext(hIMC, hKL, FALSE);
 }
 
-/***********************************************************************
- *             ImmDisableIME (IMM32.@)
- */
-BOOL WINAPI ImmDisableIME(DWORD dwThreadId)
+static inline BOOL EscapeRequiresWA(UINT uEscape)
 {
-    return NtUserDisableThreadIme(dwThreadId);
+    if (uEscape == IME_ESC_GET_EUDC_DICTIONARY ||
+        uEscape == IME_ESC_SET_EUDC_DICTIONARY ||
+        uEscape == IME_ESC_IME_NAME ||
+        uEscape == IME_ESC_GETHELPFILENAME)
+        return TRUE;
+    return FALSE;
 }
 
-/*
- * These functions absorb the difference between Ansi and Wide.
+/***********************************************************************
+ *             ImmEscapeA (IMM32.@)
  */
-typedef struct ENUM_WORD_A2W
-{
-    REGISTERWORDENUMPROCW lpfnEnumProc;
-    LPVOID lpData;
-    UINT ret;
-} ENUM_WORD_A2W, *LPENUM_WORD_A2W;
-
-typedef struct ENUM_WORD_W2A
-{
-    REGISTERWORDENUMPROCA lpfnEnumProc;
-    LPVOID lpData;
-    UINT ret;
-} ENUM_WORD_W2A, *LPENUM_WORD_W2A;
-
-static INT CALLBACK
-Imm32EnumWordProcA2W(LPCSTR pszReadingA, DWORD dwStyle, LPCSTR pszRegisterA, 
LPVOID lpData)
+LRESULT WINAPI ImmEscapeA(HKL hKL, HIMC hIMC, UINT uEscape, LPVOID lpData)
 {
-    INT ret = 0;
-    LPENUM_WORD_A2W lpEnumData = lpData;
-    LPWSTR pszReadingW = NULL, pszRegisterW = NULL;
-
-    if (pszReadingA)
-    {
-        pszReadingW = Imm32WideFromAnsi(pszReadingA);
-        if (pszReadingW == NULL)
-            goto Quit;
-    }
+    ImmHkl *immHkl = IMM_GetImmHkl(hKL);
+    TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
 
-    if (pszRegisterA)
-    {
-        pszRegisterW = Imm32WideFromAnsi(pszRegisterA);
-        if (pszRegisterW == NULL)
-            goto Quit;
-    }
-
-    ret = lpEnumData->lpfnEnumProc(pszReadingW, dwStyle, pszRegisterW, 
lpEnumData->lpData);
-    lpEnumData->ret = ret;
-
-Quit:
-    if (pszReadingW)
-        HeapFree(g_hImm32Heap, 0, pszReadingW);
-    if (pszRegisterW)
-        HeapFree(g_hImm32Heap, 0, pszRegisterW);
-    return ret;
-}
-
-static INT CALLBACK
-Imm32EnumWordProcW2A(LPCWSTR pszReadingW, DWORD dwStyle, LPCWSTR pszRegisterW, 
LPVOID lpData)
-{
-    INT ret = 0;
-    LPENUM_WORD_W2A lpEnumData = lpData;
-    LPSTR pszReadingA = NULL, pszRegisterA = NULL;
-
-    if (pszReadingW)
-    {
-        pszReadingA = Imm32AnsiFromWide(pszReadingW);
-        if (pszReadingW == NULL)
-            goto Quit;
-    }
-
-    if (pszRegisterW)
-    {
-        pszRegisterA = Imm32AnsiFromWide(pszRegisterW);
-        if (pszRegisterA == NULL)
-            goto Quit;
-    }
-
-    ret = lpEnumData->lpfnEnumProc(pszReadingA, dwStyle, pszRegisterA, 
lpEnumData->lpData);
-    lpEnumData->ret = ret;
-
-Quit:
-    if (pszReadingA)
-        HeapFree(g_hImm32Heap, 0, pszReadingA);
-    if (pszRegisterA)
-        HeapFree(g_hImm32Heap, 0, pszRegisterA);
-    return ret;
-}
-
-/***********************************************************************
- *             ImmEnumRegisterWordA (IMM32.@)
- */
-UINT WINAPI ImmEnumRegisterWordA(
-  HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
-  LPCSTR lpszReading, DWORD dwStyle,
-  LPCSTR lpszRegister, LPVOID lpData)
-{
-    UINT ret = 0;
-    LPWSTR pszReadingW = NULL, pszRegisterW = NULL;
-    ENUM_WORD_W2A EnumDataW2A;
-    PIMEDPI pImeDpi;
-
-    TRACE("(%p, %p, %s, 0x%lX, %s, %p)", hKL, lpfnEnumProc, 
debugstr_a(lpszReading),
-          dwStyle, debugstr_a(lpszRegister), lpData);
-
-    pImeDpi = ImmLockOrLoadImeDpi(hKL);
-    if (!pImeDpi)
-        return 0;
-
-    if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))
-    {
-        ret = pImeDpi->ImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
-                                           lpszRegister, lpData);
-        ImmUnlockImeDpi(pImeDpi);
-        return ret;
-    }
-
-    if (lpszReading)
-    {
-        pszReadingW = Imm32WideFromAnsi(lpszReading);
-        if (pszReadingW == NULL)
-            goto Quit;
-    }
-
-    if (lpszRegister)
-    {
-        pszRegisterW = Imm32WideFromAnsi(lpszRegister);
-        if (pszRegisterW == NULL)
-            goto Quit;
-    }
-
-    EnumDataW2A.lpfnEnumProc = lpfnEnumProc;
-    EnumDataW2A.lpData = lpData;
-    EnumDataW2A.ret = 0;
-    pImeDpi->ImeEnumRegisterWord(Imm32EnumWordProcW2A, pszReadingW, dwStyle,
-                                 pszRegisterW, &EnumDataW2A);
-    ret = EnumDataW2A.ret;
-
-Quit:
-    if (pszReadingW)
-        HeapFree(g_hImm32Heap, 0, pszReadingW);
-    if (pszRegisterW)
-        HeapFree(g_hImm32Heap, 0, pszRegisterW);
-    ImmUnlockImeDpi(pImeDpi);
-    return ret;
-}
-
-/***********************************************************************
- *             ImmEnumRegisterWordW (IMM32.@)
- */
-UINT WINAPI ImmEnumRegisterWordW(
-  HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
-  LPCWSTR lpszReading, DWORD dwStyle,
-  LPCWSTR lpszRegister, LPVOID lpData)
-{
-    UINT ret = 0;
-    LPSTR pszReadingA = NULL, pszRegisterA = NULL;
-    ENUM_WORD_A2W EnumDataA2W;
-    PIMEDPI pImeDpi;
-
-    TRACE("(%p, %p, %s, 0x%lX, %s, %p)", hKL, lpfnEnumProc, 
debugstr_w(lpszReading),
-          dwStyle, debugstr_w(lpszRegister), lpData);
-
-    pImeDpi = ImmLockOrLoadImeDpi(hKL);
-    if (!pImeDpi)
-        return 0;
-
-    if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
-    {
-        ret = pImeDpi->ImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
-                                           lpszRegister, lpData);
-        ImmUnlockImeDpi(pImeDpi);
-        return ret;
-    }
-
-    if (lpszReading)
-    {
-        pszReadingA = Imm32AnsiFromWide(lpszReading);
-        if (pszReadingA == NULL)
-            goto Quit;
-    }
-
-    if (lpszRegister)
-    {
-        pszRegisterA = Imm32AnsiFromWide(lpszRegister);
-        if (pszRegisterA == NULL)
-            goto Quit;
-    }
-
-    EnumDataA2W.lpfnEnumProc = lpfnEnumProc;
-    EnumDataA2W.lpData = lpData;
-    EnumDataA2W.ret = 0;
-    pImeDpi->ImeEnumRegisterWord(Imm32EnumWordProcA2W, pszReadingA, dwStyle,
-                                 pszRegisterA, &EnumDataA2W);
-    ret = EnumDataA2W.ret;
-
-Quit:
-    if (pszReadingA)
-        HeapFree(g_hImm32Heap, 0, pszReadingA);
-    if (pszRegisterA)
-        HeapFree(g_hImm32Heap, 0, pszRegisterA);
-    ImmUnlockImeDpi(pImeDpi);
-    return ret;
-}
-
-static inline BOOL EscapeRequiresWA(UINT uEscape)
-{
-        if (uEscape == IME_ESC_GET_EUDC_DICTIONARY ||
-            uEscape == IME_ESC_SET_EUDC_DICTIONARY ||
-            uEscape == IME_ESC_IME_NAME ||
-            uEscape == IME_ESC_GETHELPFILENAME)
-        return TRUE;
-    return FALSE;
-}
-
-/***********************************************************************
- *             ImmEscapeA (IMM32.@)
- */
-LRESULT WINAPI ImmEscapeA(
-  HKL hKL, HIMC hIMC,
-  UINT uEscape, LPVOID lpData)
-{
-    ImmHkl *immHkl = IMM_GetImmHkl(hKL);
-    TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
-
-    if (immHkl->hIME && immHkl->pImeEscape)
+    if (immHkl->hIME && immHkl->pImeEscape)
     {
         if (!EscapeRequiresWA(uEscape) || !is_kbd_ime_unicode(immHkl))
             return immHkl->pImeEscape(hIMC,uEscape,lpData);
@@ -1538,9 +691,7 @@ LRESULT WINAPI ImmEscapeA(
 /***********************************************************************
  *             ImmEscapeW (IMM32.@)
  */
-LRESULT WINAPI ImmEscapeW(
-  HKL hKL, HIMC hIMC,
-  UINT uEscape, LPVOID lpData)
+LRESULT WINAPI ImmEscapeW(HKL hKL, HIMC hIMC, UINT uEscape, LPVOID lpData)
 {
     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
     TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
@@ -1576,266 +727,6 @@ static PCLIENTIMC APIENTRY Imm32GetClientImcCache(void)
     return NULL;
 }
 
-static DWORD APIENTRY Imm32AllocAndBuildHimcList(DWORD dwThreadId, HIMC 
**pphList)
-{
-#define INITIAL_COUNT 0x40
-#define MAX_RETRY 10
-    NTSTATUS Status;
-    DWORD dwCount = INITIAL_COUNT, cRetry = 0;
-    HIMC *phNewList;
-
-    phNewList = Imm32HeapAlloc(0, dwCount * sizeof(HIMC));
-    if (phNewList == NULL)
-        return 0;
-
-    Status = NtUserBuildHimcList(dwThreadId, dwCount, phNewList, &dwCount);
-    while (Status == STATUS_BUFFER_TOO_SMALL)
-    {
-        HeapFree(g_hImm32Heap, 0, phNewList);
-        if (cRetry++ >= MAX_RETRY)
-            return 0;
-
-        phNewList = Imm32HeapAlloc(0, dwCount * sizeof(HIMC));
-        if (phNewList == NULL)
-            return 0;
-
-        Status = NtUserBuildHimcList(dwThreadId, dwCount, phNewList, &dwCount);
-    }
-
-    if (NT_ERROR(Status) || !dwCount)
-    {
-        HeapFree(g_hImm32Heap, 0, phNewList);
-        return 0;
-    }
-
-    *pphList = phNewList;
-    return dwCount;
-#undef INITIAL_COUNT
-#undef MAX_RETRY
-}
-
-static BOOL APIENTRY Imm32ImeNonImeToggle(HIMC hIMC, HKL hKL, HWND hWnd, 
LANGID LangID)
-{
-    LPINPUTCONTEXT pIC;
-    BOOL fOpen;
-
-    if (hWnd != NULL)
-        return FALSE;
-
-    if (!IS_IME_HKL(hKL) || LOWORD(hKL) != LangID)
-    {
-        FIXME("We have to do something here\n");
-        return TRUE;
-    }
-
-    pIC = ImmLockIMC(hIMC);
-    if (pIC == NULL)
-        return TRUE;
-
-    fOpen = pIC->fOpen;
-    ImmUnlockIMC(hIMC);
-
-    if (!fOpen)
-    {
-        ImmSetOpenStatus(hIMC, TRUE);
-        return TRUE;
-    }
-
-    FIXME("We have to do something here\n");
-    return TRUE;
-}
-
-static BOOL APIENTRY Imm32CShapeToggle(HIMC hIMC, HKL hKL, HWND hWnd)
-{
-    LPINPUTCONTEXT pIC;
-    BOOL fOpen;
-    DWORD dwConversion, dwSentence;
-
-    if (hWnd == NULL || !IS_IME_HKL(hKL))
-        return FALSE;
-
-    pIC = ImmLockIMC(hIMC);
-    if (pIC == NULL)
-        return TRUE;
-
-    fOpen = pIC->fOpen;
-    if (fOpen)
-    {
-        dwConversion = (pIC->fdwConversion ^ IME_CMODE_FULLSHAPE);
-        dwSentence = pIC->fdwSentence;
-    }
-
-    ImmUnlockIMC(hIMC);
-
-    if (fOpen)
-        ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
-    else
-        ImmSetOpenStatus(hIMC, TRUE);
-
-    return TRUE;
-}
-
-static BOOL APIENTRY Imm32CSymbolToggle(HIMC hIMC, HKL hKL, HWND hWnd)
-{
-    LPINPUTCONTEXT pIC;
-    BOOL fOpen;
-    DWORD dwConversion, dwSentence;
-
-    if (hWnd == NULL || !IS_IME_HKL(hKL))
-        return FALSE;
-
-    pIC = ImmLockIMC(hIMC);
-    if (pIC == NULL)
-        return TRUE;
-
-    fOpen = pIC->fOpen;
-    if (fOpen)
-    {
-        dwConversion = (pIC->fdwConversion ^ IME_CMODE_SYMBOL);
-        dwSentence = pIC->fdwSentence;
-    }
-
-    ImmUnlockIMC(hIMC);
-
-    if (fOpen)
-        ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
-    else
-        ImmSetOpenStatus(hIMC, TRUE);
-
-    return TRUE;
-}
-
-static BOOL APIENTRY Imm32JCloseOpen(HIMC hIMC, HKL hKL, HWND hWnd)
-{
-    BOOL fOpen;
-
-    if (ImmIsIME(hKL) && LOWORD(hKL) == LANGID_JAPANESE)
-    {
-        fOpen = ImmGetOpenStatus(hIMC);
-        ImmSetOpenStatus(hIMC, !fOpen);
-        return TRUE;
-    }
-
-    FIXME("We have to do something here\n");
-    return TRUE;
-}
-
-static BOOL APIENTRY Imm32KShapeToggle(HIMC hIMC)
-{
-    LPINPUTCONTEXT pIC;
-    DWORD dwConversion, dwSentence;
-
-    pIC = ImmLockIMC(hIMC);
-    if (pIC == NULL)
-        return FALSE;
-
-    dwConversion = (pIC->fdwConversion ^ IME_CMODE_FULLSHAPE);
-    dwSentence = pIC->fdwSentence;
-    ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
-
-    if (pIC->fdwConversion & (IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE))
-        ImmSetOpenStatus(hIMC, TRUE);
-    else
-        ImmSetOpenStatus(hIMC, FALSE);
-
-    ImmUnlockIMC(hIMC);
-    return TRUE;
-}
-
-static BOOL APIENTRY Imm32KHanjaConvert(HIMC hIMC)
-{
-    LPINPUTCONTEXT pIC;
-    DWORD dwConversion, dwSentence;
-
-    pIC = ImmLockIMC(hIMC);
-    if (!pIC)
-        return FALSE;
-
-    dwConversion = (pIC->fdwConversion ^ IME_CMODE_HANJACONVERT);
-    dwSentence = pIC->fdwSentence;
-    ImmUnlockIMC(hIMC);
-
-    ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
-    return TRUE;
-}
-
-static BOOL APIENTRY Imm32KEnglish(HIMC hIMC)
-{
-    LPINPUTCONTEXT pIC;
-    DWORD dwConversion, dwSentence;
-    BOOL fOpen;
-
-    pIC = ImmLockIMC(hIMC);
-    if (pIC == NULL)
-        return FALSE;
-
-    dwConversion = (pIC->fdwConversion ^ IME_CMODE_NATIVE);
-    dwSentence = pIC->fdwSentence;
-    ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
-
-    fOpen = ((pIC->fdwConversion & (IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE)) 
!= 0);
-    ImmSetOpenStatus(hIMC, fOpen);
-
-    ImmUnlockIMC(hIMC);
-    return TRUE;
-}
-
-static BOOL APIENTRY Imm32ProcessHotKey(HWND hWnd, HIMC hIMC, HKL hKL, DWORD 
dwHotKeyID)
-{
-    PIMEDPI pImeDpi;
-    BOOL ret;
-
-    if (hIMC && Imm32IsCrossThreadAccess(hIMC))
-        return FALSE;
-
-    switch (dwHotKeyID)
-    {
-        case IME_CHOTKEY_IME_NONIME_TOGGLE:
-            return Imm32ImeNonImeToggle(hIMC, hKL, hWnd, 
LANGID_CHINESE_SIMPLIFIED);
-
-        case IME_CHOTKEY_SHAPE_TOGGLE:
-            return Imm32CShapeToggle(hIMC, hKL, hWnd);
-
-        case IME_CHOTKEY_SYMBOL_TOGGLE:
-            return Imm32CSymbolToggle(hIMC, hKL, hWnd);
-
-        case IME_JHOTKEY_CLOSE_OPEN:
-            return Imm32JCloseOpen(hIMC, hKL, hWnd);
-
-        case IME_KHOTKEY_SHAPE_TOGGLE:
-            return Imm32KShapeToggle(hIMC);
-
-        case IME_KHOTKEY_HANJACONVERT:
-            return Imm32KHanjaConvert(hIMC);
-
-        case IME_KHOTKEY_ENGLISH:
-            return Imm32KEnglish(hIMC);
-
-        case IME_THOTKEY_IME_NONIME_TOGGLE:
-            return Imm32ImeNonImeToggle(hIMC, hKL, hWnd, 
LANGID_CHINESE_TRADITIONAL);
-
-        case IME_THOTKEY_SHAPE_TOGGLE:
-            return Imm32CShapeToggle(hIMC, hKL, hWnd);
-
-        case IME_THOTKEY_SYMBOL_TOGGLE:
-            return Imm32CSymbolToggle(hIMC, hKL, hWnd);
-
-        default:
-            break;
-    }
-
-    if (dwHotKeyID < IME_HOTKEY_PRIVATE_FIRST || IME_HOTKEY_PRIVATE_LAST < 
dwHotKeyID)
-        return FALSE;
-
-    pImeDpi = ImmLockImeDpi(hKL);
-    if (pImeDpi == NULL)
-        return FALSE;
-
-    ret = (BOOL)pImeDpi->ImeEscape(hIMC, IME_ESC_PRIVATE_HOTKEY, &dwHotKeyID);
-    ImmUnlockImeDpi(pImeDpi);
-    return ret;
-}
-
 /***********************************************************************
  *             ImmLockClientImc (IMM32.@)
  */
@@ -1934,671 +825,210 @@ Quit:
     return hIMC;
 }
 
-static DWORD APIENTRY
-CandidateListWideToAnsi(const CANDIDATELIST *pWideCL, LPCANDIDATELIST pAnsiCL, 
DWORD dwBufLen,
-                        UINT uCodePage)
+
+/* Helpers for the GetCompositionString functions */
+
+/* Source encoding is defined by context, source length is always given in 
respective characters. Destination buffer
+   length is always in bytes. */
+static INT
+CopyCompStringIMEtoClient(const InputContextData *data, const void *src, INT 
src_len, void *dst,
+                          INT dst_len, BOOL unicode)
 {
-    BOOL bUsedDefault;
-    DWORD dwSize, dwIndex, cbGot, cbLeft;
-    const BYTE *pbWide;
-    LPBYTE pbAnsi;
-    LPDWORD pibOffsets;
-
-    /* calculate total ansi size */
-    if (pWideCL->dwCount > 0)
+    int char_size = unicode ? sizeof(WCHAR) : sizeof(char);
+    INT ret;
+
+    if (is_himc_ime_unicode(data) ^ unicode)
     {
-        dwSize = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * 
sizeof(DWORD));
-        for (dwIndex = 0; dwIndex < pWideCL->dwCount; ++dwIndex)
-        {
-            pbWide = (const BYTE *)pWideCL + pWideCL->dwOffset[dwIndex];
-            cbGot = WideCharToMultiByte(uCodePage, 0, (LPCWSTR)pbWide, -1, 
NULL, 0,
-                                        NULL, &bUsedDefault);
-            dwSize += cbGot;
-        }
+        if (unicode)
+            ret = MultiByteToWideChar(CP_ACP, 0, src, src_len, dst, dst_len / 
sizeof(WCHAR));
+        else
+            ret = WideCharToMultiByte(CP_ACP, 0, src, src_len, dst, dst_len, 
NULL, NULL);
+        ret *= char_size;
     }
     else
     {
-        dwSize = sizeof(CANDIDATELIST);
+        if (dst_len)
+        {
+            ret = min(src_len * char_size, dst_len);
+            memcpy(dst, src, ret);
+        }
+        else
+            ret = src_len * char_size;
     }
 
-    dwSize = ROUNDUP4(dwSize);
-    if (dwBufLen == 0)
-        return dwSize;
-    if (dwBufLen < dwSize)
-        return 0;
-
-    /* store to ansi */
-    pAnsiCL->dwSize = dwBufLen;
-    pAnsiCL->dwStyle = pWideCL->dwStyle;
-    pAnsiCL->dwCount = pWideCL->dwCount;
-    pAnsiCL->dwSelection = pWideCL->dwSelection;
-    pAnsiCL->dwPageStart = pWideCL->dwPageStart;
-    pAnsiCL->dwPageSize = pWideCL->dwPageSize;
+    return ret;
+}
 
-    pibOffsets = pAnsiCL->dwOffset;
-    if (pWideCL->dwCount > 0)
+/* Composition string encoding is defined by context, returned attributes 
correspond to string, converted according to
+   passed mode. String length is in characters, attributes are in byte arrays. 
*/
+static INT
+CopyCompAttrIMEtoClient(const InputContextData *data, const BYTE *src, INT 
src_len, const void *comp_string,
+                        INT str_len, BYTE *dst, INT dst_len, BOOL unicode)
+{
+    union
     {
-        pibOffsets[0] = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * 
sizeof(DWORD));
-        cbLeft = dwBufLen - pibOffsets[0];
-
-        for (dwIndex = 0; dwIndex < pWideCL->dwCount; ++dwIndex)
-        {
-            pbWide = (const BYTE *)pWideCL + pWideCL->dwOffset[dwIndex];
-            pbAnsi = (LPBYTE)pAnsiCL + pibOffsets[dwIndex];
+        const void *str;
+        const WCHAR *strW;
+        const char *strA;
+    } string;
+    INT rc;
 
-            /* convert to ansi */
-            cbGot = WideCharToMultiByte(uCodePage, 0, (LPCWSTR)pbWide, -1,
-                                        (LPSTR)pbAnsi, cbLeft, NULL, 
&bUsedDefault);
-            cbLeft -= cbGot;
+    string.str = comp_string;
 
-            if (dwIndex < pWideCL->dwCount - 1)
-                pibOffsets[dwIndex + 1] = pibOffsets[dwIndex] + cbGot;
-        }
-    }
-    else
+    if (is_himc_ime_unicode(data) && !unicode)
     {
-        pibOffsets[0] = sizeof(CANDIDATELIST);
-    }
+        rc = WideCharToMultiByte(CP_ACP, 0, string.strW, str_len, NULL, 0, 
NULL, NULL);
+        if (dst_len)
+        {
+            int i, j = 0, k = 0;
 
-    return dwBufLen;
-}
+            if (rc < dst_len)
+                dst_len = rc;
+            for (i = 0; i < str_len; ++i)
+            {
+                int len;
 
-static DWORD APIENTRY
-CandidateListAnsiToWide(const CANDIDATELIST *pAnsiCL, LPCANDIDATELIST pWideCL, 
DWORD dwBufLen,
-                        UINT uCodePage)
-{
-    DWORD dwSize, dwIndex, cchGot, cbGot, cbLeft;
-    const BYTE *pbAnsi;
-    LPBYTE pbWide;
-    LPDWORD pibOffsets;
+                len = WideCharToMultiByte(CP_ACP, 0, string.strW + i, 1, NULL, 
0, NULL, NULL);
+                for (; len > 0; --len)
+                {
+                    dst[j++] = src[k];
 
-    /* calculate total wide size */
-    if (pAnsiCL->dwCount > 0)
-    {
-        dwSize = sizeof(CANDIDATELIST) + ((pAnsiCL->dwCount - 1) * 
sizeof(DWORD));
-        for (dwIndex = 0; dwIndex < pAnsiCL->dwCount; ++dwIndex)
-        {
-            pbAnsi = (const BYTE *)pAnsiCL + pAnsiCL->dwOffset[dwIndex];
-            cchGot = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, 
(LPCSTR)pbAnsi, -1, NULL, 0);
-            dwSize += cchGot * sizeof(WCHAR);
+                    if (j >= dst_len)
+                        goto end;
+                }
+                ++k;
+            }
+        end:
+            rc = j;
         }
     }
-    else
-    {
-        dwSize = sizeof(CANDIDATELIST);
-    }
-
-    dwSize = ROUNDUP4(dwSize);
-    if (dwBufLen == 0)
-        return dwSize;
-    if (dwBufLen < dwSize)
-        return 0;
-
-    /* store to wide */
-    pWideCL->dwSize = dwBufLen;
-    pWideCL->dwStyle = pAnsiCL->dwStyle;
-    pWideCL->dwCount = pAnsiCL->dwCount;
-    pWideCL->dwSelection = pAnsiCL->dwSelection;
-    pWideCL->dwPageStart = pAnsiCL->dwPageStart;
-    pWideCL->dwPageSize = pAnsiCL->dwPageSize;
-
-    pibOffsets = pWideCL->dwOffset;
-    if (pAnsiCL->dwCount > 0)
+    else if (!is_himc_ime_unicode(data) && unicode)
     {
-        pibOffsets[0] = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * 
sizeof(DWORD));
-        cbLeft = dwBufLen - pibOffsets[0];
-
-        for (dwIndex = 0; dwIndex < pAnsiCL->dwCount; ++dwIndex)
+        rc = MultiByteToWideChar(CP_ACP, 0, string.strA, str_len, NULL, 0);
+        if (dst_len)
         {
-            pbAnsi = (const BYTE *)pAnsiCL + pAnsiCL->dwOffset[dwIndex];
-            pbWide = (LPBYTE)pWideCL + pibOffsets[dwIndex];
+            int i, j = 0;
+
+            if (rc < dst_len)
+                dst_len = rc;
+            for (i = 0; i < str_len; ++i)
+            {
+                if (IsDBCSLeadByte(string.strA[i]))
+                    continue;
 
-            /* convert to wide */
-            cchGot = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, 
(LPCSTR)pbAnsi, -1,
-                                         (LPWSTR)pbWide, cbLeft / 
sizeof(WCHAR));
-            cbGot = cchGot * sizeof(WCHAR);
-            cbLeft -= cbGot;
+                dst[j++] = src[i];
 
-            if (dwIndex + 1 < pAnsiCL->dwCount)
-                pibOffsets[dwIndex + 1] = pibOffsets[dwIndex] + cbGot;
+                if (j >= dst_len)
+                    break;
+            }
+            rc = j;
         }
     }
     else
     {
-        pibOffsets[0] = sizeof(CANDIDATELIST);
+        memcpy(dst, src, min(src_len, dst_len));
+        rc = src_len;
     }
 
-    return dwBufLen;
+    return rc;
 }
 
-static DWORD APIENTRY
-ImmGetCandidateListAW(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, 
DWORD dwBufLen,
-                      BOOL bAnsi)
+static INT
+CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, 
LPBYTE ssource,
+                          LPBYTE target, INT tlen, BOOL unicode )
 {
-    DWORD ret = 0;
-    LPINPUTCONTEXT pIC;
-    PCLIENTIMC pClientImc;
-    LPCANDIDATEINFO pCI;
-    LPCANDIDATELIST pCL;
-    DWORD dwSize;
-
-    pClientImc = ImmLockClientImc(hIMC);
-    if (!pClientImc)
-        return 0;
-
-    pIC = ImmLockIMC(hIMC);
-    if (pIC == NULL)
-    {
-        ImmUnlockClientImc(pClientImc);
-        return 0;
-    }
-
-    pCI = ImmLockIMCC(pIC->hCandInfo);
-    if (pCI == NULL)
-    {
-        ImmUnlockIMC(hIMC);
-        ImmUnlockClientImc(pClientImc);
-        return 0;
-    }
-
-    if (pCI->dwSize < sizeof(CANDIDATEINFO) || pCI->dwCount <= dwIndex)
-        goto Quit;
-
-    /* get required size */
-    pCL = (LPCANDIDATELIST)((LPBYTE)pCI + pCI->dwOffset[dwIndex]);
-    if (bAnsi)
-    {
-        if (pClientImc->dwFlags & CLIENTIMC_WIDE)
-            dwSize = CandidateListAnsiToWide(pCL, NULL, 0, CP_ACP);
-        else
-            dwSize = pCL->dwSize;
-    }
-    else
-    {
-        if (pClientImc->dwFlags & CLIENTIMC_WIDE)
-            dwSize = pCL->dwSize;
-        else
-            dwSize = CandidateListWideToAnsi(pCL, NULL, 0, CP_ACP);
-    }
+    INT rc;
 
-    if (dwBufLen != 0 && dwSize != 0)
+    if (is_himc_ime_unicode(data) && !unicode)
     {
-        if (lpCandList == NULL || dwBufLen < dwSize)
-            goto Quit;
-
-        /* store */
-        if (bAnsi)
+        if (tlen)
         {
-            if (pClientImc->dwFlags & CLIENTIMC_WIDE)
-                CandidateListAnsiToWide(pCL, lpCandList, dwSize, CP_ACP);
-            else
-                RtlCopyMemory(lpCandList, pCL, dwSize);
+            int i;
+
+            if (slen < tlen)
+                tlen = slen;
+            tlen /= sizeof (DWORD);
+            for (i = 0; i < tlen; ++i)
+            {
+                ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, 
(LPWSTR)ssource,
+                                                          ((DWORD *)source)[i],
+                                                          NULL, 0,
+                                                          NULL, NULL);
+            }
+            rc = sizeof (DWORD) * i;
         }
         else
-        {
-            if (pClientImc->dwFlags & CLIENTIMC_WIDE)
-                RtlCopyMemory(lpCandList, pCL, dwSize);
-            else
-                CandidateListWideToAnsi(pCL, lpCandList, dwSize, CP_ACP);
-        }
-    }
-
-    ret = dwSize;
-
-Quit:
-    ImmUnlockIMCC(pIC->hCandInfo);
-    ImmUnlockIMC(hIMC);
-    ImmUnlockClientImc(pClientImc);
-    return ret;
-}
-
-DWORD APIENTRY ImmGetCandidateListCountAW(HIMC hIMC, LPDWORD lpdwListCount, 
BOOL bAnsi)
-{
-    DWORD ret = 0, cbGot, dwIndex;
-    PCLIENTIMC pClientImc;
-    LPINPUTCONTEXT pIC;
-    const CANDIDATEINFO *pCI;
-    const BYTE *pb;
-    const CANDIDATELIST *pCL;
-    const DWORD *pdwOffsets;
-
-    if (lpdwListCount == NULL)
-        return 0;
-
-    *lpdwListCount = 0;
-
-    pClientImc = ImmLockClientImc(hIMC);
-    if (pClientImc == NULL)
-        return 0;
-
-    pIC = ImmLockIMC(hIMC);
-    if (pIC == NULL)
-    {
-        ImmUnlockClientImc(pClientImc);
-        return 0;
-    }
-
-    pCI = ImmLockIMCC(pIC->hCandInfo);
-    if (pCI == NULL)
-    {
-        ImmUnlockIMC(hIMC);
-        ImmUnlockClientImc(pClientImc);
-        return 0;
+            rc = slen;
     }
-
-    if (pCI->dwSize < sizeof(CANDIDATEINFO))
-        goto Quit;
-
-    *lpdwListCount = pCI->dwCount; /* the number of candidate lists */
-
-    /* calculate total size of candidate lists */
-    if (bAnsi)
+    else if (!is_himc_ime_unicode(data) && unicode)
     {
-        if (pClientImc->dwFlags & CLIENTIMC_WIDE)
+        if (tlen)
         {
-            ret = ROUNDUP4(pCI->dwPrivateSize);
-            pdwOffsets = pCI->dwOffset;
-            for (dwIndex = 0; dwIndex < pCI->dwCount; ++dwIndex)
+            int i;
+
+            if (slen < tlen)
+                tlen = slen;
+            tlen /= sizeof (DWORD);
+            for (i = 0; i < tlen; ++i)
             {
-                pb = (const BYTE *)pCI + pdwOffsets[dwIndex];
-                pCL = (const CANDIDATELIST *)pb;
-                cbGot = CandidateListWideToAnsi(pCL, NULL, 0, CP_ACP);
-                ret += cbGot;
+                ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, 
(LPSTR)ssource,
+                                                          ((DWORD *)source)[i],
+                                                          NULL, 0);
             }
+            rc = sizeof (DWORD) * i;
         }
         else
-        {
-            ret = pCI->dwSize;
-        }
+            rc = slen;
     }
     else
     {
-        if (pClientImc->dwFlags & CLIENTIMC_WIDE)
-        {
-            ret = pCI->dwSize;
-        }
-        else
-        {
-            ret = ROUNDUP4(pCI->dwPrivateSize);
-            pdwOffsets = pCI->dwOffset;
-            for (dwIndex = 0; dwIndex < pCI->dwCount; ++dwIndex)
-            {
-                pb = (const BYTE *)pCI + pdwOffsets[dwIndex];
-                pCL = (const CANDIDATELIST *)pb;
-                cbGot = CandidateListAnsiToWide(pCL, NULL, 0, CP_ACP);
-                ret += cbGot;
-            }
-        }
+        memcpy( target, source, min(slen,tlen));
+        rc = slen;
     }
 
-Quit:
-    ImmUnlockIMCC(pIC->hCandInfo);
-    ImmUnlockIMC(hIMC);
-    ImmUnlockClientImc(pClientImc);
-    return ret;
-}
-
-/***********************************************************************
- *             ImmGetCandidateListA (IMM32.@)
- */
-DWORD WINAPI ImmGetCandidateListA(
-  HIMC hIMC, DWORD dwIndex,
-  LPCANDIDATELIST lpCandList, DWORD dwBufLen)
-{
-    return ImmGetCandidateListAW(hIMC, dwIndex, lpCandList, dwBufLen, TRUE);
-}
-
-/***********************************************************************
- *             ImmGetCandidateListCountA (IMM32.@)
- */
-DWORD WINAPI ImmGetCandidateListCountA(
-  HIMC hIMC, LPDWORD lpdwListCount)
-{
-    return ImmGetCandidateListCountAW(hIMC, lpdwListCount, TRUE);
-}
-
-/***********************************************************************
- *             ImmGetCandidateListCountW (IMM32.@)
- */
-DWORD WINAPI ImmGetCandidateListCountW(
-  HIMC hIMC, LPDWORD lpdwListCount)
-{
-    return ImmGetCandidateListCountAW(hIMC, lpdwListCount, FALSE);
-}
-
-/***********************************************************************
- *             ImmGetCandidateListW (IMM32.@)
- */
-DWORD WINAPI ImmGetCandidateListW(
-  HIMC hIMC, DWORD dwIndex,
-  LPCANDIDATELIST lpCandList, DWORD dwBufLen)
-{
-    return ImmGetCandidateListAW(hIMC, dwIndex, lpCandList, dwBufLen, FALSE);
+    return rc;
 }
 
-/***********************************************************************
- *             ImmGetCandidateWindow (IMM32.@)
- */
-BOOL WINAPI ImmGetCandidateWindow(
-  HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
+static INT
+CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE 
ssource, BOOL unicode)
 {
-    BOOL ret = FALSE;
-    LPINPUTCONTEXT pIC;
-    LPCANDIDATEFORM pCF;
-
-    TRACE("(%p, %lu, %p)\n", hIMC, dwIndex, lpCandidate);
-
-    pIC = ImmLockIMC(hIMC);
-    if (pIC  == NULL)
-        return FALSE;
+    int rc;
 
-    pCF = &pIC->cfCandForm[dwIndex];
-    if (pCF->dwIndex != IMM_INVALID_CANDFORM)
+    if (is_himc_ime_unicode(data) && !unicode)
     {
-        *lpCandidate = *pCF;
-        ret = TRUE;
+        rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, 
NULL, NULL);
     }
+    else if (!is_himc_ime_unicode(data) && unicode)
+    {
+        rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0);
+    }
+    else
+        rc = offset;
 
-    ImmUnlockIMC(hIMC);
-    return ret;
-}
-
-static VOID APIENTRY LogFontAnsiToWide(const LOGFONTA *plfA, LPLOGFONTW plfW)
-{
-    size_t cch;
-    RtlCopyMemory(plfW, plfA, offsetof(LOGFONTA, lfFaceName));
-    StringCchLengthA(plfA->lfFaceName, _countof(plfA->lfFaceName), &cch);
-    cch = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, plfA->lfFaceName, 
(INT)cch,
-                              plfW->lfFaceName, _countof(plfW->lfFaceName));
-    if (cch > _countof(plfW->lfFaceName) - 1)
-        cch = _countof(plfW->lfFaceName) - 1;
-    plfW->lfFaceName[cch] = 0;
-}
-
-static VOID APIENTRY LogFontWideToAnsi(const LOGFONTW *plfW, LPLOGFONTA plfA)
-{
-    size_t cch;
-    RtlCopyMemory(plfA, plfW, offsetof(LOGFONTW, lfFaceName));
-    StringCchLengthW(plfW->lfFaceName, _countof(plfW->lfFaceName), &cch);
-    cch = WideCharToMultiByte(CP_ACP, 0, plfW->lfFaceName, (INT)cch,
-                              plfA->lfFaceName, _countof(plfA->lfFaceName), 
NULL, NULL);
-    if (cch > _countof(plfA->lfFaceName) - 1)
-        cch = _countof(plfA->lfFaceName) - 1;
-    plfA->lfFaceName[cch] = 0;
+    return rc;
 }
 
-/***********************************************************************
- *             ImmGetCompositionFontA (IMM32.@)
- */
-BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
+static LONG
+ImmGetCompositionStringT(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf,
+                         DWORD dwBufLen, BOOL unicode)
 {
-    PCLIENTIMC pClientImc;
-    BOOL ret = FALSE, bWide;
-    LPINPUTCONTEXT pIC;
+    LONG rc = 0;
+    InputContextData *data = get_imc_data(hIMC);
+    LPCOMPOSITIONSTRING compstr;
+    LPBYTE compdata;
 
-    TRACE("(%p, %p)\n", hIMC, lplf);
+    TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
 
-    pClientImc = ImmLockClientImc(hIMC);
-    if (pClientImc == NULL)
-        return FALSE;
+    if (!data)
+       return FALSE;
 
-    bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
-    ImmUnlockClientImc(pClientImc);
+    if (!data->IMC.hCompStr)
+       return FALSE;
 
-    pIC = ImmLockIMC(hIMC);
-    if (pIC == NULL)
-        return FALSE;
+    compdata = ImmLockIMCC(data->IMC.hCompStr);
+    compstr = (LPCOMPOSITIONSTRING)compdata;
 
-    if (pIC->fdwInit & INIT_LOGFONT)
-    {
-        if (bWide)
-            LogFontWideToAnsi(&pIC->lfFont.W, lplf);
-        else
-            *lplf = pIC->lfFont.A;
-
-        ret = TRUE;
-    }
-
-    ImmUnlockIMC(hIMC);
-    return ret;
-}
-
-/***********************************************************************
- *             ImmGetCompositionFontW (IMM32.@)
- */
-BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
-{
-    PCLIENTIMC pClientImc;
-    BOOL bWide;
-    LPINPUTCONTEXT pIC;
-    BOOL ret = FALSE;
-
-    TRACE("(%p, %p)\n", hIMC, lplf);
-
-    pClientImc = ImmLockClientImc(hIMC);
-    if (pClientImc == NULL)
-        return FALSE;
-
-    bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
-    ImmUnlockClientImc(pClientImc);
-
-    pIC = ImmLockIMC(hIMC);
-    if (pIC == NULL)
-        return FALSE;
-
-    if (pIC->fdwInit & INIT_LOGFONT)
-    {
-        if (bWide)
-            *lplf = pIC->lfFont.W;
-        else
-            LogFontAnsiToWide(&pIC->lfFont.A, lplf);
-
-        ret = TRUE;
-    }
-
-    ImmUnlockIMC(hIMC);
-    return ret;
-}
-
-
-/* Helpers for the GetCompositionString functions */
-
-/* Source encoding is defined by context, source length is always given in 
respective characters. Destination buffer
-   length is always in bytes. */
-static INT CopyCompStringIMEtoClient(const InputContextData *data, const void 
*src, INT src_len, void *dst,
-        INT dst_len, BOOL unicode)
-{
-    int char_size = unicode ? sizeof(WCHAR) : sizeof(char);
-    INT ret;
-
-    if (is_himc_ime_unicode(data) ^ unicode)
-    {
-        if (unicode)
-            ret = MultiByteToWideChar(CP_ACP, 0, src, src_len, dst, dst_len / 
sizeof(WCHAR));
-        else
-            ret = WideCharToMultiByte(CP_ACP, 0, src, src_len, dst, dst_len, 
NULL, NULL);
-        ret *= char_size;
-    }
-    else
-    {
-        if (dst_len)
-        {
-            ret = min(src_len * char_size, dst_len);
-            memcpy(dst, src, ret);
-        }
-        else
-            ret = src_len * char_size;
-    }
-
-    return ret;
-}
-
-/* Composition string encoding is defined by context, returned attributes 
correspond to string, converted according to
-   passed mode. String length is in characters, attributes are in byte arrays. 
*/
-static INT CopyCompAttrIMEtoClient(const InputContextData *data, const BYTE 
*src, INT src_len, const void *comp_string,
-        INT str_len, BYTE *dst, INT dst_len, BOOL unicode)
-{
-    union
-    {
-        const void *str;
-        const WCHAR *strW;
-        const char *strA;
-    } string;
-    INT rc;
-
-    string.str = comp_string;
-
-    if (is_himc_ime_unicode(data) && !unicode)
-    {
-        rc = WideCharToMultiByte(CP_ACP, 0, string.strW, str_len, NULL, 0, 
NULL, NULL);
-        if (dst_len)
-        {
-            int i, j = 0, k = 0;
-
-            if (rc < dst_len)
-                dst_len = rc;
-            for (i = 0; i < str_len; ++i)
-            {
-                int len;
-
-                len = WideCharToMultiByte(CP_ACP, 0, string.strW + i, 1, NULL, 
0, NULL, NULL);
-                for (; len > 0; --len)
-                {
-                    dst[j++] = src[k];
-
-                    if (j >= dst_len)
-                        goto end;
-                }
-                ++k;
-            }
-        end:
-            rc = j;
-        }
-    }
-    else if (!is_himc_ime_unicode(data) && unicode)
-    {
-        rc = MultiByteToWideChar(CP_ACP, 0, string.strA, str_len, NULL, 0);
-        if (dst_len)
-        {
-            int i, j = 0;
-
-            if (rc < dst_len)
-                dst_len = rc;
-            for (i = 0; i < str_len; ++i)
-            {
-                if (IsDBCSLeadByte(string.strA[i]))
-                    continue;
-
-                dst[j++] = src[i];
-
-                if (j >= dst_len)
-                    break;
-            }
-            rc = j;
-        }
-    }
-    else
-    {
-        memcpy(dst, src, min(src_len, dst_len));
-        rc = src_len;
-    }
-
-    return rc;
-}
-
-static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, 
INT slen, LPBYTE ssource,
-                                     LPBYTE target, INT tlen, BOOL unicode )
-{
-    INT rc;
-
-    if (is_himc_ime_unicode(data) && !unicode)
-    {
-        if (tlen)
-        {
-            int i;
-
-            if (slen < tlen)
-                tlen = slen;
-            tlen /= sizeof (DWORD);
-            for (i = 0; i < tlen; ++i)
-            {
-                ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, 
(LPWSTR)ssource,
-                                                          ((DWORD *)source)[i],
-                                                          NULL, 0,
-                                                          NULL, NULL);
-            }
-            rc = sizeof (DWORD) * i;
-        }
-        else
-            rc = slen;
-    }
-    else if (!is_himc_ime_unicode(data) && unicode)
-    {
-        if (tlen)
-        {
-            int i;
-
-            if (slen < tlen)
-                tlen = slen;
-            tlen /= sizeof (DWORD);
-            for (i = 0; i < tlen; ++i)
-            {
-                ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, 
(LPSTR)ssource,
-                                                          ((DWORD *)source)[i],
-                                                          NULL, 0);
-            }
-            rc = sizeof (DWORD) * i;
-        }
-        else
-            rc = slen;
-    }
-    else
-    {
-        memcpy( target, source, min(slen,tlen));
-        rc = slen;
-    }
-
-    return rc;
-}
-
-static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, 
LPBYTE ssource, BOOL unicode)
-{
-    int rc;
-
-    if (is_himc_ime_unicode(data) && !unicode)
-    {
-        rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, 
NULL, NULL);
-    }
-    else if (!is_himc_ime_unicode(data) && unicode)
-    {
-        rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0);
-    }
-    else
-        rc = offset;
-
-    return rc;
-}
-
-static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf,
-                                      DWORD dwBufLen, BOOL unicode)
-{
-    LONG rc = 0;
-    InputContextData *data = get_imc_data(hIMC);
-    LPCOMPOSITIONSTRING compstr;
-    LPBYTE compdata;
-
-    TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
-
-    if (!data)
-       return FALSE;
-
-    if (!data->IMC.hCompStr)
-       return FALSE;
-
-    compdata = ImmLockIMCC(data->IMC.hCompStr);
-    compstr = (LPCOMPOSITIONSTRING)compdata;
-
-    switch (dwIndex)
+    switch (dwIndex)
     {
     case GCS_RESULTSTR:
         TRACE("GCS_RESULTSTR\n");
@@ -2673,47 +1103,19 @@ static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD 
dwIndex, LPVOID lpBuf,
 /***********************************************************************
  *             ImmGetCompositionStringA (IMM32.@)
  */
-LONG WINAPI ImmGetCompositionStringA(
-  HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
+LONG WINAPI ImmGetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, 
DWORD dwBufLen)
 {
     return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
 }
 
-
 /***********************************************************************
  *             ImmGetCompositionStringW (IMM32.@)
  */
-LONG WINAPI ImmGetCompositionStringW(
-  HIMC hIMC, DWORD dwIndex,
-  LPVOID lpBuf, DWORD dwBufLen)
+LONG WINAPI ImmGetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, 
DWORD dwBufLen)
 {
     return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
 }
 
-/***********************************************************************
- *             ImmGetCompositionWindow (IMM32.@)
- */
-BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
-{
-    LPINPUTCONTEXT pIC;
-    BOOL ret = FALSE;
-
-    TRACE("(%p, %p)\n", hIMC, lpCompForm);
-
-    pIC = ImmLockIMC(hIMC);
-    if (!pIC)
-        return FALSE;
-
-    if (pIC->fdwInit & INIT_COMPFORM)
-    {
-        *lpCompForm = pIC->cfCompForm;
-        ret = TRUE;
-    }
-
-    ImmUnlockIMC(hIMC);
-    return ret;
-}
-
 /***********************************************************************
  *             ImmGetContext (IMM32.@)
  */
@@ -2726,1806 +1128,96 @@ HIMC WINAPI ImmGetContext(HWND hWnd)
 }
 
 /***********************************************************************
- *             ImmGetConversionListA (IMM32.@)
+ *             CtfImmIsCiceroEnabled (IMM32.@)
  */
-DWORD WINAPI ImmGetConversionListA(
-  HKL hKL, HIMC hIMC,
-  LPCSTR pSrc, LPCANDIDATELIST lpDst,
-  DWORD dwBufLen, UINT uFlag)
+BOOL WINAPI CtfImmIsCiceroEnabled(VOID)
 {
-    DWORD ret = 0;
-    UINT cb;
-    LPWSTR pszSrcW = NULL;
-    LPCANDIDATELIST pCL = NULL;
-    PIMEDPI pImeDpi;
-
-    TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL, hIMC, debugstr_a(pSrc),
-          lpDst, dwBufLen, uFlag);
-
-    pImeDpi = ImmLockOrLoadImeDpi(hKL);
-    if (pImeDpi == NULL)
-        return 0;
+    return (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED));
+}
 
-    if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))
-    {
-        ret = pImeDpi->ImeConversionList(hIMC, pSrc, lpDst, dwBufLen, uFlag);
-        ImmUnlockImeDpi(pImeDpi);
-        return ret;
-    }
+/***********************************************************************
+ *             ImmInstallIMEA (IMM32.@)
+ */
+HKL WINAPI ImmInstallIMEA(LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
+{
+    HKL hKL = NULL;
+    LPWSTR pszFileNameW = NULL, pszLayoutTextW = NULL;
 
-    if (pSrc)
-    {
-        pszSrcW = Imm32WideFromAnsi(pSrc);
-        if (pszSrcW == NULL)
-            goto Quit;
-    }
+    TRACE("(%s, %s)\n", debugstr_a(lpszIMEFileName), 
debugstr_a(lpszLayoutText));
 
-    cb = pImeDpi->ImeConversionList(hIMC, pszSrcW, NULL, 0, uFlag);
-    if (cb == 0)
+    pszFileNameW = Imm32WideFromAnsi(lpszIMEFileName);
+    if (pszFileNameW == NULL)
         goto Quit;
 
-    pCL = Imm32HeapAlloc(0, cb);
-    if (pCL == NULL)
+    pszLayoutTextW = Imm32WideFromAnsi(lpszLayoutText);
+    if (pszLayoutTextW == NULL)
         goto Quit;
 
-    cb = pImeDpi->ImeConversionList(hIMC, pszSrcW, pCL, cb, uFlag);
-    if (cb == 0)
-        goto Quit;
-
-    ret = CandidateListWideToAnsi(pCL, lpDst, dwBufLen, CP_ACP);
-
-Quit:
-    if (pszSrcW)
-        HeapFree(g_hImm32Heap, 0, pszSrcW);
-    if (pCL)
-        HeapFree(g_hImm32Heap, 0, pCL);
-    ImmUnlockImeDpi(pImeDpi);
-    return ret;
-}
-
-/***********************************************************************
- *             ImmGetConversionListW (IMM32.@)
- */
-DWORD WINAPI ImmGetConversionListW(
-  HKL hKL, HIMC hIMC,
-  LPCWSTR pSrc, LPCANDIDATELIST lpDst,
-  DWORD dwBufLen, UINT uFlag)
-{
-    DWORD ret = 0;
-    INT cb;
-    PIMEDPI pImeDpi;
-    LPCANDIDATELIST pCL = NULL;
-    LPSTR pszSrcA = NULL;
-
-    TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL, hIMC, debugstr_w(pSrc),
-          lpDst, dwBufLen, uFlag);
-
-    pImeDpi = ImmLockOrLoadImeDpi(hKL);
-    if (!pImeDpi)
-        return 0;
-
-    if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
-    {
-        ret = pImeDpi->ImeConversionList(hIMC, pSrc, lpDst, dwBufLen, uFlag);
-        ImmUnlockImeDpi(pImeDpi);
-        return ret;
-    }
-
-    if (pSrc)
-    {
-        pszSrcA = Imm32AnsiFromWide(pSrc);
-        if (pszSrcA == NULL)
-            goto Quit;
-    }
-
-    cb = pImeDpi->ImeConversionList(hIMC, pszSrcA, NULL, 0, uFlag);
-    if (cb == 0)
-        goto Quit;
-
-    pCL = Imm32HeapAlloc(0, cb);
-    if (!pCL)
-        goto Quit;
-
-    cb = pImeDpi->ImeConversionList(hIMC, pszSrcA, pCL, cb, uFlag);
-    if (!cb)
-        goto Quit;
-
-    ret = CandidateListAnsiToWide(pCL, lpDst, dwBufLen, CP_ACP);
-
-Quit:
-    if (pszSrcA)
-        HeapFree(g_hImm32Heap, 0, pszSrcA);
-    if (pCL)
-        HeapFree(g_hImm32Heap, 0, pCL);
-    ImmUnlockImeDpi(pImeDpi);
-    return ret;
-}
-
-/***********************************************************************
- *             ImmGetConversionStatus (IMM32.@)
- */
-BOOL WINAPI ImmGetConversionStatus(
-  HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
-{
-    LPINPUTCONTEXT pIC;
-
-    TRACE("(%p %p %p)\n", hIMC, lpfdwConversion, lpfdwSentence);
-
-    pIC = ImmLockIMC(hIMC);
-    if (!pIC)
-        return FALSE;
-
-    if (lpfdwConversion)
-        *lpfdwConversion = pIC->fdwConversion;
-    if (lpfdwSentence)
-        *lpfdwSentence = pIC->fdwSentence;
-
-    ImmUnlockIMC(hIMC);
-    return TRUE;
-}
-
-/***********************************************************************
- *             ImmGetDefaultIMEWnd (IMM32.@)
- */
-HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
-{
-    if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
-        return NULL;
-
-    // FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
-    if (hWnd == NULL)
-        return (HWND)NtUserGetThreadState(3);
-
-    return (HWND)NtUserQueryWindow(hWnd, QUERY_WINDOW_DEFAULT_IME);
-}
-
-/***********************************************************************
- *             CtfImmIsCiceroEnabled (IMM32.@)
- */
-BOOL WINAPI CtfImmIsCiceroEnabled(VOID)
-{
-    return (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED));
-}
-
-/***********************************************************************
- *             ImmGetDescriptionA (IMM32.@)
- */
-UINT WINAPI ImmGetDescriptionA(
-  HKL hKL, LPSTR lpszDescription, UINT uBufLen)
-{
-    IMEINFOEX info;
-    size_t cch;
-
-    TRACE("(%p,%p,%d)\n", hKL, lpszDescription, uBufLen);
-
-    if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || 
!IS_IME_HKL(hKL))
-        return 0;
-
-    StringCchLengthW(info.wszImeDescription, _countof(info.wszImeDescription), 
&cch);
-    cch = WideCharToMultiByte(CP_ACP, 0, info.wszImeDescription, (INT)cch,
-                              lpszDescription, uBufLen, NULL, NULL);
-    if (uBufLen)
-        lpszDescription[cch] = 0;
-    return (UINT)cch;
-}
-
-/***********************************************************************
- *             ImmGetDescriptionW (IMM32.@)
- */
-UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
-{
-    IMEINFOEX info;
-    size_t cch;
-
-    TRACE("(%p, %p, %d)\n", hKL, lpszDescription, uBufLen);
-
-    if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || 
!IS_IME_HKL(hKL))
-        return 0;
-
-    if (uBufLen != 0)
-        StringCchCopyW(lpszDescription, uBufLen, info.wszImeDescription);
-
-    StringCchLengthW(info.wszImeDescription, _countof(info.wszImeDescription), 
&cch);
-    return (UINT)cch;
-}
-
-static DWORD APIENTRY
-ImmGetGuideLineAW(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen, BOOL 
bAnsi)
-{
-    PCLIENTIMC pClientImc;
-    LPINPUTCONTEXT pIC;
-    LPGUIDELINE pGuideLine;
-    DWORD cb, ret = 0;
-    LPVOID pvStr, pvPrivate;
-    BOOL bUsedDefault;
-
-    pClientImc = ImmLockClientImc(hIMC);
-    if (!pClientImc)
-        return 0;
-
-    pIC = ImmLockIMC(hIMC);
-    if (!pIC)
-    {
-        ImmUnlockClientImc(pClientImc);
-        return 0;
-    }
-
-    pGuideLine = ImmLockIMCC(pIC->hGuideLine);
-    if (!pGuideLine)
-    {
-        ImmUnlockIMC(hIMC);
-        ImmUnlockClientImc(pClientImc);
-        return 0;
-    }
-
-    if (dwIndex == GGL_LEVEL)
-    {
-        ret = pGuideLine->dwLevel;
-        goto Quit;
-    }
-
-    if (dwIndex == GGL_INDEX)
-    {
-        ret = pGuideLine->dwIndex;
-        goto Quit;
-    }
-
-    if (dwIndex == GGL_STRING)
-    {
-        pvStr = (LPBYTE)pGuideLine + pGuideLine->dwStrOffset;
-
-        /* get size */
-        if (bAnsi)
-        {
-            if (pClientImc->dwFlags & CLIENTIMC_WIDE)
-            {
-                cb = WideCharToMultiByte(CP_ACP, 0, pvStr, 
pGuideLine->dwStrLen,
-                                         NULL, 0, NULL, &bUsedDefault);
-            }
-            else
-            {
-                cb = pGuideLine->dwStrLen * sizeof(CHAR);
-            }
-        }
-        else
-        {
-            if (pClientImc->dwFlags & CLIENTIMC_WIDE)
-            {
-                cb = pGuideLine->dwStrLen * sizeof(WCHAR);
-            }
-            else
-            {
-                cb = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pvStr, 
pGuideLine->dwStrLen,
-                                         NULL, 0) * sizeof(WCHAR);
-            }
-        }
-
-        if (dwBufLen == 0 || cb == 0 || lpBuf == NULL || dwBufLen < cb)
-        {
-            ret = cb;
-            goto Quit;
-        }
-
-        /* store to buffer */
-        if (bAnsi)
-        {
-            if (pClientImc->dwFlags & CLIENTIMC_WIDE)
-            {
-                ret = WideCharToMultiByte(CP_ACP, 0, pvStr, 
pGuideLine->dwStrLen,
-                                          lpBuf, dwBufLen, NULL, 
&bUsedDefault);
-                goto Quit;
-            }
-        }
-        else
-        {
-            if (!(pClientImc->dwFlags & CLIENTIMC_WIDE))
-            {
-                ret = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pvStr, 
pGuideLine->dwStrLen,
-                                          lpBuf, dwBufLen) * sizeof(WCHAR);
-                goto Quit;
-            }
-        }
-
-        RtlCopyMemory(lpBuf, pvStr, cb);
-        ret = cb;
-        goto Quit;
-    }
-
-    if (dwIndex == GGL_PRIVATE)
-    {
-        pvPrivate = (LPBYTE)pGuideLine + pGuideLine->dwPrivateOffset;
-
-        /* get size */
-        if (bAnsi)
-        {
-            if ((pClientImc->dwFlags & CLIENTIMC_WIDE) &&
-                pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
-            {
-                cb = CandidateListWideToAnsi(pvPrivate, NULL, 0, CP_ACP);
-            }
-            else
-            {
-                cb = pGuideLine->dwPrivateSize;
-            }
-        }
-        else
-        {
-            if (!(pClientImc->dwFlags & CLIENTIMC_WIDE) &&
-                pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
-            {
-                cb = CandidateListAnsiToWide(pvPrivate, NULL, 0, CP_ACP);
-            }
-            else
-            {
-                cb = pGuideLine->dwPrivateSize;
-            }
-        }
-
-        if (dwBufLen == 0 || cb == 0 || lpBuf == NULL || dwBufLen < cb)
-        {
-            ret = cb;
-            goto Quit;
-        }
-
-        /* store to buffer */
-        if (bAnsi)
-        {
-            if ((pClientImc->dwFlags & CLIENTIMC_WIDE) &&
-                pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
-            {
-                ret = CandidateListWideToAnsi(pvPrivate, lpBuf, cb, CP_ACP);
-                goto Quit;
-            }
-        }
-        else
-        {
-            if (!(pClientImc->dwFlags & CLIENTIMC_WIDE) &&
-                pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
-            {
-                ret = CandidateListAnsiToWide(pvPrivate, lpBuf, cb, CP_ACP);
-                goto Quit;
-            }
-        }
-
-        RtlCopyMemory(lpBuf, pvPrivate, cb);
-        ret = cb;
-        goto Quit;
-    }
-
-Quit:
-    ImmUnlockIMCC(pIC->hGuideLine);
-    ImmUnlockIMC(hIMC);
-    ImmUnlockClientImc(pClientImc);
-    return ret;
-}
-
-/***********************************************************************
- *             ImmGetGuideLineA (IMM32.@)
- */
-DWORD WINAPI ImmGetGuideLineA(
-  HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
-{
-    TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen);
-    return ImmGetGuideLineAW(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
-}
-
-/***********************************************************************
- *             ImmGetGuideLineW (IMM32.@)
- */
-DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD 
dwBufLen)
-{
-    TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen);
-    return ImmGetGuideLineAW(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
-}
-
-/***********************************************************************
- *             ImmGetIMEFileNameA (IMM32.@)
- */
-UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
-{
-    BOOL bDefUsed;
-    IMEINFOEX info;
-    size_t cch;
-
-    TRACE("(%p, %p, %u)\n", hKL, lpszFileName, uBufLen);
-
-    if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || 
!IS_IME_HKL(hKL))
-    {
-        if (uBufLen > 0)
-            lpszFileName[0] = 0;
-        return 0;
-    }
-
-    StringCchLengthW(info.wszImeFile, _countof(info.wszImeFile), &cch);
-
-    cch = WideCharToMultiByte(CP_ACP, 0, info.wszImeFile, (INT)cch,
-                              lpszFileName, uBufLen, NULL, &bDefUsed);
-    if (uBufLen == 0)
-        return (UINT)cch;
-
-    if (cch > uBufLen - 1)
-        cch = uBufLen - 1;
-
-    lpszFileName[cch] = 0;
-    return (UINT)cch;
-}
-
-/***********************************************************************
- *             ImmGetIMEFileNameW (IMM32.@)
- */
-UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
-{
-    IMEINFOEX info;
-    size_t cch;
-
-    TRACE("(%p, %p, %u)\n", hKL, lpszFileName, uBufLen);
-
-    if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || 
!IS_IME_HKL(hKL))
-    {
-        if (uBufLen > 0)
-            lpszFileName[0] = 0;
-        return 0;
-    }
-
-    StringCchLengthW(info.wszImeFile, _countof(info.wszImeFile), &cch);
-    if (uBufLen == 0)
-        return (UINT)cch;
-
-    StringCchCopyNW(lpszFileName, uBufLen, info.wszImeFile, cch);
-
-    if (cch > uBufLen - 1)
-        cch = uBufLen - 1;
-
-    lpszFileName[cch] = 0;
-    return (UINT)cch;
-}
-
-/***********************************************************************
- *             ImmGetOpenStatus (IMM32.@)
- */
-BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
-{
-    BOOL ret;
-    LPINPUTCONTEXT pIC;
-
-    TRACE("(%p)\n", hIMC);
-
-    if (!hIMC)
-        return FALSE;
-
-    pIC = ImmLockIMC(hIMC);
-    if (!pIC)
-        return FALSE;
-
-    ret = pIC->fOpen;
-
-    ImmUnlockIMC(hIMC);
-    return ret;
-}
-
-/***********************************************************************
- *             ImmGetProperty (IMM32.@)
- */
-DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
-{
-    IMEINFOEX ImeInfoEx;
-    LPIMEINFO pImeInfo;
-    DWORD dwValue;
-    PIMEDPI pImeDpi = NULL;
-
-    TRACE("(%p, %lu)\n", hKL, fdwIndex);
-
-    if (!ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExKeyboardLayout, &hKL))
-        return FALSE;
-
-    if (fdwIndex == IGP_GETIMEVERSION)
-        return ImeInfoEx.dwImeWinVersion;
-
-    if (ImeInfoEx.fLoadFlag != 2)
-    {
-        pImeDpi = ImmLockOrLoadImeDpi(hKL);
-        if (pImeDpi == NULL)
-            return FALSE;
-
-        pImeInfo = &pImeDpi->ImeInfo;
-    }
-    else
-    {
-        pImeInfo = &ImeInfoEx.ImeInfo;
-    }
-
-    switch (fdwIndex)
-    {
-        case IGP_PROPERTY:      dwValue = pImeInfo->fdwProperty; break;
-        case IGP_CONVERSION:    dwValue = pImeInfo->fdwConversionCaps; break;
-        case IGP_SENTENCE:      dwValue = pImeInfo->fdwSentenceCaps; break;
-        case IGP_UI:            dwValue = pImeInfo->fdwUICaps; break;
-        case IGP_SETCOMPSTR:    dwValue = pImeInfo->fdwSCSCaps; break;
-        case IGP_SELECT:        dwValue = pImeInfo->fdwSelectCaps; break;
-        default:                dwValue = 0; break;
-    }
-
-    if (pImeDpi)
-        ImmUnlockImeDpi(pImeDpi);
-    return dwValue;
-}
-
-/***********************************************************************
- *             ImmGetRegisterWordStyleA (IMM32.@)
- */
-UINT WINAPI ImmGetRegisterWordStyleA(
-  HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
-{
-    UINT iItem, ret = 0;
-    PIMEDPI pImeDpi;
-    LPSTYLEBUFA pDestA;
-    LPSTYLEBUFW pSrcW, pNewStylesW = NULL;
-    size_t cchW;
-    INT cchA;
-
-    TRACE("(%p, %u, %p)\n", hKL, nItem, lpStyleBuf);
-
-    pImeDpi = ImmLockOrLoadImeDpi(hKL);
-    if (!pImeDpi)
-        return 0;
-
-    if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))
-    {
-        ret = pImeDpi->ImeGetRegisterWordStyle(nItem, lpStyleBuf);
-        goto Quit;
-    }
-
-    if (nItem > 0)
-    {
-        pNewStylesW = Imm32HeapAlloc(0, nItem * sizeof(STYLEBUFW));
-        if (!pNewStylesW)
-            goto Quit;
-    }
-
-    ret = pImeDpi->ImeGetRegisterWordStyle(nItem, pNewStylesW);
-
-    if (nItem > 0)
-    {
-        /* lpStyleBuf <-- pNewStylesW */
-        for (iItem = 0; iItem < ret; ++iItem)
-        {
-            pSrcW = &pNewStylesW[iItem];
-            pDestA = &lpStyleBuf[iItem];
-            pDestA->dwStyle = pSrcW->dwStyle;
-            StringCchLengthW(pSrcW->szDescription, 
_countof(pSrcW->szDescription), &cchW);
-            cchA = WideCharToMultiByte(CP_ACP, MB_PRECOMPOSED,
-                                       pSrcW->szDescription, (INT)cchW,
-                                       pDestA->szDescription, 
_countof(pDestA->szDescription),
-                                       NULL, NULL);
-            if (cchA > _countof(pDestA->szDescription) - 1)
-                cchA = _countof(pDestA->szDescription) - 1;
-            pDestA->szDescription[cchA] = 0;
-        }
-    }
-
-Quit:
-    if (pNewStylesW)
-        HeapFree(g_hImm32Heap, 0, pNewStylesW);
-    ImmUnlockImeDpi(pImeDpi);
-    return ret;
-}
-
-/***********************************************************************
- *             ImmGetRegisterWordStyleW (IMM32.@)
- */
-UINT WINAPI ImmGetRegisterWordStyleW(
-  HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
-{
-    UINT iItem, ret = 0;
-    PIMEDPI pImeDpi;
-    LPSTYLEBUFA pSrcA, pNewStylesA = NULL;
-    LPSTYLEBUFW pDestW;
-    size_t cchA;
-    INT cchW;
-
-    TRACE("(%p, %u, %p)\n", hKL, nItem, lpStyleBuf);
-
-    pImeDpi = ImmLockOrLoadImeDpi(hKL);
-    if (!pImeDpi)
-        return 0;
-
-    if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
-    {
-        ret = pImeDpi->ImeGetRegisterWordStyle(nItem, lpStyleBuf);
-        goto Quit;
-    }
-
-    if (nItem > 0)
-    {
-        pNewStylesA = Imm32HeapAlloc(0, nItem * sizeof(STYLEBUFA));
-        if (!pNewStylesA)
-            goto Quit;
-    }
-
-    ret = pImeDpi->ImeGetRegisterWordStyle(nItem, pNewStylesA);
-
-    if (nItem > 0)
-    {
-        /* lpStyleBuf <-- pNewStylesA */
-        for (iItem = 0; iItem < ret; ++iItem)
-        {
-            pSrcA = &pNewStylesA[iItem];
-            pDestW = &lpStyleBuf[iItem];
-            pDestW->dwStyle = pSrcA->dwStyle;
-            StringCchLengthA(pSrcA->szDescription, 
_countof(pSrcA->szDescription), &cchA);
-            cchW = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
-                                       pSrcA->szDescription, (INT)cchA,
-                                       pDestW->szDescription, 
_countof(pDestW->szDescription));
-            if (cchW > _countof(pDestW->szDescription) - 1)
-                cchW = _countof(pDestW->szDescription) - 1;
-            pDestW->szDescription[cchW] = 0;
-        }
-    }
-
-Quit:
-    if (pNewStylesA)
-        HeapFree(g_hImm32Heap, 0, pNewStylesA);
-    ImmUnlockImeDpi(pImeDpi);
-    return ret;
-}
-
-/***********************************************************************
- *             ImmGetStatusWindowPos (IMM32.@)
- */
-BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
-{
-    LPINPUTCONTEXT pIC;
-    BOOL ret;
-
-    TRACE("(%p, %p)\n", hIMC, lpptPos);
-
-    pIC = ImmLockIMC(hIMC);
-    if (pIC == NULL)
-        return FALSE;
-
-    ret = !!(pIC->fdwInit & INIT_STATUSWNDPOS);
-    if (ret)
-        *lpptPos = pIC->ptStatusWndPos;
-
-    ImmUnlockIMC(hIMC);
-    return ret;
-}
-
-/***********************************************************************
- *             ImmGetVirtualKey (IMM32.@)
- */
-UINT WINAPI ImmGetVirtualKey(HWND hWnd)
-{
-    HIMC hIMC;
-    LPINPUTCONTEXTDX pIC;
-    UINT ret = VK_PROCESSKEY;
-
-    TRACE("(%p)\n", hWnd);
-
-    hIMC = ImmGetContext(hWnd);
-    pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
-    if (!pIC)
-        return ret;
-
-    if (pIC->bNeedsTrans)
-        ret = pIC->nVKey;
-
-    ImmUnlockIMC(hIMC);
-    return ret;
-}
-
-/***********************************************************************
- *             ImmInstallIMEA (IMM32.@)
- */
-HKL WINAPI ImmInstallIMEA(
-  LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
-{
-    HKL hKL = NULL;
-    LPWSTR pszFileNameW = NULL, pszLayoutTextW = NULL;
-
-    TRACE("(%s, %s)\n", debugstr_a(lpszIMEFileName), 
debugstr_a(lpszLayoutText));
-
-    pszFileNameW = Imm32WideFromAnsi(lpszIMEFileName);
-    if (pszFileNameW == NULL)
-        goto Quit;
-
-    pszLayoutTextW = Imm32WideFromAnsi(lpszLayoutText);
-    if (pszLayoutTextW == NULL)
-        goto Quit;
-
-    hKL = ImmInstallIMEW(pszFileNameW, pszLayoutTextW);
-
-Quit:
-    if (pszFileNameW)
-        HeapFree(g_hImm32Heap, 0, pszFileNameW);
-    if (pszLayoutTextW)
-        HeapFree(g_hImm32Heap, 0, pszLayoutTextW);
-    return hKL;
-}
-
-/***********************************************************************
- *             ImmInstallIMEW (IMM32.@)
- */
-HKL WINAPI ImmInstallIMEW(
-  LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
-{
-    INT lcid = GetUserDefaultLCID();
-    INT count;
-    HKL hkl;
-    DWORD rc;
-    HKEY hkey;
-    WCHAR regKey[ARRAY_SIZE(szImeRegFmt)+8];
-
-    TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName),
-                          debugstr_w(lpszLayoutText));
-
-    /* Start with 2.  e001 will be blank and so default to the wine internal 
IME */
-    count = 2;
-
-    while (count < 0xfff)
-    {
-        DWORD disposition = 0;
-
-        hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count );
-        wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl);
-
-        rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, 
KEY_WRITE, NULL, &hkey, &disposition);
-        if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
-            break;
-        else if (rc == ERROR_SUCCESS)
-            RegCloseKey(hkey);
-
-        count++;
-    }
-
-    if (count == 0xfff)
-    {
-        WARN("Unable to find slot to install IME\n");
-        return 0;
-    }
-
-    if (rc == ERROR_SUCCESS)
-    {
-        rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (const 
BYTE*)lpszIMEFileName,
-                            (lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR));
-        if (rc == ERROR_SUCCESS)
-            rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (const 
BYTE*)lpszLayoutText,
-                                (lstrlenW(lpszLayoutText) + 1) * 
sizeof(WCHAR));
-        RegCloseKey(hkey);
-        return hkl;
-    }
-    else
-    {
-        WARN("Unable to set IME registry values\n");
-        return 0;
-    }
-}
-
-/***********************************************************************
- *             ImmIsIME (IMM32.@)
- */
-BOOL WINAPI ImmIsIME(HKL hKL)
-{
-    IMEINFOEX info;
-    TRACE("(%p)\n", hKL);
-    return !!ImmGetImeInfoEx(&info, ImeInfoExImeWindow, &hKL);
-}
-
-static BOOL APIENTRY
-ImmIsUIMessageAW(HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam, BOOL 
bAnsi)
-{
-    switch (msg)
-    {
-        case WM_IME_STARTCOMPOSITION: case WM_IME_ENDCOMPOSITION:
-        case WM_IME_COMPOSITION: case WM_IME_SETCONTEXT: case WM_IME_NOTIFY:
-        case WM_IME_COMPOSITIONFULL: case WM_IME_SELECT: case WM_IME_SYSTEM:
-            break;
-        default:
-            return FALSE;
-    }
-
-    if (!hWndIME)
-        return TRUE;
-
-    if (bAnsi)
-        SendMessageA(hWndIME, msg, wParam, lParam);
-    else
-        SendMessageW(hWndIME, msg, wParam, lParam);
-
-    return TRUE;
-}
-
-/***********************************************************************
- *             ImmIsUIMessageA (IMM32.@)
- */
-BOOL WINAPI ImmIsUIMessageA(
-  HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
-{
-    TRACE("(%p, 0x%X, %p, %p)\n", hWndIME, msg, wParam, lParam);
-    return ImmIsUIMessageAW(hWndIME, msg, wParam, lParam, TRUE);
-}
-
-/***********************************************************************
- *             ImmIsUIMessageW (IMM32.@)
- */
-BOOL WINAPI ImmIsUIMessageW(
-  HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
-{
-    TRACE("(%p, 0x%X, %p, %p)\n", hWndIME, msg, wParam, lParam);
-    return ImmIsUIMessageAW(hWndIME, msg, wParam, lParam, FALSE);
-}
-
-/***********************************************************************
- *             ImmNotifyIME (IMM32.@)
- */
-BOOL WINAPI ImmNotifyIME(
-  HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
-{
-    HKL hKL;
-    PIMEDPI pImeDpi;
-    BOOL ret;
-
-    TRACE("(%p, %lu, %lu, %lu)\n", hIMC, dwAction, dwIndex, dwValue);
-
-    if (hIMC && Imm32IsCrossThreadAccess(hIMC))
-        return FALSE;
-
-    hKL = GetKeyboardLayout(0);
-    pImeDpi = ImmLockImeDpi(hKL);
-    if (pImeDpi == NULL)
-        return FALSE;
-
-    ret = pImeDpi->NotifyIME(hIMC, dwAction, dwIndex, dwValue);
-    ImmUnlockImeDpi(pImeDpi);
-    return ret;
-}
-
-/***********************************************************************
- *             ImmRegisterWordA (IMM32.@)
- */
-BOOL WINAPI ImmRegisterWordA(
-  HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
-{
-    BOOL ret = FALSE;
-    PIMEDPI pImeDpi;
-    LPWSTR pszReadingW = NULL, pszRegisterW = NULL;
-
-    TRACE("(%p, %s, 0x%lX, %s)\n", hKL, debugstr_a(lpszReading), dwStyle,
-          debugstr_a(lpszRegister));
-
-    pImeDpi = ImmLockOrLoadImeDpi(hKL);
-    if (!pImeDpi)
-        return FALSE;
-
-    if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))
-    {
-        ret = pImeDpi->ImeRegisterWord(lpszReading, dwStyle, lpszRegister);
-        ImmUnlockImeDpi(pImeDpi);
-        return ret;
-    }
-
-    if (lpszReading)
-    {
-        pszReadingW = Imm32WideFromAnsi(lpszReading);
-        if (pszReadingW == NULL)
-            goto Quit;
-    }
-
-    if (lpszRegister)
-    {
-        pszRegisterW = Imm32WideFromAnsi(lpszRegister);
-        if (pszRegisterW == NULL)
-            goto Quit;
-    }
-
-    ret = pImeDpi->ImeRegisterWord(pszReadingW, dwStyle, pszRegisterW);
-
-Quit:
-    if (pszReadingW)
-        HeapFree(g_hImm32Heap, 0, pszReadingW);
-    if (pszRegisterW)
-        HeapFree(g_hImm32Heap, 0, pszRegisterW);
-    ImmUnlockImeDpi(pImeDpi);
-    return ret;
-}
-
-/***********************************************************************
- *             ImmRegisterWordW (IMM32.@)
- */
-BOOL WINAPI ImmRegisterWordW(
-  HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
-{
-    BOOL ret = FALSE;
-    PIMEDPI pImeDpi;
-    LPSTR pszReadingA = NULL, pszRegisterA = NULL;
-
-    TRACE("(%p, %s, 0x%lX, %s)\n", hKL, debugstr_w(lpszReading), dwStyle,
-          debugstr_w(lpszRegister));
-
-    pImeDpi = ImmLockOrLoadImeDpi(hKL);
-    if (!pImeDpi)
-        return FALSE;
-
-    if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
-    {
-        ret = pImeDpi->ImeRegisterWord(lpszReading, dwStyle, lpszRegister);
-        ImmUnlockImeDpi(pImeDpi);
-        return ret;
-    }
-
-    if (lpszReading)
-    {
-        pszReadingA = Imm32AnsiFromWide(lpszReading);
-        if (!pszReadingA)
-            goto Quit;
-    }
-
-    if (lpszRegister)
-    {
-        pszRegisterA = Imm32AnsiFromWide(lpszRegister);
-        if (!pszRegisterA)
-            goto Quit;
-    }
-
-    ret = pImeDpi->ImeRegisterWord(pszReadingA, dwStyle, pszRegisterA);
-
-Quit:
-    if (pszReadingA)
-        HeapFree(g_hImm32Heap, 0, pszReadingA);
-    if (pszRegisterA)
-        HeapFree(g_hImm32Heap, 0, pszRegisterA);
-    ImmUnlockImeDpi(pImeDpi);
-    return ret;
-}
-
-/***********************************************************************
- *             ImmReleaseContext (IMM32.@)
- */
-BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
-{
-    TRACE("(%p, %p)\n", hWnd, hIMC);
-    UNREFERENCED_PARAMETER(hWnd);
-    UNREFERENCED_PARAMETER(hIMC);
... 3516 lines suppressed ...

Reply via email to