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

commit 692a30a84ab8df23e48851d62c6552678180636e
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Wed Aug 4 09:41:59 2021 +0900
Commit:     GitHub <[email protected]>
CommitDate: Wed Aug 4 09:41:59 2021 +0900

    [IMM32] ImmCreateContext, ImmDestroyContext, DllMain etc. (#3867)
    
    - Rewrite ImmCreateContext, ImmDestroyContext, and DllMain functions.
    - Add g_hImm32Inst, g_bClientRegd, and g_SharedInfo global variables. 
Delete g_dwImm32Flags (that was g_psi->dwSRVIFlags).
    - Implement ImmLoadIME and ImmRegisterClient functions.
    - Modify CLIENTIMC and IMEDPI structures. Move CLIENTIMC definition into 
ntuser.h.
    - Add file win32ss/include/imetable.h.
    - Rename SRVINFO_METRICS macro as SRVINFO_CICERO_ENABLED.
    CORE-11700
---
 dll/win32/imm32/CMakeLists.txt    |   2 +-
 dll/win32/imm32/imm.c             | 710 +++++++++++++++++++++++++-------------
 dll/win32/imm32/imm32.spec        |   2 +-
 sdk/include/psdk/imm.h            |   6 +-
 sdk/include/reactos/imm32_undoc.h |  18 -
 win32ss/include/imetable.h        |  22 ++
 win32ss/include/ntuser.h          |  92 +++--
 win32ss/user/ntuser/ime.c         |   4 +-
 win32ss/user/ntuser/metric.c      |   2 +-
 win32ss/user/ntuser/ntstubs.c     |  14 +-
 10 files changed, 581 insertions(+), 291 deletions(-)

diff --git a/dll/win32/imm32/CMakeLists.txt b/dll/win32/imm32/CMakeLists.txt
index 10c1a6e3708..9ccdcd26f20 100644
--- a/dll/win32/imm32/CMakeLists.txt
+++ b/dll/win32/imm32/CMakeLists.txt
@@ -15,5 +15,5 @@ list(APPEND SOURCE
 add_library(imm32 MODULE ${SOURCE} version.rc)
 set_module_type(imm32 win32dll)
 target_link_libraries(imm32 wine win32ksys)
-add_importlibs(imm32 advapi32 user32 msvcrt kernel32 ntdll)
+add_importlibs(imm32 advapi32 user32 gdi32 msvcrt kernel32 ntdll)
 add_cd_file(TARGET imm32 DESTINATION reactos/system32 FOR all)
diff --git a/dll/win32/imm32/imm.c b/dll/win32/imm32/imm.c
index 62f1569c354..7e3f932b517 100644
--- a/dll/win32/imm32/imm.c
+++ b/dll/win32/imm32/imm.c
@@ -57,11 +57,55 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm);
 #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;
 
-BOOL WINAPI User32InitializeImmEntryTable(DWORD);
+static BOOL APIENTRY Imm32InitInstance(HMODULE hMod)
+{
+    NTSTATUS status;
+
+    if (hMod)
+        g_hImm32Inst = hMod;
+
+    if (g_bClientRegd)
+        return TRUE;
+
+    status = RtlInitializeCriticalSection(&g_csImeDpi);
+    if (NT_ERROR(status))
+        return FALSE;
+
+    g_bClientRegd = TRUE;
+    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 DWORD_PTR APIENTRY Imm32QueryWindow(HWND hWnd, DWORD Index)
+{
+    return NtUserQueryWindow(hWnd, Index);
+}
+
+static DWORD APIENTRY
+Imm32UpdateInputContext(HIMC hIMC, DWORD Unknown1, PCLIENTIMC pClientImc)
+{
+    return NtUserUpdateInputContext(hIMC, Unknown1, pClientImc);
+}
 
 static DWORD APIENTRY Imm32QueryInputContext(HIMC hIMC, DWORD dwUnknown2)
 {
@@ -73,6 +117,21 @@ static DWORD APIENTRY Imm32NotifyIMEStatus(HWND hwnd, HIMC 
hIMC, DWORD dwConvers
     return NtUserNotifyIMEStatus(hwnd, hIMC, dwConversion);
 }
 
+static HIMC APIENTRY Imm32CreateInputContext(PCLIENTIMC pClientImc)
+{
+    return NtUserCreateInputContext(pClientImc);
+}
+
+static BOOL APIENTRY Imm32DestroyInputContext(HIMC hIMC)
+{
+    return NtUserDestroyInputContext(hIMC);
+}
+
+DWORD_PTR APIENTRY Imm32GetThreadState(DWORD Routine)
+{
+    return NtUserGetThreadState(Routine);
+}
+
 static VOID APIENTRY Imm32FreeImeDpi(PIMEDPI pImeDpi, BOOL bDestroy)
 {
     if (pImeDpi->hInst == NULL)
@@ -115,6 +174,269 @@ Imm32NotifyAction(HIMC hIMC, HWND hwnd, DWORD dwAction, 
DWORD_PTR dwIndex, DWORD
     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;
+}
+
+DWORD APIENTRY Imm32SetImeOwnerWindow(PIMEINFOEX pImeInfoEx, BOOL fFlag)
+{
+    return NtUserSetImeOwnerWindow(pImeInfoEx, fFlag);
+}
+
+static BOOL APIENTRY Imm32InquireIme(PIMEDPI pImeDpi)
+{
+    WCHAR szUIClass[64];
+    WNDCLASSW wcW;
+    DWORD dwSysInfoFlags = 0; // TODO: ???
+    LPIMEINFO pImeInfo = &pImeDpi->ImeInfo;
+
+    // TODO: Imm32GetThreadState(THREADSTATE_UNKNOWN16);
+
+    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;
+
+    Imm32SetImeOwnerWindow(pImeInfoEx, TRUE);
+    return TRUE;
+
+Failed:
+    FreeLibrary(pImeDpi->hInst);
+    pImeDpi->hInst = NULL;
+    return FALSE;
+}
+
+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;
+    }
+}
+
+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);
+}
+
 HKL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx)
 {
     DWORD cbData;
@@ -127,7 +449,7 @@ HKL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx)
     TRACE("ImmLoadLayout(%p, %p)\n", hKL, pImeInfoEx);
 
     if (IS_IME_HKL(hKL) ||
-        !g_psi || (g_psi->dwSRVIFlags & SRVINFO_METRICS) == 0 ||
+        !g_psi || !(g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED) ||
         ((PW32CLIENTINFO)NtCurrentTeb()->Win32ClientInfo)->W32ClientInfo[0] & 
2)
     {
         UnicodeString.Buffer = szLayout;
@@ -256,7 +578,6 @@ static inline BOOL is_kbd_ime_unicode(const ImmHkl *hkl)
     return !!(hkl->imeInfo.fdwProperty & IME_PROP_UNICODE);
 }
 
