[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
This commit is contained in:
Katayama Hirofumi MZ 2022-02-12 08:32:13 +09:00 committed by GitHub
parent 27d73cd78b
commit b5c9d532e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 224 additions and 26 deletions

View file

@ -19,7 +19,8 @@
#define USER32_CALLBACK_SETOBM (15) #define USER32_CALLBACK_SETOBM (15)
#define USER32_CALLBACK_LPK (16) #define USER32_CALLBACK_LPK (16)
#define USER32_CALLBACK_UMPD (17) #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 typedef struct _WINDOWPROC_CALLBACK_ARGUMENTS
{ {
@ -168,6 +169,15 @@ typedef struct _LPK_CALLBACK_ARGUMENTS
BOOL bRect; BOOL bRect;
} LPK_CALLBACK_ARGUMENTS, *PLPK_CALLBACK_ARGUMENTS; } 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 NTSTATUS WINAPI
User32CallCopyImageFromKernel(PVOID Arguments, ULONG ArgumentLength); User32CallCopyImageFromKernel(PVOID Arguments, ULONG ArgumentLength);
NTSTATUS WINAPI NTSTATUS WINAPI
@ -204,4 +214,6 @@ NTSTATUS WINAPI
User32CallLPKFromKernel(PVOID Arguments, ULONG ArgumentLength); User32CallLPKFromKernel(PVOID Arguments, ULONG ArgumentLength);
NTSTATUS WINAPI NTSTATUS WINAPI
User32CallUMPDFromKernel(PVOID Arguments, ULONG ArgumentLength); User32CallUMPDFromKernel(PVOID Arguments, ULONG ArgumentLength);
NTSTATUS WINAPI
User32CallImmProcessKeyFromKernel(PVOID Arguments, ULONG ArgumentLength);
#endif /* __INCLUDE_USER32_CALLBACK_H */ #endif /* __INCLUDE_USER32_CALLBACK_H */

View file

@ -1247,4 +1247,28 @@ co_UserCBClientPrinterThunk( PVOID pkt, INT InSize, PVOID pvOutData, INT OutSize
return 0; 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 */ /* EOF */

View file

@ -76,3 +76,7 @@ BOOL FASTCALL co_IntSetWndIcons(VOID);
VOID FASTCALL co_IntDeliverUserAPC(VOID); VOID FASTCALL co_IntDeliverUserAPC(VOID);
VOID FASTCALL co_IntSetupOBM(VOID); VOID FASTCALL co_IntSetupOBM(VOID);
BOOL FASTCALL IntMsgCreateStructW(PWND,CREATESTRUCTW*,CREATESTRUCTW*,PVOID*,PVOID*); BOOL FASTCALL IntMsgCreateStructW(PWND,CREATESTRUCTW*,CREATESTRUCTW*,PVOID*,PVOID*);
DWORD
APIENTRY
co_IntImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam, DWORD dwHotKeyID);

View file

@ -58,6 +58,14 @@ typedef struct tagIMEHOTKEY
PIMEHOTKEY gpImeHotKeyList = NULL; PIMEHOTKEY gpImeHotKeyList = NULL;
LCID glcid = 0; LCID glcid = 0;
DWORD FASTCALL IntGetImeCompatFlags(PTHREADINFO pti)
{
if (!pti)
pti = PsGetCurrentThreadWin32Thread();
return pti->ppi->dwImeCompatFlags;
}
UINT FASTCALL IntGetImeHotKeyLanguageScore(HKL hKL, LANGID HotKeyLangId) UINT FASTCALL IntGetImeHotKeyLanguageScore(HKL hKL, LANGID HotKeyLangId)
{ {
LCID lcid; LCID lcid;
@ -343,7 +351,10 @@ IntSetImeHotKey(DWORD dwHotKeyId, UINT uModifiers, UINT uVirtualKey, HKL hKL, DW
case SETIMEHOTKEY_DELETE: case SETIMEHOTKEY_DELETE:
pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId); pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId);
if (!pNode) if (!pNode)
{
ERR("dwHotKeyId: 0x%lX\n", dwHotKeyId);
return FALSE; return FALSE;
}
IntDeleteImeHotKey(&gpImeHotKeyList, pNode); IntDeleteImeHotKey(&gpImeHotKeyList, pNode);
return TRUE; return TRUE;
@ -550,29 +561,122 @@ DWORD FASTCALL UserBuildHimcList(PTHREADINFO pti, DWORD dwCount, HIMC *phList)
} }
UINT FASTCALL 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); ASSERT_REFS_CO(pWnd);
if ( Msg == WM_KEYDOWN || switch (uMsg)
Msg == WM_SYSKEYDOWN ||
Msg == WM_KEYUP ||
Msg == WM_SYSKEYUP )
{ {
//Vk = wParam & 0xff; case WM_KEYDOWN:
pKbdLayout = pWnd->head.pti->KeyboardLayout; case WM_KEYUP:
if (pKbdLayout == NULL) return 0; case WM_SYSKEYDOWN:
// case WM_SYSKEYUP:
if (!(gpsi->dwSRVIFlags & SRVINFO_IMM32)) return 0; break;
// need ime.h!
default:
return 0;
} }
// Call User32:
// Anything but BOOL! hWnd = UserHMGetHandle(pWnd);
//ImmRet = co_IntImmProcessKey(UserHMGetHandle(pWnd), pKbdLayout->hkl, Vk, lParam, HotKey); pKL = pWnd->head.pti->KeyboardLayout;
FIXME(" is UNIMPLEMENTED.\n"); if (!pKL)
return 0; 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 NTSTATUS
@ -587,6 +691,7 @@ NtUserBuildHimcList(DWORD dwThreadId, DWORD dwCount, HIMC *phList, LPDWORD pdwCo
if (!IS_IMM_MODE()) if (!IS_IMM_MODE())
{ {
ERR("!IS_IMM_MODE()\n");
EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED); EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
goto Quit; goto Quit;
} }
@ -695,8 +800,14 @@ NtUserNotifyIMEStatus(HWND hwnd, BOOL fOpen, DWORD dwConversion)
UserEnterExclusive(); UserEnterExclusive();
if (!IS_IMM_MODE())
{
ERR("!IS_IMM_MODE()\n");
goto Quit;
}
pwnd = ValidateHwndNoErr(hwnd); pwnd = ValidateHwndNoErr(hwnd);
if (!pwnd || !IS_IMM_MODE()) if (!pwnd)
goto Quit; goto Quit;
pti = pwnd->head.pti; pti = pwnd->head.pti;
@ -741,6 +852,7 @@ NtUserDisableThreadIme(
if (!IS_IMM_MODE()) if (!IS_IMM_MODE())
{ {
ERR("!IS_IMM_MODE()\n");
EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED); EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
goto Quit; goto Quit;
} }
@ -812,6 +924,7 @@ NtUserGetAppImeLevel(HWND hWnd)
if (!IS_IMM_MODE()) if (!IS_IMM_MODE())
{ {
ERR("!IS_IMM_MODE()\n");
EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED); EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
goto Quit; goto Quit;
} }
@ -886,7 +999,10 @@ NtUserGetImeInfoEx(
UserEnterShared(); UserEnterShared();
if (!IS_IMM_MODE()) if (!IS_IMM_MODE())
{
ERR("!IS_IMM_MODE()\n");
goto Quit; goto Quit;
}
_SEH2_TRY _SEH2_TRY
{ {
@ -928,16 +1044,17 @@ NtUserSetAppImeLevel(HWND hWnd, DWORD dwLevel)
UserEnterExclusive(); UserEnterExclusive();
pWnd = ValidateHwndNoErr(hWnd);
if (!pWnd)
goto Quit;
if (!IS_IMM_MODE()) if (!IS_IMM_MODE())
{ {
ERR("!IS_IMM_MODE()\n");
EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED); EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
goto Quit; goto Quit;
} }
pWnd = ValidateHwndNoErr(hWnd);
if (!pWnd)
goto Quit;
pti = PsGetCurrentThreadWin32Thread(); pti = PsGetCurrentThreadWin32Thread();
if (pWnd->head.pti->ppi == pti->ppi) if (pWnd->head.pti->ppi == pti->ppi)
ret = UserSetProp(pWnd, AtomImeLevel, (HANDLE)(ULONG_PTR)dwLevel, TRUE); ret = UserSetProp(pWnd, AtomImeLevel, (HANDLE)(ULONG_PTR)dwLevel, TRUE);
@ -983,7 +1100,10 @@ NtUserSetImeInfoEx(PIMEINFOEX pImeInfoEx)
UserEnterExclusive(); UserEnterExclusive();
if (!IS_IMM_MODE()) if (!IS_IMM_MODE())
{
ERR("!IS_IMM_MODE()\n");
goto Quit; goto Quit;
}
_SEH2_TRY _SEH2_TRY
{ {
@ -1012,8 +1132,14 @@ NtUserSetImeOwnerWindow(HWND hImeWnd, HWND hwndFocus)
UserEnterExclusive(); UserEnterExclusive();
if (!IS_IMM_MODE())
{
ERR("!IS_IMM_MODE()\n");
goto Quit;
}
pImeWnd = ValidateHwndNoErr(hImeWnd); pImeWnd = ValidateHwndNoErr(hImeWnd);
if (!IS_IMM_MODE() || !pImeWnd || pImeWnd->fnid != FNID_IME) if (!pImeWnd || pImeWnd->fnid != FNID_IME)
goto Quit; goto Quit;
pwndFocus = ValidateHwndNoErr(hwndFocus); pwndFocus = ValidateHwndNoErr(hwndFocus);
@ -1140,6 +1266,7 @@ BOOL NTAPI NtUserDestroyInputContext(HIMC hIMC)
if (!IS_IMM_MODE()) if (!IS_IMM_MODE())
{ {
ERR("!IS_IMM_MODE()\n");
EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED); EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
goto Quit; goto Quit;
} }
@ -1185,7 +1312,10 @@ PIMC FASTCALL UserCreateInputContext(ULONG_PTR dwClientImcData)
PDESKTOP pdesk = pti->rpdesk; PDESKTOP pdesk = pti->rpdesk;
if (!IS_IMM_MODE() || (pti->TIF_flags & TIF_DISABLEIME)) // Disabled? if (!IS_IMM_MODE() || (pti->TIF_flags & TIF_DISABLEIME)) // Disabled?
{
ERR("IME is disabled\n");
return NULL; return NULL;
}
if (!pdesk) // No desktop? if (!pdesk) // No desktop?
return NULL; return NULL;
@ -1232,7 +1362,10 @@ NtUserCreateInputContext(ULONG_PTR dwClientImcData)
UserEnterExclusive(); UserEnterExclusive();
if (!IS_IMM_MODE()) if (!IS_IMM_MODE())
{
ERR("!IS_IMM_MODE()\n");
goto Quit; goto Quit;
}
pIMC = UserCreateInputContext(dwClientImcData); pIMC = UserCreateInputContext(dwClientImcData);
if (pIMC) if (pIMC)
@ -1317,8 +1450,14 @@ NtUserAssociateInputContext(HWND hWnd, HIMC hIMC, DWORD dwFlags)
UserEnterExclusive(); UserEnterExclusive();
if (!IS_IMM_MODE())
{
ERR("!IS_IMM_MODE()\n");
goto Quit;
}
pWnd = ValidateHwndNoErr(hWnd); pWnd = ValidateHwndNoErr(hWnd);
if (!pWnd || !IS_IMM_MODE()) if (!pWnd)
goto Quit; goto Quit;
pIMC = (hIMC ? UserGetObjectNoErr(gHandleTable, hIMC, TYPE_INPUTCONTEXT) : NULL); pIMC = (hIMC ? UserGetObjectNoErr(gHandleTable, hIMC, TYPE_INPUTCONTEXT) : NULL);
@ -1373,7 +1512,10 @@ NtUserUpdateInputContext(
UserEnterExclusive(); UserEnterExclusive();
if (!IS_IMM_MODE()) if (!IS_IMM_MODE())
{
ERR("!IS_IMM_MODE()\n");
goto Quit; goto Quit;
}
pIMC = UserGetObject(gHandleTable, hIMC, TYPE_INPUTCONTEXT); pIMC = UserGetObject(gHandleTable, hIMC, TYPE_INPUTCONTEXT);
if (!pIMC) if (!pIMC)
@ -1397,7 +1539,10 @@ NtUserQueryInputContext(HIMC hIMC, DWORD dwType)
UserEnterExclusive(); UserEnterExclusive();
if (!IS_IMM_MODE()) if (!IS_IMM_MODE())
{
ERR("!IS_IMM_MODE()\n");
goto Quit; goto Quit;
}
pIMC = UserGetObject(gHandleTable, hIMC, TYPE_INPUTCONTEXT); pIMC = UserGetObject(gHandleTable, hIMC, TYPE_INPUTCONTEXT);
if (!pIMC) if (!pIMC)

View file

@ -223,10 +223,10 @@ PVOID apfnDispatch[USER32_CALLBACK_MAXIMUM + 1] =
User32CallOBMFromKernel, User32CallOBMFromKernel,
User32CallLPKFromKernel, User32CallLPKFromKernel,
User32CallUMPDFromKernel, User32CallUMPDFromKernel,
User32CallImmProcessKeyFromKernel,
}; };
VOID VOID
WINAPI WINAPI
GdiProcessSetup(VOID); GdiProcessSetup(VOID);
@ -712,3 +712,16 @@ NTSTATUS WINAPI User32CallUMPDFromKernel(PVOID Arguments, ULONG ArgumentLength)
} }
return ZwCallbackReturn( pktOut, cbSize, Status ); 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);
}