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

commit b5c9d532e83c7a2d0d10863b26e2592c6f74bcce
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Sat Feb 12 08:32:13 2022 +0900
Commit:     GitHub <[email protected]>
CommitDate: Sat Feb 12 08:32:13 2022 +0900

    [NTUSER][USER32] Implement IntImmProcessKey (#4353)
    
    - Establish the trampoline callback USER32_CALLBACK_IMMPROCESSKEY for 
imm32!ImmProcessKey function, between NTUSER and IMM32.
    - Add IntGetImeCompatFlags helper function.
    - Implement co_IntImmProcessKey and IntImmProcessKey functions.
    CORE-11700
---
 win32ss/include/callback.h         |  14 ++-
 win32ss/user/ntuser/callback.c     |  24 +++++
 win32ss/user/ntuser/callback.h     |   4 +
 win32ss/user/ntuser/ime.c          | 197 ++++++++++++++++++++++++++++++++-----
 win32ss/user/user32/misc/dllmain.c |  15 ++-
 5 files changed, 226 insertions(+), 28 deletions(-)

diff --git a/win32ss/include/callback.h b/win32ss/include/callback.h
index 7eef1d6c278..a75a6de3803 100644
--- a/win32ss/include/callback.h
+++ b/win32ss/include/callback.h
@@ -19,7 +19,8 @@
 #define USER32_CALLBACK_SETOBM                (15)
 #define USER32_CALLBACK_LPK                   (16)
 #define USER32_CALLBACK_UMPD                  (17)
-#define USER32_CALLBACK_MAXIMUM               (17)
+#define USER32_CALLBACK_IMMPROCESSKEY         (18)
+#define USER32_CALLBACK_MAXIMUM               (18)
 
 typedef struct _WINDOWPROC_CALLBACK_ARGUMENTS
 {
@@ -168,6 +169,15 @@ typedef struct _LPK_CALLBACK_ARGUMENTS
     BOOL bRect;
 } LPK_CALLBACK_ARGUMENTS, *PLPK_CALLBACK_ARGUMENTS;
 
+typedef struct _IMMPROCESSKEY_CALLBACK_ARGUMENTS
+{
+    HWND    hWnd;
+    HKL     hKL;
+    UINT    vKey;
+    LPARAM  lParam;
+    DWORD   dwHotKeyID;
+} IMMPROCESSKEY_CALLBACK_ARGUMENTS, *PIMMPROCESSKEY_CALLBACK_ARGUMENTS;
+
 NTSTATUS WINAPI
 User32CallCopyImageFromKernel(PVOID Arguments, ULONG ArgumentLength);
 NTSTATUS WINAPI
@@ -204,4 +214,6 @@ NTSTATUS WINAPI
 User32CallLPKFromKernel(PVOID Arguments, ULONG ArgumentLength);
 NTSTATUS WINAPI
 User32CallUMPDFromKernel(PVOID Arguments, ULONG ArgumentLength);
+NTSTATUS WINAPI
+User32CallImmProcessKeyFromKernel(PVOID Arguments, ULONG ArgumentLength);
 #endif /* __INCLUDE_USER32_CALLBACK_H */
diff --git a/win32ss/user/ntuser/callback.c b/win32ss/user/ntuser/callback.c
index 25e6eee5dd7..9b5ac56965a 100644
--- a/win32ss/user/ntuser/callback.c
+++ b/win32ss/user/ntuser/callback.c
@@ -1247,4 +1247,28 @@ co_UserCBClientPrinterThunk( PVOID pkt, INT InSize, 
PVOID pvOutData, INT OutSize
    return 0;
 }
 
+DWORD
+APIENTRY
+co_IntImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam, DWORD 
dwHotKeyID)
+{
+    DWORD ret = 0;
+    NTSTATUS Status;
+    ULONG ResultLength = sizeof(DWORD);
+    PVOID ResultPointer = NULL;
+    IMMPROCESSKEY_CALLBACK_ARGUMENTS Common = { hWnd, hKL, vKey, lParam, 
dwHotKeyID };
+
+    UserLeaveCo();
+    Status = KeUserModeCallback(USER32_CALLBACK_IMMPROCESSKEY,
+                                &Common,
+                                sizeof(Common),
+                                &ResultPointer,
+                                &ResultLength);
+    UserEnterCo();
+
+    if (NT_SUCCESS(Status))
+        ret = *(LPDWORD)ResultPointer;
+
+    return ret;
+}
+
 /* EOF */