-static BOOL IMM_DestroyContext(HIMC hIMC);
 static InputContextData* get_imc_data(HIMC hIMC);
 
 static inline WCHAR *strdupAtoW( const char *str )
@@ -393,36 +714,6 @@ static IMMThreadData *IMM_GetThreadData(HWND hwnd, DWORD 
thread)
     return data;
 }
 
-static BOOL IMM_IsDefaultContext(HIMC imc)
-{
-    InputContextData *data = get_imc_data(imc);
-
-    if (!data)
-        return FALSE;
-
-    return data->threadDefault;
-}
-
-static void IMM_FreeThreadData(void)
-{
-    IMMThreadData *data;
-
-    EnterCriticalSection(&threaddata_cs);
-    LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
-    {
-        if (data->threadID == GetCurrentThreadId())
-        {
-            list_remove(&data->entry);
-            LeaveCriticalSection(&threaddata_cs);
-            IMM_DestroyContext(data->defaultContext);
-            HeapFree(GetProcessHeap(),0,data);
-            TRACE("Thread Data Destroyed\n");
-            return;
-        }
-    }
-    LeaveCriticalSection(&threaddata_cs);
-}
-
 static HMODULE load_graphics_driver(void)
 {
     static const WCHAR display_device_guid_propW[] = {
@@ -531,49 +822,6 @@ HWND WINAPI __wine_get_ui_window(HKL hkl)
     return immHkl->UIWnd;
 }
 
-static void IMM_FreeAllImmHkl(void)
-{
-    ImmHkl *ptr,*cursor2;
-
-    LIST_FOR_EACH_ENTRY_SAFE(ptr, cursor2, &ImmHklList, ImmHkl, entry)
-    {
-        list_remove(&ptr->entry);
-        if (ptr->hIME)
-        {
-            ptr->pImeDestroy(1);
-            FreeLibrary(ptr->hIME);
-        }
-        if (ptr->UIWnd)
-            DestroyWindow(ptr->UIWnd);
-        HeapFree(GetProcessHeap(),0,ptr);
-    }
-}
-
-BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
-{
-    TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
-    switch (fdwReason)
-    {
-        case DLL_PROCESS_ATTACH:
-            if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC))
-            {
-                return FALSE;
-            }
-            break;
-        case DLL_THREAD_ATTACH:
-            break;
-        case DLL_THREAD_DETACH:
-            IMM_FreeThreadData();
-            break;
-        case DLL_PROCESS_DETACH:
-            if (lpReserved) break;
-            IMM_FreeThreadData();
-            IMM_FreeAllImmHkl();
-            break;
-    }
-    return TRUE;
-}
-
 /* for posting messages as the IME */
 static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM 
