Adding Art Yerkes Keyboard Testing Code

svn path=/trunk/; revision=5323
This commit is contained in:
James Tabor 2003-07-29 23:03:01 +00:00
parent 9b70e2debd
commit bf7329e25b
7 changed files with 476 additions and 51 deletions

View file

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

View file

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

View file

@ -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;
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,12 +2509,14 @@ 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)
{
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;

View file

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

View file

@ -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 <ddk/ntddk.h>
#include <ddk/winddi.h>
/*
* 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 */

View file

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

View file

@ -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 <ddk/ntddk.h>
#include <win32k/win32k.h>
#include <internal/safe.h>
#include <internal/kbd.h>
#include <include/guicheck.h>
#include <include/msgqueue.h>
#include <include/window.h>
@ -43,9 +44,11 @@
#define NDEBUG
#include <debug.h>
/* 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,
ToUnicodeInner(UINT wVirtKey,
UINT wScanCode,
PBYTE lpKeyState,
LPWSTR pwszBuff,
int cchBuff,
UINT wFlags)
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,14 +411,15 @@ NtUserTranslateMessage(LPMSG lpMsg,
}
dead_char = 0;
}
}
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)
{
NewMsg.message =
@ -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(