diff --git a/win32ss/user/ntuser/callback.h b/win32ss/user/ntuser/callback.h
index c83be89a976..79217f86425 100644
--- a/win32ss/user/ntuser/callback.h
+++ b/win32ss/user/ntuser/callback.h
@@ -76,3 +76,7 @@ BOOL FASTCALL co_IntSetWndIcons(VOID);
 VOID FASTCALL co_IntDeliverUserAPC(VOID);
 VOID FASTCALL co_IntSetupOBM(VOID);
 BOOL FASTCALL 
IntMsgCreateStructW(PWND,CREATESTRUCTW*,CREATESTRUCTW*,PVOID*,PVOID*);
+
+DWORD
+APIENTRY
+co_IntImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam, DWORD 
dwHotKeyID);
diff --git a/win32ss/user/ntuser/ime.c b/win32ss/user/ntuser/ime.c
index 1ea65ef512b..f7c67164c4e 100644
--- a/win32ss/user/ntuser/ime.c
+++ b/win32ss/user/ntuser/ime.c
@@ -58,6 +58,14 @@ typedef struct tagIMEHOTKEY
 PIMEHOTKEY gpImeHotKeyList = NULL;
 LCID glcid = 0;
 
+DWORD FASTCALL IntGetImeCompatFlags(PTHREADINFO pti)
+{
+    if (!pti)
+        pti = PsGetCurrentThreadWin32Thread();
+
+    return pti->ppi->dwImeCompatFlags;
+}
+
 UINT FASTCALL IntGetImeHotKeyLanguageScore(HKL hKL, LANGID HotKeyLangId)
 {
     LCID lcid;
@@ -343,7 +351,10 @@ IntSetImeHotKey(DWORD dwHotKeyId, UINT uModifiers, UINT 
uVirtualKey, HKL hKL, DW
         case SETIMEHOTKEY_DELETE:
             pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId);
             if (!pNode)
+            {
+                ERR("dwHotKeyId: 0x%lX\n", dwHotKeyId);
                 return FALSE;
+            }
 
             IntDeleteImeHotKey(&gpImeHotKeyList, pNode);
             return TRUE;
@@ -550,29 +561,122 @@ DWORD FASTCALL UserBuildHimcList(PTHREADINFO pti, DWORD 
dwCount, HIMC *phList)
 }
 
 UINT FASTCALL
