[IMM32] Imm(Lock|Unlock)ImeDpi and ImmSetOpenStatus (#3830)
authorKatayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
Sun, 25 Jul 2021 02:57:57 +0000 (11:57 +0900)
committerGitHub <noreply@github.com>
Sun, 25 Jul 2021 02:57:57 +0000 (11:57 +0900)
- Add IMEDPI structure to ntuser.h.
- Implement ImmLockImeDpi/ImmUnlockImeDpi functions.
- Rewrite ImmSetOpenStatus function.
- Modify some NTUSER function prototypes.
- Modify imm32.spec.
CORE-11700

dll/win32/imm32/imm.c
dll/win32/imm32/imm32.spec
sdk/include/reactos/imm32_undoc.h
win32ss/include/ntuser.h
win32ss/user/ntuser/ime.c
win32ss/user/ntuser/ntstubs.c

index 53c13d2..66c740a 100644 (file)
@@ -48,8 +48,63 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm);
 #define IMM_INIT_MAGIC 0x19650412
 #define IMM_INVALID_CANDFORM ULONG_MAX
 
+RTL_CRITICAL_SECTION g_csImeDpi;
+PIMEDPI g_pImeDpiList = NULL;
+
 BOOL WINAPI User32InitializeImmEntryTable(DWORD);
 
+static DWORD APIENTRY Imm32QueryInputContext(HIMC hIMC, DWORD dwUnknown2)
+{
+    return NtUserQueryInputContext(hIMC, dwUnknown2);
+}
+
+static DWORD APIENTRY Imm32NotifyIMEStatus(HWND hwnd, HIMC hIMC, DWORD dwConversion)
+{
+    return NtUserNotifyIMEStatus(hwnd, hIMC, dwConversion);
+}
+
+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 = Imm32QueryInputContext(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;
+}
+
 typedef struct _tagImmHkl{
     struct list entry;
     HKL         hkl;
@@ -2951,40 +3006,119 @@ BOOL WINAPI ImmSetConversionStatus(
     return TRUE;
 }
 
+/***********************************************************************
+ *             ImmLockImeDpi (IMM32.@)
+ */
+PIMEDPI WINAPI ImmLockImeDpi(HKL hKL)
+{
+    PIMEDPI pImeDpi = NULL;
+
+    TRACE("ImmLockImeDpi(%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("ImmUnlockImeDpi(%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_UNKNOWN2) == 0 ||
+            (pImeDpi->dwUnknown1 & 1) == 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);
+}
+
 /***********************************************************************
  *             ImmSetOpenStatus (IMM32.@)
  */
 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
 {
-    InputContextData *data = get_imc_data(hIMC);
+    DWORD idImeThread, idThread, dwConversion;
+    LPINPUTCONTEXT pIC;
+    HWND hWnd;
+    BOOL bHasChange = FALSE;
 
-    TRACE("%p %d\n", hIMC, fOpen);
+    TRACE("ImmSetOpenStatus(%p, %d)\n", hIMC, fOpen);
 
-    if (!data)
-    {
-        SetLastError(ERROR_INVALID_HANDLE);
+    idImeThread = Imm32QueryInputContext(hIMC, 1);
+    idThread = GetCurrentThreadId();
+    if (idImeThread != idThread)
         return FALSE;
-    }
 
-    if (IMM_IsCrossThreadAccess(NULL, hIMC))
+    pIC = ImmLockIMC(hIMC);
+    if (pIC == NULL)
         return FALSE;
 
-    if (data->immKbd->UIWnd == NULL)
+    if (pIC->fOpen != fOpen)
     {
-        /* create the ime window */
-        data->immKbd->UIWnd = CreateWindowExW( WS_EX_TOOLWINDOW,
-                    data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0,
-                    0, data->immKbd->hIME, 0);
-        SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
+        pIC->fOpen = fOpen;
+        hWnd = pIC->hWnd;
+        dwConversion = pIC->fdwConversion;
+        bHasChange = TRUE;
     }
-    else if (fOpen)
-        SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
 
-    if (!fOpen != !data->IMC.fOpen)
+    ImmUnlockIMC(hIMC);
+
+    if (bHasChange)
     {
-        data->IMC.fOpen = fOpen;
-        ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS);
-        ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0);
+        Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0,
+                          IMC_SETOPENSTATUS, IMN_SETOPENSTATUS, 0);
+        Imm32NotifyIMEStatus(hWnd, hIMC, dwConversion);
     }
 
     return TRUE;
index 3c95067..365d672 100644 (file)
@@ -73,7 +73,7 @@
 @ stdcall ImmLockClientImc(ptr)
 @ stdcall ImmLockIMC(ptr)
 @ stdcall ImmLockIMCC(ptr)