wParam, LPARAM lParam)
 {
@@ -607,18 +855,6 @@ static LRESULT ImmInternalSendIMENotify(InputContextData 
*data, WPARAM notify, L
     return 0;
 }
 
-static HIMCC ImmCreateBlankCompStr(void)
-{
-    HIMCC rc;
-    LPCOMPOSITIONSTRING ptr;
-    rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
-    ptr = ImmLockIMCC(rc);
-    memset(ptr,0,sizeof(COMPOSITIONSTRING));
-    ptr->dwSize = sizeof(COMPOSITIONSTRING);
-    ImmUnlockIMCC(rc);
-    return rc;
-}
-
 static InputContextData* get_imc_data(HIMC hIMC)
 {
     InputContextData *data = hIMC;
@@ -636,43 +872,8 @@ static InputContextData* get_imc_data(HIMC hIMC)
 
 static HIMC get_default_context( HWND hwnd )
 {
-    HIMC ret;
-    IMMThreadData* thread_data = IMM_GetThreadData( hwnd, 0 );
-
-    if (!thread_data) return 0;
-
-    if (thread_data->defaultContext)
-    {
-        ret = thread_data->defaultContext;
-        LeaveCriticalSection(&threaddata_cs);
-        return ret;
-    }
-
-    /* can't create a default context in another thread */
-    if (thread_data->threadID != GetCurrentThreadId())
-    {
-        LeaveCriticalSection(&threaddata_cs);
-        return 0;
-    }
-
-    LeaveCriticalSection(&threaddata_cs);
-
-    ret = ImmCreateContext();
-    if (!ret) return 0;
-    ((InputContextData*)ret)->threadDefault = TRUE;
-
-    /* thread_data is in the current thread so we can assume it's still valid 
*/
-    EnterCriticalSection(&threaddata_cs);
-
-    if (thread_data->defaultContext) /* someone beat us */
-    {
-        IMM_DestroyContext( ret );
-        ret = thread_data->defaultContext;
-    }
-    else thread_data->defaultContext = ret;
-
-    LeaveCriticalSection(&threaddata_cs);
-    return ret;
+    FIXME("Don't use this function\n");
+    return FALSE;
 }
 
 static BOOL IMM_IsCrossThreadAccess(HWND hWnd,  HIMC hIMC)
@@ -873,83 +1074,106 @@ BOOL WINAPI ImmConfigureIMEW(
  */
 HIMC WINAPI ImmCreateContext(void)
 {
-    InputContextData *new_context;
-    LPGUIDELINE gl;
-    LPCANDIDATEINFO ci;
-    int i;
+    PCLIENTIMC pClientImc;
+    HIMC hIMC;
 
-    new_context = 
HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
+    TRACE("ImmCreateContext()\n");
 
-    /* Load the IME */
-    new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
+    if (g_psi == NULL || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
+        return NULL;
 
-    if (!new_context->immKbd->hIME)
+    pClientImc = Imm32HeapAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC));
+    if (pClientImc == NULL)
+        return NULL;
+
+    hIMC = Imm32CreateInputContext(pClientImc);
+    if (hIMC == NULL)
     {
-        TRACE("IME dll could not be loaded\n");
-        HeapFree(GetProcessHeap(),0,new_context);
-        return 0;
+        HeapFree(g_hImm32Heap, 0, pClientImc);
+        return NULL;
     }
 
-    /* the HIMCCs are never NULL */
-    new_context->IMC.hCompStr = ImmCreateBlankCompStr();
-    new_context->IMC.hMsgBuf = ImmCreateIMCC(0);
-    new_context->IMC.hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
-    ci = ImmLockIMCC(new_context->IMC.hCandInfo);
-    memset(ci,0,sizeof(CANDIDATEINFO));
-    ci->dwSize = sizeof(CANDIDATEINFO);
-    ImmUnlockIMCC(new_context->IMC.hCandInfo);
-    new_context->IMC.hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
-    gl = ImmLockIMCC(new_context->IMC.hGuideLine);
-    memset(gl,0,sizeof(GUIDELINE));
-    gl->dwSize = sizeof(GUIDELINE);
-    ImmUnlockIMCC(new_context->IMC.hGuideLine);
+    RtlInitializeCriticalSection(&pClientImc->cs);
+    pClientImc->unknown = Imm32GetThreadState(THREADSTATE_UNKNOWN13);
+    return hIMC;
+}
 
-    for (i = 0; i < ARRAY_SIZE(new_context->IMC.cfCandForm); i++)
-        new_context->IMC.cfCandForm[i].dwIndex = ~0u;
+static VOID APIENTRY Imm32CleanupContextExtra(LPINPUTCONTEXT pIC)
+{
+    FIXME("We have to do something do here");
+}
 
-    /* Initialize the IME Private */
-    new_context->IMC.hPrivate = 
ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
+static PCLIENTIMC APIENTRY Imm32FindClientImc(HIMC hIMC)
+{
+    // FIXME
+    return NULL;
+}
 
-    new_context->IMC.fdwConversion = 
new_context->immKbd->imeInfo.fdwConversionCaps;
-    new_context->IMC.fdwSentence = 
new_context->immKbd->imeInfo.fdwSentenceCaps;
+BOOL APIENTRY Imm32CleanupContext(HIMC hIMC, HKL hKL, BOOL bKeep)
+{
+    PIMEDPI pImeDpi;
+    LPINPUTCONTEXT pIC;
+    PCLIENTIMC pClientImc;
 
-    if (!new_context->immKbd->pImeSelect(new_context, TRUE))
+    if (g_psi == NULL || !(g_psi->dwSRVIFlags & SRVINFO_IMM32) || hIMC == NULL)
+        return FALSE;
+
+    FIXME("We have do something to do here\n");
+    pClientImc = Imm32FindClientImc(hIMC);
+    if (!pClientImc)
+        return FALSE;
+
+    if (pClientImc->hImc == NULL)
     {
-        TRACE("Selection of IME failed\n");
-        IMM_DestroyContext(new_context);
-        return 0;
+        pClientImc->dwFlags |= CLIENTIMC_UNKNOWN1;
+        ImmUnlockClientImc(pClientImc);
+        if (!bKeep)
+            return Imm32DestroyInputContext(hIMC);
+        return TRUE;
     }
-    new_context->threadID = GetCurrentThreadId();
-    SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)new_context->immKbd);
 
-    new_context->immKbd->uSelected++;
-    TRACE("Created context %p\n",new_context);
+    pIC = ImmLockIMC(hIMC);
+    if (pIC == NULL)
+    {
+        ImmUnlockClientImc(pClientImc);
+        return FALSE;
+    }
 
-    new_context->magic = WINE_IMC_VALID_MAGIC;
-    return new_context;
-}
+    FIXME("We have do something to do here\n");
 
