https://git.reactos.org/?p=reactos.git;a=commitdiff;h=85e292d58f952f7941eed…
commit 85e292d58f952f7941eed0b3056c94f08a7b53a3
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Mon Sep 5 08:34:00 2022 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Mon Sep 5 08:34:00 2022 +0900
[NTUSER][USER32][IMM32] Initialize pKL->piiex by using ImmLoadLayout (#4645)
To recognize IME, we have to initialize pKL->piiex.
- Add co_ClientImmLoadLayout and User32CallImmLoadLayoutFromKernel functions to call
imm32!ImmLoadLayout on user mode from kernel.
- Use co_ClientImmLoadLayout in NtUserLoadKeyboardLayoutEx.
- Improve Imm32LoadIME to sanitize the IME table.
CORE-11700
---
dll/win32/imm32/ime.c | 26 ++++++++++++++-------
dll/win32/imm32/imm.c | 38 ++++++++++++------------------
dll/win32/imm32/utils.c | 1 +
win32ss/include/callback.h | 17 +++++++++++++-
win32ss/user/ntuser/callback.c | 46 +++++++++++++++++++++++++++++++++++++
win32ss/user/ntuser/callback.h | 6 +++++
win32ss/user/ntuser/kbdlayout.c | 30 +++++++++++++++++++++++-
win32ss/user/ntuser/ntuser.h | 1 +
win32ss/user/user32/misc/dllmain.c | 10 ++++++++
win32ss/user/user32/windows/input.c | 24 +++++++++++++++----
10 files changed, 161 insertions(+), 38 deletions(-)
diff --git a/dll/win32/imm32/ime.c b/dll/win32/imm32/ime.c
index 79c40435188..dd3519087a4 100644
--- a/dll/win32/imm32/ime.c
+++ b/dll/win32/imm32/ime.c
@@ -149,6 +149,15 @@ BOOL APIENTRY Imm32InquireIme(PIMEDPI pImeDpi)
return GetClassInfoW(pImeDpi->hInst, pImeDpi->szUIClass, &wcW);
}
+/* Define stub IME functions */
+#define DEFINE_IME_ENTRY(type, name, params, optional) \
+ type APIENTRY Stub##name params { \
+ FIXME("%s: Why stub called?\n", #name); \
+ return (type)0; \
+ }
+#include "imetable.h"
+#undef DEFINE_IME_ENTRY
+
// Win: LoadIME
BOOL APIENTRY Imm32LoadIME(PIMEINFOEX pImeInfoEx, PIMEDPI pImeDpi)
{
@@ -160,18 +169,19 @@ BOOL APIENTRY Imm32LoadIME(PIMEINFOEX pImeInfoEx, PIMEDPI pImeDpi)
if (!Imm32GetSystemLibraryPath(szPath, _countof(szPath), pImeInfoEx->wszImeFile))
return FALSE;
- hIME = GetModuleHandleW(szPath);
+ pImeDpi->hInst = hIME = LoadLibraryW(szPath);
if (hIME == NULL)
{
- hIME = LoadLibraryW(szPath);
- if (hIME == NULL)
- {
- ERR("Imm32LoadIME: LoadLibraryW(%S) failed\n", szPath);
- return FALSE;
- }
+ ERR("Imm32LoadIME: LoadLibraryW(%s) failed\n", debugstr_w(szPath));
+ return FALSE;
}
- pImeDpi->hInst = hIME;
+ /* Populate the table by stub IME functions */
+#define DEFINE_IME_ENTRY(type, name, params, optional) pImeDpi->name = Stub##name;
+#include "imetable.h"
+#undef DEFINE_IME_ENTRY
+
+ /* Populate the table by real IME functions */
#define DEFINE_IME_ENTRY(type, name, params, optional) \
do { \
fn = GetProcAddress(hIME, #name); \
diff --git a/dll/win32/imm32/imm.c b/dll/win32/imm32/imm.c
index 94a1afcd488..13512cadb11 100644
--- a/dll/win32/imm32/imm.c
+++ b/dll/win32/imm32/imm.c
@@ -53,57 +53,49 @@ BOOL WINAPI ImmRegisterClient(PSHAREDINFO ptr, HINSTANCE hMod)
*/
BOOL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx)
{
- DWORD cbData;
- HKEY hLayoutKey = NULL, hLayoutsKey = NULL;
+ DWORD cbData, dwType;
+ HKEY hLayoutKey;
LONG error;
WCHAR szLayout[MAX_PATH];
TRACE("(%p, %p)\n", hKL, pImeInfoEx);
+ ZeroMemory(pImeInfoEx, sizeof(IMEINFOEX));
+
if (IS_IME_HKL(hKL) || !Imm32IsCiceroMode() || Imm32Is16BitMode())
{
- Imm32UIntToStr((DWORD)(DWORD_PTR)hKL, 16, szLayout, _countof(szLayout));
-
- error = RegOpenKeyW(HKEY_LOCAL_MACHINE, REGKEY_KEYBOARD_LAYOUTS,
&hLayoutsKey);
- if (error)
- {
- ERR("RegOpenKeyW: 0x%08lX\n", error);
- return FALSE;
- }
+ StringCchPrintfW(szLayout, _countof(szLayout), L"%s\\%08lX",
+ REGKEY_KEYBOARD_LAYOUTS, HandleToUlong(hKL));
- error = RegOpenKeyW(hLayoutsKey, szLayout, &hLayoutKey);
+ error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szLayout, 0, KEY_READ,
&hLayoutKey);
if (error)
{
- ERR("RegOpenKeyW: 0x%08lX\n", error);
- RegCloseKey(hLayoutsKey);
+ ERR("RegOpenKeyExW: 0x%08lX\n", error);
return FALSE;
}
}
else
{
- error = RegOpenKeyW(HKEY_LOCAL_MACHINE, REGKEY_IMM, &hLayoutKey);
+ error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, REGKEY_IMM, 0, KEY_READ,
&hLayoutKey);
if (error)
{
- ERR("RegOpenKeyW: 0x%08lX\n", error);
+ ERR("RegOpenKeyExW: 0x%08lX\n", error);
return FALSE;
}
}
cbData = sizeof(pImeInfoEx->wszImeFile);
- error = RegQueryValueExW(hLayoutKey, L"Ime File", 0, 0,
+ error = RegQueryValueExW(hLayoutKey, L"Ime File", NULL, &dwType,
(LPBYTE)pImeInfoEx->wszImeFile, &cbData);
- pImeInfoEx->wszImeFile[_countof(pImeInfoEx->wszImeFile) - 1] = 0;
+ pImeInfoEx->wszImeFile[_countof(pImeInfoEx->wszImeFile) - 1] = UNICODE_NULL;
RegCloseKey(hLayoutKey);
- if (hLayoutsKey)
- RegCloseKey(hLayoutsKey);
pImeInfoEx->fLoadFlag = 0;
- if (error)
+ if (error != ERROR_SUCCESS || dwType != REG_SZ)
{
- ERR("RegQueryValueExW: 0x%08lX\n", error);
- pImeInfoEx->hkl = NULL;
+ ERR("RegQueryValueExW: 0x%lX, 0x%lX\n", error, dwType);
return FALSE;
}
@@ -116,7 +108,7 @@ BOOL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx)
*/
BOOL WINAPI ImmFreeLayout(DWORD dwUnknown)
{
- WCHAR szKBD[9];
+ WCHAR szKBD[KL_NAMELENGTH];
UINT iKL, cKLs;
HKL hOldKL, hNewKL, *pList;
PIMEDPI pImeDpi;
diff --git a/dll/win32/imm32/utils.c b/dll/win32/imm32/utils.c
index ca9385aed14..9e0c07195dd 100644
--- a/dll/win32/imm32/utils.c
+++ b/dll/win32/imm32/utils.c
@@ -776,6 +776,7 @@ BOOL APIENTRY Imm32LoadImeVerInfo(PIMEINFOEX pImeInfoEx)
hinstVersion = LoadLibraryW(szPath);
if (!hinstVersion)
return FALSE;
+
bLoaded = TRUE;
}
diff --git a/win32ss/include/callback.h b/win32ss/include/callback.h
index a75a6de3803..4c4d56323f0 100644
--- a/win32ss/include/callback.h
+++ b/win32ss/include/callback.h
@@ -20,7 +20,8 @@
#define USER32_CALLBACK_LPK (16)
#define USER32_CALLBACK_UMPD (17)
#define USER32_CALLBACK_IMMPROCESSKEY (18)
-#define USER32_CALLBACK_MAXIMUM (18)
+#define USER32_CALLBACK_IMMLOADLAYOUT (19)
+#define USER32_CALLBACK_MAXIMUM USER32_CALLBACK_IMMLOADLAYOUT
typedef struct _WINDOWPROC_CALLBACK_ARGUMENTS
{
@@ -178,6 +179,17 @@ typedef struct _IMMPROCESSKEY_CALLBACK_ARGUMENTS
DWORD dwHotKeyID;
} IMMPROCESSKEY_CALLBACK_ARGUMENTS, *PIMMPROCESSKEY_CALLBACK_ARGUMENTS;
+typedef struct _IMMLOADLAYOUT_CALLBACK_ARGUMENTS
+{
+ HKL hKL;
+} IMMLOADLAYOUT_CALLBACK_ARGUMENTS, *PIMMLOADLAYOUT_CALLBACK_ARGUMENTS;
+
+typedef struct _IMMLOADLAYOUT_CALLBACK_OUTPUT
+{
+ BOOL ret;
+ IMEINFOEX iiex;
+} IMMLOADLAYOUT_CALLBACK_OUTPUT, *PIMMLOADLAYOUT_CALLBACK_OUTPUT;
+
NTSTATUS WINAPI
User32CallCopyImageFromKernel(PVOID Arguments, ULONG ArgumentLength);
NTSTATUS WINAPI
@@ -216,4 +228,7 @@ NTSTATUS WINAPI
User32CallUMPDFromKernel(PVOID Arguments, ULONG ArgumentLength);
NTSTATUS WINAPI
User32CallImmProcessKeyFromKernel(PVOID Arguments, ULONG ArgumentLength);
+NTSTATUS WINAPI
+User32CallImmLoadLayoutFromKernel(PVOID Arguments, ULONG ArgumentLength);
+
#endif /* __INCLUDE_USER32_CALLBACK_H */
diff --git a/win32ss/user/ntuser/callback.c b/win32ss/user/ntuser/callback.c
index 4e1c053e4bf..801e8e971db 100644
--- a/win32ss/user/ntuser/callback.c
+++ b/win32ss/user/ntuser/callback.c
@@ -1272,4 +1272,50 @@ co_IntImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam,
DWORD dwHotKey
return ret;
}
+/* Win: ClientImmLoadLayout */
+BOOL
+APIENTRY
+co_ClientImmLoadLayout(
+ _In_ HKL hKL,
+ _Inout_ PIMEINFOEX pImeInfoEx)
+{
+ BOOL ret;
+ NTSTATUS Status;
+ IMMLOADLAYOUT_CALLBACK_ARGUMENTS Common = { hKL };
+ ULONG ResultLength = sizeof(IMMLOADLAYOUT_CALLBACK_OUTPUT);
+ PIMMLOADLAYOUT_CALLBACK_OUTPUT ResultPointer = NULL;
+
+ RtlZeroMemory(pImeInfoEx, sizeof(IMEINFOEX));
+
+ UserLeaveCo();
+ Status = KeUserModeCallback(USER32_CALLBACK_IMMLOADLAYOUT,
+ &Common,
+ sizeof(Common),
+ (PVOID*)&ResultPointer,
+ &ResultLength);
+ UserEnterCo();
+
+ if (!NT_SUCCESS(Status) || !ResultPointer ||
+ ResultLength != sizeof(IMMLOADLAYOUT_CALLBACK_OUTPUT))
+ {
+ ERR("0x%lX, %p, %lu\n", Status, ResultPointer, ResultLength);
+ return FALSE;
+ }
+
+ _SEH2_TRY
+ {
+ ProbeForRead(ResultPointer, ResultLength, 1);
+ ret = ResultPointer->ret;
+ if (ret)
+ RtlCopyMemory(pImeInfoEx, &ResultPointer->iiex, sizeof(IMEINFOEX));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ret = FALSE;
+ }
+ _SEH2_END;
+
+ return ret;
+}
+
/* EOF */
diff --git a/win32ss/user/ntuser/callback.h b/win32ss/user/ntuser/callback.h
index 79217f86425..dde7152a952 100644
--- a/win32ss/user/ntuser/callback.h
+++ b/win32ss/user/ntuser/callback.h
@@ -80,3 +80,9 @@ BOOL FASTCALL
IntMsgCreateStructW(PWND,CREATESTRUCTW*,CREATESTRUCTW*,PVOID*,PVOI
DWORD
APIENTRY
co_IntImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam, DWORD dwHotKeyID);
+
+BOOL
+APIENTRY
+co_ClientImmLoadLayout(
+ _In_ HKL hKL,
+ _Inout_ PIMEINFOEX pImeInfoEx);
diff --git a/win32ss/user/ntuser/kbdlayout.c b/win32ss/user/ntuser/kbdlayout.c
index 83d89d9632a..d41f53d3472 100644
--- a/win32ss/user/ntuser/kbdlayout.c
+++ b/win32ss/user/ntuser/kbdlayout.c
@@ -497,6 +497,10 @@ UserUnloadKbl(PKL pKl)
pKl->pklPrev->pklNext = pKl->pklNext;
pKl->pklNext->pklPrev = pKl->pklPrev;
UnloadKbdFile(pKl->spkf);
+ if (pKl->piiex)
+ {
+ ExFreePoolWithTag(pKl->piiex, USERTAG_IME);
+ }
UserDeleteObject(pKl->head.h, TYPE_KBDLAYOUT);
return TRUE;
}
@@ -995,12 +999,34 @@ cleanup:
return bRet;
}
+/* Win: xxxImmLoadLayout */
+PIMEINFOEX FASTCALL co_UserImmLoadLayout(_In_ HKL hKL)
+{
+ PIMEINFOEX piiex;
+
+ if (!IS_IME_HKL(hKL) && !IS_CICERO_MODE())
+ return NULL;
+
+ piiex = ExAllocatePoolWithTag(PagedPool, sizeof(IMEINFOEX), USERTAG_IME);
+ if (!piiex)
+ return NULL;
+
+ if (!co_ClientImmLoadLayout(hKL, piiex))
+ {
+ ExFreePoolWithTag(piiex, USERTAG_IME);
+ return NULL;
+ }
+
+ return piiex;
+}
+
/*
* NtUserLoadKeyboardLayoutEx
*
* Loads keyboard layout with given locale id
*
* NOTE: We adopt a different design from Microsoft's one for security reason.
+ * We don't use the 1st and 3rd parameters of NtUserLoadKeyboardLayoutEx.
*/
HKL
APIENTRY
@@ -1015,7 +1041,7 @@ NtUserLoadKeyboardLayoutEx(
{
HKL hklRet = NULL;
PKL pKl = NULL, pklLast;
- WCHAR Buffer[9];
+ WCHAR Buffer[KL_NAMELENGTH];
UNICODE_STRING ustrSafeKLID;
if (Flags & ~(KLF_ACTIVATE|KLF_NOTELLSHELL|KLF_REORDER|KLF_REPLACELANG|
@@ -1082,6 +1108,8 @@ NtUserLoadKeyboardLayoutEx(
pKl->pklPrev = pKl;
gspklBaseLayout = pKl;
}
+
+ pKl->piiex = co_UserImmLoadLayout(UlongToHandle(hkl));
}
/* If this layout was prepared to unload, undo it */
diff --git a/win32ss/user/ntuser/ntuser.h b/win32ss/user/ntuser/ntuser.h
index a72571dc26f..5060a661305 100644
--- a/win32ss/user/ntuser/ntuser.h
+++ b/win32ss/user/ntuser/ntuser.h
@@ -11,6 +11,7 @@
typedef VOID (*TL_FN_FREE)(PVOID);
+/* Thread Lock structure */
typedef struct _TL
{
struct _TL* next;
diff --git a/win32ss/user/user32/misc/dllmain.c b/win32ss/user/user32/misc/dllmain.c
index 77fc525d913..18dd9ec0710 100644
--- a/win32ss/user/user32/misc/dllmain.c
+++ b/win32ss/user/user32/misc/dllmain.c
@@ -224,6 +224,7 @@ PVOID apfnDispatch[USER32_CALLBACK_MAXIMUM + 1] =
User32CallLPKFromKernel,
User32CallUMPDFromKernel,
User32CallImmProcessKeyFromKernel,
+ User32CallImmLoadLayoutFromKernel,
};
@@ -725,3 +726,12 @@ User32CallImmProcessKeyFromKernel(PVOID Arguments, ULONG
ArgumentLength)
return ZwCallbackReturn(&Result, sizeof(DWORD), STATUS_SUCCESS);
}
+
+NTSTATUS WINAPI
+User32CallImmLoadLayoutFromKernel(PVOID Arguments, ULONG ArgumentLength)
+{
+ PIMMLOADLAYOUT_CALLBACK_ARGUMENTS Common = Arguments;
+ IMMLOADLAYOUT_CALLBACK_OUTPUT Result;
+ Result.ret = IMM_FN(ImmLoadLayout)(Common->hKL, &Result.iiex);
+ return ZwCallbackReturn(&Result, sizeof(Result), STATUS_SUCCESS);
+}
diff --git a/win32ss/user/user32/windows/input.c b/win32ss/user/user32/windows/input.c
index 1dfa587602e..a018d3aeca2 100644
--- a/win32ss/user/user32/windows/input.c
+++ b/win32ss/user/user32/windows/input.c
@@ -638,6 +638,13 @@ LoadKeyboardLayoutA(LPCSTR pszKLID,
return LoadKeyboardLayoutW(wszKLID, Flags);
}
+inline BOOL IsValidKLID(_In_ LPCWSTR pwszKLID)
+{
+ return (pwszKLID != NULL) && (wcsspn(pwszKLID,
L"0123456789ABCDEFabcdef") == (KL_NAMELENGTH - 1));
+}
+
+#define ENGLISH_US MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)
+
/*
* @unimplemented
*
@@ -656,12 +663,20 @@ IntLoadKeyboardLayout(
UNICODE_STRING ustrKbdName;
UNICODE_STRING ustrKLID;
WCHAR wszRegKey[256] = L"SYSTEM\\CurrentControlSet\\Control\\Keyboard
Layouts\\";
- WCHAR wszLayoutId[10], wszNewKLID[10], szImeFileName[80];
+ WCHAR wszLayoutId[10], wszNewKLID[KL_NAMELENGTH], szImeFileName[80];
+ PWCHAR endptr;
HKL hNewKL;
HKEY hKey;
BOOL bIsIME;
- dwhkl = wcstoul(pwszKLID, NULL, 16);
+ if (!IsValidKLID(pwszKLID))
+ {
+ ERR("pwszKLID: %s\n", debugstr_w(pwszKLID));
+ return UlongToHandle(MAKELONG(ENGLISH_US, ENGLISH_US));
+ }
+
+ dwhkl = wcstoul(pwszKLID, &endptr, 16);
+
bIsIME = IS_IME_HKL(UlongToHandle(dwhkl));
if (!bIsIME) /* Not IME? */
{
@@ -690,8 +705,7 @@ IntLoadKeyboardLayout(
StringCbCatW(wszRegKey, sizeof(wszRegKey), pwszKLID);
/* Open layout registry key for read */
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszRegKey, 0,
- KEY_READ, &hKey) == ERROR_SUCCESS)
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszRegKey, 0, KEY_READ, &hKey) ==
ERROR_SUCCESS)
{
dwSize = sizeof(wszLayoutId);
if (RegQueryValueExW(hKey, L"Layout Id", NULL, &dwType,
(LPBYTE)wszLayoutId, &dwSize) == ERROR_SUCCESS)
@@ -744,7 +758,7 @@ HKL WINAPI
LoadKeyboardLayoutW(LPCWSTR pwszKLID,
UINT Flags)
{
- TRACE("(%s, 0x%X)", debugstr_w(pwszKLID), Flags);
+ TRACE("(%s, 0x%X)\n", debugstr_w(pwszKLID), Flags);
return IntLoadKeyboardLayout(NULL, pwszKLID, 0, Flags, FALSE);
}