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

commit 85e292d58f952f7941eed0b3056c94f08a7b53a3
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Mon Sep 5 08:34:00 2022 +0900
Commit:     GitHub <nore...@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);
 }
 

Reply via email to