-static BOOL IMM_DestroyContext(HIMC hIMC)
-{
-    InputContextData *data = get_imc_data(hIMC);
+    if (pClientImc->hKL == hKL)
+    {
+        pImeDpi = ImmLockImeDpi(hKL);
+        if (pImeDpi != NULL)
+        {
+            if (IS_IME_HKL(hKL))
+            {
+                pImeDpi->ImeSelect(hIMC, FALSE);
+            }
+            else if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
+            {
+                FIXME("We have do something to do here\n");
+            }
+            ImmUnlockImeDpi(pImeDpi);
+        }
+        pClientImc->hKL = NULL;
+    }
 
-    TRACE("Destroying %p\n",hIMC);
+    ImmDestroyIMCC(pIC->hPrivate);
+    ImmDestroyIMCC(pIC->hMsgBuf);
+    ImmDestroyIMCC(pIC->hGuideLine);
+    ImmDestroyIMCC(pIC->hCandInfo);
+    ImmDestroyIMCC(pIC->hCompStr);
 
-    if (!data)
-        return FALSE;
+    Imm32CleanupContextExtra(pIC);
 
-    data->immKbd->uSelected --;
-    data->immKbd->pImeSelect(hIMC, FALSE);
-    SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)data->immKbd);
+    ImmUnlockIMC(hIMC);
 
-    ImmDestroyIMCC(data->IMC.hCompStr);
-    ImmDestroyIMCC(data->IMC.hCandInfo);
-    ImmDestroyIMCC(data->IMC.hGuideLine);
-    ImmDestroyIMCC(data->IMC.hPrivate);
-    ImmDestroyIMCC(data->IMC.hMsgBuf);
+    pClientImc->dwFlags |= CLIENTIMC_UNKNOWN1;
+    ImmUnlockClientImc(pClientImc);
 
-    data->magic = 0;
-    HeapFree(GetProcessHeap(),0,data);
+    if (!bKeep)
+        return Imm32DestroyInputContext(hIMC);
 
     return TRUE;
 }
@@ -959,10 +1183,21 @@ static BOOL IMM_DestroyContext(HIMC hIMC)
  */
 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
 {
-    if (!IMM_IsDefaultContext(hIMC) && !IMM_IsCrossThreadAccess(NULL, hIMC))
-        return IMM_DestroyContext(hIMC);
-    else
+    DWORD dwImeThreadId, dwThreadId;
+    HKL hKL;
+
+    TRACE("ImmDestroyContext(%p)\n", hIMC);
+
+    if (g_psi == NULL || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
         return FALSE;
+
+    dwImeThreadId = Imm32QueryInputContext(hIMC, 1);
+    dwThreadId = GetCurrentThreadId();
+    if (dwImeThreadId != dwThreadId)
+        return FALSE;
+
+    hKL = GetKeyboardLayout(0);
+    return Imm32CleanupContext(hIMC, hKL, FALSE);
 }
 
 /***********************************************************************
@@ -1122,43 +1357,6 @@ LRESULT WINAPI ImmEscapeW(
         return 0;
 }
 
-#define ROUNDUP4(n) (((n) + 3) & ~3)  /* DWORD alignment */
-
-HANDLE g_hImm32Heap = NULL;
-DWORD g_dwImm32Flags = 0;
-
-/* flags for g_dwImm32Flags */
-#define IMM32_FLAG_UNKNOWN 0x4
-#define IMM32_FLAG_CICERO_ENABLED 0x20
-
-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 DWORD_PTR APIENTRY
-Imm32GetThreadState(DWORD Routine)
-{
-    return NtUserGetThreadState(Routine);
-}
-
-static DWORD_PTR APIENTRY Imm32QueryWindow(HWND hWnd, DWORD Index)
-{
-    return NtUserQueryWindow(hWnd, Index);
-}
-
-static DWORD APIENTRY
-Imm32UpdateInputContext(HIMC hIMC, DWORD Unknown1, PCLIENTIMC pClientImc)
-{
-    return NtUserUpdateInputContext(hIMC, Unknown1, pClientImc);
-}
-
 static PCLIENTIMC APIENTRY Imm32GetClientImcCache(void)
 {
     // FIXME: Do something properly here
@@ -2501,7 +2699,7 @@ void WINAPI __wine_unregister_window(HWND hwnd)
  */
 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
 {
-    if (!(g_dwImm32Flags & IMM32_FLAG_UNKNOWN))
+    if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
         return NULL;
 
     if (hWnd == NULL)
@@ -2515,7 +2713,7 @@ HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
  */
 BOOL WINAPI CtfImmIsCiceroEnabled(VOID)
 {
-    return !!(g_dwImm32Flags & IMM32_FLAG_CICERO_ENABLED);
+    return (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED));
 }
 
 /***********************************************************************
@@ -3401,8 +3599,8 @@ VOID WINAPI ImmUnlockImeDpi(PIMEDPI pImeDpi)
 
     if ((pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN) == 0)
     {
-        if ((pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN2) == 0 ||
-            (pImeDpi->dwUnknown1 & 1) == 0)
+        if ((pImeDpi->dwFlags & IMEDPI_FLAG_LOCKED) == 0 ||
+            (pImeDpi->ImeInfo.fdwProperty & IME_PROP_END_UNLOAD) == 0)
         {
             RtlLeaveCriticalSection(&g_csImeDpi);
             return;
@@ -4110,11 +4308,11 @@ BOOL WINAPI ImmSetActiveContextConsoleIME(HWND hwnd, 
BOOL fFlag)
 *              ImmRegisterClient(IMM32.@)
 *       ( Undocumented, called from user32.dll )
 */
-BOOL WINAPI ImmRegisterClient(PVOID ptr, /* FIXME: should point to SHAREDINFO 
structure */
-                              HINSTANCE hMod)
+BOOL WINAPI ImmRegisterClient(PSHAREDINFO ptr, HINSTANCE hMod)
 {
-    FIXME("Stub\n");
-    return TRUE;
+    g_SharedInfo = *ptr;
+    g_psi = g_SharedInfo.psi;
+    return Imm32InitInstance(hMod);
 }
 
 /***********************************************************************
@@ -4167,7 +4365,7 @@ ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx,
 
     if (!IS_IME_HKL(hKL))
     {
-        if (g_dwImm32Flags & IMM32_FLAG_CICERO_ENABLED)
+        if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
         {
             pTeb = NtCurrentTeb();
             if (((PW32CLIENTINFO)pTeb->Win32ClientInfo)->W32ClientInfo[0] & 2)
@@ -4181,3 +4379,53 @@ ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx,
 Quit:
     return Imm32GetImeInfoEx(pImeInfoEx, SearchType);
 }
+
+BOOL WINAPI User32InitializeImmEntryTable(DWORD);
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
+{
+    HKL hKL;
+    HWND hWnd;
+    PTEB pTeb;
+
+    TRACE("DllMain(%p, 0x%X, %p)\n", hinstDLL, fdwReason, lpReserved);
+
+    switch (fdwReason)
+    {
+        case DLL_PROCESS_ATTACH:
+            //Imm32GenerateRandomSeed(hinstDLL, 1, lpReserved); // Non-sense
+            if (!Imm32InitInstance(hinstDLL))
+            {
+                ERR("Imm32InitInstance failed\n");
+                return FALSE;
+            }
+            if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC))
+            {
+                ERR("User32InitializeImmEntryTable failed\n");
+                return FALSE;
+            }
+            break;
+
+        case DLL_THREAD_ATTACH:
+            break;
+
+        case DLL_THREAD_DETACH:
+            if (g_psi == NULL || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
+                return TRUE;
+
+            pTeb = NtCurrentTeb();
+            if (pTeb->Win32ThreadInfo == NULL)
+                return TRUE;
+
+            hKL = GetKeyboardLayout(0);
+            hWnd = (HWND)Imm32GetThreadState(THREADSTATE_CAPTUREWINDOW);
+            Imm32CleanupContext(hWnd, hKL, TRUE);
+            break;
+
+        case DLL_PROCESS_DETACH:
+            RtlDeleteCriticalSection(&g_csImeDpi);
+            break;
+    }
+
+    return TRUE;
+}
diff --git a/dll/win32/imm32/imm32.spec b/dll/win32/imm32/imm32.spec
index d7a269dd5be..104e4242fc0 100644
--- a/dll/win32/imm32/imm32.spec
+++ b/dll/win32/imm32/imm32.spec
@@ -68,7 +68,7 @@
 @ stdcall ImmIsIME(long)
 @ stdcall ImmIsUIMessageA(long long long long)
 @ stdcall ImmIsUIMessageW(long long long long)
-@ stdcall -stub ImmLoadIME(long)
+@ stdcall ImmLoadIME(ptr)
 @ stdcall ImmLoadLayout(ptr ptr)
 @ stdcall ImmLockClientImc(ptr)
 @ stdcall ImmLockIMC(ptr)
diff --git a/sdk/include/psdk/imm.h b/sdk/include/psdk/imm.h
index e856648c170..7b0888b033e 100644
--- a/sdk/include/psdk/imm.h
+++ b/sdk/include/psdk/imm.h
@@ -215,6 +215,7 @@ typedef struct tagCANDIDATEINFO {
 #define IME_PROP_IGNORE_UPKEYS          0x0004
 #define IME_PROP_NEED_ALTKEY            0x0008
 #define IME_PROP_NO_KEYS_ON_CLOSE       0x0010
+#define IME_PROP_ACCEPT_WIDE_VKEY       0x0020
 
 /* for NI_CONTEXTUPDATED */
 #define IMC_SETCONVERSIONMODE           0x0002
@@ -381,7 +382,6 @@ DWORD WINAPI ImeGetImeMenuItems(HIMC, DWORD, DWORD, 
LPIMEMENUITEMINFOW, LPIMEMEN
 #define IMEVER_0310                     0x0003000A
 #define IMEVER_0400                     0x00040000
 
-
 /* IME property bits */
 #define IME_PROP_AT_CARET               0x00010000
 #define IME_PROP_SPECIAL_UI             0x00020000
@@ -389,17 +389,17 @@ DWORD WINAPI ImeGetImeMenuItems(HIMC, DWORD, DWORD, 
LPIMEMENUITEMINFOW, LPIMEMEN
 #define IME_PROP_UNICODE                0x00080000
 #define IME_PROP_COMPLETE_ON_UNSELECT  0x00100000
 
-
 /* IME UICapability bits */
 #define UI_CAP_2700                     0x00000001
 #define UI_CAP_ROT90                    0x00000002
 #define UI_CAP_ROTANY                   0x00000004
+#define UI_CAP_SOFTKBD                  0x00010000
+
 /* ImmSetCompositionString Capability bits */
 #define SCS_CAP_COMPSTR                 0x00000001
 #define SCS_CAP_MAKEREAD                0x00000002
 #define SCS_CAP_SETRECONVERTSTRING     0x00000004
 
-
 /* IME WM_IME_SELECT inheritance Capability bits */
 #define SELECT_CAP_CONVERSION           0x00000001
 #define SELECT_CAP_SENTENCE             0x00000002
diff --git a/sdk/include/reactos/imm32_undoc.h 
b/sdk/include/reactos/imm32_undoc.h
index a9a20c49b18..be00e353492 100644
--- a/sdk/include/reactos/imm32_undoc.h
+++ b/sdk/include/reactos/imm32_undoc.h
@@ -7,24 +7,6 @@
 
 #pragma once
 
-/* unconfirmed */
-typedef struct tagCLIENTIMC
-{
-    HIMC hImc;
-    LONG cLockObj;
-    DWORD dwFlags;
-    DWORD unknown;
-    RTL_CRITICAL_SECTION cs;
-    DWORD unknown2;
-    DWORD unknown3;
-    BOOL bUnknown4;
-} CLIENTIMC, *PCLIENTIMC;
-
-/* flags for CLIENTIMC */
-#define CLIENTIMC_WIDE 0x1
-#define CLIENTIMC_UNKNOWN1 0x40
-#define CLIENTIMC_UNKNOWN2 0x100
-
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/win32ss/include/imetable.h b/win32ss/include/imetable.h
new file mode 100644
index 00000000000..5157ec43030
--- /dev/null
+++ b/win32ss/include/imetable.h
@@ -0,0 +1,22 @@
+/* DEFINE_IME_ENTRY(type, name, params, extended) */
+DEFINE_IME_ENTRY(BOOL, ImeInquire, (LPIMEINFO lpIMEInfo, LPWSTR lpszWndClass, 
DWORD dwSystemInfoFlags), FALSE)
+DEFINE_IME_ENTRY(DWORD, ImeConversionList, (HIMC hIMC, LPCWSTR lpSrc, 
LPCANDIDATELIST lpDst, DWORD dwBufLen, UINT uFlag), FALSE)
+DEFINE_IME_ENTRY(BOOL, ImeRegisterWord, (LPCWSTR lpszReading, DWORD dwStyle, 
LPCWSTR lpszString), FALSE)
+DEFINE_IME_ENTRY(BOOL, ImeUnregisterWord, (LPCWSTR lpszReading, DWORD dwStyle, 
LPCWSTR lpszString), FALSE)
+DEFINE_IME_ENTRY(UINT, ImeGetRegisterWordStyle, (UINT nItem, LPSTYLEBUFW 
lpStyleBuf), FALSE)
+DEFINE_IME_ENTRY(UINT, ImeEnumRegisterWord, (HKL hKL, REGISTERWORDENUMPROCW 
lpfnEnumProc, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszString, LPVOID 
lpData), FALSE)
+DEFINE_IME_ENTRY(BOOL, ImeConfigure, (HKL hKL, HWND hWnd, DWORD dwMode, LPVOID 
lpData), FALSE)
+DEFINE_IME_ENTRY(BOOL, ImeDestroy, (UINT uReserved), FALSE)
+DEFINE_IME_ENTRY(LRESULT, ImeEscape, (HIMC hIMC, UINT uEscape, LPVOID lpData), 
FALSE)
+DEFINE_IME_ENTRY(BOOL, ImeSelect, (HIMC hIMC, BOOL fSelect), FALSE)
+DEFINE_IME_ENTRY(BOOL, ImeProcessKey, (HIMC hIMC, UINT uVirKey, DWORD lParam, 
CONST LPBYTE lpbKeyState), FALSE)
+DEFINE_IME_ENTRY(BOOL, ImeSetActiveContext, (HIMC hIMC, BOOL fFlag), FALSE)
+DEFINE_IME_ENTRY(UINT, ImeToAsciiEx, (UINT uVirKey, UINT uScanCode, CONST 
LPBYTE lpbKeyState, /*FIXME: LPTRANSMSGLIST*/ LPVOID lpTransMsgList, UINT 
fuState, HIMC hIMC), FALSE)
+DEFINE_IME_ENTRY(BOOL, NotifyIME, (HIMC hIMC, DWORD dwAction, DWORD dwIndex, 
DWORD dwValue), FALSE)
+DEFINE_IME_ENTRY(BOOL, ImeSetCompositionString, (HIMC hIMC, DWORD dwIndex, 
LPCVOID lpComp, DWORD dwCompLen, LPCVOID lpRead, DWORD dwReadLen), FALSE)
+DEFINE_IME_ENTRY(DWORD, ImeGetImeMenuItems, (HIMC hIMC, DWORD dwFlags, DWORD 
dwType, LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu, DWORD 
dwSize), FALSE)
+DEFINE_IME_ENTRY(DWORD, CtfImeInquireExW, (VOID /* FIXME: unknown */), TRUE)
+DEFINE_IME_ENTRY(DWORD, CtfImeSelectEx, (VOID /* FIXME: unknown */), TRUE)
+DEFINE_IME_ENTRY(DWORD, CtfImeEscapeEx, (VOID /* FIXME: unknown */), TRUE)
+DEFINE_IME_ENTRY(DWORD, CtfImeGetGuidAtom, (VOID /* FIXME: unknown */), TRUE)
+DEFINE_IME_ENTRY(DWORD, CtfImeIsGuidMapEnable, (VOID /* FIXME: unknown */), 
TRUE)
diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h
index 024e9413a0a..26e89fb396a 100644
--- a/win32ss/include/ntuser.h
+++ b/win32ss/include/ntuser.h
@@ -912,7 +912,7 @@ typedef LONG_PTR
 #define SRVINFO_DBCSENABLED 0x0002
 #define SRVINFO_IMM32       0x0004
 #define SRVINFO_APIHOOK     0x0010
-#define SRVINFO_METRICS     0x0020
+#define SRVINFO_CICERO_ENABLED 0x0020
 #define SRVINFO_KBDPREF     0x0080
 
 #define NUM_SYSCOLORS 31
@@ -1212,42 +1212,88 @@ typedef struct _IMEWND
     PIMEUI pimeui;
 } IMEWND, *PIMEWND;
 
-typedef BOOL (WINAPI *FN_ImeDestroy)(UINT uReserved);
-typedef LRESULT (WINAPI *FN_ImeEscape)(HIMC hIMC, UINT uEscape, LPVOID lpData);
-typedef BOOL (WINAPI *FN_NotifyIME)(HIMC hIMC, DWORD dwAction, DWORD dwIndex, 
DWORD dwValue);
+#define DEFINE_IME_ENTRY(type, name, params, extended) typedef type (WINAPI 
*FN_##name) params;
+#include "imetable.h"
+#undef DEFINE_IME_ENTRY
 
-typedef struct IMEDPI /* unconfirmed */
+typedef struct IMEDPI
 {
     struct IMEDPI *pNext;
     HINSTANCE      hInst;
     HKL            hKL;
-    DWORD          dwUnknown0;
-    DWORD          dwUnknown1;
-    DWORD          dwUnknown2[14];
+    IMEINFO        ImeInfo;
+    UINT           uCodePage;
+    WCHAR          szUIClass[16];
     DWORD          cLockObj;
     DWORD          dwFlags;
-    DWORD          dwUnknown3[7];
-    FN_ImeDestroy  ImeDestroy;
-    FN_ImeEscape   ImeEscape;
-    DWORD          dwUnknown4[4];
-    FN_NotifyIME   NotifyIME;
-    /* ... */
+#define DEFINE_IME_ENTRY(type, name, params, extended) FN_##name name;
+#include "imetable.h"
+#undef DEFINE_IME_ENTRY
 } IMEDPI, *PIMEDPI;
 
 #ifndef _WIN64
 C_ASSERT(offsetof(IMEDPI, pNext) == 0x0);
 C_ASSERT(offsetof(IMEDPI, hInst) == 0x4);
 C_ASSERT(offsetof(IMEDPI, hKL) == 0x8);
+C_ASSERT(offsetof(IMEDPI, ImeInfo) == 0xc);
+C_ASSERT(offsetof(IMEDPI, uCodePage) == 0x28);
+C_ASSERT(offsetof(IMEDPI, szUIClass) == 0x2c);
 C_ASSERT(offsetof(IMEDPI, cLockObj) == 0x4c);
 C_ASSERT(offsetof(IMEDPI, dwFlags) == 0x50);
+C_ASSERT(offsetof(IMEDPI, ImeInquire) == 0x54);
+C_ASSERT(offsetof(IMEDPI, ImeConversionList) == 0x58);
+C_ASSERT(offsetof(IMEDPI, ImeRegisterWord) == 0x5c);
+C_ASSERT(offsetof(IMEDPI, ImeUnregisterWord) == 0x60);
+C_ASSERT(offsetof(IMEDPI, ImeGetRegisterWordStyle) == 0x64);
+C_ASSERT(offsetof(IMEDPI, ImeEnumRegisterWord) == 0x68);
+C_ASSERT(offsetof(IMEDPI, ImeConfigure) == 0x6c);
 C_ASSERT(offsetof(IMEDPI, ImeDestroy) == 0x70);
 C_ASSERT(offsetof(IMEDPI, ImeEscape) == 0x74);
+C_ASSERT(offsetof(IMEDPI, ImeSelect) == 0x78);
+C_ASSERT(offsetof(IMEDPI, ImeProcessKey) == 0x7c);
+C_ASSERT(offsetof(IMEDPI, ImeSetActiveContext) == 0x80);
+C_ASSERT(offsetof(IMEDPI, ImeToAsciiEx) == 0x84);
 C_ASSERT(offsetof(IMEDPI, NotifyIME) == 0x88);
+C_ASSERT(offsetof(IMEDPI, ImeSetCompositionString) == 0x8c);
+C_ASSERT(offsetof(IMEDPI, ImeGetImeMenuItems) == 0x90);
+C_ASSERT(offsetof(IMEDPI, CtfImeInquireExW) == 0x94);
+C_ASSERT(offsetof(IMEDPI, CtfImeSelectEx) == 0x98);
+C_ASSERT(offsetof(IMEDPI, CtfImeEscapeEx) == 0x9c);
+C_ASSERT(offsetof(IMEDPI, CtfImeGetGuidAtom) == 0xa0);
+C_ASSERT(offsetof(IMEDPI, CtfImeIsGuidMapEnable) == 0xa4);
+C_ASSERT(sizeof(IMEDPI) == 0xa8);
 #endif
 
 /* flags for IMEDPI.dwFlags */
-#define IMEDPI_FLAG_UNKNOWN 1
-#define IMEDPI_FLAG_UNKNOWN2 2
+#define IMEDPI_FLAG_UNKNOWN 0x1
+#define IMEDPI_FLAG_LOCKED 0x2
+
+/* unconfirmed */
+typedef struct tagCLIENTIMC
+{
+    HIMC hImc;
+    LONG cLockObj;
+    DWORD dwFlags;
+    DWORD unknown;
+    RTL_CRITICAL_SECTION cs;
+    DWORD unknown2;
+    HKL hKL;
+    BOOL bUnknown4;
+} CLIENTIMC, *PCLIENTIMC;
+
+#ifndef _WIN64
+C_ASSERT(offsetof(CLIENTIMC, hImc) == 0x0);
+C_ASSERT(offsetof(CLIENTIMC, cLockObj) == 0x4);
+C_ASSERT(offsetof(CLIENTIMC, dwFlags) == 0x8);
+C_ASSERT(offsetof(CLIENTIMC, cs) == 0x10);
+C_ASSERT(offsetof(CLIENTIMC, hKL) == 0x2c);
+C_ASSERT(sizeof(CLIENTIMC) == 0x34);
+#endif
+
+/* flags for CLIENTIMC */
+#define CLIENTIMC_WIDE 0x1
+#define CLIENTIMC_UNKNOWN1 0x40
+#define CLIENTIMC_UNKNOWN2 0x100
 
 DWORD
 NTAPI
@@ -1869,10 +1915,9 @@ NtUserCreateDesktop(
     DWORD dwFlags,
     ACCESS_MASK dwDesiredAccess);
 
-DWORD
+HIMC
 NTAPI
-NtUserCreateInputContext(
-    DWORD dwUnknown1);
+NtUserCreateInputContext(PCLIENTIMC pClientImc);
 
 NTSTATUS
 NTAPI
@@ -1964,10 +2009,9 @@ NtUserDestroyCursor(
   _In_ HANDLE Handle,
   _In_ BOOL bForce);
 
-DWORD
+BOOL
 NTAPI
-NtUserDestroyInputContext(
-    DWORD dwUnknown1);
+NtUserDestroyInputContext(HIMC hIMC);
 
 BOOLEAN
 NTAPI
@@ -3130,9 +3174,7 @@ NtUserSetImeInfoEx(
 
 DWORD
 NTAPI
-NtUserSetImeOwnerWindow(
-    DWORD Unknown0,
-    DWORD Unknown1);
+NtUserSetImeOwnerWindow(PIMEINFOEX pImeInfoEx, BOOL fFlag);
 
 DWORD
 NTAPI
diff --git a/win32ss/user/ntuser/ime.c b/win32ss/user/ntuser/ime.c
index dd5ccbc874a..cac0d64b662 100644
--- a/win32ss/user/ntuser/ime.c
+++ b/win32ss/user/ntuser/ime.c
@@ -133,11 +133,9 @@ NtUserSetImeInfoEx(
 }
 
 DWORD APIENTRY
-NtUserSetImeOwnerWindow(DWORD Unknown0,
-                        DWORD Unknown1)
+NtUserSetImeOwnerWindow(PIMEINFOEX pImeInfoEx, BOOL fFlag)
 {
    STUB
-
    return 0;
 }
 
diff --git a/win32ss/user/ntuser/metric.c b/win32ss/user/ntuser/metric.c
index df7138b999b..cae66b0807d 100644
--- a/win32ss/user/ntuser/metric.c
+++ b/win32ss/user/ntuser/metric.c
@@ -169,7 +169,7 @@ InitMetrics(VOID)
     piSysMet[90] = 0;
 #endif
 
-    gpsi->dwSRVIFlags |= SRVINFO_METRICS;
+    gpsi->dwSRVIFlags |= SRVINFO_CICERO_ENABLED;
     Setup = TRUE;
 
     return TRUE;
diff --git a/win32ss/user/ntuser/ntstubs.c b/win32ss/user/ntuser/ntstubs.c
index 9ee6b4f8a39..c770f883e25 100644
--- a/win32ss/user/ntuser/ntstubs.c
+++ b/win32ss/user/ntuser/ntstubs.c
@@ -419,22 +419,20 @@ NtUserYieldTask(VOID)
    return 0;
 }
 
-DWORD
+HIMC
 APIENTRY
-NtUserCreateInputContext(
-    DWORD dwUnknown1)
+NtUserCreateInputContext(PCLIENTIMC pClientImc)
 {
     STUB;
-    return 0;
+    return NULL;
 }
 
-DWORD
+BOOL
 APIENTRY
-NtUserDestroyInputContext(
-    DWORD dwUnknown1)
+NtUserDestroyInputContext(HIMC hIMC)
 {
     STUB;
-    return 0;
+    return FALSE;
 }
 
 DWORD

Reply via email to