mirror of
https://github.com/reactos/reactos.git
synced 2025-04-21 20:50:29 +00:00
Adding Art Yerkes Keyboard Testing Code
svn path=/trunk/; revision=5323
This commit is contained in:
parent
9b70e2debd
commit
bf7329e25b
7 changed files with 476 additions and 51 deletions
|
@ -9,7 +9,7 @@ include $(PATH_TO_TOP)/rules.mak
|
||||||
|
|
||||||
# Console system utilities
|
# Console system utilities
|
||||||
# cabman cat net objdir partinfo pice ps sc stats
|
# 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 =
|
UTIL_NET_APPS =
|
||||||
|
|
||||||
|
|
111
reactos/ntoskrnl/include/internal/kbd.h
Normal file
111
reactos/ntoskrnl/include/internal/kbd.h
Normal 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
|
|
@ -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
|
* reactos/subsys/csrss/api/conio.c
|
||||||
*
|
*
|
||||||
|
@ -33,6 +33,7 @@ static HANDLE KeyboardDeviceHandle;
|
||||||
static PCSRSS_CONSOLE ActiveConsole;
|
static PCSRSS_CONSOLE ActiveConsole;
|
||||||
CRITICAL_SECTION ActiveConsoleLock;
|
CRITICAL_SECTION ActiveConsoleLock;
|
||||||
static COORD PhysicalConsoleSize;
|
static COORD PhysicalConsoleSize;
|
||||||
|
static BOOL KeyReadInhibit = FALSE;
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
@ -926,8 +927,12 @@ VOID Console_Api( DWORD RefreshEvent )
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
KeyEventRecord->InputEvent.EventType = KEY_EVENT;
|
KeyEventRecord->InputEvent.EventType = KEY_EVENT;
|
||||||
|
if( !KeyReadInhibit ) {
|
||||||
Status = NtReadFile( KeyboardDeviceHandle, Events[0], NULL, NULL, &Iosb,
|
Status = NtReadFile( KeyboardDeviceHandle, Events[0], NULL, NULL, &Iosb,
|
||||||
&KeyEventRecord->InputEvent.Event.KeyEvent, sizeof( KEY_EVENT_RECORD ), NULL, 0 );
|
&KeyEventRecord->InputEvent.Event.KeyEvent, sizeof( KEY_EVENT_RECORD ), NULL, 0 );
|
||||||
|
} else {
|
||||||
|
Status = STATUS_PENDING;
|
||||||
|
}
|
||||||
if( !NT_SUCCESS( Status ) )
|
if( !NT_SUCCESS( Status ) )
|
||||||
{
|
{
|
||||||
DbgPrint( "CSR: ReadFile on keyboard device failed\n" );
|
DbgPrint( "CSR: ReadFile on keyboard device failed\n" );
|
||||||
|
@ -2462,9 +2467,20 @@ CSR_API(CsrWriteConsoleInput)
|
||||||
*/
|
*/
|
||||||
static NTSTATUS FASTCALL SetConsoleHardwareState (PCSRSS_CONSOLE Console, DWORD ConsoleHwState)
|
static NTSTATUS FASTCALL SetConsoleHardwareState (PCSRSS_CONSOLE Console, DWORD ConsoleHwState)
|
||||||
{
|
{
|
||||||
|
DbgPrint( "Console Hardware State: %d\n", ConsoleHwState );
|
||||||
|
|
||||||
if ( (CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState)
|
if ( (CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState)
|
||||||
||(CONSOLE_HARDWARE_STATE_DIRECT == 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)
|
if (Console->HardwareState != ConsoleHwState)
|
||||||
{
|
{
|
||||||
/* TODO: implement switching from full screen to windowed mode */
|
/* TODO: implement switching from full screen to windowed mode */
|
||||||
|
@ -2493,12 +2509,14 @@ CSR_API(CsrHardwareStateProperty)
|
||||||
);
|
);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
DbgPrint( "Failed to get console handle in SetConsoleHardwareState\n" );
|
||||||
Reply->Status = Status;
|
Reply->Status = Status;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(Console->Header.Type != CSRSS_CONSOLE_MAGIC)
|
if(Console->Header.Type != CSRSS_CONSOLE_MAGIC)
|
||||||
{
|
{
|
||||||
|
DbgPrint( "Bad magic on Console: %08x\n", Console->Header.Type );
|
||||||
Reply->Status = STATUS_INVALID_HANDLE;
|
Reply->Status = STATUS_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2510,6 +2528,7 @@ CSR_API(CsrHardwareStateProperty)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CONSOLE_HARDWARE_STATE_SET:
|
case CONSOLE_HARDWARE_STATE_SET:
|
||||||
|
DbgPrint( "Setting console hardware state.\n" );
|
||||||
Reply->Status = SetConsoleHardwareState (Console, Request->Data.ConsoleHardwareStateRequest.State);
|
Reply->Status = SetConsoleHardwareState (Console, Request->Data.ConsoleHardwareStateRequest.State);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -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
|
* reactos/subsys/csrss/api/wapi.c
|
||||||
*
|
*
|
||||||
|
@ -68,6 +68,7 @@ static const CsrFunc CsrFuncs[] = {
|
||||||
CsrCloseHandle,
|
CsrCloseHandle,
|
||||||
CsrVerifyHandle,
|
CsrVerifyHandle,
|
||||||
CsrDuplicateHandle,
|
CsrDuplicateHandle,
|
||||||
|
CsrHardwareStateProperty,
|
||||||
0 };
|
0 };
|
||||||
|
|
||||||
static void Thread_Api2(HANDLE ServerPort)
|
static void Thread_Api2(HANDLE ServerPort)
|
||||||
|
|
|
@ -16,13 +16,77 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* 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/ntddk.h>
|
||||||
#include <ddk/winddi.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
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
@ -60,4 +124,52 @@ EngLoadModule(LPWSTR ModuleName)
|
||||||
return (HANDLE)GdiDriverInfo.ModuleBase;
|
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 */
|
/* EOF */
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* 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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -108,6 +108,10 @@ KeyboardThreadMain(PVOID StartContext)
|
||||||
sizeof(KEY_EVENT_RECORD),
|
sizeof(KEY_EVENT_RECORD),
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
DbgPrint( "KeyRaw: %s %04x\n",
|
||||||
|
KeyEvent.bKeyDown ? "down" : "up",
|
||||||
|
KeyEvent.wVirtualScanCode );
|
||||||
|
|
||||||
if (Status == STATUS_ALERTED && !InputThreadsRunning)
|
if (Status == STATUS_ALERTED && !InputThreadsRunning)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -119,6 +123,7 @@ KeyboardThreadMain(PVOID StartContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
SysKey = KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED);
|
SysKey = KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED);
|
||||||
|
DbgPrint( "Key: %s\n", KeyEvent.bKeyDown ? "down" : "up" );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Post a keyboard message.
|
* 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 */
|
lParam |= (1 << 29); /* Context mode. 1 if ALT if pressed while the key is pressed */
|
||||||
}
|
}
|
||||||
|
MsqPostKeyboardMessage(SysKey ? WM_SYSKEYUP : WM_KEYUP, KeyEvent.wVirtualKeyCode,
|
||||||
|
|
||||||
MsqPostKeyboardMessage(SysKey ? WM_SYSKEYDOWN : WM_KEYDOWN, KeyEvent.wVirtualKeyCode,
|
|
||||||
lParam);
|
lParam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* 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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -32,6 +32,7 @@
|
||||||
#include <ddk/ntddk.h>
|
#include <ddk/ntddk.h>
|
||||||
#include <win32k/win32k.h>
|
#include <win32k/win32k.h>
|
||||||
#include <internal/safe.h>
|
#include <internal/safe.h>
|
||||||
|
#include <internal/kbd.h>
|
||||||
#include <include/guicheck.h>
|
#include <include/guicheck.h>
|
||||||
#include <include/msgqueue.h>
|
#include <include/msgqueue.h>
|
||||||
#include <include/window.h>
|
#include <include/window.h>
|
||||||
|
@ -43,9 +44,11 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
DWORD ModBits = 0;
|
||||||
|
|
||||||
BYTE QueueKeyStateTable[256];
|
BYTE QueueKeyStateTable[256];
|
||||||
|
static PVOID pkKeyboardLayout = 0;
|
||||||
|
|
||||||
|
/* arty -- These should be phased out for the general kbdxx.dll tables */
|
||||||
|
|
||||||
struct accent_char
|
struct accent_char
|
||||||
{
|
{
|
||||||
|
@ -164,35 +167,225 @@ static const struct accent_char accent_chars[] =
|
||||||
/* {'.', 'I', '\335'}, {'.', 'i', '\375'}, */ /* dot above */
|
/* {'.', '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
|
int STDCALL
|
||||||
ToUnicode(UINT wVirtKey,
|
ToUnicodeInner(UINT wVirtKey,
|
||||||
UINT wScanCode,
|
UINT wScanCode,
|
||||||
PBYTE lpKeyState,
|
PBYTE lpKeyState,
|
||||||
LPWSTR pwszBuff,
|
LPWSTR pwszBuff,
|
||||||
int cchBuff,
|
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
|
BOOL STDCALL
|
||||||
NtUserTranslateMessage(LPMSG lpMsg,
|
NtUserTranslateMessage(LPMSG lpMsg,
|
||||||
DWORD Unknown1)
|
DWORD Unknown1) /* Used to pass the kbd layout */
|
||||||
{
|
{
|
||||||
LONG UState;
|
static INT dead_char = 0;
|
||||||
WCHAR wp[2];
|
LONG UState = 0;
|
||||||
MSG NewMsg;
|
WCHAR wp[2] = { 0 };
|
||||||
static INT dead_char;
|
MSG NewMsg = { 0 };
|
||||||
PUSER_MESSAGE UMsg;
|
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_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);
|
return(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Should pass current keyboard layout for this thread. */
|
DbgPrint( "About to SetKeyState( %04x, TRUE );\n", lpMsg->wParam );
|
||||||
UState = ToUnicode(lpMsg->wParam, HIWORD(lpMsg->lParam),
|
SetKeyState( lpMsg->wParam, TRUE ); /* Strike key */
|
||||||
QueueKeyStateTable, wp, 2, 0);
|
|
||||||
|
/* 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)
|
if (UState == 1)
|
||||||
{
|
{
|
||||||
NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
|
NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
|
||||||
|
@ -218,14 +411,15 @@ NtUserTranslateMessage(LPMSG lpMsg,
|
||||||
}
|
}
|
||||||
dead_char = 0;
|
dead_char = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
NewMsg.hwnd = lpMsg->hwnd;
|
NewMsg.hwnd = lpMsg->hwnd;
|
||||||
NewMsg.wParam = wp[0];
|
NewMsg.wParam = wp[0];
|
||||||
NewMsg.lParam = lpMsg->lParam;
|
NewMsg.lParam = lpMsg->lParam;
|
||||||
UMsg = MsqCreateMessage(&NewMsg);
|
UMsg = MsqCreateMessage(&NewMsg);
|
||||||
|
DbgPrint( "CHAR='%c' %04x %08x\n", wp[0], wp[0], lpMsg->lParam );
|
||||||
MsqPostMessage(PsGetWin32Thread()->MessageQueue, UMsg);
|
MsqPostMessage(PsGetWin32Thread()->MessageQueue, UMsg);
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (UState == -1)
|
else if (UState == -1)
|
||||||
{
|
{
|
||||||
NewMsg.message =
|
NewMsg.message =
|
||||||
|
@ -247,21 +441,6 @@ NtUserSetFocus(HWND hWnd)
|
||||||
return W32kSetFocusWindow(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
|
DWORD
|
||||||
STDCALL
|
STDCALL
|
||||||
NtUserGetKeyboardState(
|
NtUserGetKeyboardState(
|
||||||
|
|
Loading…
Reference in a new issue