Author: rharabien
Date: Wed Oct 19 20:03:50 2011
New Revision: 54203
URL:
http://svn.reactos.org/svn/reactos?rev=54203&view=rev
Log:
[WIN32K|USER32]
- Make keyboard layouts code more compatible
- Layouts and kbd files are user objects
- Preloaded layouts are added by Winlogon, not win32k
- Support Keyboard Layout substitutes in registry
Modified:
trunk/reactos/base/system/winlogon/winlogon.c
trunk/reactos/base/system/winlogon/winlogon.h
trunk/reactos/boot/bootdata/hivesys_i386.inf
trunk/reactos/subsystems/win32/win32k/include/input.h
trunk/reactos/subsystems/win32/win32k/main/dllmain.c
trunk/reactos/subsystems/win32/win32k/ntuser/input.c
trunk/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c
trunk/reactos/subsystems/win32/win32k/ntuser/keyboard.c
Modified: trunk/reactos/base/system/winlogon/winlogon.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/winlogon/winlo…
==============================================================================
--- trunk/reactos/base/system/winlogon/winlogon.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/winlogon/winlogon.c [iso-8859-1] Wed Oct 19 20:03:50 2011
@@ -267,6 +267,65 @@
}
+static BOOL
+InitKeyboardLayouts()
+{
+ WCHAR wszKeyName[12], wszKLID[10];
+ DWORD dwSize = sizeof(wszKLID), dwType, i;
+ HKEY hKey;
+ UINT Flags;
+ BOOL bRet = FALSE;
+
+ /* Open registry key with preloaded layouts */
+ if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Preload", 0, KEY_READ,
&hKey) != ERROR_SUCCESS)
+ {
+ ERR("RegOpenKeyExW failed!\n");
+ return FALSE;
+ }
+
+ i = 1;
+ while(TRUE)
+ {
+ /* Read values with integer names only */
+ swprintf(wszKeyName, L"%d", i);
+ if (RegQueryValueExW(hKey, wszKeyName, NULL, &dwType, (LPBYTE)wszKLID,
&dwSize) != ERROR_SUCCESS)
+ {
+ /* If we loaded at least one layout and there is no more
+ registry values return TRUE */
+ if (i > 1)
+ bRet = TRUE;
+ break;
+ }
+
+ /* Only REG_SZ values are valid */
+ if (dwType != REG_SZ)
+ {
+ ERR("Wrong type!\n");
+ break;
+ }
+
+ /* Load keyboard layout with given locale id */
+ Flags = KLF_SUBSTITUTE_OK;
+ if (i > 1)
+ Flags |= KLF_NOTELLSHELL|KLF_REPLACELANG;
+ else // First layout
+ Flags |= KLF_ACTIVATE; // |0x40000000
+ if (!LoadKeyboardLayoutW(wszKLID, Flags))
+ {
+ ERR("LoadKeyboardLayoutW failed!\n");
+ break;
+ }
+
+ /* Move to the next entry */
+ ++i;
+ }
+
+ /* Close the key now */
+ RegCloseKey(hKey);
+
+ return bRet;
+}
+
BOOL
DisplayStatusMessage(
IN PWLSESSION Session,
@@ -390,6 +449,14 @@
}
LockWorkstation(WLSession);
+ /* Load default keyboard layouts */
+ if (!InitKeyboardLayouts())
+ {
+ ERR("WL: Could not preload keyboard layouts\n");
+ NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk,
&HardErrorResponse);
+ ExitProcess(1);
+ }
+
if (!StartServicesManager())
{
ERR("WL: Could not start services.exe\n");
Modified: trunk/reactos/base/system/winlogon/winlogon.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/winlogon/winlo…
==============================================================================
--- trunk/reactos/base/system/winlogon/winlogon.h [iso-8859-1] (original)
+++ trunk/reactos/base/system/winlogon/winlogon.h [iso-8859-1] Wed Oct 19 20:03:50 2011
@@ -29,6 +29,7 @@
#define USE_GETLASTINPUTINFO
#define WIN32_NO_STATUS
+#include <stdio.h>
#include <windows.h>
#include <userenv.h>
#include <winwlx.h>
Modified: trunk/reactos/boot/bootdata/hivesys_i386.inf
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/bootdata/hivesys_i386…
==============================================================================
--- trunk/reactos/boot/bootdata/hivesys_i386.inf [iso-8859-1] (original)
+++ trunk/reactos/boot/bootdata/hivesys_i386.inf [iso-8859-1] Wed Oct 19 20:03:50 2011
@@ -423,6 +423,7 @@
HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000411","Layout
File",0x00000000,"kbdja.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000411","Layout
Text",0x00000000,"Japanese"
HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000411","Layout
Display Name",0x00000000,"(a)%SystemRoot%\system32\input.dll,-5061"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000411","Layout
Id",0x00000000,"0001"
HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041c","Layout
File",0x00000000,"kbdal.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041c","Layout
Text",0x00000000,"Albanian"
@@ -625,6 +626,7 @@
HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000412","Layout
File",0x00000000,"kbdko.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000412","Layout
Text",0x00000000,"Korean"
HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000412","Layout
Display Name",0x00000000,"(a)%SystemRoot%\system32\input.dll,-5063"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000412","Layout
Id",0x00000000,"0001"
; Keyboard layouts
HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout",,0x00000012
Modified: trunk/reactos/subsystems/win32/win32k/include/input.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/in…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/input.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/include/input.h [iso-8859-1] Wed Oct 19 20:03:50
2011
@@ -1,31 +1,54 @@
#pragma once
#include <ndk/kbd.h>
+
+typedef struct tagKBDNLSLAYER
+{
+ USHORT OEMIdentifier;
+ USHORT LayoutInformation;
+ UINT NumOfVkToF;
+ struct _VK_TO_FUNCTION_TABLE *pVkToF;
+ INT NumOfMouseVKey;
+ PUSHORT pusMouseVKey;
+} KBDNLSLAYER, *PKBDNLSLAYER;
+
+typedef struct tagKBDFILE
+{
+ HEAD head;
+ struct tagKBDFILE *pkfNext;
+ WCHAR awchKF[20];
+ HANDLE hBase;
+ struct _KBDTABLES *pKbdTbl;
+ ULONG Size;
+ PKBDNLSLAYER pKbdNlsTbl;
+} KBDFILE, *PKBDFILE;
-typedef struct _KL
+typedef struct tagKL
{
- LIST_ENTRY List;
- DWORD Flags;
- WCHAR Name[KL_NAMELENGTH]; // used w GetKeyboardLayoutName same as wszKLID.
- struct _KBDTABLES *KBTables; // KBDTABLES in ndk/kbd.h
- HANDLE hModule;
- ULONG RefCount;
- HKL hkl;
- DWORD klid; // Low word - language id. High word - device id.
+ HEAD head;
+ struct tagKL *pklNext;
+ struct tagKL *pklPrev;
+ DWORD dwKL_Flags;
+ HKL hkl;
+ PKBDFILE spkf;
+ DWORD dwFontSigs;
+ UINT iBaseCharset;
+ USHORT CodePage;
+ WCHAR wchDiacritic;
+ //PIMEINFOEX piiex;
} KL, *PKL;
typedef struct _ATTACHINFO
{
- struct _ATTACHINFO* paiNext;
+ struct _ATTACHINFO *paiNext;
PTHREADINFO pti1;
PTHREADINFO pti2;
} ATTACHINFO, *PATTACHINFO;
extern PATTACHINFO gpai;
-#define KBL_UNLOAD 1
-#define KBL_PRELOAD 2
-#define KBL_RESET 4
+/* Keyboard layout undocumented flags */
+#define KLF_UNLOAD 0x20000000
/* Key States */
#define KS_DOWN_BIT 0x80
Modified: trunk/reactos/subsystems/win32/win32k/main/dllmain.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ma…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/main/dllmain.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/main/dllmain.c [iso-8859-1] Wed Oct 19 20:03:50
2011
@@ -286,6 +286,8 @@
}
ptiCurrent->MessageQueue = MsqCreateMessageQueue(Thread);
ptiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout();
+ if (ptiCurrent->KeyboardLayout)
+ UserReferenceObject(ptiCurrent->KeyboardLayout);
ptiCurrent->pEThread = Thread;
/* HAAAAAAAACK! This should go to Win32kProcessCallback */
@@ -421,6 +423,8 @@
IntBlockInput(ptiCurrent, FALSE);
MsqDestroyMessageQueue(ptiCurrent->MessageQueue);
IntCleanupThreadCallbacks(ptiCurrent);
+ if (ptiCurrent->KeyboardLayout)
+ UserDereferenceObject(ptiCurrent->KeyboardLayout);
/* cleanup user object references stack */
psle = PopEntryList(&ptiCurrent->ReferencesList);
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/input.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/input.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/input.c [iso-8859-1] Wed Oct 19 20:03:50
2011
@@ -328,12 +328,6 @@
return STATUS_UNSUCCESSFUL;
}
KeInitializeTimer(MasterTimer);
-
- /* Initialize the default keyboard layout */
- if (!UserInitDefaultKeyboardLayout())
- {
- ERR("Failed to initialize default keyboard layout!\n");
- }
return STATUS_SUCCESS;
}
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c [iso-8859-1] Wed Oct 19
20:03:50 2011
@@ -11,66 +11,46 @@
#include <win32k.h>
DBG_DEFAULT_CHANNEL(UserKbdLayout);
-PKL gpklFirst = NULL; // Keyboard layout list.
-
-typedef PVOID (*PFNKBDLAYERDESCRIPTOR)(VOID);
+PKL gspklBaseLayout = NULL;
+PKBDFILE gpkfList = NULL;
+
+typedef PVOID (*PFN_KBDLAYERDESCRIPTOR)(VOID);
/* PRIVATE FUNCTIONS ******************************************************/
+/*
+ * UserLoadKbdDll
+ *
+ * Loads keyboard layout DLL and gets address to KbdTables
+ */
static BOOL
-UserLoadKbdDll(CONST WCHAR *wszKLID,
+UserLoadKbdDll(WCHAR *pwszLayoutPath,
HANDLE *phModule,
PKBDTABLES *pKbdTables)
{
- NTSTATUS Status;
- HKEY hKey;
- ULONG cbSize;
- PFNKBDLAYERDESCRIPTOR pfnKbdLayerDescriptor;
- WCHAR wszLayoutRegKey[256] =
L"\\REGISTRY\\Machine\\SYSTEM\\CurrentControlSet\\"
- L"Control\\Keyboard Layouts\\";
- WCHAR wszLayoutPath[MAX_PATH] = L"\\SystemRoot\\System32\\";
-
- /* Open layout registry key */
- RtlStringCbCatW(wszLayoutRegKey, sizeof(wszLayoutRegKey), wszKLID);
- Status = RegOpenKey(wszLayoutRegKey, &hKey);
- if (!NT_SUCCESS(Status))
- {
- ERR("Failed to open keyboard layouts registry key %ws (%lx)\n",
wszKLID, Status);
+ PFN_KBDLAYERDESCRIPTOR pfnKbdLayerDescriptor;
+
+ /* Load keyboard layout DLL */
+ TRACE("Loading Keyboard DLL %ws\n", pwszLayoutPath);
+ *phModule = EngLoadImage(pwszLayoutPath);
+ if (!(*phModule))
+ {
+ ERR("Failed to load dll %ws\n", pwszLayoutPath);
return FALSE;
}
- /* Read filename of layout DLL and close the key */
- cbSize = sizeof(wszLayoutPath) - (wcslen(wszLayoutPath) + 1)*sizeof(WCHAR);
- Status = RegQueryValue(hKey,
- L"Layout File",
- REG_SZ,
- wszLayoutPath + wcslen(wszLayoutPath),
- &cbSize);
- ZwClose(hKey);
- if (!NT_SUCCESS(Status))
- {
- TRACE("Can't get layout filename for %ws (%lx)\n", wszKLID,
Status);
- return FALSE;
- }
-
- /* Load keyboard layout DLL */
- TRACE("Loading Keyboard DLL %ws\n", wszLayoutPath);
- *phModule = EngLoadImage(wszLayoutPath);
- if (!(*phModule))
- {
- ERR("Failed to load dll %ws\n", wszLayoutPath);
- return FALSE;
- }
-
/* Find KbdLayerDescriptor function and get layout tables */
- TRACE("Loaded %ws\n", wszLayoutPath);
+ TRACE("Loaded %ws\n", pwszLayoutPath);
pfnKbdLayerDescriptor = EngFindImageProcAddress(*phModule,
"KbdLayerDescriptor");
+
+ /* FIXME: Windows reads file instead of executing!
+ It's not safe to kbdlayout DLL in kernel mode! */
if (pfnKbdLayerDescriptor)
*pKbdTables = pfnKbdLayerDescriptor();
else
- ERR("Error: %ws has no KbdLayerDescriptor()\n", wszLayoutPath);
+ ERR("Error: %ws has no KbdLayerDescriptor()\n", pwszLayoutPath);
if (!pfnKbdLayerDescriptor || !*pKbdTables)
{
@@ -79,7 +59,7 @@
return FALSE;
}
-#if 0 // Dump keyboard layout
+#if 0 /* Dump keyboard layout */
{
unsigned i;
PVK_TO_BIT pVkToBit = (*pKbdTables)->pCharModifiers->pVkToBit;
@@ -134,300 +114,333 @@
return TRUE;
}
+/*
+ * UserLoadKbdFile
+ *
+ * Loads keyboard layout DLL and creates KBDFILE object
+ */
+static PKBDFILE
+UserLoadKbdFile(PUNICODE_STRING pwszKLID)
+{
+ PKBDFILE pkf, pRet = NULL;
+ NTSTATUS Status;
+ ULONG cbSize;
+ HKEY hKey = NULL;
+ WCHAR wszLayoutPath[MAX_PATH] = L"\\SystemRoot\\System32\\";
+ WCHAR wszLayoutRegKey[256] =
L"\\REGISTRY\\Machine\\SYSTEM\\CurrentControlSet\\"
+ L"Control\\Keyboard Layouts\\";
+
+ /* Create keyboard layout file object */
+ pkf = UserCreateObject(gHandleTable, NULL, NULL, otKBDfile, sizeof(KBDFILE));
+ if (!pkf)
+ {
+ ERR("Failed to create object!\n");
+ return NULL;
+ }
+
+ /* Set keyboard layout name */
+ swprintf(pkf->awchKF, L"%wZ", pwszKLID);
+
+ /* Open layout registry key */
+ RtlStringCbCatW(wszLayoutRegKey, sizeof(wszLayoutRegKey), pkf->awchKF);
+ Status = RegOpenKey(wszLayoutRegKey, &hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("Failed to open keyboard layouts registry key %ws (%lx)\n",
wszLayoutRegKey, Status);
+ goto cleanup;
+ }
+
+ /* Read filename of layout DLL */
+ cbSize = sizeof(wszLayoutPath) - wcslen(wszLayoutPath)*sizeof(WCHAR);
+ Status = RegQueryValue(hKey,
+ L"Layout File",
+ REG_SZ,
+ wszLayoutPath + wcslen(wszLayoutPath),
+ &cbSize);
+
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("Can't get layout filename for %wZ (%lx)\n", pwszKLID,
Status);
+ goto cleanup;
+ }
+
+ /* Load keyboard file now */
+ if (!UserLoadKbdDll(wszLayoutPath, &pkf->hBase, &pkf->pKbdTbl))
+ {
+ ERR("Failed to load %ws dll!\n", wszLayoutPath);
+ goto cleanup;
+ }
+
+ /* Update next field */
+ pkf->pkfNext = gpkfList;
+ gpkfList = pkf;
+
+ /* Return keyboard file */
+ pRet = pkf;
+
+cleanup:
+ if (hKey)
+ ZwClose(hKey);
+ if (pkf)
+ UserDereferenceObject(pkf); // we dont need ptr anymore
+ if (!pRet)
+ {
+ /* We have failed - destroy created object */
+ if (pkf)
+ UserDeleteObject(pkf->head.h, otKBDfile);
+ }
+
+ return pRet;
+}
+
+/*
+ * UserLoadKbdLayout
+ *
+ * Loads keyboard layout and creates KL object
+ */
static PKL
-UserLoadDllAndCreateKbl(DWORD LocaleId)
-{
- PKL pNewKbl;
- ULONG hKl;
- LANGID langid;
-
- pNewKbl = ExAllocatePoolWithTag(PagedPool, sizeof(KL), USERTAG_KBDLAYOUT);
-
- if (!pNewKbl)
- {
- ERR("Can't allocate memory!\n");
+UserLoadKbdLayout(PUNICODE_STRING pwszKLID, HKL hKL)
+{
+ PKL pKl;
+
+ /* Create keyboard layout object */
+ pKl = UserCreateObject(gHandleTable, NULL, NULL, otKBDlayout, sizeof(KL));
+ if (!pKl)
+ {
+ ERR("Failed to create object!\n");
return NULL;
}
- swprintf(pNewKbl->Name, L"%08lx", LocaleId);
-
- if (!UserLoadKbdDll(pNewKbl->Name, &pNewKbl->hModule,
&pNewKbl->KBTables))
- {
- ERR("Failed to load %x dll!\n", LocaleId);
- ExFreePoolWithTag(pNewKbl, USERTAG_KBDLAYOUT);
+ pKl->hkl = hKL;
+ pKl->spkf = UserLoadKbdFile(pwszKLID);
+
+ /* Dereference keyboard layout */
+ UserDereferenceObject(pKl);
+
+ /* If we failed, remove KL object */
+ if (!pKl->spkf)
+ {
+ ERR("UserLoadKbdFile(%wZ) failed!\n", pwszKLID);
+ UserDeleteObject(pKl->head.h, otKBDlayout);
return NULL;
}
- /* Microsoft Office expects this value to be something specific
- * for Japanese and Korean Windows with an IME the value is 0xe001
- * We should probably check to see if an IME exists and if so then
- * set this word properly.
- */
- langid = PRIMARYLANGID(LANGIDFROMLCID(LocaleId));
- hKl = LocaleId;
-
- if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
- hKl |= 0xe001 << 16; /* FIXME */
- else hKl |= hKl << 16;
-
- pNewKbl->hkl = (HKL)(ULONG_PTR) hKl;
- pNewKbl->klid = LocaleId;
- pNewKbl->Flags = 0;
- pNewKbl->RefCount = 0;
-
- return pNewKbl;
-}
-
+ return pKl;
+}
+
+/*
+ * UnloadKbdFile
+ *
+ * Destroys specified Keyboard File object
+ */
+static
+VOID
+UnloadKbdFile(PKBDFILE pkf)
+{
+ PKBDFILE *ppkfLink = &gpkfList;
+
+ /* Find previous object */
+ while (*ppkfLink)
+ {
+ if (*ppkfLink == pkf)
+ break;
+
+ ppkfLink = &(*ppkfLink)->pkfNext;
+ }
+
+ if (*ppkfLink == pkf)
+ *ppkfLink = pkf->pkfNext;
+
+ EngUnloadImage(pkf->hBase);
+ UserDeleteObject(pkf->head.h, otKBDfile);
+}
+
+/*
+ * UserUnloadKbl
+ *
+ * Unloads specified Keyboard Layout if possible
+ */
BOOL
-UserInitDefaultKeyboardLayout()
-{
- LCID LocaleId;
- NTSTATUS Status;
-
- /* Load keyboard layout for default locale */
- Status = ZwQueryDefaultLocale(FALSE, &LocaleId);
- if (NT_SUCCESS(Status))
- {
- TRACE("DefaultLocale = %08lx\n", LocaleId);
- gpklFirst = UserLoadDllAndCreateKbl(LocaleId);
- }
- else
- ERR("Could not get default locale (%08lx).\n", Status);
-
- if (!NT_SUCCESS(Status) || !gpklFirst)
- {
- /* If failed load US keyboard layout */
- ERR("Trying to load US Keyboard Layout.\n");
- LocaleId = 0x409;
-
- if (!(gpklFirst = UserLoadDllAndCreateKbl(LocaleId)))
- {
- ERR("Failed to load any Keyboard Layout\n");
+UserUnloadKbl(PKL pKl)
+{
+ /* According to msdn, UnloadKeyboardLayout can fail
+ if the keyboard layout identifier was preloaded. */
+ if (pKl == gspklBaseLayout)
+ {
+ if (pKl->pklNext == pKl->pklPrev)
+ {
+ /* There is only one layout */
return FALSE;
}
- }
-
- /* Add layout to the list */
- gpklFirst->Flags |= KBL_PRELOAD;
- InitializeListHead(&gpklFirst->List);
-
+
+ /* Set next layout as default */
+ gspklBaseLayout = pKl->pklNext;
+ }
+
+ if (pKl->head.cLockObj > 1)
+ {
+ /* Layout is used by other threads */
+ pKl->dwKL_Flags |= KLF_UNLOAD;
+ return FALSE;
+ }
+
+ /* Unload the layout */
+ pKl->pklPrev->pklNext = pKl->pklNext;
+ pKl->pklNext->pklPrev = pKl->pklPrev;
+ UnloadKbdFile(pKl->spkf);
+ UserDeleteObject(pKl->head.h, otKBDlayout);
return TRUE;
}
+/*
+ * W32kGetDefaultKeyLayout
+ *
+ * Returns default layout for new threads
+ */
PKL
W32kGetDefaultKeyLayout(VOID)
{
- CONST WCHAR wszDefaultUserPath[] = L"\\REGISTRY\\USER\\.DEFAULT";
- CONST WCHAR wszKeyboardLayoutPath[] = L"\\Keyboard Layout\\Preload";
- WCHAR wszKbdLayoutKey[256], *pwsz;
- size_t cbRemaining;
- HKEY hKey;
- ULONG cbValue;
- LCID LayoutLocaleId = 0;
- NTSTATUS Status;
- PKL pKbl;
- UNICODE_STRING CurrentUserPath;
- WCHAR wszBuffer[MAX_PATH];
-
- /* Try to get default alayout from HKCU\Keyboard Layout\Preload first */
- Status = RtlFormatCurrentUserKeyPath(&CurrentUserPath);
- if (NT_SUCCESS(Status))
- {
- /* FIXME: We're called very early, so HKEY_CURRENT_USER might not be
- available yet. Check this first. */
- RtlStringCbCopyNExW(wszKbdLayoutKey, sizeof(wszKbdLayoutKey),
- CurrentUserPath.Buffer, CurrentUserPath.Length,
- &pwsz, &cbRemaining, 0);
- RtlStringCbCopyW(pwsz, cbRemaining, wszKeyboardLayoutPath);
- Status = RegOpenKey(wszKbdLayoutKey, &hKey);
-
- /* Free CurrentUserPath - we dont need it anymore */
- RtlFreeUnicodeString(&CurrentUserPath);
- }
-
- /* If failed try HKU\.DEFAULT\Keyboard Layout\Preload */
- if (!NT_SUCCESS(Status))
- {
- RtlStringCbCopyNExW(wszKbdLayoutKey, sizeof(wszKbdLayoutKey),
- wszDefaultUserPath, sizeof(wszDefaultUserPath),
- &pwsz, &cbRemaining, 0);
- RtlStringCbCopyW(pwsz, cbRemaining, wszKeyboardLayoutPath);
- Status = RegOpenKey(wszKbdLayoutKey, &hKey);
- }
-
- if (NT_SUCCESS(Status))
- {
- /* Return the first keyboard layout listed there */
- cbValue = sizeof(wszBuffer);
- Status = RegQueryValue(hKey, L"1", REG_SZ, wszBuffer, &cbValue);
- if (NT_SUCCESS(Status))
- LayoutLocaleId = (LCID)wcstol(wszBuffer, NULL, 16);
- else
- ERR("RegQueryValue failed (%08lx)\n", Status);
-
- /* Close the key */
- ZwClose(hKey);
- }
- else
- ERR("Failed to open keyboard layout preload key (%08lx)\n", Status);
-
- /* If we failed loading settings from registry use US layout */
- if (!LayoutLocaleId)
- {
- ERR("Assuming default locale for the keyboard layout (0x409 - US)\n");
- LayoutLocaleId = 0x409;
- }
-
- /* Check if layout is already loaded */
- pKbl = gpklFirst;
+ PKL pKl = gspklBaseLayout;
+
+ if (!pKl)
+ return NULL;
+
+ /* Return not unloaded layout */
do
{
- if (pKbl->klid == LayoutLocaleId)
- return pKbl;
-
- pKbl = CONTAINING_RECORD(pKbl->List.Flink, KL, List);
- } while (pKbl != gpklFirst);
-
- /* Load the keyboard layout */
- TRACE("Loading new default keyboard layout.\n");
- pKbl = UserLoadDllAndCreateKbl(LayoutLocaleId);
- if (!pKbl)
- {
- ERR("Failed to load %x!!! Returning any available KL.\n",
LayoutLocaleId);
- return gpklFirst;
- }
-
- /* Add loaded layout to the list */
- InsertTailList(&gpklFirst->List, &pKbl->List);
- return pKbl;
-}
-
+ if (!(pKl->dwKL_Flags & KLF_UNLOAD))
+ return pKl;
+
+ pKl = pKl->pklPrev; /* Confirmed on Win2k */
+ } while(pKl != gspklBaseLayout);
+
+ /* We have not found proper KL */
+ return NULL;
+}
+
+/*
+ * UserHklToKbl
+ *
+ * Gets KL object from hkl value
+ */
PKL
UserHklToKbl(HKL hKl)
{
- PKL pKbl = gpklFirst;
+ PKL pKl = gspklBaseLayout;
+
+ if (!gspklBaseLayout)
+ return NULL;
+
do
{
- if (pKbl->hkl == hKl)
- return pKbl;
-
- pKbl = CONTAINING_RECORD(pKbl->List.Flink, KL, List);
- } while (pKbl != gpklFirst);
+ if (pKl->hkl == hKl)
+ return pKl;
+
+ pKl = pKl->pklNext;
+ } while (pKl != gspklBaseLayout);
return NULL;
}
-BOOL
-UserUnloadKbl(PKL pKbl)
-{
- /* According to msdn, UnloadKeyboardLayout can fail
- if the keyboard layout identifier was preloaded. */
-
- if (pKbl->Flags & KBL_PRELOAD)
- {
- ERR("Attempted to unload preloaded keyboard layout.\n");
- return FALSE;
- }
-
- if (pKbl->RefCount > 0)
- {
- /* Layout is used by other threads.
- Mark it as unloaded and don't do anything else. */
- pKbl->Flags |= KBL_UNLOAD;
- }
- else
- {
- //Unload the layout
- EngUnloadImage(pKbl->hModule);
- RemoveEntryList(&pKbl->List);
- ExFreePoolWithTag(pKbl, USERTAG_KBDLAYOUT);
- }
-
- return TRUE;
-}
-
+/*
+ * co_UserActivateKbl
+ *
+ * Activates given layout in specified thread
+ */
static PKL
-co_UserActivateKbl(PTHREADINFO pti, PKL pKbl, UINT Flags)
+co_UserActivateKbl(PTHREADINFO pti, PKL pKl, UINT Flags)
{
PKL pklPrev;
pklPrev = pti->KeyboardLayout;
- pklPrev->RefCount--;
- pti->KeyboardLayout = pKbl;
- pKbl->RefCount++;
+ if (pklPrev)
+ UserDereferenceObject(pklPrev);
+
+ pti->KeyboardLayout = pKl;
+ UserReferenceObject(pKl);
if (Flags & KLF_SETFORPROCESS)
{
//FIXME
-
- }
-
- if (pklPrev->Flags & KBL_UNLOAD && pklPrev->RefCount == 0)
- {
- UserUnloadKbl(pklPrev);
}
// Send WM_INPUTLANGCHANGE to thread's focus window
co_IntSendMessage(pti->MessageQueue->FocusWindow,
WM_INPUTLANGCHANGE,
- 0, // FIXME: put charset here (what is this?)
- (LPARAM)pKbl->hkl); //klid
+ (WPARAM)pKl->iBaseCharset, // FIXME: how to set it?
+ (LPARAM)pKl->hkl); //hkl
return pklPrev;
}
/* EXPORTS *******************************************************************/
+/*
+ * UserGetKeyboardLayout
+ *
+ * Returns hkl of given thread keyboard layout
+ */
HKL FASTCALL
UserGetKeyboardLayout(
DWORD dwThreadId)
{
NTSTATUS Status;
- PETHREAD Thread;
+ PETHREAD pThread;
PTHREADINFO pti;
- HKL Ret;
+ PKL pKl;
+ HKL hKl;
if (!dwThreadId)
{
pti = PsGetCurrentThreadWin32Thread();
- return pti->KeyboardLayout->hkl;
- }
-
- Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)dwThreadId, &Thread);
+ pKl = pti->KeyboardLayout;
+ return pKl ? pKl->hkl : NULL;
+ }
+
+ Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)dwThreadId, &pThread);
if (!NT_SUCCESS(Status))
{
EngSetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
- pti = PsGetThreadWin32Thread(Thread);
- Ret = pti->KeyboardLayout->hkl;
- ObDereferenceObject(Thread);
- return Ret;
-}
-
+ pti = PsGetThreadWin32Thread(pThread);
+ pKl = pti->KeyboardLayout;
+ hKl = pKl ? pKl->hkl : NULL;;
+ ObDereferenceObject(pThread);
+ return hKl;
+}
+
+/*
+ * NtUserGetKeyboardLayoutList
+ *
+ * Returns list of loaded keyboard layouts in system
+ */
UINT
APIENTRY
NtUserGetKeyboardLayoutList(
INT nBuff,
- HKL* pHklBuff)
+ HKL *pHklBuff)
{
UINT uRet = 0;
- PKL pKbl;
-
- UserEnterShared();
- pKbl = gpklFirst;
+ PKL pKl;
if (!pHklBuff)
nBuff = 0;
+ UserEnterShared();
+
+ if (!gspklBaseLayout)
+ return 0;
+ pKl = gspklBaseLayout;
+
if (nBuff == 0)
{
do
{
uRet++;
- pKbl = CONTAINING_RECORD(pKbl->List.Flink, KL, List);
- } while (pKbl != gpklFirst);
+ pKl = pKl->pklNext;
+ } while (pKl != gspklBaseLayout);
}
else
{
@@ -437,16 +450,12 @@
while (uRet < nBuff)
{
- if (!(pKbl->Flags & KBL_UNLOAD))
- {
- pHklBuff[uRet] = pKbl->hkl;
- uRet++;
- pKbl = CONTAINING_RECORD(pKbl->List.Flink, KL, List);
- if (pKbl == gpklFirst)
- break;
- }
+ pHklBuff[uRet] = pKl->hkl;
+ uRet++;
+ pKl = pKl->pklNext;
+ if (pKl == gspklBaseLayout)
+ break;
}
-
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
@@ -460,23 +469,32 @@
return uRet;
}
+/*
+ * NtUserGetKeyboardLayoutName
+ *
+ * Returns KLID of current thread keyboard layout
+ */
BOOL
APIENTRY
NtUserGetKeyboardLayoutName(
- LPWSTR lpszName)
+ LPWSTR pwszName)
{
BOOL bRet = FALSE;
- PKL pKbl;
+ PKL pKl;
PTHREADINFO pti;
UserEnterShared();
+ pti = PsGetCurrentThreadWin32Thread();
+ pKl = pti->KeyboardLayout;
+
+ if (!pKl)
+ goto cleanup;
+
_SEH2_TRY
{
- ProbeForWrite(lpszName, KL_NAMELENGTH*sizeof(WCHAR), 1);
- pti = PsGetCurrentThreadWin32Thread();
- pKbl = pti->KeyboardLayout;
- RtlCopyMemory(lpszName, pKbl->Name, KL_NAMELENGTH*sizeof(WCHAR));
+ ProbeForWrite(pwszName, KL_NAMELENGTH*sizeof(WCHAR), 1);
+ wcscpy(pwszName, pKl->spkf->awchKF);
bRet = TRUE;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@@ -485,155 +503,207 @@
}
_SEH2_END;
+cleanup:
UserLeave();
return bRet;
}
+/*
+ * NtUserLoadKeyboardLayoutEx
+ *
+ * Loads keyboard layout with given locale id
+ */
HKL
APIENTRY
NtUserLoadKeyboardLayoutEx(
- IN HANDLE Handle,
- IN DWORD offTable,
- IN PUNICODE_STRING puszKeyboardName,
- IN HKL hKL,
- IN PUNICODE_STRING puszKLID,
- IN DWORD dwKLID,
+ IN HANDLE Handle, // hFile (See
downloads.securityfocus.com/vulnerabilities/exploits/43774.c)
+ IN DWORD offTable, // offset to KbdTables
+ IN PUNICODE_STRING puszKeyboardName, // not used?
+ IN HKL hklUnload,
+ IN PUNICODE_STRING pustrKLID,
+ IN DWORD hkl,
IN UINT Flags)
{
HKL hklRet = NULL;
- PKL pKbl = NULL, pklCur;
+ PKL pKl = NULL, pklLast;
+ WCHAR Buffer[9];
+ UNICODE_STRING ustrSafeKLID;
if (Flags & ~(KLF_ACTIVATE|KLF_NOTELLSHELL|KLF_REORDER|KLF_REPLACELANG|
- KLF_SUBSTITUTE_OK|KLF_SETFORPROCESS|KLF_UNLOADPREVIOUS))
+ KLF_SUBSTITUTE_OK|KLF_SETFORPROCESS|KLF_UNLOADPREVIOUS|
+ KLF_RESET|KLF_SETFORPROCESS|KLF_SHIFTLOCK))
{
ERR("Invalid flags: %x\n", Flags);
EngSetLastError(ERROR_INVALID_FLAGS);
- return 0;
- }
+ return NULL;
+ }
+
+ /* FIXME: it seems KLF_RESET is only supported for WINLOGON */
+
+ RtlInitEmptyUnicodeString(&ustrSafeKLID, Buffer, sizeof(Buffer));
+ _SEH2_TRY
+ {
+ ProbeForRead(pustrKLID, sizeof(*pustrKLID), 1);
+ ProbeForRead(pustrKLID->Buffer, sizeof(pustrKLID->Length), 1);
+ RtlCopyUnicodeString(&ustrSafeKLID, pustrKLID);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ _SEH2_YIELD(return NULL);
+ }
+ _SEH2_END;
UserEnterExclusive();
- //Let's see if layout was already loaded.
- pklCur = gpklFirst;
- do
- {
- if (pklCur->klid == dwKLID)
- {
- pKbl = pklCur;
- pKbl->Flags &= ~KBL_UNLOAD;
- break;
- }
-
- pklCur = CONTAINING_RECORD(pKbl->List.Flink, KL, List);
- } while (pklCur != gpklFirst);
-
- //It wasn't, so load it.
- if (!pKbl)
- {
- pKbl = UserLoadDllAndCreateKbl(dwKLID);
-
- if (!pKbl)
- {
+ /* If hklUnload is specified, unload it and load new layput as default */
+ if (hklUnload && hklUnload != (HKL)hkl)
+ {
+ pKl = UserHklToKbl(hklUnload);
+ if (pKl)
+ UserUnloadKbl(pKl);
+ }
+
+ /* Let's see if layout was already loaded. */
+ pKl = UserHklToKbl((HKL)hkl);
+ if (!pKl)
+ {
+ /* It wasn't, so load it. */
+ pKl = UserLoadKbdLayout(&ustrSafeKLID, (HKL)hkl);
+ if (!pKl)
goto cleanup;
- }
-
- InsertTailList(&gpklFirst->List, &pKbl->List);
- }
-
- if (Flags & KLF_REORDER) gpklFirst = pKbl;
-
+
+ if (gspklBaseLayout)
+ {
+ /* Find last not unloaded layout */
+ pklLast = gspklBaseLayout->pklPrev;
+ while (pklLast != gspklBaseLayout && pklLast->dwKL_Flags &
KLF_UNLOAD)
+ pklLast = pklLast->pklPrev;
+
+ /* Add new layout to the list */
+ pKl->pklNext = pklLast->pklNext;
+ pKl->pklPrev = pklLast;
+ pKl->pklNext->pklPrev = pKl;
+ pKl->pklPrev->pklNext = pKl;
+ }
+ else
+ {
+ /* This is the first layout */
+ pKl->pklNext = pKl;
+ pKl->pklPrev = pKl;
+ gspklBaseLayout = pKl;
+ }
+ }
+
+ /* If this layout was prepared to unload, undo it */
+ pKl->dwKL_Flags &= ~KLF_UNLOAD;
+
+ /* Loaded keyboard layout became the default */
+ gspklBaseLayout = pKl;
+
+ /* Activate this layout in current thread */
if (Flags & KLF_ACTIVATE)
- {
- co_UserActivateKbl(PsGetCurrentThreadWin32Thread(), pKbl, Flags);
- }
-
- hklRet = pKbl->hkl;
-
- //FIXME: KLF_NOTELLSHELL
- // KLF_REPLACELANG
- // KLF_SUBSTITUTE_OK
+ co_UserActivateKbl(PsGetCurrentThreadWin32Thread(), pKl, Flags);
+
+ /* Send shell message */
+ if (!(Flags & KLF_NOTELLSHELL))
+ co_IntShellHookNotify(HSHELL_LANGUAGE, (LPARAM)hkl);
+
+ /* Return hkl on success */
+ hklRet = (HKL)hkl;
+
+ /* FIXME: KLF_REPLACELANG
+ KLF_REORDER */
cleanup:
UserLeave();
return hklRet;
}
+/*
+ * NtUserActivateKeyboardLayout
+ *
+ * Activates specified layout for thread or process
+ */
HKL
APIENTRY
NtUserActivateKeyboardLayout(
HKL hKl,
ULONG Flags)
{
- PKL pKbl;
- HKL hklRet = NULL;
+ PKL pKl = NULL;
+ HKL hkl = NULL;
PTHREADINFO pti;
UserEnterExclusive();
pti = PsGetCurrentThreadWin32Thread();
- if (pti->KeyboardLayout->hkl == hKl)
- {
- hklRet = hKl;
+ /* hKl can have special value HKL_NEXT or HKL_PREV */
+ if (hKl == (HKL)HKL_NEXT)
+ {
+ /* Get next keyboard layout starting with current */
+ if (pti->KeyboardLayout)
+ pKl = pti->KeyboardLayout->pklNext;
+ }
+ else if (hKl == (HKL)HKL_PREV)
+ {
+ /* Get previous keyboard layout starting with current */
+ if (pti->KeyboardLayout)
+ pKl = pti->KeyboardLayout->pklNext;
+ }
+ else
+ pKl = UserHklToKbl(hKl);
+
+ if (!pKl)
+ {
+ ERR("Invalid HKL %x!\n", hKl);
goto cleanup;
}
- if (hKl == (HKL)HKL_NEXT)
- {
- pKbl = CONTAINING_RECORD(pti->KeyboardLayout->List.Flink, KL, List);
- }
- else if (hKl == (HKL)HKL_PREV)
- {
- pKbl = CONTAINING_RECORD(pti->KeyboardLayout->List.Blink, KL, List);
- }
- else pKbl = UserHklToKbl(hKl);
-
- //FIXME: KLF_RESET, KLF_SHIFTLOCK
-
- if (pKbl)
- {
- if (Flags & KLF_REORDER)
- gpklFirst = pKbl;
-
- if (pKbl == pti->KeyboardLayout)
- {
- hklRet = pKbl->hkl;
- }
- else
- {
- pKbl = co_UserActivateKbl(pti, pKbl, Flags);
- hklRet = pKbl->hkl;
- }
- }
- else
- {
- ERR("Invalid HKL %x!\n", hKl);
+ hkl = pKl->hkl;
+
+ /* FIXME: KLF_RESET
+ KLF_SHIFTLOCK */
+
+ if (Flags & KLF_REORDER)
+ gspklBaseLayout = pKl;
+
+ if (pKl != pti->KeyboardLayout)
+ {
+ /* Activate layout for current thread */
+ pKl = co_UserActivateKbl(pti, pKl, Flags);
+
+ /* Send shell message */
+ if (!(Flags & KLF_NOTELLSHELL))
+ co_IntShellHookNotify(HSHELL_LANGUAGE, (LPARAM)hkl);
}
cleanup:
UserLeave();
- return hklRet;
-}
-
+ return hkl;
+}
+
+/*
+ * NtUserUnloadKeyboardLayout
+ *
+ * Unloads keyboard layout with specified hkl value
+ */
BOOL
APIENTRY
NtUserUnloadKeyboardLayout(
HKL hKl)
{
- PKL pKbl;
+ PKL pKl;
BOOL bRet = FALSE;
UserEnterExclusive();
- pKbl = UserHklToKbl(hKl);
- if (pKbl)
- {
- bRet = UserUnloadKbl(pKbl);
- }
+ pKl = UserHklToKbl(hKl);
+ if (pKl)
+ bRet = UserUnloadKbl(pKl);
else
- {
ERR("Invalid HKL %x!\n", hKl);
- }
UserLeave();
return bRet;
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/keyboard.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/keyboard.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/keyboard.c [iso-8859-1] Wed Oct 19
20:03:50 2011
@@ -891,7 +891,7 @@
UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected)
{
WORD wScanCode, wVk;
- PKL pKbl = NULL;
+ PKL pKl = NULL;
PKBDTABLES pKbdTbl;
PUSER_MESSAGE_QUEUE pFocusQueue;
struct _ETHREAD *pFocusThread;
@@ -906,18 +906,18 @@
{
pFocusThread = pFocusQueue->Thread;
if (pFocusThread && pFocusThread->Tcb.Win32Thread)
- pKbl = ((PTHREADINFO)pFocusThread->Tcb.Win32Thread)->KeyboardLayout;
- }
-
- if (!pKbl)
- pKbl = W32kGetDefaultKeyLayout();
- if (!pKbl)
+ pKl = ((PTHREADINFO)pFocusThread->Tcb.Win32Thread)->KeyboardLayout;
+ }
+
+ if (!pKl)
+ pKl = W32kGetDefaultKeyLayout();
+ if (!pKl)
{
ERR("No keyboard layout!\n");
return FALSE;
}
- pKbdTbl = pKbl->KBTables;
+ pKbdTbl = pKl->spkf->pKbdTbl;
/* Note: wScan field is always used */
wScanCode = pKbdInput->wScan;
@@ -973,7 +973,7 @@
PKEYBOARD_INPUT_DATA pKbdInputData)
{
WORD wScanCode, wVk;
- PKL pKbl = NULL;
+ PKL pKl = NULL;
PKBDTABLES pKbdTbl;
PUSER_MESSAGE_QUEUE pFocusQueue;
struct _ETHREAD *pFocusThread;
@@ -992,15 +992,15 @@
{
pFocusThread = pFocusQueue->Thread;
if (pFocusThread && pFocusThread->Tcb.Win32Thread)
- pKbl = ((PTHREADINFO)pFocusThread->Tcb.Win32Thread)->KeyboardLayout;
- }
-
- if (!pKbl)
- pKbl = W32kGetDefaultKeyLayout();
- if (!pKbl)
+ pKl = ((PTHREADINFO)pFocusThread->Tcb.Win32Thread)->KeyboardLayout;
+ }
+
+ if (!pKl)
+ pKl = W32kGetDefaultKeyLayout();
+ if (!pKl)
return;
- pKbdTbl = pKbl->KBTables;
+ pKbdTbl = pKl->spkf->pKbdTbl;
/* Convert scan code to virtual key.
Note: we could call UserSendKeyboardInput using scan code,
@@ -1068,7 +1068,7 @@
}
pti = pWnd->head.pti;
- pKbdTbl = pti->KeyboardLayout->KBTables;
+ pKbdTbl = pti->KeyboardLayout->spkf->pKbdTbl;
if (!pKbdTbl)
return FALSE;
@@ -1207,15 +1207,15 @@
pti = PsGetCurrentThreadWin32Thread();
if (pti && pti->KeyboardLayout)
- pKbdTbl = pti->KeyboardLayout->KBTables;
+ pKbdTbl = pti->KeyboardLayout->spkf->pKbdTbl;
}
else
{
- PKL pKbl;
-
- pKbl = UserHklToKbl(dwhkl);
- if (pKbl)
- pKbdTbl = pKbl->KBTables;
+ PKL pKl;
+
+ pKl = UserHklToKbl(dwhkl);
+ if (pKl)
+ pKbdTbl = pKl->spkf->pKbdTbl;
}
if (pKbdTbl)
@@ -1246,7 +1246,7 @@
BYTE afKeyState[256 * 2 / 8] = {0};
PWCHAR pwszBuff = NULL;
INT i, iRet = 0;
- PKL pKbl = NULL;
+ PKL pKl = NULL;
TRACE("Enter NtUserSetKeyboardState\n");
@@ -1288,12 +1288,12 @@
UserEnterExclusive(); // Note: we modify wchDead static variable
if (dwhkl)
- pKbl = UserHklToKbl(dwhkl);
-
- if (!pKbl)
+ pKl = UserHklToKbl(dwhkl);
+
+ if (!pKl)
{
pti = PsGetCurrentThreadWin32Thread();
- pKbl = pti->KeyboardLayout;
+ pKl = pti->KeyboardLayout;
}
iRet = IntToUnicodeEx(wVirtKey,
@@ -1302,7 +1302,7 @@
pwszBuff,
cchBuff,
wFlags,
- pKbl ? pKbl->KBTables : NULL);
+ pKl ? pKl->spkf->pKbdTbl : NULL);
MmCopyToCaller(pwszBuffUnsafe, pwszBuff, cchBuff * sizeof(WCHAR));
ExFreePoolWithTag(pwszBuff, TAG_STRING);
@@ -1336,7 +1336,7 @@
/* Get current keyboard layout */
pti = PsGetCurrentThreadWin32Thread();
- pKbdTbl = pti ? pti->KeyboardLayout->KBTables : 0;
+ pKbdTbl = pti ? pti->KeyboardLayout->spkf->pKbdTbl : 0;
if (!pKbdTbl || cchSize < 1)
{
@@ -1451,7 +1451,7 @@
PKBDTABLES pKbdTbl;
PVK_TO_WCHAR_TABLE pVkToWchTbl;
PVK_TO_WCHARS10 pVkToWch;
- PKL pKbl = NULL;
+ PKL pKl = NULL;
DWORD i, dwModBits = 0, dwModNumber = 0, Ret = (DWORD)-1;
TRACE("NtUserVkKeyScanEx() wch %d, KbdLayout 0x%p\n", wch, dwhkl);
@@ -1461,18 +1461,18 @@
{
// Use given keyboard layout
if (dwhkl)
- pKbl = UserHklToKbl(dwhkl);
+ pKl = UserHklToKbl(dwhkl);
}
else
{
// Use thread keyboard layout
- pKbl = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->KeyboardLayout;
- }
-
- if (!pKbl)
+ pKl = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->KeyboardLayout;
+ }
+
+ if (!pKl)
goto Exit;
- pKbdTbl = pKbl->KBTables;
+ pKbdTbl = pKl->spkf->pKbdTbl;
// Interate through all VkToWchar tables while pVkToWchars is not NULL
for (i = 0; pKbdTbl->pVkToWcharTable[i].pVkToWchars; i++)