diff --git a/reactos/dll/win32/user32/user32.def b/reactos/dll/win32/user32/user32.def index 13af78be68d..9c30a850864 100644 --- a/reactos/dll/win32/user32/user32.def +++ b/reactos/dll/win32/user32/user32.def @@ -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 diff --git a/reactos/dll/win32/user32/windows/input.c b/reactos/dll/win32/user32/windows/input.c index b829a1caa69..eeffeac27ef 100644 --- a/reactos/dll/win32/user32/windows/input.c +++ b/reactos/dll/win32/user32/windows/input.c @@ -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); } diff --git a/reactos/include/reactos/win32k/ntuser.h b/reactos/include/reactos/win32k/ntuser.h index 19ff0687983..14c848f3bc8 100644 --- a/reactos/include/reactos/win32k/ntuser.h +++ b/reactos/include/reactos/win32k/ntuser.h @@ -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 diff --git a/reactos/subsystems/win32/win32k/include/input.h b/reactos/subsystems/win32/win32k/include/input.h index 6f201eae1b7..a97e4b8b352 100644 --- a/reactos/subsystems/win32/win32k/include/input.h +++ b/reactos/subsystems/win32/win32k/include/input.h @@ -3,19 +3,16 @@ #include -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) diff --git a/reactos/subsystems/win32/win32k/include/win32.h b/reactos/subsystems/win32/win32k/include/win32.h index 326bb96e548..61f5783b5e9 100644 --- a/reactos/subsystems/win32/win32k/include/win32.h +++ b/reactos/subsystems/win32/win32k/include/win32.h @@ -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; diff --git a/reactos/subsystems/win32/win32k/ntuser/input.c b/reactos/subsystems/win32/win32k/ntuser/input.c index fbf830334a8..1d251d41a5f 100644 --- a/reactos/subsystems/win32/win32k/ntuser/input.c +++ b/reactos/subsystems/win32/win32k/ntuser/input.c @@ -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, diff --git a/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c b/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c new file mode 100644 index 00000000000..24c8d5d4e63 --- /dev/null +++ b/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c @@ -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 + +#define NDEBUG +#include + +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 */ diff --git a/reactos/subsystems/win32/win32k/ntuser/keyboard.c b/reactos/subsystems/win32/win32k/ntuser/keyboard.c index dcc915f5f06..e725d4db1bc 100644 --- a/reactos/subsystems/win32/win32k/ntuser/keyboard.c +++ b/reactos/subsystems/win32/win32k/ntuser/keyboard.c @@ -33,8 +33,7 @@ #define NDEBUG #include -/* 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. diff --git a/reactos/subsystems/win32/win32k/ntuser/ntstubs.c b/reactos/subsystems/win32/win32k/ntuser/ntstubs.c index 56495fc0ae6..21d7a4b9027 100644 --- a/reactos/subsystems/win32/win32k/ntuser/ntstubs.c +++ b/reactos/subsystems/win32/win32k/ntuser/ntstubs.c @@ -13,17 +13,6 @@ #define NDEBUG #include -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 diff --git a/reactos/subsystems/win32/win32k/win32k.rbuild b/reactos/subsystems/win32/win32k/win32k.rbuild index e609299d8c9..6121772e665 100644 --- a/reactos/subsystems/win32/win32k/win32k.rbuild +++ b/reactos/subsystems/win32/win32k/win32k.rbuild @@ -120,6 +120,7 @@ hotkey.c input.c keyboard.c + kbdlayout.c menu.c message.c metric.c diff --git a/reactos/tools/nci/w32ksvc.db b/reactos/tools/nci/w32ksvc.db index 958d72d4738..dacd1ba1418 100644 --- a/reactos/tools/nci/w32ksvc.db +++ b/reactos/tools/nci/w32ksvc.db @@ -428,7 +428,7 @@ NtUserInternalGetWindowText 3 NtUserIsClipboardFormatAvailable 1 NtUserKillSystemTimer 2 NtUserKillTimer 2 -NtUserLoadKeyboardLayoutEx 6 +NtUserLoadKeyboardLayoutEx 2 NtUserLockWindowStation 1 NtUserLockWindowUpdate 1 NtUserLockWorkStation 0