Author: tretiakov Date: Fri Feb 9 23:48:37 2007 New Revision: 25758
URL: http://svn.reactos.org/svn/reactos?rev=25758&view=rev Log: Add multiple keyboard layout support. Implemented NtUserLoadKeyboardLayoutEx, NtUserActivateKeyboardLayout, NtUserGetKeyboardLayoutList, NtUserGetKeyboardLayoutName.
Added: trunk/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c Modified: trunk/reactos/dll/win32/user32/user32.def trunk/reactos/dll/win32/user32/windows/input.c trunk/reactos/include/reactos/win32k/ntuser.h trunk/reactos/subsystems/win32/win32k/include/input.h trunk/reactos/subsystems/win32/win32k/include/win32.h trunk/reactos/subsystems/win32/win32k/ntuser/input.c trunk/reactos/subsystems/win32/win32k/ntuser/keyboard.c trunk/reactos/subsystems/win32/win32k/ntuser/ntstubs.c trunk/reactos/subsystems/win32/win32k/win32k.rbuild trunk/reactos/tools/nci/w32ksvc.db
Modified: trunk/reactos/dll/win32/user32/user32.def URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/user32.def... ============================================================================== --- trunk/reactos/dll/win32/user32/user32.def (original) +++ trunk/reactos/dll/win32/user32/user32.def Fri Feb 9 23:48:37 2007 @@ -1,7 +1,7 @@ LIBRARY user32.dll
EXPORTS -ActivateKeyboardLayout@8 +ActivateKeyboardLayout@8=NtUserActivateKeyboardLayout@8 AdjustWindowRect@12 AdjustWindowRectEx@16 AlignRects@16 @@ -295,7 +295,7 @@ GetKeyNameTextW@12 GetKeyState@4 GetKeyboardLayout@4 -GetKeyboardLayoutList@8 +GetKeyboardLayoutList@8=NtUserGetKeyboardLayoutList@8 GetKeyboardLayoutNameA@4 GetKeyboardLayoutNameW@4 GetKeyboardState@4
Modified: trunk/reactos/dll/win32/user32/windows/input.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/in... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/input.c (original) +++ trunk/reactos/dll/win32/user32/windows/input.c Fri Feb 9 23:48:37 2007 @@ -44,218 +44,6 @@ static _TRACKINGLIST tracking_info; 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 *****************************************************************/ @@ -314,18 +102,6 @@
/* - * @unimplemented - */ -HKL STDCALL -ActivateKeyboardLayout(HKL hkl, - UINT Flags) -{ - UNIMPLEMENTED; - return (HKL)0; -} - - -/* * @implemented */ BOOL STDCALL @@ -461,18 +237,6 @@
/* - * @unimplemented - */ -UINT STDCALL -GetKeyboardLayoutList(int nBuff, - HKL FAR *lpList) -{ - UNIMPLEMENTED; - return 0; -} - - -/* * @implemented */ BOOL STDCALL @@ -534,15 +298,9 @@ 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 @@ 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); }
Modified: trunk/reactos/include/reactos/win32k/ntuser.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/win32k/ntus... ============================================================================== --- trunk/reactos/include/reactos/win32k/ntuser.h (original) +++ trunk/reactos/include/reactos/win32k/ntuser.h Fri Feb 9 23:48:37 2007 @@ -299,11 +299,11 @@ NtUserAcquireOrReleaseInputOwnership( BOOLEAN Release);
-DWORD +HKL NTAPI NtUserActivateKeyboardLayout( - DWORD Unknown0, - DWORD Unknown1); + HKL hKl, + ULONG Flags);
DWORD NTAPI @@ -1008,11 +1008,11 @@ NtUserGetKeyboardLayout( DWORD dwThreadid);
-DWORD +UINT NTAPI NtUserGetKeyboardLayoutList( - DWORD Unknown0, - DWORD Unknown1); + INT nItems, + HKL *pHklBuff);
BOOL NTAPI @@ -1219,11 +1219,7 @@ HKL NTAPI NtUserLoadKeyboardLayoutEx( - HANDLE Handle, - DWORD offTable, - HKL hKL, - PUNICODE_STRING puszKLID, - UINT KLayoutLangID, + LCID LocaleId, UINT Flags);
BOOL
Modified: trunk/reactos/subsystems/win32/win32k/include/input.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/input.h (original) +++ trunk/reactos/subsystems/win32/win32k/include/input.h Fri Feb 9 23:48:37 2007 @@ -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 @@ 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)
Modified: trunk/reactos/subsystems/win32/win32k/include/win32.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/win32.h (original) +++ trunk/reactos/subsystems/win32/win32k/include/win32.h Fri Feb 9 23:48:37 2007 @@ -8,7 +8,7 @@ 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 @@ LIST_ENTRY PrivateFontListHead; FAST_MUTEX DriverObjListLock; LIST_ENTRY DriverObjListHead; - struct _KBDTABLES* KeyboardLayout; + struct _KBL* KeyboardLayout; ULONG Flags; LONG GDIObjects; LONG UserObjects;
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/input.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/input.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/input.c Fri Feb 9 23:48:37 2007 @@ -529,8 +529,8 @@ KernelMode, TRUE, NULL); + DPRINT( "Keyboard Input Thread Starting...\n" ); - /* * Receive and process keyboard input. */ @@ -754,7 +754,7 @@ * 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 @@ }
/* Initialize the default keyboard layout */ - (VOID)W32kGetDefaultKeyLayout(); - + if(!UserInitDefaultKeyboardLayout()) + { + DPRINT1("Failed to initialize default keyboard layout!\n"); + }
Status = PsCreateSystemThread(&MouseThreadHandle, THREAD_ALL_ACCESS,
Added: trunk/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c (added) +++ trunk/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c Fri Feb 9 23:48:37 2007 @@ -1,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 */
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/keyboard.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/keyboard.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/keyboard.c Fri Feb 9 23:48:37 2007 @@ -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 @@ -52,8 +51,6 @@
BYTE gQueueKeyStateTable[256];
- -PKBDRVFILE KBLList = NULL; // Keyboard layout list.
/* FUNCTIONS *****************************************************************/ @@ -434,7 +431,7 @@ cchBuff, wFlags, PsGetCurrentThreadWin32Thread() ? - PsGetCurrentThreadWin32Thread()->KeyboardLayout : 0 ); + PsGetCurrentThreadWin32Thread()->KeyboardLayout->KBTables : 0 ); }
return ToUnicodeResult; @@ -456,255 +453,6 @@ 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 @@ DWORD ScanCode = 0;
- keyLayout = PsGetCurrentThreadWin32Thread()->KeyboardLayout; + keyLayout = PsGetCurrentThreadWin32Thread()->KeyboardLayout->KBTables; if( !keyLayout ) return FALSE;
@@ -960,7 +708,7 @@ DPRINT("Enter NtUserMapVirtualKeyEx\n"); UserEnterExclusive();
- keyLayout = PsGetCurrentThreadWin32Thread() ? PsGetCurrentThreadWin32Thread()->KeyboardLayout : 0; + keyLayout = PsGetCurrentThreadWin32Thread() ? PsGetCurrentThreadWin32Thread()->KeyboardLayout->KBTables : 0;
if( !keyLayout ) RETURN(0); @@ -1053,7 +801,7 @@ UserEnterShared();
keyLayout = PsGetCurrentThreadWin32Thread() ? - PsGetCurrentThreadWin32Thread()->KeyboardLayout : 0; + PsGetCurrentThreadWin32Thread()->KeyboardLayout->KBTables : 0;
if( !keyLayout || nSize < 1 ) RETURN(0); @@ -1150,7 +898,7 @@ { 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 @@
}
-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 @@ -1360,22 +1013,6 @@ DPRINT1("Unknown type!\n"); return 0; /* The book says 0 here, so 0 */ } -} - - -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; }
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/ntstubs.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/ntstubs.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/ntstubs.c Fri Feb 9 23:48:37 2007 @@ -12,17 +12,6 @@
#define NDEBUG #include <debug.h> - -DWORD -STDCALL -NtUserActivateKeyboardLayout( - DWORD Unknown0, - DWORD Unknown1) -{ - UNIMPLEMENTED - - return 0; -}
DWORD STDCALL @@ -627,15 +616,6 @@ return 0; }
-DWORD -STDCALL -NtUserUnloadKeyboardLayout( - DWORD Unknown0) -{ - UNIMPLEMENTED - - return 0; -}
DWORD STDCALL
Modified: trunk/reactos/subsystems/win32/win32k/win32k.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/win... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/win32k.rbuild (original) +++ trunk/reactos/subsystems/win32/win32k/win32k.rbuild Fri Feb 9 23:48:37 2007 @@ -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>
Modified: trunk/reactos/tools/nci/w32ksvc.db URL: http://svn.reactos.org/svn/reactos/trunk/reactos/tools/nci/w32ksvc.db?rev=25... ============================================================================== --- trunk/reactos/tools/nci/w32ksvc.db (original) +++ trunk/reactos/tools/nci/w32ksvc.db Fri Feb 9 23:48:37 2007 @@ -428,7 +428,7 @@ NtUserIsClipboardFormatAvailable 1 NtUserKillSystemTimer 2 NtUserKillTimer 2 -NtUserLoadKeyboardLayoutEx 6 +NtUserLoadKeyboardLayoutEx 2 NtUserLockWindowStation 1 NtUserLockWindowUpdate 1 NtUserLockWorkStation 0