-IntImmProcessKey(PUSER_MESSAGE_QUEUE MessageQueue, PWND pWnd, UINT Msg, WPARAM 
wParam, LPARAM lParam)
+IntImmProcessKey(PUSER_MESSAGE_QUEUE MessageQueue, PWND pWnd, UINT uMsg,
+                 WPARAM wParam, LPARAM lParam)
 {
-    PKL pKbdLayout;
+    UINT uVirtualKey, ret = 0;
+    DWORD dwHotKeyId;
+    PKL pKL;
+    PIMC pIMC = NULL;
+    PIMEHOTKEY pImeHotKey;
+    HKL hKL;
+    HWND hWnd;
 
     ASSERT_REFS_CO(pWnd);
 
-    if ( Msg == WM_KEYDOWN ||
-         Msg == WM_SYSKEYDOWN ||
-         Msg == WM_KEYUP ||
-         Msg == WM_SYSKEYUP )
-    {
-       //Vk = wParam & 0xff;
-       pKbdLayout = pWnd->head.pti->KeyboardLayout;
-       if (pKbdLayout == NULL) return 0;
-       //
-       if (!(gpsi->dwSRVIFlags & SRVINFO_IMM32)) return 0;
-       // need ime.h!
-    }
-    // Call User32:
-    // Anything but BOOL!
-    //ImmRet = co_IntImmProcessKey(UserHMGetHandle(pWnd), pKbdLayout->hkl, Vk, 
lParam, HotKey);
-    FIXME(" is UNIMPLEMENTED.\n");
-    return 0;
+    switch (uMsg)
+    {
+        case WM_KEYDOWN:
+        case WM_KEYUP:
+        case WM_SYSKEYDOWN:
+        case WM_SYSKEYUP:
+            break;
+
+        default:
+            return 0;
+    }
+
+    hWnd = UserHMGetHandle(pWnd);
+    pKL = pWnd->head.pti->KeyboardLayout;
+    if (!pKL)
+        return 0;
+
+    uVirtualKey = LOBYTE(wParam);
+    pImeHotKey = IntCheckImeHotKey(MessageQueue, uVirtualKey, lParam);
+    if (pImeHotKey)
+    {
+        dwHotKeyId = pImeHotKey->dwHotKeyId;
+        hKL = pImeHotKey->hKL;
+    }
+    else
+    {
+        dwHotKeyId = INVALID_HOTKEY;
+        hKL = NULL;
+    }
+
+    if (IME_HOTKEY_DSWITCH_FIRST <= dwHotKeyId && dwHotKeyId <= 
IME_HOTKEY_DSWITCH_LAST)
+    {
+        if (pKL->hkl != hKL)
+        {
+            UserPostMessage(hWnd, WM_INPUTLANGCHANGEREQUEST,
+                            ((pKL->dwFontSigs & gSystemFS) ? 
INPUTLANGCHANGE_SYSCHARSET : 0),
+                            (LPARAM)hKL);
+        }
+
+        if (IntGetImeCompatFlags(pWnd->head.pti) & 0x800000)
+            return 0;
+
+        return IPHK_HOTKEY;
+    }
+
+    if (!IS_IMM_MODE())
+        return 0;
+
+    if (dwHotKeyId == INVALID_HOTKEY)
+    {
+        if (!pKL->piiex)
+            return 0;
+
+        if (pWnd->hImc)
+            pIMC = UserGetObject(gHandleTable, pWnd->hImc, TYPE_INPUTCONTEXT);
+        if (!pIMC)
+            return 0;
+
+        if ((lParam & 0x80000000) &&
+            (pKL->piiex->ImeInfo.fdwProperty & IME_PROP_IGNORE_UPKEYS))
+        {
+            return 0;
+        }
+
+        switch (uVirtualKey)
+        {
+            case VK_DBE_CODEINPUT:
+            case VK_DBE_ENTERCONFIGMODE:
+            case VK_DBE_ENTERWORDREGISTERMODE:
+            case VK_DBE_HIRAGANA:
+            case VK_DBE_KATAKANA:
+            case VK_DBE_NOCODEINPUT:
+            case VK_DBE_NOROMAN:
+            case VK_DBE_ROMAN:
+                break;
+
+            default:
+            {
+                if (uMsg == WM_SYSKEYDOWN || uMsg == WM_SYSKEYUP)
+                {
+                    if (uVirtualKey != VK_MENU && uVirtualKey != VK_F10)
+                        return 0;
+                }
+
+                if (!(pKL->piiex->ImeInfo.fdwProperty & IME_PROP_NEED_ALTKEY))
+                {
+                    if (uVirtualKey == VK_MENU || (lParam & 0x20000000))
+                        return 0;
+                }
+                break;
+            }
+        }
+    }
+
+    if (LOBYTE(uVirtualKey) == VK_PACKET)
+        uVirtualKey = MAKELONG(wParam, GetW32ThreadInfo()->wchInjected);
+
+    ret = co_IntImmProcessKey(hWnd, pKL->hkl, uVirtualKey, lParam, dwHotKeyId);
+
+    if (IntGetImeCompatFlags(pWnd->head.pti) & 0x800000)
+        ret &= ~IPHK_HOTKEY;
+
+    return ret;
 }
 
 NTSTATUS
