From bf7329e25bb45cdfd13d92b2bcc704378fc626e2 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Tue, 29 Jul 2003 23:03:01 +0000 Subject: [PATCH] Adding Art Yerkes Keyboard Testing Code svn path=/trunk/; revision=5323 --- reactos/apps/utils/Makefile | 2 +- reactos/ntoskrnl/include/internal/kbd.h | 111 ++++++++++ reactos/subsys/csrss/api/conio.c | 27 ++- reactos/subsys/csrss/api/wapi.c | 3 +- reactos/subsys/win32k/ldr/loader.c | 114 ++++++++++- reactos/subsys/win32k/ntuser/input.c | 11 +- reactos/subsys/win32k/ntuser/keyboard.c | 259 ++++++++++++++++++++---- 7 files changed, 476 insertions(+), 51 deletions(-) create mode 100644 reactos/ntoskrnl/include/internal/kbd.h diff --git a/reactos/apps/utils/Makefile b/reactos/apps/utils/Makefile index 3324d935790..cf88d9fb194 100644 --- a/reactos/apps/utils/Makefile +++ b/reactos/apps/utils/Makefile @@ -9,7 +9,7 @@ include $(PATH_TO_TOP)/rules.mak # Console system utilities # cabman cat net objdir partinfo pice ps sc stats -UTIL_APPS = cat objdir partinfo pnpdump sc stats tickcount +UTIL_APPS = cat objdir partinfo pnpdump sc stats tickcount consw UTIL_NET_APPS = diff --git a/reactos/ntoskrnl/include/internal/kbd.h b/reactos/ntoskrnl/include/internal/kbd.h new file mode 100644 index 00000000000..8974d316628 --- /dev/null +++ b/reactos/ntoskrnl/include/internal/kbd.h @@ -0,0 +1,111 @@ +/* ReactOS System Header -- kbd.h */ +#define __KBD_H + +#if __GNUC__ >=3 +#pragma GCC system_header +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct _VK_TO_BIT { + BYTE Vk; + BYTE ModBits; + } VK_TO_BIT, *PVK_TO_BIT; + + typedef struct _MODIFIERS { + PVK_TO_BIT pVkToBit; + WORD wMaxModBits; + BYTE ModNumber[]; + } MODIFIERS, *PMODIFIERS; + +#define TYPEDEF_VK_TO_WCHARS(i) \ + typedef struct _VK_TO_WCHARS ## i { \ + BYTE VirtualKey; \ + BYTE Attributes; \ + WCHAR wch[i]; \ + } VK_TO_WCHARS ## i, *PVK_TO_WCHARS ## i; + + TYPEDEF_VK_TO_WCHARS(1) + TYPEDEF_VK_TO_WCHARS(2) + TYPEDEF_VK_TO_WCHARS(3) + TYPEDEF_VK_TO_WCHARS(4) + TYPEDEF_VK_TO_WCHARS(5) + TYPEDEF_VK_TO_WCHARS(6) + TYPEDEF_VK_TO_WCHARS(7) + TYPEDEF_VK_TO_WCHARS(8) + TYPEDEF_VK_TO_WCHARS(9) + TYPEDEF_VK_TO_WCHARS(10) + + typedef struct _VK_TO_WCHAR_TABLE { + PVK_TO_WCHARS1 pVkToWchars; + BYTE nModifications; + BYTE cbSize; + } VK_TO_WCHAR_TABLE, *PVK_TO_WCHAR_TABLE; + + typedef struct _DEADKEY { + DWORD dwBoth; + WCHAR wchComposed; + USHORT uFlags; + } DEADKEY, *PDEADKEY; + +#define DKF_DEAD 1 + + typedef struct _VSC_LPWSTR { + BYTE vsc; + LPWSTR pwsz; + } VSC_LPWSTR, *PVSC_LPWSTR; + + typedef struct _VSC_VK { + BYTE Vsc; + USHORT Vk; + } VSC_VK, *PVSC_VK; + +#define TYPEDEF_LIGATURE(i) \ +typedef struct _LIGATURE ## i { \ + BYTE VirtualKey; \ + WORD ModificationNumber; \ + WCHAR wch[i]; \ +} LIGATURE ## i, *PLIGATURE ## i; + + TYPEDEF_LIGATURE(1) + +#define KBD_VERSION 1 +#define GET_KBD_VERSION(p) (HIWORD((p)->fLocalFlags)) +#define KLLF_ALTGR 1 +#define KLLF_SHIFTLOCK 2 +#define KLLF_LRM_RLM 4 + + typedef struct _KBDTABLES { + PMODIFIERS pCharModifiers; + PVK_TO_WCHAR_TABLE pVkToWcharTable; + PDEADKEY pDeadKey; + VSC_LPWSTR *pKeyNames; + VSC_LPWSTR *pKeyNamesExt; + LPWSTR *pKeyNamesDead; + USHORT *pusVSCtoVK; + BYTE bMaxVSCtoVK; + PVSC_VK pVSCtoVK_E0; + PVSC_VK pVSCtoVK_E1; + DWORD fLocalFlags; + BYTE nLgMaxd; + BYTE cbLgEntry; + PLIGATURE1 pLigature; + } KBDTABLES, *PKBDTABLES; + + /* Constants that help table decoding */ +#define WCH_NONE 0xf000 +#define WCH_DEAD 0xf001 +#define WCH_LGTR 0xf002 + +#define CAPSLOK 1 +#define SGCAPS 2 +#define CAPLOKALTGR 4 +#define KANALOK 8 +#define GRPSELTAP 0x80 + + +#ifdef __cplusplus +}; +#endif//__KBD_H diff --git a/reactos/subsys/csrss/api/conio.c b/reactos/subsys/csrss/api/conio.c index 38abe19b368..0a87bf3723e 100644 --- a/reactos/subsys/csrss/api/conio.c +++ b/reactos/subsys/csrss/api/conio.c @@ -1,4 +1,4 @@ -/* $Id: conio.c,v 1.48 2003/06/19 19:38:26 ea Exp $ +/* $Id: conio.c,v 1.49 2003/07/29 23:03:01 jimtabor Exp $ * * reactos/subsys/csrss/api/conio.c * @@ -33,6 +33,7 @@ static HANDLE KeyboardDeviceHandle; static PCSRSS_CONSOLE ActiveConsole; CRITICAL_SECTION ActiveConsoleLock; static COORD PhysicalConsoleSize; +static BOOL KeyReadInhibit = FALSE; /* FUNCTIONS *****************************************************************/ @@ -926,8 +927,12 @@ VOID Console_Api( DWORD RefreshEvent ) continue; } KeyEventRecord->InputEvent.EventType = KEY_EVENT; - Status = NtReadFile( KeyboardDeviceHandle, Events[0], NULL, NULL, &Iosb, - &KeyEventRecord->InputEvent.Event.KeyEvent, sizeof( KEY_EVENT_RECORD ), NULL, 0 ); + if( !KeyReadInhibit ) { + Status = NtReadFile( KeyboardDeviceHandle, Events[0], NULL, NULL, &Iosb, + &KeyEventRecord->InputEvent.Event.KeyEvent, sizeof( KEY_EVENT_RECORD ), NULL, 0 ); + } else { + Status = STATUS_PENDING; + } if( !NT_SUCCESS( Status ) ) { DbgPrint( "CSR: ReadFile on keyboard device failed\n" ); @@ -2462,9 +2467,20 @@ CSR_API(CsrWriteConsoleInput) */ static NTSTATUS FASTCALL SetConsoleHardwareState (PCSRSS_CONSOLE Console, DWORD ConsoleHwState) { + DbgPrint( "Console Hardware State: %d\n", ConsoleHwState ); + if ( (CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState) ||(CONSOLE_HARDWARE_STATE_DIRECT == ConsoleHwState)) { + /* Inhibit keyboard input when hardware state == + * CONSOLE_HARDWARE_STATE_GDI_MANAGED */ + if (CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState) { + DbgPrint( "Keyboard Inhibited.\n" ); + KeyReadInhibit = TRUE; + } else { + DbgPrint( "Keyboard Enabled.\n" ); + KeyReadInhibit = FALSE; + } if (Console->HardwareState != ConsoleHwState) { /* TODO: implement switching from full screen to windowed mode */ @@ -2493,13 +2509,15 @@ CSR_API(CsrHardwareStateProperty) ); if (!NT_SUCCESS(Status)) { + DbgPrint( "Failed to get console handle in SetConsoleHardwareState\n" ); Reply->Status = Status; } else { if(Console->Header.Type != CSRSS_CONSOLE_MAGIC) { - Reply->Status = STATUS_INVALID_HANDLE; + DbgPrint( "Bad magic on Console: %08x\n", Console->Header.Type ); + Reply->Status = STATUS_INVALID_HANDLE; } else { @@ -2510,6 +2528,7 @@ CSR_API(CsrHardwareStateProperty) break; case CONSOLE_HARDWARE_STATE_SET: + DbgPrint( "Setting console hardware state.\n" ); Reply->Status = SetConsoleHardwareState (Console, Request->Data.ConsoleHardwareStateRequest.State); break; diff --git a/reactos/subsys/csrss/api/wapi.c b/reactos/subsys/csrss/api/wapi.c index b55a1344c90..a041d365bdb 100644 --- a/reactos/subsys/csrss/api/wapi.c +++ b/reactos/subsys/csrss/api/wapi.c @@ -1,4 +1,4 @@ -/* $Id: wapi.c,v 1.28 2003/03/09 21:42:47 hbirr Exp $ +/* $Id: wapi.c,v 1.29 2003/07/29 23:03:01 jimtabor Exp $ * * reactos/subsys/csrss/api/wapi.c * @@ -68,6 +68,7 @@ static const CsrFunc CsrFuncs[] = { CsrCloseHandle, CsrVerifyHandle, CsrDuplicateHandle, + CsrHardwareStateProperty, 0 }; static void Thread_Api2(HANDLE ServerPort) diff --git a/reactos/subsys/win32k/ldr/loader.c b/reactos/subsys/win32k/ldr/loader.c index eab837173c3..d33ff4c25e4 100644 --- a/reactos/subsys/win32k/ldr/loader.c +++ b/reactos/subsys/win32k/ldr/loader.c @@ -16,13 +16,77 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: loader.c,v 1.11 2003/07/11 15:59:37 royce Exp $ +/* $Id: loader.c,v 1.12 2003/07/29 23:03:01 jimtabor Exp $ * */ #include #include +/* + * Blatantly stolen from ldr/utils.c in ntdll. I can't link ntdll from + * here, though. + */ +NTSTATUS STDCALL +LdrGetProcedureAddress (IN PVOID BaseAddress, + IN PANSI_STRING Name, + IN ULONG Ordinal, + OUT PVOID *ProcedureAddress) +{ + PIMAGE_EXPORT_DIRECTORY ExportDir; + PUSHORT OrdinalPtr; + PULONG NamePtr; + PULONG AddressPtr; + ULONG i = 0; + + DbgPrint("LdrGetProcedureAddress (BaseAddress %x Name %Z Ordinal %lu ProcedureAddress %x)\n", + BaseAddress, Name, Ordinal, ProcedureAddress); + + /* Get the pointer to the export directory */ + ExportDir = (PIMAGE_EXPORT_DIRECTORY) + RtlImageDirectoryEntryToData (BaseAddress, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &i); + + DbgPrint("ExportDir %x i %lu\n", ExportDir, i); + + if (!ExportDir || !i || !ProcedureAddress) + { + return STATUS_INVALID_PARAMETER; + } + + AddressPtr = (PULONG)((ULONG)BaseAddress + (ULONG)ExportDir->AddressOfFunctions); + if (Name && Name->Length) + { + /* by name */ + OrdinalPtr = (PUSHORT)((ULONG)BaseAddress + (ULONG)ExportDir->AddressOfNameOrdinals); + NamePtr = (PULONG)((ULONG)BaseAddress + (ULONG)ExportDir->AddressOfNames); + for( i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++) + { + if (!_strnicmp(Name->Buffer, (char*)(BaseAddress + *NamePtr), Name->Length)) + { + *ProcedureAddress = (PVOID)((ULONG)BaseAddress + (ULONG)AddressPtr[*OrdinalPtr]); + return STATUS_SUCCESS; + } + } + DbgPrint("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name); + } + else + { + /* by ordinal */ + Ordinal &= 0x0000FFFF; + if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions) + { + *ProcedureAddress = (PVOID)((ULONG)BaseAddress + (ULONG)AddressPtr[Ordinal - ExportDir->Base]); + return STATUS_SUCCESS; + } + DbgPrint("LdrGetProcedureAddress: Can't resolve symbol @%d\n", Ordinal); + } + + return STATUS_PROCEDURE_NOT_FOUND; +} + /* * @implemented */ @@ -60,4 +124,52 @@ EngLoadModule(LPWSTR ModuleName) return (HANDLE)GdiDriverInfo.ModuleBase; } +/* + * This is copied from ntdll... It's needed for loading keyboard dlls. + */ + +PVOID +STDCALL +RtlImageDirectoryEntryToData ( + PVOID BaseAddress, + BOOLEAN bFlag, + ULONG Directory, + PULONG Size + ) +{ + PIMAGE_NT_HEADERS NtHeader; + PIMAGE_SECTION_HEADER SectionHeader; + ULONG Va; + ULONG Count; + + NtHeader = RtlImageNtHeader (BaseAddress); + if (NtHeader == NULL) + return NULL; + + if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes) + return NULL; + + Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress; + if (Va == 0) + return NULL; + + if (Size) + *Size = NtHeader->OptionalHeader.DataDirectory[Directory].Size; + + if (bFlag) + return (PVOID)(BaseAddress + Va); + + /* image mapped as ordinary file, we must find raw pointer */ + SectionHeader = (PIMAGE_SECTION_HEADER)(NtHeader + 1); + Count = NtHeader->FileHeader.NumberOfSections; + while (Count--) + { + if (SectionHeader->VirtualAddress == Va) + return (PVOID)(BaseAddress + SectionHeader->PointerToRawData); + SectionHeader++; + } + + return NULL; +} + /* EOF */ diff --git a/reactos/subsys/win32k/ntuser/input.c b/reactos/subsys/win32k/ntuser/input.c index 75918439953..1d729f8fd0c 100644 --- a/reactos/subsys/win32k/ntuser/input.c +++ b/reactos/subsys/win32k/ntuser/input.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: input.c,v 1.8 2003/07/05 16:04:01 chorns Exp $ +/* $Id: input.c,v 1.9 2003/07/29 23:03:01 jimtabor Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -108,6 +108,10 @@ KeyboardThreadMain(PVOID StartContext) sizeof(KEY_EVENT_RECORD), NULL, NULL); + DbgPrint( "KeyRaw: %s %04x\n", + KeyEvent.bKeyDown ? "down" : "up", + KeyEvent.wVirtualScanCode ); + if (Status == STATUS_ALERTED && !InputThreadsRunning) { break; @@ -119,6 +123,7 @@ KeyboardThreadMain(PVOID StartContext) } SysKey = KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED); + DbgPrint( "Key: %s\n", KeyEvent.bKeyDown ? "down" : "up" ); /* * Post a keyboard message. @@ -157,9 +162,7 @@ KeyboardThreadMain(PVOID StartContext) { lParam |= (1 << 29); /* Context mode. 1 if ALT if pressed while the key is pressed */ } - - - MsqPostKeyboardMessage(SysKey ? WM_SYSKEYDOWN : WM_KEYDOWN, KeyEvent.wVirtualKeyCode, + MsqPostKeyboardMessage(SysKey ? WM_SYSKEYUP : WM_KEYUP, KeyEvent.wVirtualKeyCode, lParam); } } diff --git a/reactos/subsys/win32k/ntuser/keyboard.c b/reactos/subsys/win32k/ntuser/keyboard.c index 06bb208f23a..ddd93f4e361 100644 --- a/reactos/subsys/win32k/ntuser/keyboard.c +++ b/reactos/subsys/win32k/ntuser/keyboard.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: keyboard.c,v 1.5 2003/07/20 05:32:19 jimtabor Exp $ +/* $Id: keyboard.c,v 1.6 2003/07/29 23:03:01 jimtabor Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -43,9 +44,11 @@ #define NDEBUG #include -/* FUNCTIONS *****************************************************************/ - +DWORD ModBits = 0; BYTE QueueKeyStateTable[256]; +static PVOID pkKeyboardLayout = 0; + +/* arty -- These should be phased out for the general kbdxx.dll tables */ struct accent_char { @@ -164,35 +167,225 @@ static const struct accent_char accent_chars[] = /* {'.', 'I', '\335'}, {'.', 'i', '\375'}, */ /* dot above */ }; +/* FUNCTIONS *****************************************************************/ + +/*** Statics used by TranslateMessage ***/ + +static VOID STDCALL SetKeyState(DWORD key, BOOL down) { + if( key >= 'a' && key <= 'z' ) key += 'A' - 'a'; + QueueKeyStateTable[key] = down; +} + +static BOOL SetModKey( PKBDTABLES pkKT, WORD wVK, BOOL down ) { + int i; + + for( i = 0; pkKT->pCharModifiers->pVkToBit[i].Vk; i++ ) { + DbgPrint( "vk[%d] = { %04x, %x }\n", i, + pkKT->pCharModifiers->pVkToBit[i].Vk, + pkKT->pCharModifiers->pVkToBit[i].ModBits ); + if( pkKT->pCharModifiers->pVkToBit[i].Vk == wVK ) { + if( down ) ModBits |= pkKT->pCharModifiers->pVkToBit[i].ModBits; + else ModBits &= ~pkKT->pCharModifiers->pVkToBit[i].ModBits; + DbgPrint( "ModBits: %x\n", ModBits ); + return TRUE; + } + } + + return FALSE; +} + +static BOOL TryToTranslateChar( WORD wVirtKey, + PVK_TO_WCHAR_TABLE vtwTbl, + DWORD ModBits, + PBOOL pbDead, + PBOOL pbLigature, + PWCHAR pwcTranslatedChar ) { + int i,j; + size_t size_this_entry = vtwTbl->cbSize; + int nStates = vtwTbl->nModifications; + PVK_TO_WCHARS10 vkPtr; + + for( i = 0;; i++ ) { + vkPtr = (PVK_TO_WCHARS10) + (((BYTE *)vtwTbl->pVkToWchars) + i * size_this_entry); + + if( !vkPtr->VirtualKey ) return FALSE; + if( wVirtKey == vkPtr->VirtualKey ) { + for( j = 0; j < nStates; j++ ) { + if( j == ModBits ) { /* OK, we found a wchar with the correct + shift state and vk */ + *pbDead = vkPtr->wch[j] == WCH_DEAD; + *pbLigature = vkPtr->wch[j] == WCH_LGTR; + *pwcTranslatedChar = vkPtr->wch[j]; + if( *pbDead ) { + i++; + vkPtr = (PVK_TO_WCHARS10) + (((BYTE *)vtwTbl->pVkToWchars) + i * size_this_entry); + if( vkPtr->VirtualKey != 0xff ) { + DPRINT( "Found dead key with no trailer in the table.\n" ); + DPRINT( "VK: %04x, ADDR: %08x\n", wVirtKey, (int)vkPtr ); + return FALSE; + } + *pwcTranslatedChar = vkPtr->wch[j]; + } + return TRUE; + } + } + } + } +} + +static int STDCALL -ToUnicode(UINT wVirtKey, - UINT wScanCode, - PBYTE lpKeyState, - LPWSTR pwszBuff, - int cchBuff, - UINT wFlags) +ToUnicodeInner(UINT wVirtKey, + UINT wScanCode, + PBYTE lpKeyState, + LPWSTR pwszBuff, + int cchBuff, + UINT wFlags, + DWORD ModBits, + PKBDTABLES pkKT) { - return(0); + int i; + + DbgPrint("wVirtKey=%08x, wScanCode=%08x, lpKeyState=[], " + "pwszBuff=%S, cchBuff=%d, wFlags=%x\n", + wVirtKey, wScanCode, /* lpKeyState, */ pwszBuff, + cchBuff, wFlags ); + + for( i = 0; pkKT->pVkToWcharTable[i].nModifications; i++ ) { + WCHAR wcTranslatedChar; + BOOL bDead; + BOOL bLigature; + + if( TryToTranslateChar( wVirtKey, + &pkKT->pVkToWcharTable[i], + ModBits, + &bDead, + &bLigature, + &wcTranslatedChar ) ) { + if( bLigature ) { + DPRINT("Not handling ligature (yet)\n" ); + return 0; + } + + if( cchBuff > 0 ) pwszBuff[0] = wcTranslatedChar; + + if( bDead ) return -1; + else return 1; + } + } + + return 0; +} + +DWORD +STDCALL +NtUserGetKeyState( + DWORD key) +{ + DWORD ret; + + if (key >= 'a' && key <= 'z') key += 'A' - 'a'; + ret = ((DWORD)(QueueKeyStateTable[key] & 0x80) << 8 ) | + (QueueKeyStateTable[key] & 0x80) | + (QueueKeyStateTable[key] & 0x01); + return ret; +} + +int STDCALL ToUnicode( UINT wVirtKey, + UINT wScanCode, + PBYTE lpKeyState, + LPWSTR pwszBuff, + int cchBuff, + UINT wFlags ) { + return ToUnicodeInner( wVirtKey, + wScanCode, + QueueKeyStateTable, + pwszBuff, + cchBuff, + wFlags, + ModBits, + pkKeyboardLayout ); +} + +typedef PVOID (*KbdLayerDescriptor)(VOID); +NTSTATUS STDCALL LdrGetProcedureAddress(PVOID module, + PANSI_STRING import_name, + DWORD flags, + PVOID *func_addr); + +void InitKbdLayout( PVOID *pkKeyboardLayout ) { + HMODULE kbModule = 0; + ANSI_STRING kbdProcedureName; + NTSTATUS Status; + + KbdLayerDescriptor layerDescGetFn; + + kbModule = EngLoadImage(L"\\SystemRoot\\system32\\kbdus.dll"); + + if( !kbModule ) { + DbgPrint( "Foo: No kbdus.dll\n" ); + return; + } + + RtlInitAnsiString( &kbdProcedureName, "KbdLayerDescriptor" ); + LdrGetProcedureAddress((PVOID)kbModule, + &kbdProcedureName, + 0, + &layerDescGetFn); + if( layerDescGetFn ) { + *pkKeyboardLayout = layerDescGetFn(); + } } BOOL STDCALL NtUserTranslateMessage(LPMSG lpMsg, - DWORD Unknown1) + DWORD Unknown1) /* Used to pass the kbd layout */ { - LONG UState; - WCHAR wp[2]; - MSG NewMsg; - static INT dead_char; + static INT dead_char = 0; + LONG UState = 0; + WCHAR wp[2] = { 0 }; + MSG NewMsg = { 0 }; PUSER_MESSAGE UMsg; + /* FIXME: Should pass current keyboard layout for this thread. */ + /* At the moment, the keyboard layout is global. */ + /* Also, we're fixed at kbdus.dll ... */ + if( !pkKeyboardLayout ) InitKbdLayout( &pkKeyboardLayout ); + if( !pkKeyboardLayout ) { + DbgPrint( "Not Translating due to empty layout.\n" ); + return FALSE; + } + if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN) { + if (lpMsg->message == WM_KEYUP) { + DbgPrint( "About to SetKeyState( %04x, FALSE );\n", lpMsg->wParam ); + SetKeyState( lpMsg->wParam, FALSE ); /* Release key */ + DbgPrint( "About to SetModKey();\n" ); + SetModKey( pkKeyboardLayout, lpMsg->wParam, FALSE ); + /* Release Mod if any */ + DbgPrint( "Done with keys.\n" ); + } return(FALSE); } - /* FIXME: Should pass current keyboard layout for this thread. */ - UState = ToUnicode(lpMsg->wParam, HIWORD(lpMsg->lParam), - QueueKeyStateTable, wp, 2, 0); + DbgPrint( "About to SetKeyState( %04x, TRUE );\n", lpMsg->wParam ); + SetKeyState( lpMsg->wParam, TRUE ); /* Strike key */ + + /* Pass 1: Search for modifiers */ + DbgPrint( "About to SetModKey();\n" ); + if( SetModKey( pkKeyboardLayout, lpMsg->wParam, TRUE ) ) return TRUE; + DbgPrint( "Done with keys.\n" ); + + /* Pass 2: Get Unicode Character */ + DbgPrint( "Calling ToUnicodeString()\n" ); + UState = ToUnicodeInner(lpMsg->wParam, HIWORD(lpMsg->lParam), + QueueKeyStateTable, wp, 2, 0, ModBits, + pkKeyboardLayout); + + DbgPrint( "UState is %d after key %04x\n", UState, wp[0] ); if (UState == 1) { NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR; @@ -218,13 +411,14 @@ NtUserTranslateMessage(LPMSG lpMsg, } dead_char = 0; } - NewMsg.hwnd = lpMsg->hwnd; - NewMsg.wParam = wp[0]; - NewMsg.lParam = lpMsg->lParam; - UMsg = MsqCreateMessage(&NewMsg); - MsqPostMessage(PsGetWin32Thread()->MessageQueue, UMsg); - return(TRUE); - } + } + NewMsg.hwnd = lpMsg->hwnd; + NewMsg.wParam = wp[0]; + NewMsg.lParam = lpMsg->lParam; + UMsg = MsqCreateMessage(&NewMsg); + DbgPrint( "CHAR='%c' %04x %08x\n", wp[0], wp[0], lpMsg->lParam ); + MsqPostMessage(PsGetWin32Thread()->MessageQueue, UMsg); + return(TRUE); } else if (UState == -1) { @@ -247,21 +441,6 @@ NtUserSetFocus(HWND hWnd) return W32kSetFocusWindow(hWnd); } - -DWORD -STDCALL -NtUserGetKeyState( - DWORD key) -{ -DWORD ret; - - if (key >= 'a' && key <= 'z') key += 'A' - 'a'; - ret = ((DWORD)(QueueKeyStateTable[key] & 0x80) << 8 ) | - (QueueKeyStateTable[key] & 0x80) | - (QueueKeyStateTable[key] & 0x01); - return ret; -} - DWORD STDCALL NtUserGetKeyboardState(