-@ stdcall -stub ImmLockImeDpi(long)
+@ stdcall ImmLockImeDpi(ptr)
 @ stdcall ImmNotifyIME(ptr long long long)
 @ stub ImmPenAuxInput
 @ stdcall ImmProcessKey(ptr long long long long)
 @ stdcall ImmUnlockClientImc(ptr)
 @ stdcall ImmUnlockIMC(ptr)
 @ stdcall ImmUnlockIMCC(ptr)
-@ stdcall -stub ImmUnlockImeDpi(ptr)
+@ stdcall ImmUnlockImeDpi(ptr)
 @ stdcall ImmUnregisterWordA(long str long str)
 @ stdcall ImmUnregisterWordW(long wstr long wstr)
 @ stdcall -stub ImmWINNLSEnableIME(ptr long)
index a2b068f..a9a20c4 100644 (file)
@@ -34,6 +34,8 @@ ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx, IMEINFOEXCLASS SearchType, PVOID pvSearch
 
 PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc);
 VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc);
+PIMEDPI WINAPI ImmLockImeDpi(HKL hKL);
+VOID WINAPI ImmUnlockImeDpi(PIMEDPI pImeDpi);
 
 #ifdef __cplusplus
 } // extern "C"
index cc454ba..7c30a21 100644 (file)
@@ -1212,6 +1212,40 @@ typedef struct _IMEWND
     PIMEUI pimeui;
 } IMEWND, *PIMEWND;
 
+typedef BOOL (WINAPI *FN_ImeDestroy)(UINT uReserved);
+typedef BOOL (WINAPI *FN_NotifyIME)(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue);
+
+typedef struct IMEDPI /* unconfirmed */
+{
+    struct IMEDPI *pNext;
+    HINSTANCE      hInst;
+    HKL            hKL;
+    DWORD          dwUnknown0;
+    DWORD          dwUnknown1;
+    DWORD          dwUnknown2[14];
+    DWORD          cLockObj;
+    DWORD          dwFlags;
+    DWORD          dwUnknown3[7];
+    FN_ImeDestroy  ImeDestroy;
+    DWORD          dwUnknown4[5];
+    FN_NotifyIME   NotifyIME;
+    /* ... */
+} 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, cLockObj) == 0x4c);
+C_ASSERT(offsetof(IMEDPI, dwFlags) == 0x50);
+C_ASSERT(offsetof(IMEDPI, ImeDestroy) == 0x70);
+C_ASSERT(offsetof(IMEDPI, NotifyIME) == 0x88);
+#endif
+
+/* flags for IMEDPI.dwFlags */
+#define IMEDPI_FLAG_UNKNOWN 1
+#define IMEDPI_FLAG_UNKNOWN2 2
+
 DWORD
 NTAPI
 NtUserAssociateInputContext(
@@ -2676,9 +2710,9 @@ NtUserMoveWindow(
 DWORD
 NTAPI
 NtUserNotifyIMEStatus(
-    DWORD Unknown0,
-    DWORD Unknown1,
-    DWORD Unknown2);
+    HWND hwnd,
+    HIMC hIMC,
+    DWORD dwConversion);
 
 BOOL
 NTAPI
@@ -2787,7 +2821,7 @@ NtUserQueryInformationThread(
 DWORD
 NTAPI
 NtUserQueryInputContext(
-    DWORD dwUnknown1,
+    HIMC hIMC,
     DWORD dwUnknown2);
 
 DWORD
index 4b58766..dd5ccbc 100644 (file)
@@ -50,13 +50,12 @@ NtUserGetImeHotKey(IN DWORD dwHotKey,
 DWORD
 APIENTRY
 NtUserNotifyIMEStatus(
-   DWORD Unknown0,
-   DWORD Unknown1,
-   DWORD Unknown2)
+    HWND hwnd,
+    HIMC hIMC,
+    DWORD dwConversion)
 {
-   STUB
-
-   return 0;
+    TRACE("NtUserNotifyIMEStatus(%p, %p, 0x%lX)\n", hwnd, hIMC, dwConversion);
+    return 0;
 }
 
 
index 87d2c3e..5ebde8b 100644 (file)
@@ -630,10 +630,10 @@ Quit:
 DWORD
 APIENTRY
 NtUserQueryInputContext(
-    DWORD dwUnknown1,
+    HIMC hIMC,
     DWORD dwUnknown2)
 {
-    STUB;
+    TRACE("NtUserQueryInputContext(%p, 0x%lX)\n", hIMC, dwUnknown2);
     return 0;
 }