https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b5c9d532e83c7a2d0d108…
commit b5c9d532e83c7a2d0d10863b26e2592c6f74bcce
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Sat Feb 12 08:32:13 2022 +0900
Commit: GitHub <noreply(a)github.com>
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);
+}