mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 17:05:46 +00:00
Add multiple keyboard layout support. Implemented NtUserLoadKeyboardLayoutEx, NtUserActivateKeyboardLayout, NtUserGetKeyboardLayoutList, NtUserGetKeyboardLayoutName.
svn path=/trunk/; revision=25758
This commit is contained in:
parent
cd679a1f7e
commit
c1145464aa
11 changed files with 508 additions and 666 deletions
|
@ -1,7 +1,7 @@
|
|||
LIBRARY user32.dll
|
||||
|
||||
EXPORTS
|
||||
ActivateKeyboardLayout@8
|
||||
ActivateKeyboardLayout@8=NtUserActivateKeyboardLayout@8
|
||||
AdjustWindowRect@12
|
||||
AdjustWindowRectEx@16
|
||||
AlignRects@16
|
||||
|
@ -295,7 +295,7 @@ GetKeyNameTextA@12
|
|||
GetKeyNameTextW@12
|
||||
GetKeyState@4
|
||||
GetKeyboardLayout@4
|
||||
GetKeyboardLayoutList@8
|
||||
GetKeyboardLayoutList@8=NtUserGetKeyboardLayoutList@8
|
||||
GetKeyboardLayoutNameA@4
|
||||
GetKeyboardLayoutNameW@4
|
||||
GetKeyboardState@4
|
||||
|
|
|
@ -46,218 +46,6 @@ static UINT_PTR timer;
|
|||
static const INT iTimerInterval = 50; /* msec for timer interval */
|
||||
|
||||
|
||||
/* LOCALE FUNCTIONS **********************************************************/
|
||||
|
||||
/*
|
||||
* 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 FASTCALL
|
||||
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_ALL_ACCESS, &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 = LocalAlloc(LMEM_ZEROINIT, ResLength);
|
||||
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);
|
||||
LocalFree(KeyValuePartialInfo);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* At this point, KeyValuePartialInfo->Data contains the key data */
|
||||
ReturnBuffer = LocalAlloc(0, KeyValuePartialInfo->DataLength);
|
||||
if(!ReturnBuffer)
|
||||
{
|
||||
NtClose(KeyHandle);
|
||||
LocalFree(KeyValuePartialInfo);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
RtlCopyMemory(ReturnBuffer, KeyValuePartialInfo->Data, KeyValuePartialInfo->DataLength);
|
||||
RtlInitUnicodeString(ReturnedValue, ReturnBuffer);
|
||||
|
||||
LocalFree(KeyValuePartialInfo);
|
||||
NtClose(KeyHandle);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
HKL FASTCALL
|
||||
IntLoadKeyboardLayout( LPCWSTR pwszKLID,
|
||||
UINT Flags)
|
||||
{
|
||||
HANDLE Handle;
|
||||
HINSTANCE KBModule = 0;
|
||||
FARPROC pAddr = 0;
|
||||
DWORD offTable = 0;
|
||||
HKL hKL;
|
||||
NTSTATUS Status;
|
||||
WCHAR LocaleBuffer[16];
|
||||
UNICODE_STRING LayoutKeyName;
|
||||
UNICODE_STRING LayoutValueName;
|
||||
UNICODE_STRING DefaultLocale;
|
||||
UNICODE_STRING LayoutFile;
|
||||
UNICODE_STRING FullLayoutPath;
|
||||
LCID LocaleId;
|
||||
ULONG_PTR layout;
|
||||
LANGID langid;
|
||||
WCHAR FullPathBuffer[MAX_PATH];
|
||||
WCHAR LayoutKeyNameBuffer[128] = L"\\REGISTRY\\Machine\\SYSTEM\\CurrentControlSet"
|
||||
L"\\Control\\KeyboardLayouts\\";
|
||||
|
||||
layout = (ULONG_PTR) wcstoul(pwszKLID, NULL, 16);
|
||||
|
||||
// LocaleId = GetSystemDefaultLCID();
|
||||
|
||||
LocaleId = (LCID) layout;
|
||||
|
||||
/* Create the HKL to be used by NtUserLoadKeyboardLayoutEx*/
|
||||
/*
|
||||
* 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(layout));
|
||||
if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
|
||||
layout |= 0xe001 << 16; /* FIXME */
|
||||
else
|
||||
layout |= layout << 16;
|
||||
|
||||
DPRINT("Input = %S, DefaultLocale = %lx\n", pwszKLID, LocaleId );
|
||||
swprintf(LocaleBuffer, L"%08lx", LocaleId);
|
||||
DPRINT("DefaultLocale = %S\n", LocaleBuffer);
|
||||
RtlInitUnicodeString(&DefaultLocale, LocaleBuffer);
|
||||
|
||||
RtlInitUnicodeString(&LayoutKeyName, LayoutKeyNameBuffer);
|
||||
LayoutKeyName.MaximumLength = sizeof(LayoutKeyNameBuffer);
|
||||
RtlAppendUnicodeStringToString(&LayoutKeyName, &DefaultLocale);
|
||||
DPRINT("LayoutKeyName=%wZ\n", &LayoutKeyName);
|
||||
RtlInitUnicodeString(&LayoutValueName, L"Layout File");
|
||||
Status = ReadRegistryValue(&LayoutKeyName,&LayoutValueName,&LayoutFile);
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to read registry value, %x\n", Status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DPRINT("Read registry and got %wZ\n", &LayoutFile);
|
||||
|
||||
Status = GetSystemDirectory(FullPathBuffer, sizeof(FullPathBuffer));
|
||||
if(Status == 0 || Status > sizeof(FullPathBuffer))
|
||||
{
|
||||
DPRINT1("GetSystemDirectory() failed! (%d)\n", GetLastError());
|
||||
RtlFreeUnicodeString(&LayoutFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString(&FullLayoutPath, FullPathBuffer);
|
||||
FullLayoutPath.MaximumLength = sizeof(FullPathBuffer);
|
||||
if(FullLayoutPath.Length < FullLayoutPath.MaximumLength-1)
|
||||
{
|
||||
FullLayoutPath.Buffer[FullLayoutPath.Length/sizeof(WCHAR)] = '\\';
|
||||
FullLayoutPath.Buffer[FullLayoutPath.Length/sizeof(WCHAR)+1] = 0;
|
||||
FullLayoutPath.Length+=sizeof(WCHAR);
|
||||
}
|
||||
Status = RtlAppendUnicodeStringToString(&FullLayoutPath, &LayoutFile);
|
||||
DPRINT("Loading Keyboard DLL %wZ\n", &FullLayoutPath);
|
||||
RtlFreeUnicodeString(&LayoutFile);
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("RtlAppendUnicodeStringToString() failed! (%x)\n", Status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
KBModule = LoadLibraryEx(FullPathBuffer, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||
|
||||
if(!KBModule )
|
||||
{
|
||||
DPRINT1( "Failed to load %wZ, lasterror = %d\n", &FullLayoutPath, GetLastError() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pAddr = GetProcAddress( KBModule, (LPCSTR) 1);
|
||||
offTable = (DWORD) pAddr - (DWORD) KBModule; // Weeks to figure this out!
|
||||
|
||||
DPRINT( "Load Keyboard Module Offset: %x\n", offTable );
|
||||
|
||||
FreeLibrary(KBModule);
|
||||
|
||||
Handle = CreateFileW( FullPathBuffer,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
hKL = NtUserLoadKeyboardLayoutEx( Handle,
|
||||
offTable,
|
||||
(HKL) layout,
|
||||
&DefaultLocale,
|
||||
(UINT) layout,
|
||||
Flags);
|
||||
|
||||
NtClose(Handle);
|
||||
|
||||
return hKL;
|
||||
}
|
||||
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
|
||||
|
@ -313,18 +101,6 @@ DragDetect(
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
HKL STDCALL
|
||||
ActivateKeyboardLayout(HKL hkl,
|
||||
UINT Flags)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return (HKL)0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
@ -460,18 +236,6 @@ GetKeyState(int nVirtKey)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
UINT STDCALL
|
||||
GetKeyboardLayoutList(int nBuff,
|
||||
HKL FAR *lpList)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
@ -534,15 +298,9 @@ HKL STDCALL
|
|||
LoadKeyboardLayoutA(LPCSTR pwszKLID,
|
||||
UINT Flags)
|
||||
{
|
||||
HKL ret;
|
||||
UNICODE_STRING pwszKLIDW;
|
||||
|
||||
if (pwszKLID) RtlCreateUnicodeStringFromAsciiz(&pwszKLIDW, pwszKLID);
|
||||
else pwszKLIDW.Buffer = NULL;
|
||||
|
||||
ret = LoadKeyboardLayoutW(pwszKLIDW.Buffer, Flags);
|
||||
RtlFreeUnicodeString(&pwszKLIDW);
|
||||
return ret;
|
||||
return NtUserLoadKeyboardLayoutEx(
|
||||
strtoul(pwszKLID, NULL, 16),
|
||||
Flags);
|
||||
}
|
||||
|
||||
|
||||
|
@ -553,7 +311,11 @@ HKL STDCALL
|
|||
LoadKeyboardLayoutW(LPCWSTR pwszKLID,
|
||||
UINT Flags)
|
||||
{
|
||||
return IntLoadKeyboardLayout( pwszKLID, Flags);
|
||||
// Look at revision 25596 to see how it's done in windows.
|
||||
// We will do things our own way.
|
||||
return NtUserLoadKeyboardLayoutEx(
|
||||
wcstoul(pwszKLID, NULL, 16),
|
||||
Flags);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -299,11 +299,11 @@ NTAPI
|
|||
NtUserAcquireOrReleaseInputOwnership(
|
||||
BOOLEAN Release);
|
||||
|
||||
DWORD
|
||||
HKL
|
||||
NTAPI
|
||||
NtUserActivateKeyboardLayout(
|
||||
DWORD Unknown0,
|
||||
DWORD Unknown1);
|
||||
HKL hKl,
|
||||
ULONG Flags);
|
||||
|
||||
DWORD
|
||||
NTAPI
|
||||
|
@ -1008,11 +1008,11 @@ NTAPI
|
|||
NtUserGetKeyboardLayout(
|
||||
DWORD dwThreadid);
|
||||
|
||||
DWORD
|
||||
UINT
|
||||
NTAPI
|
||||
NtUserGetKeyboardLayoutList(
|
||||
DWORD Unknown0,
|
||||
DWORD Unknown1);
|
||||
INT nItems,
|
||||
HKL *pHklBuff);
|
||||
|
||||
BOOL
|
||||
NTAPI
|
||||
|
@ -1219,11 +1219,7 @@ NtUserKillTimer
|
|||
HKL
|
||||
NTAPI
|
||||
NtUserLoadKeyboardLayoutEx(
|
||||
HANDLE Handle,
|
||||
DWORD offTable,
|
||||
HKL hKL,
|
||||
PUNICODE_STRING puszKLID,
|
||||
UINT KLayoutLangID,
|
||||
LCID LocaleId,
|
||||
UINT Flags);
|
||||
|
||||
BOOL
|
||||
|
|
|
@ -3,19 +3,16 @@
|
|||
|
||||
#include <internal/kbd.h>
|
||||
|
||||
typedef struct _KBDRVFILE
|
||||
{
|
||||
PSINGLE_LIST_ENTRY pkbdfChain;
|
||||
WCHAR wcKBDF[9]; // used w GetKeyboardLayoutName same as wszKLID.
|
||||
struct _KBDTABLES* KBTables; // KBDTABLES in ntoskrnl/include/internal/kbd.h
|
||||
} KBDRVFILE, *PKBDRVFILE;
|
||||
|
||||
typedef struct _KBL
|
||||
{
|
||||
PLIST_ENTRY pklChain;
|
||||
DWORD dwKBLFlags;
|
||||
LIST_ENTRY List;
|
||||
DWORD Flags;
|
||||
WCHAR Name[9]; // used w GetKeyboardLayoutName same as wszKLID.
|
||||
struct _KBDTABLES* KBTables; // KBDTABLES in ntoskrnl/include/internal/kbd.h
|
||||
HANDLE hModule;
|
||||
ULONG RefCount;
|
||||
HKL hkl;
|
||||
PKBDRVFILE pkbdf;
|
||||
LCID lcid;
|
||||
} KBL, *PKBL;
|
||||
|
||||
#define KBL_UNLOADED 0x20000000
|
||||
|
@ -27,12 +24,14 @@ NTSTATUS FASTCALL
|
|||
InitKeyboardImpl(VOID);
|
||||
PUSER_MESSAGE_QUEUE W32kGetPrimitiveMessageQueue(VOID);
|
||||
VOID W32kUnregisterPrimitiveMessageQueue(VOID);
|
||||
PKBDTABLES W32kGetDefaultKeyLayout(VOID);
|
||||
PKBL W32kGetDefaultKeyLayout(VOID);
|
||||
VOID FASTCALL W32kKeyProcessMessage(LPMSG Msg, PKBDTABLES KeyLayout, BYTE Prefix);
|
||||
BOOL FASTCALL IntBlockInput(PW32THREAD W32Thread, BOOL BlockIt);
|
||||
BOOL FASTCALL IntMouseInput(MOUSEINPUT *mi);
|
||||
BOOL FASTCALL IntKeyboardInput(KEYBDINPUT *ki);
|
||||
|
||||
BOOL UserInitDefaultKeyboardLayout();
|
||||
|
||||
#define ThreadHasInputAccess(W32Thread) \
|
||||
(TRUE)
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ typedef struct _W32THREAD
|
|||
struct _USER_MESSAGE_QUEUE* MessageQueue;
|
||||
LIST_ENTRY WindowListHead;
|
||||
LIST_ENTRY W32CallbackListHead;
|
||||
struct _KBDTABLES* KeyboardLayout;
|
||||
struct _KBL* KeyboardLayout;
|
||||
struct _DESKTOP_OBJECT* Desktop;
|
||||
HANDLE hDesktop;
|
||||
DWORD MessagePumpHookValue;
|
||||
|
@ -36,7 +36,7 @@ typedef struct _W32PROCESS
|
|||
LIST_ENTRY PrivateFontListHead;
|
||||
FAST_MUTEX DriverObjListLock;
|
||||
LIST_ENTRY DriverObjListHead;
|
||||
struct _KBDTABLES* KeyboardLayout;
|
||||
struct _KBL* KeyboardLayout;
|
||||
ULONG Flags;
|
||||
LONG GDIObjects;
|
||||
LONG UserObjects;
|
||||
|
|
|
@ -529,8 +529,8 @@ KeyboardThreadMain(PVOID StartContext)
|
|||
KernelMode,
|
||||
TRUE,
|
||||
NULL);
|
||||
DPRINT( "Keyboard Input Thread Starting...\n" );
|
||||
|
||||
DPRINT( "Keyboard Input Thread Starting...\n" );
|
||||
/*
|
||||
* Receive and process keyboard input.
|
||||
*/
|
||||
|
@ -754,7 +754,7 @@ KeyboardThreadMain(PVOID StartContext)
|
|||
* keyboard layout in use.
|
||||
*/
|
||||
W32kKeyProcessMessage(&msg,
|
||||
((PW32THREAD)FocusThread->Tcb.Win32Thread)->KeyboardLayout,
|
||||
((PW32THREAD)FocusThread->Tcb.Win32Thread)->KeyboardLayout->KBTables,
|
||||
KeyInput.Flags & KEY_E0 ? 0xE0 :
|
||||
(KeyInput.Flags & KEY_E1 ? 0xE1 : 0));
|
||||
|
||||
|
@ -816,8 +816,10 @@ InitInputImpl(VOID)
|
|||
}
|
||||
|
||||
/* Initialize the default keyboard layout */
|
||||
(VOID)W32kGetDefaultKeyLayout();
|
||||
|
||||
if(!UserInitDefaultKeyboardLayout())
|
||||
{
|
||||
DPRINT1("Failed to initialize default keyboard layout!\n");
|
||||
}
|
||||
|
||||
Status = PsCreateSystemThread(&MouseThreadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
|
|
465
reactos/subsystems/win32/win32k/ntuser/kbdlayout.c
Normal file
465
reactos/subsystems/win32/win32k/ntuser/kbdlayout.c
Normal file
|
@ -0,0 +1,465 @@
|
|||
|
||||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: subsystems/win32/win32k/ntuser/kbdlayout.c
|
||||
* PURPOSE: Keyboard layout management
|
||||
* COPYRIGHT: Copyright 2007 Saveliy Tretiakov
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <w32k.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
PKBL KBLList = NULL; // Keyboard layout list.
|
||||
PKBL DefaultKL = NULL;
|
||||
|
||||
typedef PVOID (*KbdLayerDescriptor)(VOID);
|
||||
NTSTATUS STDCALL LdrGetProcedureAddress(PVOID module,
|
||||
PANSI_STRING import_name,
|
||||
DWORD flags,
|
||||
PVOID *func_addr);
|
||||
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS ******************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* 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 NTAPI 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_ALL_ACCESS, &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);
|
||||
ExFreePool(KeyValuePartialInfo);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* At this point, KeyValuePartialInfo->Data contains the key data */
|
||||
ReturnBuffer = ExAllocatePoolWithTag(PagedPool,
|
||||
KeyValuePartialInfo->DataLength,
|
||||
TAG_STRING);
|
||||
|
||||
if(!ReturnBuffer)
|
||||
{
|
||||
NtClose(KeyHandle);
|
||||
ExFreePool(KeyValuePartialInfo);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
RtlCopyMemory(ReturnBuffer,
|
||||
KeyValuePartialInfo->Data,
|
||||
KeyValuePartialInfo->DataLength);
|
||||
RtlInitUnicodeString(ReturnedValue, ReturnBuffer);
|
||||
|
||||
ExFreePool(KeyValuePartialInfo);
|
||||
NtClose(KeyHandle);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
static BOOL UserLoadKbdDll(WCHAR *wsKLID,
|
||||
HANDLE *phModule,
|
||||
PKBDTABLES *pKbdTables)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
KbdLayerDescriptor layerDescGetFn;
|
||||
ANSI_STRING kbdProcedureName;
|
||||
UNICODE_STRING LayoutKeyName;
|
||||
UNICODE_STRING LayoutValueName;
|
||||
UNICODE_STRING LayoutFile;
|
||||
UNICODE_STRING FullLayoutPath;
|
||||
UNICODE_STRING klid;
|
||||
WCHAR LayoutPathBuffer[MAX_PATH] = L"\\SystemRoot\\System32\\";
|
||||
WCHAR KeyNameBuffer[MAX_PATH] = L"\\REGISTRY\\Machine\\SYSTEM\\"
|
||||
L"CurrentControlSet\\Control\\KeyboardLayouts\\";
|
||||
|
||||
RtlInitUnicodeString(&klid, wsKLID);
|
||||
RtlInitUnicodeString(&LayoutValueName,L"Layout File");
|
||||
RtlInitUnicodeString(&LayoutKeyName, KeyNameBuffer);
|
||||
LayoutKeyName.MaximumLength = sizeof(KeyNameBuffer);
|
||||
|
||||
RtlAppendUnicodeStringToString(&LayoutKeyName, &klid);
|
||||
Status = ReadRegistryValue(&LayoutKeyName, &LayoutValueName, &LayoutFile);
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Can't get layout filename for %wZ. (%08lx)\n", klid, Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DPRINT("Read registry and got %wZ\n", &LayoutFile);
|
||||
RtlInitUnicodeString(&FullLayoutPath, LayoutPathBuffer);
|
||||
FullLayoutPath.MaximumLength = sizeof(LayoutPathBuffer);
|
||||
RtlAppendUnicodeStringToString(&FullLayoutPath, &LayoutFile);
|
||||
DPRINT("Loading Keyboard DLL %wZ\n", &FullLayoutPath);
|
||||
RtlFreeUnicodeString(&LayoutFile);
|
||||
|
||||
*phModule = EngLoadImage(FullLayoutPath.Buffer);
|
||||
|
||||
if(!*phModule) DPRINT1( "Failed to load %wZ\n", &FullLayoutPath );
|
||||
else DPRINT( "Loaded Keyboard Layout: %wZ\n", &FullLayoutPath );
|
||||
|
||||
RtlInitAnsiString( &kbdProcedureName, "KbdLayerDescriptor" );
|
||||
LdrGetProcedureAddress((PVOID)*phModule,
|
||||
&kbdProcedureName,
|
||||
0,
|
||||
(PVOID*)&layerDescGetFn);
|
||||
|
||||
if(layerDescGetFn)
|
||||
{
|
||||
*pKbdTables = layerDescGetFn();
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("Error: %wZ has no KbdLayerDescriptor()\n", &FullLayoutPath);
|
||||
}
|
||||
|
||||
if(!layerDescGetFn || !*pKbdTables)
|
||||
{
|
||||
DPRINT1("Failed to load the keyboard layout.\n");
|
||||
EngUnloadImage(*phModule);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static PKBL UserLoadDllAndCreateKbl(LCID LocaleId)
|
||||
{
|
||||
PKBL NewKbl;
|
||||
ULONG hKl;
|
||||
LANGID langid;
|
||||
|
||||
NewKbl = ExAllocatePool(PagedPool, sizeof(NewKbl));
|
||||
|
||||
if(!NewKbl)
|
||||
{
|
||||
DPRINT1("%s: Can't allocate memory!\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
swprintf(NewKbl->Name, L"%08lx", LocaleId);
|
||||
|
||||
if(!UserLoadKbdDll(NewKbl->Name, &NewKbl->hModule, &NewKbl->KBTables))
|
||||
{
|
||||
DPRINT1("%s: failed to load %x dll!\n", LocaleId);
|
||||
ExFreePool(NewKbl);
|
||||
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;
|
||||
|
||||
NewKbl->hkl = (HKL) hKl;
|
||||
NewKbl->lcid = LocaleId;
|
||||
NewKbl->Flags = 0;
|
||||
NewKbl->RefCount = 0;
|
||||
|
||||
return NewKbl;
|
||||
}
|
||||
|
||||
BOOL UserInitDefaultKeyboardLayout()
|
||||
{
|
||||
|
||||
LCID LocaleId;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = ZwQueryDefaultLocale(FALSE, &LocaleId);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Could not get default locale (%08lx).\n", Status);
|
||||
}
|
||||
else DPRINT("DefaultLocale = %08lx\n", LocaleId);
|
||||
|
||||
if(!NT_SUCCESS(Status) || !(DefaultKL = UserLoadDllAndCreateKbl(LocaleId)))
|
||||
{
|
||||
DPRINT1("Trying to load US Keyboard Layout.\n");
|
||||
LocaleId = 0x409;
|
||||
|
||||
if(!(DefaultKL = UserLoadDllAndCreateKbl(LocaleId)))
|
||||
{
|
||||
DPRINT1("Failed to load any Keyboard Layout\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
InitializeListHead(&DefaultKL->List);
|
||||
KBLList = DefaultKL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
PKBL W32kGetDefaultKeyLayout(VOID)
|
||||
{
|
||||
return DefaultKL;
|
||||
}
|
||||
|
||||
static PKBL UserHklToKbl(HKL hKl)
|
||||
{
|
||||
PKBL pKbl = KBLList;
|
||||
do
|
||||
{
|
||||
if(pKbl->hkl == hKl) return pKbl;
|
||||
pKbl = (PKBL) pKbl->List.Flink;
|
||||
} while(pKbl != KBLList);
|
||||
}
|
||||
|
||||
static PKBL UserActivateKbl(PW32THREAD Thread, PKBL pKbl)
|
||||
{
|
||||
PKBL Prev;
|
||||
|
||||
Prev = Thread->KeyboardLayout;
|
||||
Prev->RefCount--;
|
||||
Thread->KeyboardLayout = pKbl;
|
||||
pKbl->RefCount++;
|
||||
|
||||
return Prev;
|
||||
}
|
||||
|
||||
HKL FASTCALL
|
||||
UserGetKeyboardLayout(
|
||||
DWORD dwThreadId)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PETHREAD Thread;
|
||||
PW32THREAD W32Thread;
|
||||
HKL Ret;
|
||||
|
||||
if(!dwThreadId)
|
||||
{
|
||||
W32Thread = PsGetCurrentThreadWin32Thread();
|
||||
return W32Thread->KeyboardLayout->hkl;
|
||||
}
|
||||
|
||||
Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
W32Thread = PsGetThreadWin32Thread(Thread);
|
||||
Ret = W32Thread->KeyboardLayout->hkl;
|
||||
ObDereferenceObject(Thread);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
/* EXPORTS *******************************************************************/
|
||||
|
||||
UINT
|
||||
STDCALL
|
||||
NtUserGetKeyboardLayoutList(
|
||||
INT nItems,
|
||||
HKL* pHklBuff)
|
||||
{
|
||||
UINT Ret = 0;
|
||||
PKBL pKbl;
|
||||
|
||||
UserEnterShared();
|
||||
pKbl = KBLList;
|
||||
|
||||
if(nItems == 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
Ret++;
|
||||
pKbl = (PKBL) pKbl->List.Flink;
|
||||
} while(pKbl != KBLList);
|
||||
}
|
||||
else
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
ProbeForWrite(pHklBuff, nItems*sizeof(HKL), 4);
|
||||
|
||||
while(Ret < nItems)
|
||||
{
|
||||
pHklBuff[Ret] = pKbl->hkl;
|
||||
Ret++;
|
||||
pKbl = (PKBL) pKbl->List.Flink;
|
||||
if(pKbl == KBLList) break;
|
||||
}
|
||||
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
SetLastNtError(_SEH_GetExceptionCode());
|
||||
Ret = 0;
|
||||
}
|
||||
_SEH_END;
|
||||
}
|
||||
|
||||
UserLeave();
|
||||
return Ret;
|
||||
}
|
||||
|
||||
BOOL
|
||||
STDCALL
|
||||
NtUserGetKeyboardLayoutName(
|
||||
LPWSTR lpszName)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
PKBL pKbl;
|
||||
|
||||
UserEnterShared();
|
||||
|
||||
_SEH_TRY
|
||||
{
|
||||
ProbeForWrite(lpszName, 9*sizeof(WCHAR), 1);
|
||||
pKbl = PsGetCurrentThreadWin32Thread()->KeyboardLayout;
|
||||
RtlCopyMemory(lpszName, pKbl->Name, 9*sizeof(WCHAR));
|
||||
ret = TRUE;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
SetLastNtError(_SEH_GetExceptionCode());
|
||||
ret = FALSE;
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
UserLeave();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
HKL
|
||||
STDCALL
|
||||
NtUserLoadKeyboardLayoutEx(
|
||||
IN LCID LocaleId,
|
||||
IN UINT Flags)
|
||||
{
|
||||
HKL Ret = NULL;
|
||||
PKBL pKbl;
|
||||
|
||||
UserEnterExclusive();
|
||||
|
||||
pKbl = KBLList;
|
||||
do
|
||||
{
|
||||
if(pKbl->lcid == LocaleId)
|
||||
{
|
||||
Ret = pKbl->hkl;
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
pKbl = (PKBL) pKbl->List.Flink;
|
||||
} while(pKbl != KBLList);
|
||||
|
||||
pKbl = UserLoadDllAndCreateKbl(LocaleId);
|
||||
InsertTailList(&KBLList->List, &pKbl->List);
|
||||
Ret = pKbl->hkl;
|
||||
|
||||
//FIXME: Respect Flags!
|
||||
|
||||
the_end:
|
||||
UserLeave();
|
||||
return Ret;
|
||||
}
|
||||
|
||||
HKL
|
||||
STDCALL
|
||||
NtUserActivateKeyboardLayout(
|
||||
HKL hKl,
|
||||
ULONG Flags)
|
||||
{
|
||||
PKBL pKbl;
|
||||
HKL Ret = NULL;
|
||||
|
||||
UserEnterExclusive();
|
||||
|
||||
pKbl = UserHklToKbl(hKl);
|
||||
|
||||
if(pKbl)
|
||||
{
|
||||
pKbl = UserActivateKbl(PsGetCurrentThreadWin32Thread(), pKbl);
|
||||
Ret = pKbl->hkl;
|
||||
|
||||
//FIXME: Respect flags!
|
||||
}
|
||||
|
||||
UserLeave();
|
||||
return Ret;
|
||||
}
|
||||
|
||||
DWORD
|
||||
STDCALL
|
||||
NtUserUnloadKeyboardLayout(
|
||||
DWORD Unknown0)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* EOF */
|
|
@ -33,8 +33,7 @@
|
|||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* Directory to load key layouts from */
|
||||
#define SYSTEMROOT_DIR L"\\SystemRoot\\System32\\"
|
||||
|
||||
/* Lock modifiers */
|
||||
#define CAPITAL_BIT 0x80000000
|
||||
#define NUMLOCK_BIT 0x40000000
|
||||
|
@ -53,8 +52,6 @@
|
|||
BYTE gQueueKeyStateTable[256];
|
||||
|
||||
|
||||
PKBDRVFILE KBLList = NULL; // Keyboard layout list.
|
||||
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
|
@ -434,7 +431,7 @@ int STDCALL ToUnicodeEx( UINT wVirtKey,
|
|||
cchBuff,
|
||||
wFlags,
|
||||
PsGetCurrentThreadWin32Thread() ?
|
||||
PsGetCurrentThreadWin32Thread()->KeyboardLayout : 0 );
|
||||
PsGetCurrentThreadWin32Thread()->KeyboardLayout->KBTables : 0 );
|
||||
}
|
||||
|
||||
return ToUnicodeResult;
|
||||
|
@ -456,255 +453,6 @@ int STDCALL ToUnicode( UINT wVirtKey,
|
|||
0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility to copy and append two unicode strings.
|
||||
*
|
||||
* IN OUT PUNICODE_STRING ResultFirst -> First string and result
|
||||
* IN PUNICODE_STRING Second -> Second string to append
|
||||
* IN BOOL Deallocate -> TRUE: Deallocate First string before
|
||||
* overwriting.
|
||||
*
|
||||
* Returns NTSTATUS.
|
||||
*/
|
||||
|
||||
NTSTATUS NTAPI AppendUnicodeString(PUNICODE_STRING ResultFirst,
|
||||
PUNICODE_STRING Second,
|
||||
BOOL Deallocate)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PWSTR new_string =
|
||||
ExAllocatePoolWithTag(PagedPool,
|
||||
(ResultFirst->Length + Second->Length + sizeof(WCHAR)),
|
||||
TAG_STRING);
|
||||
if( !new_string )
|
||||
{
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
memcpy( new_string, ResultFirst->Buffer,
|
||||
ResultFirst->Length );
|
||||
memcpy( new_string + ResultFirst->Length / sizeof(WCHAR),
|
||||
Second->Buffer,
|
||||
Second->Length );
|
||||
if( Deallocate )
|
||||
RtlFreeUnicodeString(ResultFirst);
|
||||
ResultFirst->Length += Second->Length;
|
||||
ResultFirst->MaximumLength = ResultFirst->Length;
|
||||
new_string[ResultFirst->Length / sizeof(WCHAR)] = 0;
|
||||
Status = RtlCreateUnicodeString(ResultFirst,new_string) ?
|
||||
STATUS_SUCCESS : STATUS_NO_MEMORY;
|
||||
ExFreePool(new_string);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 NTAPI 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;
|
||||
UNICODE_STRING Temp;
|
||||
|
||||
InitializeObjectAttributes(&KeyAttributes, KeyName, OBJ_CASE_INSENSITIVE,
|
||||
NULL, NULL);
|
||||
Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &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);
|
||||
ExFreePool(KeyValuePartialInfo);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Temp.Length = Temp.MaximumLength = KeyValuePartialInfo->DataLength;
|
||||
Temp.Buffer = (PWCHAR)KeyValuePartialInfo->Data;
|
||||
|
||||
/* At this point, KeyValuePartialInfo->Data contains the key data */
|
||||
RtlInitUnicodeString(ReturnedValue,L"");
|
||||
AppendUnicodeString(ReturnedValue,&Temp,FALSE);
|
||||
|
||||
ExFreePool(KeyValuePartialInfo);
|
||||
NtClose(KeyHandle);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
typedef PVOID (*KbdLayerDescriptor)(VOID);
|
||||
NTSTATUS STDCALL LdrGetProcedureAddress(PVOID module,
|
||||
PANSI_STRING import_name,
|
||||
DWORD flags,
|
||||
PVOID *func_addr);
|
||||
|
||||
void InitKbdLayout( PVOID *pkKeyboardLayout )
|
||||
{
|
||||
WCHAR LocaleBuffer[16];
|
||||
UNICODE_STRING LayoutKeyName;
|
||||
UNICODE_STRING LayoutValueName;
|
||||
UNICODE_STRING DefaultLocale;
|
||||
UNICODE_STRING LayoutFile;
|
||||
UNICODE_STRING FullLayoutPath;
|
||||
LCID LocaleId;
|
||||
PWCHAR KeyboardLayoutWSTR;
|
||||
HMODULE kbModule = 0;
|
||||
NTSTATUS Status;
|
||||
ANSI_STRING kbdProcedureName;
|
||||
KbdLayerDescriptor layerDescGetFn;
|
||||
|
||||
#define XX_STATUS(x) if (!NT_SUCCESS(Status = (x))) continue;
|
||||
|
||||
do
|
||||
{
|
||||
Status = ZwQueryDefaultLocale(FALSE, &LocaleId);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Could not get default locale (%08lx).\n", Status);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("DefaultLocale = %lx\n", LocaleId);
|
||||
swprintf(LocaleBuffer, L"%08lx", LocaleId);
|
||||
DPRINT("DefaultLocale = %S\n", LocaleBuffer);
|
||||
RtlInitUnicodeString(&DefaultLocale, LocaleBuffer);
|
||||
|
||||
RtlInitUnicodeString(&LayoutKeyName,
|
||||
L"\\REGISTRY\\Machine\\SYSTEM\\CurrentControlSet"
|
||||
L"\\Control\\KeyboardLayouts\\");
|
||||
|
||||
AppendUnicodeString(&LayoutKeyName,&DefaultLocale,FALSE);
|
||||
|
||||
RtlInitUnicodeString(&LayoutValueName,L"Layout File");
|
||||
|
||||
Status = ReadRegistryValue(&LayoutKeyName,&LayoutValueName,&LayoutFile);
|
||||
|
||||
RtlFreeUnicodeString(&LayoutKeyName);
|
||||
|
||||
if( !NT_SUCCESS(Status) )
|
||||
{
|
||||
DPRINT1("Got default locale but not layout file. (%08lx)\n",
|
||||
Status);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Read registry and got %wZ\n", &LayoutFile);
|
||||
|
||||
|
||||
RtlInitUnicodeString(&FullLayoutPath,SYSTEMROOT_DIR);
|
||||
AppendUnicodeString(&FullLayoutPath,&LayoutFile,FALSE);
|
||||
|
||||
DPRINT("Loading Keyboard DLL %wZ\n", &FullLayoutPath);
|
||||
|
||||
RtlFreeUnicodeString(&LayoutFile);
|
||||
|
||||
KeyboardLayoutWSTR =
|
||||
ExAllocatePoolWithTag(PagedPool,
|
||||
FullLayoutPath.Length + sizeof(WCHAR),
|
||||
TAG_STRING);
|
||||
|
||||
if( !KeyboardLayoutWSTR )
|
||||
{
|
||||
DPRINT1("Couldn't allocate a string for the keyboard layout name.\n");
|
||||
RtlFreeUnicodeString(&FullLayoutPath);
|
||||
return;
|
||||
}
|
||||
memcpy(KeyboardLayoutWSTR,FullLayoutPath.Buffer,
|
||||
FullLayoutPath.Length);
|
||||
KeyboardLayoutWSTR[FullLayoutPath.Length / sizeof(WCHAR)] = 0;
|
||||
|
||||
kbModule = EngLoadImage(KeyboardLayoutWSTR);
|
||||
DPRINT( "Load Keyboard Layout: %S\n", KeyboardLayoutWSTR );
|
||||
|
||||
if( !kbModule )
|
||||
DPRINT1( "Load Keyboard Layout: No %wZ\n", &FullLayoutPath );
|
||||
|
||||
ExFreePool(KeyboardLayoutWSTR);
|
||||
RtlFreeUnicodeString(&FullLayoutPath);
|
||||
}
|
||||
}
|
||||
|
||||
if( !kbModule )
|
||||
{
|
||||
DPRINT1("Trying to load US Keyboard Layout\n");
|
||||
kbModule = EngLoadImage(L"\\SystemRoot\\system32\\kbdus.dll");
|
||||
|
||||
if (!kbModule)
|
||||
{
|
||||
DPRINT1("Failed to load any Keyboard Layout\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
RtlInitAnsiString( &kbdProcedureName, "KbdLayerDescriptor" );
|
||||
|
||||
LdrGetProcedureAddress((PVOID)kbModule,
|
||||
&kbdProcedureName,
|
||||
0,
|
||||
(PVOID*)&layerDescGetFn);
|
||||
|
||||
if( layerDescGetFn )
|
||||
{
|
||||
*pkKeyboardLayout = layerDescGetFn();
|
||||
}
|
||||
}
|
||||
while (FALSE);
|
||||
|
||||
if( !*pkKeyboardLayout )
|
||||
{
|
||||
DPRINT1("Failed to load the keyboard layout.\n");
|
||||
}
|
||||
|
||||
#undef XX_STATUS
|
||||
}
|
||||
|
||||
PKBDTABLES W32kGetDefaultKeyLayout(VOID)
|
||||
{
|
||||
PKBDTABLES pkKeyboardLayout = 0;
|
||||
InitKbdLayout( (PVOID) &pkKeyboardLayout );
|
||||
return pkKeyboardLayout;
|
||||
}
|
||||
|
||||
BOOL FASTCALL
|
||||
IntTranslateKbdMessage(LPMSG lpMsg,
|
||||
|
@ -719,7 +467,7 @@ IntTranslateKbdMessage(LPMSG lpMsg,
|
|||
DWORD ScanCode = 0;
|
||||
|
||||
|
||||
keyLayout = PsGetCurrentThreadWin32Thread()->KeyboardLayout;
|
||||
keyLayout = PsGetCurrentThreadWin32Thread()->KeyboardLayout->KBTables;
|
||||
if( !keyLayout )
|
||||
return FALSE;
|
||||
|
||||
|
@ -960,7 +708,7 @@ NtUserMapVirtualKeyEx( UINT Code, UINT Type, DWORD keyboardId, HKL dwhkl )
|
|||
DPRINT("Enter NtUserMapVirtualKeyEx\n");
|
||||
UserEnterExclusive();
|
||||
|
||||
keyLayout = PsGetCurrentThreadWin32Thread() ? PsGetCurrentThreadWin32Thread()->KeyboardLayout : 0;
|
||||
keyLayout = PsGetCurrentThreadWin32Thread() ? PsGetCurrentThreadWin32Thread()->KeyboardLayout->KBTables : 0;
|
||||
|
||||
if( !keyLayout )
|
||||
RETURN(0);
|
||||
|
@ -1053,7 +801,7 @@ NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize )
|
|||
UserEnterShared();
|
||||
|
||||
keyLayout = PsGetCurrentThreadWin32Thread() ?
|
||||
PsGetCurrentThreadWin32Thread()->KeyboardLayout : 0;
|
||||
PsGetCurrentThreadWin32Thread()->KeyboardLayout->KBTables : 0;
|
||||
|
||||
if( !keyLayout || nSize < 1 )
|
||||
RETURN(0);
|
||||
|
@ -1150,7 +898,7 @@ W32kKeyProcessMessage(LPMSG Msg,
|
|||
{ VK_UP, VK_NUMPAD8 },
|
||||
{ VK_PRIOR, VK_NUMPAD9 },
|
||||
{ 0,0 } };
|
||||
PVSC_VK VscVkTable = NULL;
|
||||
PVSC_VK VscVkTable = NULL;
|
||||
|
||||
if( !KeyboardLayout || !Msg ||
|
||||
(Msg->message != WM_KEYDOWN && Msg->message != WM_SYSKEYDOWN &&
|
||||
|
@ -1247,101 +995,6 @@ W32kKeyProcessMessage(LPMSG Msg,
|
|||
|
||||
}
|
||||
|
||||
DWORD
|
||||
STDCALL
|
||||
NtUserGetKeyboardLayoutList(
|
||||
DWORD Items,
|
||||
DWORD pHklBuff)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL
|
||||
STDCALL
|
||||
NtUserGetKeyboardLayoutName(
|
||||
LPWSTR lpszName)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
LCID LocaleId;
|
||||
WCHAR LocaleBuffer[16];
|
||||
NTSTATUS Status;
|
||||
|
||||
|
||||
UserEnterExclusive();
|
||||
|
||||
DPRINT("Enter NtUserGetKeyboardLayoutName\n");
|
||||
|
||||
Status = ZwQueryDefaultLocale(FALSE, &LocaleId);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
swprintf(LocaleBuffer, L"%08lx", LocaleId);
|
||||
DPRINT("LocaleId : %08lx\n",LocaleId);
|
||||
_SEH_TRY
|
||||
{
|
||||
ProbeForWrite(lpszName, 16, 1);
|
||||
RtlCopyMemory(lpszName,LocaleBuffer,16);
|
||||
ret = TRUE;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
SetLastNtError(_SEH_GetExceptionCode());
|
||||
ret = FALSE;
|
||||
}
|
||||
_SEH_END;
|
||||
}
|
||||
UserLeave();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
HKL FASTCALL
|
||||
UserGetKeyboardLayout(
|
||||
DWORD dwThreadId)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PETHREAD Thread;
|
||||
PW32THREAD W32Thread;
|
||||
PKBDTABLES layout;
|
||||
|
||||
if (!dwThreadId)
|
||||
W32Thread = PsGetCurrentThreadWin32Thread();
|
||||
else
|
||||
{
|
||||
Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);//fixme: deref thread
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
W32Thread = Thread->Tcb.Win32Thread; /* Wrong, but returning the pointer to
|
||||
the table. */
|
||||
}
|
||||
layout = W32Thread->KeyboardLayout;
|
||||
if(!layout)
|
||||
return 0;
|
||||
return (HKL)layout;
|
||||
}
|
||||
|
||||
|
||||
HKL
|
||||
STDCALL
|
||||
NtUserGetKeyboardLayout(
|
||||
DWORD dwThreadId)
|
||||
{
|
||||
DECLARE_RETURN(HKL);
|
||||
|
||||
UserEnterShared();
|
||||
DPRINT("Enter NtUserGetKeyboardLayout\n");
|
||||
|
||||
RETURN( UserGetKeyboardLayout(dwThreadId));
|
||||
|
||||
CLEANUP:
|
||||
DPRINT("Leave NtUserGetKeyboardLayout, ret=%i\n",_ret_);
|
||||
UserLeave();
|
||||
END_CLEANUP;
|
||||
}
|
||||
|
||||
|
||||
DWORD FASTCALL
|
||||
|
@ -1363,22 +1016,6 @@ UserGetKeyboardType(
|
|||
}
|
||||
|
||||
|
||||
HKL
|
||||
STDCALL
|
||||
NtUserLoadKeyboardLayoutEx(
|
||||
IN HANDLE Handle,
|
||||
IN DWORD offTable,
|
||||
IN HKL hKL,
|
||||
IN PUNICODE_STRING puszKLID,
|
||||
IN UINT KLayoutLangID,
|
||||
IN UINT Flags)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Based on TryToTranslateChar, instead of processing VirtualKey match,
|
||||
look for wChar match.
|
||||
|
|
|
@ -13,17 +13,6 @@
|
|||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
DWORD
|
||||
STDCALL
|
||||
NtUserActivateKeyboardLayout(
|
||||
DWORD Unknown0,
|
||||
DWORD Unknown1)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD
|
||||
STDCALL
|
||||
NtUserAttachThreadInput(
|
||||
|
@ -627,15 +616,6 @@ NtUserTrackMouseEvent(
|
|||
return 0;
|
||||
}
|
||||
|
||||
DWORD
|
||||
STDCALL
|
||||
NtUserUnloadKeyboardLayout(
|
||||
DWORD Unknown0)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD
|
||||
STDCALL
|
||||
|
|
|
@ -120,6 +120,7 @@
|
|||
<file>hotkey.c</file>
|
||||
<file>input.c</file>
|
||||
<file>keyboard.c</file>
|
||||
<file>kbdlayout.c</file>
|
||||
<file>menu.c</file>
|
||||
<file>message.c</file>
|
||||
<file>metric.c</file>
|
||||
|
|
|
@ -428,7 +428,7 @@ NtUserInternalGetWindowText 3
|
|||
NtUserIsClipboardFormatAvailable 1
|
||||
NtUserKillSystemTimer 2
|
||||
NtUserKillTimer 2
|
||||
NtUserLoadKeyboardLayoutEx 6
|
||||
NtUserLoadKeyboardLayoutEx 2
|
||||
NtUserLockWindowStation 1
|
||||
NtUserLockWindowUpdate 1
|
||||
NtUserLockWorkStation 0
|
||||
|
|
Loading…
Reference in a new issue