[ros-diffs] [rharabien] 54203: [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 Lay...

rharabien at svn.reactos.org rharabien at svn.reactos.org
Wed Oct 19 20:03:51 UTC 2011


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/winlogon.c?rev=54203&r1=54202&r2=54203&view=diff
==============================================================================
--- 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/winlogon.h?rev=54203&r1=54202&r2=54203&view=diff
==============================================================================
--- 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.inf?rev=54203&r1=54202&r2=54203&view=diff
==============================================================================
--- 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,"@%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,"@%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/include/input.h?rev=54203&r1=54202&r2=54203&view=diff
==============================================================================
--- 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/main/dllmain.c?rev=54203&r1=54202&r2=54203&view=diff
==============================================================================
--- 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/ntuser/input.c?rev=54203&r1=54202&r2=54203&view=diff
==============================================================================
--- 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/ntuser/kbdlayout.c?rev=54203&r1=54202&r2=54203&view=diff
==============================================================================
--- 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/ntuser/keyboard.c?rev=54203&r1=54202&r2=54203&view=diff
==============================================================================
--- 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++)




More information about the Ros-diffs mailing list