mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[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
This commit is contained in:
parent
15a0f7adb0
commit
85e292d58f
10 changed files with 161 additions and 38 deletions
|
@ -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); \
|
||||
|
|
|
@ -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));
|
||||
StringCchPrintfW(szLayout, _countof(szLayout), L"%s\\%08lX",
|
||||
REGKEY_KEYBOARD_LAYOUTS, HandleToUlong(hKL));
|
||||
|
||||
error = RegOpenKeyW(HKEY_LOCAL_MACHINE, REGKEY_KEYBOARD_LAYOUTS, &hLayoutsKey);
|
||||
error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szLayout, 0, KEY_READ, &hLayoutKey);
|
||||
if (error)
|
||||
{
|
||||
ERR("RegOpenKeyW: 0x%08lX\n", error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
error = RegOpenKeyW(hLayoutsKey, szLayout, &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;
|
||||
|
|
|
@ -776,6 +776,7 @@ BOOL APIENTRY Imm32LoadImeVerInfo(PIMEINFOEX pImeInfoEx)
|
|||
hinstVersion = LoadLibraryW(szPath);
|
||||
if (!hinstVersion)
|
||||
return FALSE;
|
||||
|
||||
bLoaded = TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
typedef VOID (*TL_FN_FREE)(PVOID);
|
||||
|
||||
/* Thread Lock structure */
|
||||
typedef struct _TL
|
||||
{
|
||||
struct _TL* next;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue