mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 14:56:58 +00:00
[WIN32K]
- Remove ReadRegistryValue in kbdlayout.c as we already implement RegQueryValue for reading from registry in W32k. This function additionally checks value type. - Rename KBL to KL based on Techwiki - HKCU\Keyboard Layout\Preload value is REG_SZ (not REG_EXPAND_SZ) - NtUserLoadKeyboardLayoutEx should set last error if flags are invalid - Minor keyboard layout code cleanup svn path=/trunk/; revision=54163
This commit is contained in:
parent
a8c53e6e1a
commit
49793fea10
5 changed files with 285 additions and 371 deletions
|
@ -8,7 +8,7 @@ HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
|
||||||
[AddReg]
|
[AddReg]
|
||||||
|
|
||||||
; Default locale for the keyboard layout
|
; Default locale for the keyboard layout
|
||||||
HKU,".DEFAULT\Keyboard Layout\Preload","1",0x00020000,"00000409"
|
HKU,".DEFAULT\Keyboard Layout\Preload","1",0x00000000,"00000409"
|
||||||
|
|
||||||
; Cdfs (ISO96660) filesystem driver
|
; Cdfs (ISO96660) filesystem driver
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\Cdfs","Start",0x00010001,0x00000000
|
HKLM,"SYSTEM\CurrentControlSet\Services\Cdfs","Start",0x00010001,0x00000000
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <ndk/kbd.h>
|
#include <ndk/kbd.h>
|
||||||
|
|
||||||
typedef struct _KBL
|
typedef struct _KL
|
||||||
{
|
{
|
||||||
LIST_ENTRY List;
|
LIST_ENTRY List;
|
||||||
DWORD Flags;
|
DWORD Flags;
|
||||||
|
@ -12,7 +12,7 @@ typedef struct _KBL
|
||||||
ULONG RefCount;
|
ULONG RefCount;
|
||||||
HKL hkl;
|
HKL hkl;
|
||||||
DWORD klid; // Low word - language id. High word - device id.
|
DWORD klid; // Low word - language id. High word - device id.
|
||||||
} KBL, *PKBL;
|
} KL, *PKL;
|
||||||
|
|
||||||
typedef struct _ATTACHINFO
|
typedef struct _ATTACHINFO
|
||||||
{
|
{
|
||||||
|
@ -39,14 +39,14 @@ extern PATTACHINFO gpai;
|
||||||
INIT_FUNCTION NTSTATUS NTAPI InitInputImpl(VOID);
|
INIT_FUNCTION NTSTATUS NTAPI InitInputImpl(VOID);
|
||||||
INIT_FUNCTION NTSTATUS NTAPI InitKeyboardImpl(VOID);
|
INIT_FUNCTION NTSTATUS NTAPI InitKeyboardImpl(VOID);
|
||||||
VOID NTAPI UserInitKeyboard(HANDLE hKeyboardDevice);
|
VOID NTAPI UserInitKeyboard(HANDLE hKeyboardDevice);
|
||||||
PKBL W32kGetDefaultKeyLayout(VOID);
|
PKL W32kGetDefaultKeyLayout(VOID);
|
||||||
VOID NTAPI UserProcessKeyboardInput(PKEYBOARD_INPUT_DATA pKeyInput);
|
VOID NTAPI UserProcessKeyboardInput(PKEYBOARD_INPUT_DATA pKeyInput);
|
||||||
BOOL NTAPI UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected);
|
BOOL NTAPI UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected);
|
||||||
VOID NTAPI UserProcessMouseInput(PMOUSE_INPUT_DATA Data, ULONG InputCount);
|
VOID NTAPI UserProcessMouseInput(PMOUSE_INPUT_DATA Data, ULONG InputCount);
|
||||||
BOOL FASTCALL IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt);
|
BOOL FASTCALL IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt);
|
||||||
BOOL FASTCALL IntMouseInput(MOUSEINPUT *mi, BOOL Injected);
|
BOOL FASTCALL IntMouseInput(MOUSEINPUT *mi, BOOL Injected);
|
||||||
BOOL UserInitDefaultKeyboardLayout(VOID);
|
BOOL UserInitDefaultKeyboardLayout(VOID);
|
||||||
PKBL UserHklToKbl(HKL hKl);
|
PKL UserHklToKbl(HKL hKl);
|
||||||
VOID NTAPI KeyboardThreadMain(PVOID StartContext);
|
VOID NTAPI KeyboardThreadMain(PVOID StartContext);
|
||||||
DWORD NTAPI CreateSystemThreads(UINT Type);
|
DWORD NTAPI CreateSystemThreads(UINT Type);
|
||||||
BOOL FASTCALL UserAttachThreadInput(PTHREADINFO,PTHREADINFO,BOOL);
|
BOOL FASTCALL UserAttachThreadInput(PTHREADINFO,PTHREADINFO,BOOL);
|
||||||
|
|
|
@ -69,7 +69,7 @@ typedef struct _THREADINFO
|
||||||
PTL ptl;
|
PTL ptl;
|
||||||
PPROCESSINFO ppi;
|
PPROCESSINFO ppi;
|
||||||
struct _USER_MESSAGE_QUEUE* MessageQueue;
|
struct _USER_MESSAGE_QUEUE* MessageQueue;
|
||||||
struct _KBL* KeyboardLayout;
|
struct _KL* KeyboardLayout;
|
||||||
PCLIENTTHREADINFO pcti;
|
PCLIENTTHREADINFO pcti;
|
||||||
struct _DESKTOP* rpdesk;
|
struct _DESKTOP* rpdesk;
|
||||||
PDESKTOPINFO pDeskInfo;
|
PDESKTOPINFO pDeskInfo;
|
||||||
|
@ -188,7 +188,7 @@ typedef struct _PROCESSINFO
|
||||||
LIST_ENTRY PrivateFontListHead;
|
LIST_ENTRY PrivateFontListHead;
|
||||||
FAST_MUTEX DriverObjListLock;
|
FAST_MUTEX DriverObjListLock;
|
||||||
LIST_ENTRY DriverObjListHead;
|
LIST_ENTRY DriverObjListHead;
|
||||||
struct _KBL* KeyboardLayout; // THREADINFO only
|
struct _KL* KeyboardLayout; // THREADINFO only
|
||||||
W32HEAP_USER_MAPPING HeapMappings;
|
W32HEAP_USER_MAPPING HeapMappings;
|
||||||
struct _GDI_POOL *pPoolDcAttr;
|
struct _GDI_POOL *pPoolDcAttr;
|
||||||
struct _GDI_POOL *pPoolBrushAttr;
|
struct _GDI_POOL *pPoolBrushAttr;
|
||||||
|
|
|
@ -5,164 +5,74 @@
|
||||||
* PURPOSE: Keyboard layout management
|
* PURPOSE: Keyboard layout management
|
||||||
* COPYRIGHT: Copyright 2007 Saveliy Tretiakov
|
* COPYRIGHT: Copyright 2007 Saveliy Tretiakov
|
||||||
* Copyright 2008 Colin Finck
|
* Copyright 2008 Colin Finck
|
||||||
|
* Copyright 2011 Rafal Harabien
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <win32k.h>
|
#include <win32k.h>
|
||||||
DBG_DEFAULT_CHANNEL(UserKbdLayout);
|
DBG_DEFAULT_CHANNEL(UserKbdLayout);
|
||||||
|
|
||||||
PKBL KBLList = NULL; // Keyboard layout list.
|
PKL gpklFirst = NULL; // Keyboard layout list.
|
||||||
|
|
||||||
typedef PVOID (*KbdLayerDescriptor)(VOID);
|
typedef PVOID (*PFNKBDLAYERDESCRIPTOR)(VOID);
|
||||||
|
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS ******************************************************/
|
/* PRIVATE FUNCTIONS ******************************************************/
|
||||||
|
|
||||||
|
static BOOL
|
||||||
/*
|
UserLoadKbdDll(CONST WCHAR *wszKLID,
|
||||||
* Utility function to read a value from the registry more easily.
|
|
||||||
*
|
|
||||||
* IN PUNICODE_STRING KeyName -> Name of key to open
|
|
||||||
* IN PUNICODE_STRING ValueName -> Name of value to open
|
|
||||||
* OUT PUNICODE_STRING ReturnedValue -> String contained in registry
|
|
||||||
*
|
|
||||||
* Returns NTSTATUS
|
|
||||||
*/
|
|
||||||
|
|
||||||
static NTSTATUS APIENTRY ReadRegistryValue( PUNICODE_STRING KeyName,
|
|
||||||
PUNICODE_STRING ValueName,
|
|
||||||
PUNICODE_STRING ReturnedValue )
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
HANDLE KeyHandle;
|
|
||||||
OBJECT_ATTRIBUTES KeyAttributes;
|
|
||||||
PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
|
|
||||||
ULONG Length = 0;
|
|
||||||
ULONG ResLength = 0;
|
|
||||||
PWCHAR ReturnBuffer;
|
|
||||||
|
|
||||||
InitializeObjectAttributes(&KeyAttributes, KeyName, OBJ_CASE_INSENSITIVE,
|
|
||||||
NULL, NULL);
|
|
||||||
Status = ZwOpenKey(&KeyHandle, KEY_READ, &KeyAttributes);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = ZwQueryValueKey(KeyHandle, ValueName, KeyValuePartialInformation,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
&ResLength);
|
|
||||||
|
|
||||||
if (Status != STATUS_BUFFER_TOO_SMALL)
|
|
||||||
{
|
|
||||||
NtClose(KeyHandle);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResLength += sizeof(*KeyValuePartialInfo);
|
|
||||||
KeyValuePartialInfo =
|
|
||||||
ExAllocatePoolWithTag(PagedPool, ResLength, TAG_STRING);
|
|
||||||
Length = ResLength;
|
|
||||||
|
|
||||||
if (!KeyValuePartialInfo)
|
|
||||||
{
|
|
||||||
NtClose(KeyHandle);
|
|
||||||
return STATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = ZwQueryValueKey(KeyHandle,
|
|
||||||
ValueName,
|
|
||||||
KeyValuePartialInformation,
|
|
||||||
(PVOID)KeyValuePartialInfo,
|
|
||||||
Length,
|
|
||||||
&ResLength);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
NtClose(KeyHandle);
|
|
||||||
ExFreePoolWithTag(KeyValuePartialInfo, TAG_STRING);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* At this point, KeyValuePartialInfo->Data contains the key data */
|
|
||||||
ReturnBuffer = ExAllocatePoolWithTag(PagedPool,
|
|
||||||
KeyValuePartialInfo->DataLength,
|
|
||||||
TAG_STRING);
|
|
||||||
|
|
||||||
if (!ReturnBuffer)
|
|
||||||
{
|
|
||||||
NtClose(KeyHandle);
|
|
||||||
ExFreePoolWithTag(KeyValuePartialInfo, TAG_STRING);
|
|
||||||
return STATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlCopyMemory(ReturnBuffer,
|
|
||||||
KeyValuePartialInfo->Data,
|
|
||||||
KeyValuePartialInfo->DataLength);
|
|
||||||
RtlInitUnicodeString(ReturnedValue, ReturnBuffer);
|
|
||||||
|
|
||||||
ExFreePoolWithTag(KeyValuePartialInfo, TAG_STRING);
|
|
||||||
NtClose(KeyHandle);
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL UserLoadKbdDll(WCHAR *wsKLID,
|
|
||||||
HANDLE *phModule,
|
HANDLE *phModule,
|
||||||
PKBDTABLES *pKbdTables)
|
PKBDTABLES *pKbdTables)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
KbdLayerDescriptor layerDescGetFn;
|
HKEY hKey;
|
||||||
ANSI_STRING kbdProcedureName;
|
ULONG cbSize;
|
||||||
UNICODE_STRING LayoutKeyName;
|
PFNKBDLAYERDESCRIPTOR pfnKbdLayerDescriptor;
|
||||||
UNICODE_STRING LayoutValueName;
|
WCHAR wszLayoutRegKey[256] = L"\\REGISTRY\\Machine\\SYSTEM\\CurrentControlSet\\"
|
||||||
UNICODE_STRING LayoutFile;
|
L"Control\\Keyboard Layouts\\";
|
||||||
UNICODE_STRING FullLayoutPath;
|
WCHAR wszLayoutPath[MAX_PATH] = L"\\SystemRoot\\System32\\";
|
||||||
UNICODE_STRING klid;
|
|
||||||
WCHAR LayoutPathBuffer[MAX_PATH] = L"\\SystemRoot\\System32\\";
|
|
||||||
WCHAR KeyNameBuffer[MAX_PATH] = L"\\REGISTRY\\Machine\\SYSTEM\\"
|
|
||||||
L"CurrentControlSet\\Control\\Keyboard Layouts\\";
|
|
||||||
|
|
||||||
RtlInitUnicodeString(&klid, wsKLID);
|
|
||||||
RtlInitUnicodeString(&LayoutValueName, L"Layout File");
|
|
||||||
RtlInitUnicodeString(&LayoutKeyName, KeyNameBuffer);
|
|
||||||
LayoutKeyName.MaximumLength = sizeof(KeyNameBuffer);
|
|
||||||
|
|
||||||
RtlAppendUnicodeStringToString(&LayoutKeyName, &klid);
|
|
||||||
Status = ReadRegistryValue(&LayoutKeyName, &LayoutValueName, &LayoutFile);
|
|
||||||
|
|
||||||
|
/* Open layout registry key */
|
||||||
|
RtlStringCbCatW(wszLayoutRegKey, sizeof(wszLayoutRegKey), wszKLID);
|
||||||
|
Status = RegOpenKey(wszLayoutRegKey, &hKey);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
TRACE("Can't get layout filename for %wZ. (%08lx)\n", klid, Status);
|
ERR("Failed to open keyboard layouts registry key %ws (%lx)\n", wszKLID, Status);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("Read registry and got %wZ\n", &LayoutFile);
|
/* Read filename of layout DLL and close the key */
|
||||||
RtlInitUnicodeString(&FullLayoutPath, LayoutPathBuffer);
|
cbSize = sizeof(wszLayoutPath) - (wcslen(wszLayoutPath) + 1)*sizeof(WCHAR);
|
||||||
FullLayoutPath.MaximumLength = sizeof(LayoutPathBuffer);
|
Status = RegQueryValue(hKey,
|
||||||
RtlAppendUnicodeStringToString(&FullLayoutPath, &LayoutFile);
|
L"Layout File",
|
||||||
TRACE("Loading Keyboard DLL %wZ\n", &FullLayoutPath);
|
REG_SZ,
|
||||||
ExFreePoolWithTag(LayoutFile.Buffer, TAG_STRING);
|
wszLayoutPath + wcslen(wszLayoutPath),
|
||||||
|
&cbSize);
|
||||||
*phModule = EngLoadImage(FullLayoutPath.Buffer);
|
ZwClose(hKey);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
if (*phModule)
|
|
||||||
{
|
{
|
||||||
TRACE("Loaded %wZ\n", &FullLayoutPath);
|
TRACE("Can't get layout filename for %ws (%lx)\n", wszKLID, Status);
|
||||||
|
return FALSE;
|
||||||
RtlInitAnsiString( &kbdProcedureName, "KbdLayerDescriptor" );
|
|
||||||
layerDescGetFn = EngFindImageProcAddress(*phModule, "KbdLayerDescriptor");
|
|
||||||
|
|
||||||
if (layerDescGetFn)
|
|
||||||
{
|
|
||||||
*pKbdTables = layerDescGetFn();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
pfnKbdLayerDescriptor = EngFindImageProcAddress(*phModule, "KbdLayerDescriptor");
|
||||||
|
|
||||||
|
if (pfnKbdLayerDescriptor)
|
||||||
|
*pKbdTables = pfnKbdLayerDescriptor();
|
||||||
else
|
else
|
||||||
{
|
ERR("Error: %ws has no KbdLayerDescriptor()\n", wszLayoutPath);
|
||||||
ERR("Error: %wZ has no KbdLayerDescriptor()\n", &FullLayoutPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!layerDescGetFn || !*pKbdTables)
|
if (!pfnKbdLayerDescriptor || !*pKbdTables)
|
||||||
{
|
{
|
||||||
ERR("Failed to load the keyboard layout.\n");
|
ERR("Failed to load the keyboard layout.\n");
|
||||||
EngUnloadImage(*phModule);
|
EngUnloadImage(*phModule);
|
||||||
|
@ -217,39 +127,34 @@ static BOOL UserLoadKbdDll(WCHAR *wsKLID,
|
||||||
++pVscVk;
|
++pVscVk;
|
||||||
}
|
}
|
||||||
DbgPrint("}\n");
|
DbgPrint("}\n");
|
||||||
}
|
|
||||||
DbgBreakPoint();
|
DbgBreakPoint();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ERR("Failed to load dll %wZ\n", &FullLayoutPath);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PKBL UserLoadDllAndCreateKbl(DWORD LocaleId)
|
static PKL
|
||||||
|
UserLoadDllAndCreateKbl(DWORD LocaleId)
|
||||||
{
|
{
|
||||||
PKBL NewKbl;
|
PKL pNewKbl;
|
||||||
ULONG hKl;
|
ULONG hKl;
|
||||||
LANGID langid;
|
LANGID langid;
|
||||||
|
|
||||||
NewKbl = ExAllocatePoolWithTag(PagedPool, sizeof(KBL), USERTAG_KBDLAYOUT);
|
pNewKbl = ExAllocatePoolWithTag(PagedPool, sizeof(KL), USERTAG_KBDLAYOUT);
|
||||||
|
|
||||||
if (!NewKbl)
|
if (!pNewKbl)
|
||||||
{
|
{
|
||||||
ERR("%s: Can't allocate memory!\n", __FUNCTION__);
|
ERR("Can't allocate memory!\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
swprintf(NewKbl->Name, L"%08lx", LocaleId);
|
swprintf(pNewKbl->Name, L"%08lx", LocaleId);
|
||||||
|
|
||||||
if (!UserLoadKbdDll(NewKbl->Name, &NewKbl->hModule, &NewKbl->KBTables))
|
if (!UserLoadKbdDll(pNewKbl->Name, &pNewKbl->hModule, &pNewKbl->KBTables))
|
||||||
{
|
{
|
||||||
TRACE("%s: failed to load %x dll!\n", __FUNCTION__, LocaleId);
|
ERR("Failed to load %x dll!\n", LocaleId);
|
||||||
ExFreePoolWithTag(NewKbl, USERTAG_KBDLAYOUT);
|
ExFreePoolWithTag(pNewKbl, USERTAG_KBDLAYOUT);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,158 +170,155 @@ static PKBL UserLoadDllAndCreateKbl(DWORD LocaleId)
|
||||||
hKl |= 0xe001 << 16; /* FIXME */
|
hKl |= 0xe001 << 16; /* FIXME */
|
||||||
else hKl |= hKl << 16;
|
else hKl |= hKl << 16;
|
||||||
|
|
||||||
NewKbl->hkl = (HKL)(ULONG_PTR) hKl;
|
pNewKbl->hkl = (HKL)(ULONG_PTR) hKl;
|
||||||
NewKbl->klid = LocaleId;
|
pNewKbl->klid = LocaleId;
|
||||||
NewKbl->Flags = 0;
|
pNewKbl->Flags = 0;
|
||||||
NewKbl->RefCount = 0;
|
pNewKbl->RefCount = 0;
|
||||||
|
|
||||||
return NewKbl;
|
return pNewKbl;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL UserInitDefaultKeyboardLayout()
|
BOOL
|
||||||
|
UserInitDefaultKeyboardLayout()
|
||||||
{
|
{
|
||||||
LCID LocaleId;
|
LCID LocaleId;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* Load keyboard layout for default locale */
|
||||||
Status = ZwQueryDefaultLocale(FALSE, &LocaleId);
|
Status = ZwQueryDefaultLocale(FALSE, &LocaleId);
|
||||||
if (!NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
|
||||||
ERR("Could not get default locale (%08lx).\n", Status);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
TRACE("DefaultLocale = %08lx\n", LocaleId);
|
TRACE("DefaultLocale = %08lx\n", LocaleId);
|
||||||
|
gpklFirst = UserLoadDllAndCreateKbl(LocaleId);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
ERR("Could not get default locale (%08lx).\n", Status);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status) || !(KBLList = UserLoadDllAndCreateKbl(LocaleId)))
|
if (!NT_SUCCESS(Status) || !gpklFirst)
|
||||||
{
|
{
|
||||||
|
/* If failed load US keyboard layout */
|
||||||
ERR("Trying to load US Keyboard Layout.\n");
|
ERR("Trying to load US Keyboard Layout.\n");
|
||||||
LocaleId = 0x409;
|
LocaleId = 0x409;
|
||||||
|
|
||||||
if (!(KBLList = UserLoadDllAndCreateKbl(LocaleId)))
|
if (!(gpklFirst = UserLoadDllAndCreateKbl(LocaleId)))
|
||||||
{
|
{
|
||||||
ERR("Failed to load any Keyboard Layout\n");
|
ERR("Failed to load any Keyboard Layout\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KBLList->Flags |= KBL_PRELOAD;
|
/* Add layout to the list */
|
||||||
|
gpklFirst->Flags |= KBL_PRELOAD;
|
||||||
|
InitializeListHead(&gpklFirst->List);
|
||||||
|
|
||||||
InitializeListHead(&KBLList->List);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PKBL W32kGetDefaultKeyLayout(VOID)
|
PKL
|
||||||
|
W32kGetDefaultKeyLayout(VOID)
|
||||||
{
|
{
|
||||||
const WCHAR szKeyboardLayoutPath[] = L"\\Keyboard Layout\\Preload";
|
CONST WCHAR wszDefaultUserPath[] = L"\\REGISTRY\\USER\\.DEFAULT";
|
||||||
const WCHAR szDefaultUserPath[] = L"\\REGISTRY\\USER\\.DEFAULT";
|
CONST WCHAR wszKeyboardLayoutPath[] = L"\\Keyboard Layout\\Preload";
|
||||||
|
WCHAR wszKbdLayoutKey[256], *pwsz;
|
||||||
HANDLE KeyHandle;
|
size_t cbRemaining;
|
||||||
|
HKEY hKey;
|
||||||
|
ULONG cbValue;
|
||||||
LCID LayoutLocaleId = 0;
|
LCID LayoutLocaleId = 0;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
OBJECT_ATTRIBUTES KeyAttributes;
|
PKL pKbl;
|
||||||
PKBL pKbl;
|
|
||||||
UNICODE_STRING CurrentUserPath;
|
UNICODE_STRING CurrentUserPath;
|
||||||
UNICODE_STRING FullKeyboardLayoutPath;
|
|
||||||
UNICODE_STRING LayoutValueName;
|
|
||||||
UNICODE_STRING LayoutLocaleIdString;
|
|
||||||
WCHAR wszBuffer[MAX_PATH];
|
WCHAR wszBuffer[MAX_PATH];
|
||||||
|
|
||||||
// Get the path to HKEY_CURRENT_USER
|
/* Try to get default alayout from HKCU\Keyboard Layout\Preload first */
|
||||||
Status = RtlFormatCurrentUserKeyPath(&CurrentUserPath);
|
Status = RtlFormatCurrentUserKeyPath(&CurrentUserPath);
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
FullKeyboardLayoutPath.Buffer = wszBuffer;
|
/* FIXME: We're called very early, so HKEY_CURRENT_USER might not be
|
||||||
FullKeyboardLayoutPath.MaximumLength = sizeof(wszBuffer);
|
available yet. Check this first. */
|
||||||
|
RtlStringCbCopyNExW(wszKbdLayoutKey, sizeof(wszKbdLayoutKey),
|
||||||
|
CurrentUserPath.Buffer, CurrentUserPath.Length,
|
||||||
|
&pwsz, &cbRemaining, 0);
|
||||||
|
RtlStringCbCopyW(pwsz, cbRemaining, wszKeyboardLayoutPath);
|
||||||
|
Status = RegOpenKey(wszKbdLayoutKey, &hKey);
|
||||||
|
|
||||||
// FIXME: Is this 100% correct?
|
/* Free CurrentUserPath - we dont need it anymore */
|
||||||
// We're called very early, so HKEY_CURRENT_USER might not be available yet. Check this first.
|
|
||||||
InitializeObjectAttributes(&KeyAttributes, &CurrentUserPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
|
||||||
Status = ZwOpenKey(&KeyHandle, KEY_READ, &KeyAttributes);
|
|
||||||
|
|
||||||
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
|
|
||||||
{
|
|
||||||
// It is not available, so read it from HKEY_USERS\.DEFAULT
|
|
||||||
FullKeyboardLayoutPath.Length = sizeof(szDefaultUserPath) - sizeof(UNICODE_NULL);
|
|
||||||
RtlCopyMemory(wszBuffer, szDefaultUserPath, sizeof(szDefaultUserPath));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// The path is available
|
|
||||||
ZwClose(KeyHandle);
|
|
||||||
RtlCopyUnicodeString(&FullKeyboardLayoutPath, &CurrentUserPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free CurrentUserPath - we dont need it anymore
|
|
||||||
RtlFreeUnicodeString(&CurrentUserPath);
|
RtlFreeUnicodeString(&CurrentUserPath);
|
||||||
|
}
|
||||||
|
|
||||||
Status = RtlAppendUnicodeToString(&FullKeyboardLayoutPath, szKeyboardLayoutPath);
|
/* 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))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
// Return the first keyboard layout listed there
|
/* Return the first keyboard layout listed there */
|
||||||
RtlInitUnicodeString(&LayoutValueName, L"1");
|
cbValue = sizeof(wszBuffer);
|
||||||
|
Status = RegQueryValue(hKey, L"1", REG_SZ, wszBuffer, &cbValue);
|
||||||
Status = ReadRegistryValue(&FullKeyboardLayoutPath, &LayoutValueName, &LayoutLocaleIdString);
|
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
LayoutLocaleId = (LCID)wcstol(wszBuffer, NULL, 16);
|
||||||
RtlUnicodeStringToInteger(&LayoutLocaleIdString, 16, &LayoutLocaleId);
|
|
||||||
ExFreePoolWithTag(LayoutLocaleIdString.Buffer, TAG_STRING);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
ERR("ReadRegistryValue failed! (%08lx).\n", Status);
|
ERR("RegQueryValue failed (%08lx)\n", Status);
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR("RtlAppendUnicodeToString failed! (%08lx)\n", Status);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR("RtlFormatCurrentUserKeyPath 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)
|
if (!LayoutLocaleId)
|
||||||
{
|
{
|
||||||
ERR("Assuming default locale for the keyboard layout (0x409 - US)\n");
|
ERR("Assuming default locale for the keyboard layout (0x409 - US)\n");
|
||||||
LayoutLocaleId = 0x409;
|
LayoutLocaleId = 0x409;
|
||||||
}
|
}
|
||||||
|
|
||||||
pKbl = KBLList;
|
/* Check if layout is already loaded */
|
||||||
|
pKbl = gpklFirst;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (pKbl->klid == LayoutLocaleId)
|
if (pKbl->klid == LayoutLocaleId)
|
||||||
{
|
|
||||||
return pKbl;
|
return pKbl;
|
||||||
}
|
|
||||||
|
|
||||||
pKbl = (PKBL) pKbl->List.Flink;
|
pKbl = CONTAINING_RECORD(pKbl->List.Flink, KL, List);
|
||||||
} while (pKbl != KBLList);
|
} while (pKbl != gpklFirst);
|
||||||
|
|
||||||
|
/* Load the keyboard layout */
|
||||||
TRACE("Loading new default keyboard layout.\n");
|
TRACE("Loading new default keyboard layout.\n");
|
||||||
pKbl = UserLoadDllAndCreateKbl(LayoutLocaleId);
|
pKbl = UserLoadDllAndCreateKbl(LayoutLocaleId);
|
||||||
|
|
||||||
if (!pKbl)
|
if (!pKbl)
|
||||||
{
|
{
|
||||||
TRACE("Failed to load %x!!! Returning any availableKL.\n", LayoutLocaleId);
|
ERR("Failed to load %x!!! Returning any available KL.\n", LayoutLocaleId);
|
||||||
return KBLList;
|
return gpklFirst;
|
||||||
}
|
}
|
||||||
|
|
||||||
InsertTailList(&KBLList->List, &pKbl->List);
|
/* Add loaded layout to the list */
|
||||||
|
InsertTailList(&gpklFirst->List, &pKbl->List);
|
||||||
return pKbl;
|
return pKbl;
|
||||||
}
|
}
|
||||||
|
|
||||||
PKBL UserHklToKbl(HKL hKl)
|
PKL
|
||||||
|
UserHklToKbl(HKL hKl)
|
||||||
{
|
{
|
||||||
PKBL pKbl = KBLList;
|
PKL pKbl = gpklFirst;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (pKbl->hkl == hKl) return pKbl;
|
if (pKbl->hkl == hKl)
|
||||||
pKbl = (PKBL) pKbl->List.Flink;
|
return pKbl;
|
||||||
} while (pKbl != KBLList);
|
|
||||||
|
pKbl = CONTAINING_RECORD(pKbl->List.Flink, KL, List);
|
||||||
|
} while (pKbl != gpklFirst);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL UserUnloadKbl(PKBL pKbl)
|
BOOL
|
||||||
|
UserUnloadKbl(PKL pKbl)
|
||||||
{
|
{
|
||||||
/* According to msdn, UnloadKeyboardLayout can fail
|
/* According to msdn, UnloadKeyboardLayout can fail
|
||||||
if the keyboard layout identifier was preloaded. */
|
if the keyboard layout identifier was preloaded. */
|
||||||
|
@ -444,13 +346,14 @@ BOOL UserUnloadKbl(PKBL pKbl)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PKBL co_UserActivateKbl(PTHREADINFO w32Thread, PKBL pKbl, UINT Flags)
|
static PKL
|
||||||
|
co_UserActivateKbl(PTHREADINFO pti, PKL pKbl, UINT Flags)
|
||||||
{
|
{
|
||||||
PKBL Prev;
|
PKL pklPrev;
|
||||||
|
|
||||||
Prev = w32Thread->KeyboardLayout;
|
pklPrev = pti->KeyboardLayout;
|
||||||
Prev->RefCount--;
|
pklPrev->RefCount--;
|
||||||
w32Thread->KeyboardLayout = pKbl;
|
pti->KeyboardLayout = pKbl;
|
||||||
pKbl->RefCount++;
|
pKbl->RefCount++;
|
||||||
|
|
||||||
if (Flags & KLF_SETFORPROCESS)
|
if (Flags & KLF_SETFORPROCESS)
|
||||||
|
@ -459,18 +362,18 @@ static PKBL co_UserActivateKbl(PTHREADINFO w32Thread, PKBL pKbl, UINT Flags)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Prev->Flags & KBL_UNLOAD && Prev->RefCount == 0)
|
if (pklPrev->Flags & KBL_UNLOAD && pklPrev->RefCount == 0)
|
||||||
{
|
{
|
||||||
UserUnloadKbl(Prev);
|
UserUnloadKbl(pklPrev);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send WM_INPUTLANGCHANGE to thread's focus window
|
// Send WM_INPUTLANGCHANGE to thread's focus window
|
||||||
co_IntSendMessage(w32Thread->MessageQueue->FocusWindow,
|
co_IntSendMessage(pti->MessageQueue->FocusWindow,
|
||||||
WM_INPUTLANGCHANGE,
|
WM_INPUTLANGCHANGE,
|
||||||
0, // FIXME: put charset here (what is this?)
|
0, // FIXME: put charset here (what is this?)
|
||||||
(LPARAM)pKbl->hkl); //klid
|
(LPARAM)pKbl->hkl); //klid
|
||||||
|
|
||||||
return Prev;
|
return pklPrev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EXPORTS *******************************************************************/
|
/* EXPORTS *******************************************************************/
|
||||||
|
@ -481,13 +384,13 @@ UserGetKeyboardLayout(
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PETHREAD Thread;
|
PETHREAD Thread;
|
||||||
PTHREADINFO W32Thread;
|
PTHREADINFO pti;
|
||||||
HKL Ret;
|
HKL Ret;
|
||||||
|
|
||||||
if (!dwThreadId)
|
if (!dwThreadId)
|
||||||
{
|
{
|
||||||
W32Thread = PsGetCurrentThreadWin32Thread();
|
pti = PsGetCurrentThreadWin32Thread();
|
||||||
return W32Thread->KeyboardLayout->hkl;
|
return pti->KeyboardLayout->hkl;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)dwThreadId, &Thread);
|
Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)dwThreadId, &Thread);
|
||||||
|
@ -497,8 +400,8 @@ UserGetKeyboardLayout(
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
W32Thread = PsGetThreadWin32Thread(Thread);
|
pti = PsGetThreadWin32Thread(Thread);
|
||||||
Ret = W32Thread->KeyboardLayout->hkl;
|
Ret = pti->KeyboardLayout->hkl;
|
||||||
ObDereferenceObject(Thread);
|
ObDereferenceObject(Thread);
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
@ -506,37 +409,41 @@ UserGetKeyboardLayout(
|
||||||
UINT
|
UINT
|
||||||
APIENTRY
|
APIENTRY
|
||||||
NtUserGetKeyboardLayoutList(
|
NtUserGetKeyboardLayoutList(
|
||||||
INT nItems,
|
INT nBuff,
|
||||||
HKL* pHklBuff)
|
HKL* pHklBuff)
|
||||||
{
|
{
|
||||||
UINT Ret = 0;
|
UINT uRet = 0;
|
||||||
PKBL pKbl;
|
PKL pKbl;
|
||||||
|
|
||||||
UserEnterShared();
|
UserEnterShared();
|
||||||
pKbl = KBLList;
|
pKbl = gpklFirst;
|
||||||
|
|
||||||
if (nItems == 0)
|
if (!pHklBuff)
|
||||||
|
nBuff = 0;
|
||||||
|
|
||||||
|
if (nBuff == 0)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
Ret++;
|
uRet++;
|
||||||
pKbl = (PKBL) pKbl->List.Flink;
|
pKbl = CONTAINING_RECORD(pKbl->List.Flink, KL, List);
|
||||||
} while (pKbl != KBLList);
|
} while (pKbl != gpklFirst);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_SEH2_TRY
|
_SEH2_TRY
|
||||||
{
|
{
|
||||||
ProbeForWrite(pHklBuff, nItems*sizeof(HKL), 4);
|
ProbeForWrite(pHklBuff, nBuff*sizeof(HKL), 4);
|
||||||
|
|
||||||
while (Ret < nItems)
|
while (uRet < nBuff)
|
||||||
{
|
{
|
||||||
if (!(pKbl->Flags & KBL_UNLOAD))
|
if (!(pKbl->Flags & KBL_UNLOAD))
|
||||||
{
|
{
|
||||||
pHklBuff[Ret] = pKbl->hkl;
|
pHklBuff[uRet] = pKbl->hkl;
|
||||||
Ret++;
|
uRet++;
|
||||||
pKbl = (PKBL) pKbl->List.Flink;
|
pKbl = CONTAINING_RECORD(pKbl->List.Flink, KL, List);
|
||||||
if (pKbl == KBLList) break;
|
if (pKbl == gpklFirst)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,13 +451,13 @@ NtUserGetKeyboardLayoutList(
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
SetLastNtError(_SEH2_GetExceptionCode());
|
SetLastNtError(_SEH2_GetExceptionCode());
|
||||||
Ret = 0;
|
uRet = 0;
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
UserLeave();
|
UserLeave();
|
||||||
return Ret;
|
return uRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
|
@ -558,8 +465,8 @@ APIENTRY
|
||||||
NtUserGetKeyboardLayoutName(
|
NtUserGetKeyboardLayoutName(
|
||||||
LPWSTR lpszName)
|
LPWSTR lpszName)
|
||||||
{
|
{
|
||||||
BOOL ret = FALSE;
|
BOOL bRet = FALSE;
|
||||||
PKBL pKbl;
|
PKL pKbl;
|
||||||
PTHREADINFO pti;
|
PTHREADINFO pti;
|
||||||
|
|
||||||
UserEnterShared();
|
UserEnterShared();
|
||||||
|
@ -570,20 +477,18 @@ NtUserGetKeyboardLayoutName(
|
||||||
pti = PsGetCurrentThreadWin32Thread();
|
pti = PsGetCurrentThreadWin32Thread();
|
||||||
pKbl = pti->KeyboardLayout;
|
pKbl = pti->KeyboardLayout;
|
||||||
RtlCopyMemory(lpszName, pKbl->Name, KL_NAMELENGTH*sizeof(WCHAR));
|
RtlCopyMemory(lpszName, pKbl->Name, KL_NAMELENGTH*sizeof(WCHAR));
|
||||||
ret = TRUE;
|
bRet = TRUE;
|
||||||
}
|
}
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
SetLastNtError(_SEH2_GetExceptionCode());
|
SetLastNtError(_SEH2_GetExceptionCode());
|
||||||
ret = FALSE;
|
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
UserLeave();
|
UserLeave();
|
||||||
return ret;
|
return bRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HKL
|
HKL
|
||||||
APIENTRY
|
APIENTRY
|
||||||
NtUserLoadKeyboardLayoutEx(
|
NtUserLoadKeyboardLayoutEx(
|
||||||
|
@ -595,24 +500,32 @@ NtUserLoadKeyboardLayoutEx(
|
||||||
IN DWORD dwKLID,
|
IN DWORD dwKLID,
|
||||||
IN UINT Flags)
|
IN UINT Flags)
|
||||||
{
|
{
|
||||||
HKL Ret = NULL;
|
HKL hklRet = NULL;
|
||||||
PKBL pKbl = NULL, Cur;
|
PKL pKbl = NULL, pklCur;
|
||||||
|
|
||||||
|
if (Flags & ~(KLF_ACTIVATE|KLF_NOTELLSHELL|KLF_REORDER|KLF_REPLACELANG|
|
||||||
|
KLF_SUBSTITUTE_OK|KLF_SETFORPROCESS|KLF_UNLOADPREVIOUS))
|
||||||
|
{
|
||||||
|
ERR("Invalid flags: %x\n", Flags);
|
||||||
|
EngSetLastError(ERROR_INVALID_FLAGS);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
UserEnterExclusive();
|
UserEnterExclusive();
|
||||||
|
|
||||||
//Let's see if layout was already loaded.
|
//Let's see if layout was already loaded.
|
||||||
Cur = KBLList;
|
pklCur = gpklFirst;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (Cur->klid == dwKLID)
|
if (pklCur->klid == dwKLID)
|
||||||
{
|
{
|
||||||
pKbl = Cur;
|
pKbl = pklCur;
|
||||||
pKbl->Flags &= ~KBL_UNLOAD;
|
pKbl->Flags &= ~KBL_UNLOAD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cur = (PKBL) Cur->List.Flink;
|
pklCur = CONTAINING_RECORD(pKbl->List.Flink, KL, List);
|
||||||
} while (Cur != KBLList);
|
} while (pklCur != gpklFirst);
|
||||||
|
|
||||||
//It wasn't, so load it.
|
//It wasn't, so load it.
|
||||||
if (!pKbl)
|
if (!pKbl)
|
||||||
|
@ -621,28 +534,28 @@ NtUserLoadKeyboardLayoutEx(
|
||||||
|
|
||||||
if (!pKbl)
|
if (!pKbl)
|
||||||
{
|
{
|
||||||
goto the_end;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
InsertTailList(&KBLList->List, &pKbl->List);
|
InsertTailList(&gpklFirst->List, &pKbl->List);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Flags & KLF_REORDER) KBLList = pKbl;
|
if (Flags & KLF_REORDER) gpklFirst = pKbl;
|
||||||
|
|
||||||
if (Flags & KLF_ACTIVATE)
|
if (Flags & KLF_ACTIVATE)
|
||||||
{
|
{
|
||||||
co_UserActivateKbl(PsGetCurrentThreadWin32Thread(), pKbl, Flags);
|
co_UserActivateKbl(PsGetCurrentThreadWin32Thread(), pKbl, Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ret = pKbl->hkl;
|
hklRet = pKbl->hkl;
|
||||||
|
|
||||||
//FIXME: KLF_NOTELLSHELL
|
//FIXME: KLF_NOTELLSHELL
|
||||||
// KLF_REPLACELANG
|
// KLF_REPLACELANG
|
||||||
// KLF_SUBSTITUTE_OK
|
// KLF_SUBSTITUTE_OK
|
||||||
|
|
||||||
the_end:
|
cleanup:
|
||||||
UserLeave();
|
UserLeave();
|
||||||
return Ret;
|
return hklRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
HKL
|
HKL
|
||||||
|
@ -651,27 +564,27 @@ NtUserActivateKeyboardLayout(
|
||||||
HKL hKl,
|
HKL hKl,
|
||||||
ULONG Flags)
|
ULONG Flags)
|
||||||
{
|
{
|
||||||
PKBL pKbl;
|
PKL pKbl;
|
||||||
HKL Ret = NULL;
|
HKL hklRet = NULL;
|
||||||
PTHREADINFO pWThread;
|
PTHREADINFO pti;
|
||||||
|
|
||||||
UserEnterExclusive();
|
UserEnterExclusive();
|
||||||
|
|
||||||
pWThread = PsGetCurrentThreadWin32Thread();
|
pti = PsGetCurrentThreadWin32Thread();
|
||||||
|
|
||||||
if (pWThread->KeyboardLayout->hkl == hKl)
|
if (pti->KeyboardLayout->hkl == hKl)
|
||||||
{
|
{
|
||||||
Ret = hKl;
|
hklRet = hKl;
|
||||||
goto the_end;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hKl == (HKL)HKL_NEXT)
|
if (hKl == (HKL)HKL_NEXT)
|
||||||
{
|
{
|
||||||
pKbl = (PKBL)pWThread->KeyboardLayout->List.Flink;
|
pKbl = CONTAINING_RECORD(pti->KeyboardLayout->List.Flink, KL, List);
|
||||||
}
|
}
|
||||||
else if (hKl == (HKL)HKL_PREV)
|
else if (hKl == (HKL)HKL_PREV)
|
||||||
{
|
{
|
||||||
pKbl = (PKBL)pWThread->KeyboardLayout->List.Blink;
|
pKbl = CONTAINING_RECORD(pti->KeyboardLayout->List.Blink, KL, List);
|
||||||
}
|
}
|
||||||
else pKbl = UserHklToKbl(hKl);
|
else pKbl = UserHklToKbl(hKl);
|
||||||
|
|
||||||
|
@ -680,16 +593,16 @@ NtUserActivateKeyboardLayout(
|
||||||
if (pKbl)
|
if (pKbl)
|
||||||
{
|
{
|
||||||
if (Flags & KLF_REORDER)
|
if (Flags & KLF_REORDER)
|
||||||
KBLList = pKbl;
|
gpklFirst = pKbl;
|
||||||
|
|
||||||
if (pKbl == pWThread->KeyboardLayout)
|
if (pKbl == pti->KeyboardLayout)
|
||||||
{
|
{
|
||||||
Ret = pKbl->hkl;
|
hklRet = pKbl->hkl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pKbl = co_UserActivateKbl(pWThread, pKbl, Flags);
|
pKbl = co_UserActivateKbl(pti, pKbl, Flags);
|
||||||
Ret = pKbl->hkl;
|
hklRet = pKbl->hkl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -697,9 +610,9 @@ NtUserActivateKeyboardLayout(
|
||||||
ERR("Invalid HKL %x!\n", hKl);
|
ERR("Invalid HKL %x!\n", hKl);
|
||||||
}
|
}
|
||||||
|
|
||||||
the_end:
|
cleanup:
|
||||||
UserLeave();
|
UserLeave();
|
||||||
return Ret;
|
return hklRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
|
@ -707,14 +620,15 @@ APIENTRY
|
||||||
NtUserUnloadKeyboardLayout(
|
NtUserUnloadKeyboardLayout(
|
||||||
HKL hKl)
|
HKL hKl)
|
||||||
{
|
{
|
||||||
PKBL pKbl;
|
PKL pKbl;
|
||||||
BOOL Ret = FALSE;
|
BOOL bRet = FALSE;
|
||||||
|
|
||||||
UserEnterExclusive();
|
UserEnterExclusive();
|
||||||
|
|
||||||
if ((pKbl = UserHklToKbl(hKl)))
|
pKbl = UserHklToKbl(hKl);
|
||||||
|
if (pKbl)
|
||||||
{
|
{
|
||||||
Ret = UserUnloadKbl(pKbl);
|
bRet = UserUnloadKbl(pKbl);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -722,7 +636,7 @@ NtUserUnloadKeyboardLayout(
|
||||||
}
|
}
|
||||||
|
|
||||||
UserLeave();
|
UserLeave();
|
||||||
return Ret;
|
return bRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -891,7 +891,7 @@ BOOL NTAPI
|
||||||
UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected)
|
UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected)
|
||||||
{
|
{
|
||||||
WORD wScanCode, wVk;
|
WORD wScanCode, wVk;
|
||||||
PKBL pKbl = NULL;
|
PKL pKbl = NULL;
|
||||||
PKBDTABLES pKbdTbl;
|
PKBDTABLES pKbdTbl;
|
||||||
PUSER_MESSAGE_QUEUE pFocusQueue;
|
PUSER_MESSAGE_QUEUE pFocusQueue;
|
||||||
struct _ETHREAD *pFocusThread;
|
struct _ETHREAD *pFocusThread;
|
||||||
|
@ -973,7 +973,7 @@ UserProcessKeyboardInput(
|
||||||
PKEYBOARD_INPUT_DATA pKbdInputData)
|
PKEYBOARD_INPUT_DATA pKbdInputData)
|
||||||
{
|
{
|
||||||
WORD wScanCode, wVk;
|
WORD wScanCode, wVk;
|
||||||
PKBL pKbl = NULL;
|
PKL pKbl = NULL;
|
||||||
PKBDTABLES pKbdTbl;
|
PKBDTABLES pKbdTbl;
|
||||||
PUSER_MESSAGE_QUEUE pFocusQueue;
|
PUSER_MESSAGE_QUEUE pFocusQueue;
|
||||||
struct _ETHREAD *pFocusThread;
|
struct _ETHREAD *pFocusThread;
|
||||||
|
@ -1211,7 +1211,7 @@ NtUserMapVirtualKeyEx(UINT uCode, UINT uType, DWORD keyboardId, HKL dwhkl)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PKBL pKbl;
|
PKL pKbl;
|
||||||
|
|
||||||
pKbl = UserHklToKbl(dwhkl);
|
pKbl = UserHklToKbl(dwhkl);
|
||||||
if (pKbl)
|
if (pKbl)
|
||||||
|
@ -1246,7 +1246,7 @@ NtUserToUnicodeEx(
|
||||||
BYTE afKeyState[256 * 2 / 8] = {0};
|
BYTE afKeyState[256 * 2 / 8] = {0};
|
||||||
PWCHAR pwszBuff = NULL;
|
PWCHAR pwszBuff = NULL;
|
||||||
INT i, iRet = 0;
|
INT i, iRet = 0;
|
||||||
PKBL pKbl = NULL;
|
PKL pKbl = NULL;
|
||||||
|
|
||||||
TRACE("Enter NtUserSetKeyboardState\n");
|
TRACE("Enter NtUserSetKeyboardState\n");
|
||||||
|
|
||||||
|
@ -1451,7 +1451,7 @@ NtUserVkKeyScanEx(
|
||||||
PKBDTABLES pKbdTbl;
|
PKBDTABLES pKbdTbl;
|
||||||
PVK_TO_WCHAR_TABLE pVkToWchTbl;
|
PVK_TO_WCHAR_TABLE pVkToWchTbl;
|
||||||
PVK_TO_WCHARS10 pVkToWch;
|
PVK_TO_WCHARS10 pVkToWch;
|
||||||
PKBL pKbl = NULL;
|
PKL pKbl = NULL;
|
||||||
DWORD i, dwModBits = 0, dwModNumber = 0, Ret = (DWORD)-1;
|
DWORD i, dwModBits = 0, dwModNumber = 0, Ret = (DWORD)-1;
|
||||||
|
|
||||||
TRACE("NtUserVkKeyScanEx() wch %d, KbdLayout 0x%p\n", wch, dwhkl);
|
TRACE("NtUserVkKeyScanEx() wch %d, KbdLayout 0x%p\n", wch, dwhkl);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue