Add multiple keyboard layout support. Implemented NtUserLoadKeyboardLayoutEx, NtUserActivateKeyboardLayout, NtUserGetKeyboardLayoutList, NtUserGetKeyboardLayoutName.

svn path=/trunk/; revision=25758
This commit is contained in:
Saveliy Tretiakov 2007-02-09 20:48:37 +00:00
parent cd679a1f7e
commit c1145464aa
11 changed files with 508 additions and 666 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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)

View file

@ -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;

View file

@ -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,

View 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 */

View file

@ -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.

View file

@ -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

View file

@ -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>

View file

@ -428,7 +428,7 @@ NtUserInternalGetWindowText 3
NtUserIsClipboardFormatAvailable 1
NtUserKillSystemTimer 2
NtUserKillTimer 2
NtUserLoadKeyboardLayoutEx 6
NtUserLoadKeyboardLayoutEx 2
NtUserLockWindowStation 1
NtUserLockWindowUpdate 1
NtUserLockWorkStation 0