@@ -587,6 +691,7 @@ NtUserBuildHimcList(DWORD dwThreadId, DWORD dwCount, HIMC 
*phList, LPDWORD pdwCo
 
     if (!IS_IMM_MODE())
     {
+        ERR("!IS_IMM_MODE()\n");
         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
         goto Quit;
     }
@@ -695,8 +800,14 @@ NtUserNotifyIMEStatus(HWND hwnd, BOOL fOpen, DWORD 
dwConversion)
 
     UserEnterExclusive();
 
+    if (!IS_IMM_MODE())
+    {
+        ERR("!IS_IMM_MODE()\n");
+        goto Quit;
+    }
+
     pwnd = ValidateHwndNoErr(hwnd);
-    if (!pwnd || !IS_IMM_MODE())
+    if (!pwnd)
         goto Quit;
 
     pti = pwnd->head.pti;
@@ -741,6 +852,7 @@ NtUserDisableThreadIme(
 
     if (!IS_IMM_MODE())
     {
+        ERR("!IS_IMM_MODE()\n");
         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
         goto Quit;
     }
@@ -812,6 +924,7 @@ NtUserGetAppImeLevel(HWND hWnd)
 
     if (!IS_IMM_MODE())
     {
+        ERR("!IS_IMM_MODE()\n");
         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
         goto Quit;
     }
@@ -886,7 +999,10 @@ NtUserGetImeInfoEx(
     UserEnterShared();
 
     if (!IS_IMM_MODE())
+    {
+        ERR("!IS_IMM_MODE()\n");
         goto Quit;
+    }
 
     _SEH2_TRY
     {
@@ -928,16 +1044,17 @@ NtUserSetAppImeLevel(HWND hWnd, DWORD dwLevel)
 
     UserEnterExclusive();
 
-    pWnd = ValidateHwndNoErr(hWnd);
-    if (!pWnd)
-        goto Quit;
-
     if (!IS_IMM_MODE())
     {
+        ERR("!IS_IMM_MODE()\n");
         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
         goto Quit;
     }
 
+    pWnd = ValidateHwndNoErr(hWnd);
+    if (!pWnd)
+        goto Quit;
+
     pti = PsGetCurrentThreadWin32Thread();
     if (pWnd->head.pti->ppi == pti->ppi)
         ret = UserSetProp(pWnd, AtomImeLevel, (HANDLE)(ULONG_PTR)dwLevel, 
TRUE);
@@ -983,7 +1100,10 @@ NtUserSetImeInfoEx(PIMEINFOEX pImeInfoEx)
     UserEnterExclusive();
 
     if (!IS_IMM_MODE())
+    {
+        ERR("!IS_IMM_MODE()\n");
         goto Quit;
+    }
 
     _SEH2_TRY
     {
@@ -1012,8 +1132,14 @@ NtUserSetImeOwnerWindow(HWND hImeWnd, HWND hwndFocus)
 
     UserEnterExclusive();
 
+    if (!IS_IMM_MODE())
+    {
+        ERR("!IS_IMM_MODE()\n");
+        goto Quit;
+    }
+
     pImeWnd = ValidateHwndNoErr(hImeWnd);
-    if (!IS_IMM_MODE() || !pImeWnd || pImeWnd->fnid != FNID_IME)
+    if (!pImeWnd || pImeWnd->fnid != FNID_IME)
         goto Quit;
 
     pwndFocus = ValidateHwndNoErr(hwndFocus);
@@ -1140,6 +1266,7 @@ BOOL NTAPI NtUserDestroyInputContext(HIMC hIMC)
 
     if (!IS_IMM_MODE())
     {
+        ERR("!IS_IMM_MODE()\n");
         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
         goto Quit;
     }
@@ -1185,7 +1312,10 @@ PIMC FASTCALL UserCreateInputContext(ULONG_PTR 
dwClientImcData)
     PDESKTOP pdesk = pti->rpdesk;
 
     if (!IS_IMM_MODE() || (pti->TIF_flags & TIF_DISABLEIME)) // Disabled?
+    {
+        ERR("IME is disabled\n");
         return NULL;
+    }
 
     if (!pdesk) // No desktop?
         return NULL;
@@ -1232,7 +1362,10 @@ NtUserCreateInputContext(ULONG_PTR dwClientImcData)
     UserEnterExclusive();
 
     if (!IS_IMM_MODE())
+    {
+        ERR("!IS_IMM_MODE()\n");
         goto Quit;
+    }
 
     pIMC = UserCreateInputContext(dwClientImcData);
     if (pIMC)
@@ -1317,8 +1450,14 @@ NtUserAssociateInputContext(HWND hWnd, HIMC hIMC, DWORD 
dwFlags)
 
     UserEnterExclusive();
 
+    if (!IS_IMM_MODE())
+    {
+        ERR("!IS_IMM_MODE()\n");
+        goto Quit;
+    }
+
     pWnd = ValidateHwndNoErr(hWnd);
-    if (!pWnd || !IS_IMM_MODE())
+    if (!pWnd)
         goto Quit;
 
     pIMC = (hIMC ? UserGetObjectNoErr(gHandleTable, hIMC, TYPE_INPUTCONTEXT) : 
NULL);
@@ -1373,7 +1512,10 @@ NtUserUpdateInputContext(
     UserEnterExclusive();
 
     if (!IS_IMM_MODE())
+    {
+        ERR("!IS_IMM_MODE()\n");
         goto Quit;
+    }
 
     pIMC = UserGetObject(gHandleTable, hIMC, TYPE_INPUTCONTEXT);
     if (!pIMC)
@@ -1397,7 +1539,10 @@ NtUserQueryInputContext(HIMC hIMC, DWORD dwType)
     UserEnterExclusive();
 
     if (!IS_IMM_MODE())
+    {
+        ERR("!IS_IMM_MODE()\n");
         goto Quit;
+    }
 
     pIMC = UserGetObject(gHandleTable, hIMC, TYPE_INPUTCONTEXT);
     if (!pIMC)
diff --git a/win32ss/user/user32/misc/dllmain.c 
b/win32ss/user/user32/misc/dllmain.c
index 72f82aa1b43..ab5e6fcf825 100644
--- a/win32ss/user/user32/misc/dllmain.c
+++ b/win32ss/user/user32/misc/dllmain.c
@@ -223,10 +223,10 @@ PVOID apfnDispatch[USER32_CALLBACK_MAXIMUM + 1] =
     User32CallOBMFromKernel,
     User32CallLPKFromKernel,
     User32CallUMPDFromKernel,
+    User32CallImmProcessKeyFromKernel,
 };
 
 
-
 VOID
 WINAPI
 GdiProcessSetup(VOID);
@@ -712,3 +712,16 @@ NTSTATUS WINAPI User32CallUMPDFromKernel(PVOID Arguments, 
ULONG ArgumentLength)
     }
     return ZwCallbackReturn( pktOut, cbSize, Status );
 }
+
+NTSTATUS WINAPI
+User32CallImmProcessKeyFromKernel(PVOID Arguments, ULONG ArgumentLength)
+{
+    PIMMPROCESSKEY_CALLBACK_ARGUMENTS Common = Arguments;
+    DWORD Result = IMM_FN(ImmProcessKey)(Common->hWnd,
+                                         Common->hKL,
+                                         Common->vKey,
+                                         Common->lParam,
+                                         Common->dwHotKeyID);
+
+    return ZwCallbackReturn(&Result, sizeof(DWORD), STATUS_SUCCESS);
+}

Reply via email to