Keyboard sync between gui and text modes, patch by Art Yerkes and

Hartmut Birr

svn path=/trunk/; revision=6271
This commit is contained in:
Gé van Geldorp 2003-10-09 06:13:05 +00:00
parent 511fc18181
commit 3f52e9d728
20 changed files with 1027 additions and 620 deletions

View file

@ -8360,8 +8360,7 @@ ToAsciiEx(
int
STDCALL
ToUnicode(
UINT wVirtKey,
ToUnicode(UINT wVirtKey,
UINT wScanCode,
PBYTE lpKeyState,
LPWSTR pwszBuff,

View file

@ -6,6 +6,7 @@ typedef struct _W32THREAD
PVOID MessageQueue;
FAST_MUTEX WindowListLock;
LIST_ENTRY WindowListHead;
struct _KBDTABLES* KeyboardLayout;
struct _DESKTOP_OBJECT* Desktop;
} __attribute__((packed)) W32THREAD, *PW32THREAD;
@ -15,6 +16,7 @@ typedef struct _W32PROCESS
LIST_ENTRY ClassListHead;
FAST_MUTEX MenuListLock;
LIST_ENTRY MenuListHead;
struct _KBDTABLES* KeyboardLayout;
struct _WINSTATION_OBJECT* WindowStation;
} W32PROCESS, *PW32PROCESS;

View file

@ -156,6 +156,7 @@ NtUserCallNextHookEx(
DWORD Unknown2,
DWORD Unknown3);
#define NOPARAM_ROUTINE_REGISTER_PRIMITIVE 0xffff0001 /* Private ROS */
DWORD
STDCALL
NtUserCallNoParam(
@ -745,10 +746,7 @@ NtUserGetKeyboardState(
DWORD
STDCALL
NtUserGetKeyNameText(
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2);
NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize );
DWORD
STDCALL
@ -999,13 +997,12 @@ DWORD
STDCALL
NtUserLockWorkStation(VOID);
DWORD
UINT
STDCALL
NtUserMapVirtualKeyEx(
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3);
NtUserMapVirtualKeyEx( UINT keyCode,
UINT transType,
DWORD keyboardId,
HKL dwhkl );
BOOL
STDCALL
@ -1652,16 +1649,16 @@ NtUserThunkedMenuItemInfo(
LPMENUITEMINFOW lpmii,
PUNICODE_STRING lpszCaption);
DWORD
int
STDCALL
NtUserToUnicodeEx(
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3,
DWORD Unknown4,
DWORD Unknown5,
DWORD Unknown6);
UINT wVirtKey,
UINT wScanCode,
PBYTE lpKeyState,
LPWSTR pwszBuff,
int cchBuff,
UINT wFlags,
HKL dwhkl );
DWORD
STDCALL
@ -1689,7 +1686,7 @@ BOOL
STDCALL
NtUserTranslateMessage(
LPMSG lpMsg,
DWORD Unknown1);
HKL dwhkl );
DWORD
STDCALL

View file

@ -80,10 +80,10 @@ ROSDATA USHORT scancode_to_vk[] = {
/* - 0f - */
/* First Letters Row */
VK_TAB, 'Q', 'W', 'E',
'R', 'T', 'U', 'I',
'O', 'P',
'R', 'T', 'Y', 'U',
'I', 'O', 'P',
VK_OEM_4, VK_OEM_6, VK_RETURN,
/* - 1c - */
/* - 1d - */
/* Second Letters Row */
VK_LCONTROL,
'A', 'S', 'D', 'F',
@ -95,11 +95,9 @@ ROSDATA USHORT scancode_to_vk[] = {
'Z', 'X', 'C', 'V',
'B', 'N', 'M', VK_OEM_COMMA,
VK_OEM_PERIOD,VK_OEM_2, VK_RSHIFT,
/* - 35 - */
/* - 37 - */
/* Bottom Row */
VK_EMPTY, VK_RSHIFT | KEXT,
VK_MULTIPLY, VK_LMENU,
' ', VK_CAPITAL,
VK_MULTIPLY, VK_LMENU, VK_SPACE, VK_CAPITAL,
/* - 3b - */
/* F-Keys */
@ -153,8 +151,6 @@ ROSDATA VSC_VK extcode1_to_vk[] = {
{ 0, 0 },
};
#define VK_ALT
ROSDATA VK_TO_BIT modifier_keys[] = {
{ VK_SHIFT, KSHIFT },
{ VK_CONTROL, KCTRL },
@ -164,8 +160,8 @@ ROSDATA VK_TO_BIT modifier_keys[] = {
typedef struct _mymod {
PVOID mod_keys;
int maxmod;
int mod_max[4];
WORD maxmod;
BYTE mod_max[4];
} INTERNAL_KBD_MODIFIERS;
ROSDATA INTERNAL_KBD_MODIFIERS modifier_bits[] = {
@ -285,7 +281,7 @@ ROSDATA VK_TO_WCHAR_TABLE vk_to_wchar_master_table[] = {
};
ROSDATA VSC_LPWSTR key_names[] = {
{ 0x00, L"Error" },
{ 0x00, L"" },
{ 0x01, L"Esc" },
{ 0x0e, L"Backspace" },
{ 0x0f, L"Tab" },
@ -369,7 +365,7 @@ ROSDATA VSC_LPWSTR extended_key_names[] = {
/* Finally, the master table */
ROSDATA KBDTABLES keyboard_layout_table = {
/* modifier assignments */
(PMODIFIERS)modifier_bits,
(PMODIFIERS)&modifier_bits,
/* character from vk tables */
vk_to_wchar_master_table,

View file

@ -1,4 +1,4 @@
/* $Id: isbad.c,v 1.7 2003/07/10 18:50:51 chorns Exp $
/* $Id: isbad.c,v 1.8 2003/10/09 06:13:04 gvg Exp $
*
* lib/kernel32/mem/isbad.c
*
@ -28,7 +28,7 @@ wcsnlen (
/* FIXME: Stubs. What is it for? */
/*
* @unimplemented
* @implemented
*/
UINT
strnlen (
@ -36,9 +36,9 @@ strnlen (
UINT uiMax
)
{
DPRINT1("strnlen stub called\n");
return 0;
UINT i = 0;
while( lpsz[i] && i < uiMax ) i++;
return i;
}
/* --- --- --- */

View file

@ -10,6 +10,7 @@
typedef struct _USER32_THREAD_DATA
{
MSG LastMessage;
HKL KeyboardLayoutHandle;
} USER32_THREAD_DATA, *PUSER32_THREAD_DATA;
PUSER32_THREAD_DATA User32GetThreadData();

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.18 2003/09/12 12:54:26 weiden Exp $
/* $Id: input.c,v 1.19 2003/10/09 06:13:04 gvg Exp $
*
* PROJECT: ReactOS user32.dll
* FILE: lib/user32/windows/input.c
@ -31,6 +31,7 @@
#include <windows.h>
#include <user32.h>
#include <debug.h>
#include <wchar.h>
/* FUNCTIONS *****************************************************************/
@ -134,33 +135,47 @@ GetKBCodePage(VOID)
/*
* @unimplemented
* @implemented
*/
int STDCALL
GetKeyNameTextA(LONG lParam,
LPSTR lpString,
int nSize)
{
UNIMPLEMENTED;
return 0;
LPWSTR intermediateString =
HeapAlloc(GetProcessHeap(),0,nSize * sizeof(WCHAR));
int ret = 0;
UINT wstrLen = 0;
BOOL defChar = FALSE;
if( !intermediateString ) return 0;
ret = GetKeyNameTextW(lParam,intermediateString,nSize);
if( ret == 0 ) { lpString[0] = 0; return 0; }
wstrLen = wcslen( intermediateString );
ret = WideCharToMultiByte(CP_ACP, 0,
intermediateString, wstrLen,
lpString, nSize, ".", &defChar );
lpString[ret] = 0;
HeapFree(GetProcessHeap(),0,intermediateString);
return ret;
}
/*
* @unimplemented
* @implemented
*/
int STDCALL
GetKeyNameTextW(LONG lParam,
LPWSTR lpString,
int nSize)
{
UNIMPLEMENTED;
return 0;
return NtUserGetKeyNameText( lParam, lpString, nSize );
}
/*
* @unimplemented
* @implemented
*/
SHORT STDCALL
GetKeyState(int nVirtKey)
@ -261,52 +276,48 @@ LoadKeyboardLayoutW(LPCWSTR pwszKLID,
/*
* @unimplemented
* @implemented
*/
UINT STDCALL
MapVirtualKeyA(UINT uCode,
UINT uMapType)
{
UNIMPLEMENTED;
return 0;
return MapVirtualKeyExA( uCode, uMapType, GetKeyboardLayout( 0 ) );
}
/*
* @unimplemented
* @implemented
*/
UINT STDCALL
MapVirtualKeyExA(UINT uCode,
UINT uMapType,
HKL dwhkl)
{
UNIMPLEMENTED;
return 0;
return MapVirtualKeyExW( uCode, uMapType, dwhkl );
}
/*
* @unimplemented
* @implemented
*/
UINT STDCALL
MapVirtualKeyExW(UINT uCode,
UINT uMapType,
HKL dwhkl)
{
UNIMPLEMENTED;
return 0;
return NtUserMapVirtualKeyEx( uCode, uMapType, 0, dwhkl );
}
/*
* @unimplemented
* @implemented
*/
UINT STDCALL
MapVirtualKeyW(UINT uCode,
UINT uMapType)
{
UNIMPLEMENTED;
return 0;
return MapVirtualKeyExW( uCode, uMapType, GetKeyboardLayout( 0 ) );
}
@ -401,7 +412,7 @@ ToAsciiEx(UINT uVirtKey,
/*
* @unimplemented
* @implemented
*/
int STDCALL
ToUnicode(UINT wVirtKey,
@ -411,8 +422,8 @@ ToUnicode(UINT wVirtKey,
int cchBuff,
UINT wFlags)
{
UNIMPLEMENTED;
return 0;
return ToUnicodeEx( wVirtKey, wScanCode, lpKeyState, pwszBuff, cchBuff,
wFlags, 0 );
}
@ -428,8 +439,8 @@ ToUnicodeEx(UINT wVirtKey,
UINT wFlags,
HKL dwhkl)
{
UNIMPLEMENTED;
return 0;
return NtUserToUnicodeEx( wVirtKey, wScanCode, lpKeyState, pwszBuff, cchBuff,
wFlags, dwhkl );
}

View file

@ -1,4 +1,4 @@
/* $Id: message.c,v 1.24 2003/08/14 20:25:52 royce Exp $
/* $Id: message.c,v 1.25 2003/10/09 06:13:04 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS user32.dll
@ -698,7 +698,7 @@ TranslateMessage(CONST MSG *lpMsg)
WINBOOL STDCALL
TranslateMessageEx(CONST MSG *lpMsg, DWORD unk)
{
return(NtUserTranslateMessage((LPMSG)lpMsg, unk));
return(NtUserTranslateMessage((LPMSG)lpMsg, (HKL)unk));
}

View file

@ -21,6 +21,7 @@ typedef struct ConsoleInput_t
LIST_ENTRY ListEntry;
INPUT_RECORD InputEvent;
BOOLEAN Echoed; // already been echoed or not
BOOLEAN Fake; // synthesized, not a real event
} ConsoleInput;

View file

@ -1,4 +1,4 @@
/* $Id: conio.c,v 1.52 2003/08/28 13:38:23 gvg Exp $
/* $Id: conio.c,v 1.53 2003/10/09 06:13:04 gvg Exp $
*
* reactos/subsys/csrss/api/conio.c
*
@ -15,6 +15,7 @@
#include "api.h"
#include <ntdll/rtl.h>
#include <ddk/ntddblue.h>
#include <win32k/ntuser.h>
#define NDEBUG
#include <debug.h>
@ -29,11 +30,9 @@ extern VOID CsrConsoleCtrlEvent(DWORD Event, PCSRSS_PROCESS_DATA ProcessData);
/* GLOBALS *******************************************************************/
static HANDLE ConsoleDeviceHandle;
static HANDLE KeyboardDeviceHandle;
static PCSRSS_CONSOLE ActiveConsole;
CRITICAL_SECTION ActiveConsoleLock;
static COORD PhysicalConsoleSize;
static BOOL KeyReadInhibit = FALSE;
/* FUNCTIONS *****************************************************************/
@ -164,18 +163,30 @@ CSR_API(CsrAllocConsole)
CSR_API(CsrFreeConsole)
{
PCSRSS_CONSOLE Console;
Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
sizeof(LPC_MESSAGE);
if (ProcessData == NULL)
LOCK;
if (ProcessData == NULL || ProcessData->Console == NULL)
{
UNLOCK;
return(Reply->Status = STATUS_INVALID_PARAMETER);
}
Reply->Status = STATUS_NOT_IMPLEMENTED;
Console = ProcessData->Console;
Console->Header.ReferenceCount--;
ProcessData->Console = 0;
if( Console->Header.ReferenceCount == 0 ) {
if( Console != ActiveConsole )
CsrDeleteConsole( Console );
}
UNLOCK;
return(STATUS_NOT_IMPLEMENTED);
return(STATUS_SUCCESS);
}
CSR_API(CsrReadConsole)
@ -242,7 +253,9 @@ CSR_API(CsrReadConsole)
Input->Echoed = TRUE; // mark as echoed so we don't echo it below
}
// do not copy backspace to buffer
else Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar;
else {
Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar;
}
// echo to screen if enabled and we did not already echo the char
if( Console->Mode & ENABLE_ECHO_INPUT &&
!Input->Echoed &&
@ -895,6 +908,8 @@ VOID STDCALL CsrInitConsoleSupport(VOID)
CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
DPRINT("CSR: CsrInitConsoleSupport()\n");
/* Should call LoadKeyboardLayout */
RtlInitUnicodeStringFromLiteral(&DeviceName, L"\\??\\BlueScreen");
InitializeObjectAttributes(&ObjectAttributes,
@ -913,23 +928,6 @@ VOID STDCALL CsrInitConsoleSupport(VOID)
DbgPrint("CSR: Failed to open console. Expect problems.\n");
}
RtlInitUnicodeStringFromLiteral(&DeviceName, L"\\??\\Keyboard");
InitializeObjectAttributes(&ObjectAttributes,
&DeviceName,
0,
NULL,
NULL);
Status = NtOpenFile(&KeyboardDeviceHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
&Iosb,
0,
0);
if (!NT_SUCCESS(Status))
{
DbgPrint("CSR: Failed to open keyboard. Expect problems.\n");
}
ActiveConsole = 0;
RtlInitializeCriticalSection( &ActiveConsoleLock );
Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, 0, 0, &ScrInfo, sizeof( ScrInfo ) );
@ -941,302 +939,406 @@ VOID STDCALL CsrInitConsoleSupport(VOID)
PhysicalConsoleSize = ScrInfo.dwSize;
}
static void CsrpProcessChar( PCSRSS_CONSOLE Console,
ConsoleInput *KeyEventRecord ) {
BOOL updown;
BOOL bClientWake = FALSE;
ConsoleInput *TempInput;
/* process Ctrl-C and Ctrl-Break */
if (Console->Mode & ENABLE_PROCESSED_INPUT &&
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown &&
((KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE) ||
(KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == 'C')) &&
(KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)))
{
PCSRSS_PROCESS_DATA current;
PLIST_ENTRY current_entry;
DPRINT1("Console_Api Ctrl-C\n");
LOCK;
current_entry = Console->ProcessList.Flink;
while (current_entry != &Console->ProcessList)
{
current = CONTAINING_RECORD(current_entry, CSRSS_PROCESS_DATA, ProcessEntry);
current_entry = current_entry->Flink;
CsrConsoleCtrlEvent((DWORD)CTRL_C_EVENT, current);
}
UNLOCK;
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
return;
}
if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState &
( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) &&
( KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP ||
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) )
{
if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE )
{
/* scroll up or down */
LOCK;
if( Console == 0 )
{
DbgPrint( "CSR: No Active Console!\n" );
UNLOCK;
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
return;
}
if( KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP )
{
/* only scroll up if there is room to scroll up into */
if( Console->ActiveBuffer->ShowY != ((Console->ActiveBuffer->CurrentY + 1) %
Console->ActiveBuffer->MaxY) )
Console->ActiveBuffer->ShowY = (Console->ActiveBuffer->ShowY +
Console->ActiveBuffer->MaxY - 1) % Console->ActiveBuffer->MaxY;
}
else if( Console->ActiveBuffer->ShowY != Console->ActiveBuffer->CurrentY )
/* only scroll down if there is room to scroll down into */
if( Console->ActiveBuffer->ShowY % Console->ActiveBuffer->MaxY !=
Console->ActiveBuffer->CurrentY )
if( ((Console->ActiveBuffer->CurrentY + 1) % Console->ActiveBuffer->MaxY) !=
(Console->ActiveBuffer->ShowY + PhysicalConsoleSize.Y) % Console->ActiveBuffer->MaxY )
Console->ActiveBuffer->ShowY = (Console->ActiveBuffer->ShowY + 1) %
Console->ActiveBuffer->MaxY;
CsrDrawConsole( Console->ActiveBuffer );
UNLOCK;
}
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
return;
}
if( Console == 0 )
{
DbgPrint( "CSR: No Active Console!\n" );
UNLOCK;
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
return;
}
if( Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT) )
switch( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar )
{
case '\r':
// first add the \r
KeyEventRecord->InputEvent.EventType = KEY_EVENT;
updown = KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown;
KeyEventRecord->Echoed = FALSE;
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\r';
InsertTailList(&Console->InputEvents, &KeyEventRecord->ListEntry);
Console->WaitingChars++;
KeyEventRecord = RtlAllocateHeap( CsrssApiHeap, 0, sizeof( ConsoleInput ) );
if( !KeyEventRecord )
{
DbgPrint( "CSR: Failed to allocate KeyEventRecord\n" );
return;
}
KeyEventRecord->InputEvent.EventType = KEY_EVENT;
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown = updown;
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode = 0;
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualScanCode = 0;
KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\n';
KeyEventRecord->Fake = TRUE;
}
// add event to the queue
InsertTailList(&Console->InputEvents, &KeyEventRecord->ListEntry);
Console->WaitingChars++;
// if line input mode is enabled, only wake the client on enter key down
if( !(Console->Mode & ENABLE_LINE_INPUT ) ||
Console->EarlyReturn ||
( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' &&
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == FALSE) )
{
if( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' )
Console->WaitingLines++;
bClientWake = TRUE;
NtSetEvent( Console->ActiveEvent, 0 );
}
KeyEventRecord->Echoed = FALSE;
if( Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT) &&
KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\b' &&
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown )
{
// walk the input queue looking for a char to backspace
for( TempInput = (ConsoleInput *)Console->InputEvents.Blink;
TempInput != (ConsoleInput *)&Console->InputEvents &&
(TempInput->InputEvent.EventType != KEY_EVENT ||
TempInput->InputEvent.Event.KeyEvent.bKeyDown == FALSE ||
TempInput->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\b' );
TempInput = (ConsoleInput *)TempInput->ListEntry.Blink );
// if we found one, delete it, otherwise, wake the client
if( TempInput != (ConsoleInput *)&Console->InputEvents )
{
// delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue
RemoveEntryList(&TempInput->ListEntry);
if( TempInput->Echoed )
CsrpWriteConsole( Console->ActiveBuffer, &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE );
RtlFreeHeap( CsrssApiHeap, 0, TempInput );
RemoveEntryList(&KeyEventRecord->ListEntry);
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
Console->WaitingChars -= 2;
}
else {
NtSetEvent( Console->ActiveEvent, 0 );
}
}
else {
// echo chars if we are supposed to and client is waiting for some
if( ( Console->Mode & ENABLE_ECHO_INPUT ) && Console->EchoCount &&
KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar &&
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE &&
KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar != '\r' )
{
// mark the char as already echoed
CsrpWriteConsole( Console->ActiveBuffer, &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE );
Console->EchoCount--;
KeyEventRecord->Echoed = TRUE;
}
}
/* Console->WaitingChars++; */
if( bClientWake || !(Console->Mode & ENABLE_LINE_INPUT) ) {
NtSetEvent( Console->ActiveEvent, 0 );
}
}
static DWORD CsrpGetShiftState( PBYTE KeyState ) {
int i;
DWORD ssOut = 0;
for( i = 0; i < 0x100; i++ ) {
if( KeyState[i] & 0x80 ) {
UINT vk = NtUserMapVirtualKeyEx( i, 3, 0, 0 ) & 0xff;
switch( vk ) {
case VK_LSHIFT:
case VK_RSHIFT:
case VK_SHIFT:
ssOut |= SHIFT_PRESSED;
break;
case VK_LCONTROL:
case VK_CONTROL:
ssOut |= LEFT_CTRL_PRESSED;
break;
case VK_RCONTROL:
ssOut |= RIGHT_CTRL_PRESSED | ENHANCED_KEY;
break;
case VK_LMENU:
case VK_MENU:
ssOut |= LEFT_ALT_PRESSED;
break;
case VK_RMENU:
ssOut |= RIGHT_ALT_PRESSED | ENHANCED_KEY;
break;
}
}
}
return ssOut;
}
VOID Console_Api( DWORD RefreshEvent )
{
/* keep reading events from the keyboard and stuffing them into the current
console's input queue */
ConsoleInput *KeyEventRecord;
ConsoleInput *TempInput;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
HANDLE Events[2]; // 0 = keyboard, 1 = refresh
int c;
int updown;
PCSRSS_CONSOLE SwapConsole = 0; // console we are thinking about swapping with
MSG msg;
ConsoleInput *ConInRec;
UINT RepeatCount;
WCHAR UnicodeChar;
UINT VirtualKeyCode;
UINT VirtualScanCode;
UINT AsciiChar;
DWORD ShiftState;
BOOL SubmitKey;
BOOL Down = FALSE;
BOOL Ext = FALSE;
BYTE KeyState[256] = { 0 };
int RetChars;
WCHAR Chars[2] = { 0 };
INPUT_RECORD er;
NTSTATUS Status;
IO_STATUS_BLOCK Iosb;
BYTE Mask;
Events[0] = 0;
Status = NtCreateEvent( &Events[0], STANDARD_RIGHTS_ALL, NULL, FALSE, FALSE );
if( !NT_SUCCESS( Status ) )
{
DbgPrint( "CSR: NtCreateEvent failed: %x\n", Status );
NtTerminateProcess( NtCurrentProcess(), Status );
/* This call establishes our message queue */
NtUserPeekMessage( &msg, 0,0,0, PM_NOREMOVE );
/* This call registers our message queue */
NtUserCallNoParam( NOPARAM_ROUTINE_REGISTER_PRIMITIVE );
/* This call turns on the input system in win32k */
NtUserAcquireOrReleaseInputOwnership( FALSE );
while( TRUE ) {
NtUserGetMessage( &msg, 0,0,0 );
NtUserTranslateMessage( &msg, 0 );
SubmitKey = FALSE;
if( msg.message == WM_KEYDOWN || msg.message == WM_KEYUP ||
msg.message == WM_SYSKEYDOWN || msg.message == WM_SYSKEYUP ) {
RepeatCount = 1;
VirtualScanCode = (msg.lParam >> 16) & 0xff;
VirtualKeyCode = msg.wParam;
Down = msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN;
Ext = msg.lParam & 0x01000000 ? TRUE : FALSE;
if (Ext)
Mask = 0x40;
else
Mask = 0x80;
if( Down )
KeyState[VirtualScanCode] |= Mask;
else
KeyState[VirtualScanCode] &= ~Mask;
ShiftState = CsrpGetShiftState( KeyState );
RetChars = NtUserToUnicodeEx( VirtualKeyCode,
VirtualScanCode,
KeyState,
Chars,
2,
0,
0 );
if( RetChars == 1 )
UnicodeChar = Chars[0];
else
UnicodeChar = 0;
ULONG ResultSize;
RtlUnicodeToOemN (&AsciiChar,
1,
&ResultSize,
&UnicodeChar,
2);
if( ResultSize == 0 ) AsciiChar = 0;
SubmitKey = TRUE;
}
Events[1] = (HANDLE)RefreshEvent;
while( 1 )
{
KeyEventRecord = RtlAllocateHeap(CsrssApiHeap,
0,
sizeof(ConsoleInput));
if ( KeyEventRecord == 0 )
{
DbgPrint( "CSR: Memory allocation failure!" );
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" );
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
continue;
}
if( Status == STATUS_PENDING )
{
while( 1 )
{
Status = NtWaitForMultipleObjects( 2, Events, WaitAny, FALSE, NULL );
if( Status == STATUS_WAIT_0 + 1 )
{
LOCK;
CsrDrawConsole( ActiveConsole->ActiveBuffer );
UNLOCK;
continue;
}
else if( Status != STATUS_WAIT_0 )
{
DbgPrint( "CSR: NtWaitForMultipleObjects failed: %x, exiting\n", Status );
NtTerminateProcess( NtCurrentProcess(), Status );
}
else break;
}
}
if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState &
( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED )&&
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_TAB )
if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE )
{
ANSI_STRING Title;
void * Buffer;
COORD *pos;
/* alt-tab, swap consoles */
// move SwapConsole to next console, and print its title
LOCK;
if( !SwapConsole )
SwapConsole = ActiveConsole;
if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED )
SwapConsole = SwapConsole->Prev;
else SwapConsole = SwapConsole->Next;
Title.MaximumLength = RtlUnicodeStringToAnsiSize( &SwapConsole->Title );
Title.Length = 0;
Buffer = RtlAllocateHeap( CsrssApiHeap,
0,
sizeof( COORD ) + Title.MaximumLength);
pos = (COORD *)Buffer;
Title.Buffer = Buffer + sizeof( COORD );
RtlUnicodeStringToAnsiString(&Title, &SwapConsole->Title, FALSE);
pos->Y = PhysicalConsoleSize.Y / 2;
pos->X = ( PhysicalConsoleSize.X - Title.Length ) / 2;
// redraw the console to clear off old title
CsrDrawConsole( ActiveConsole->ActiveBuffer );
Status = NtDeviceIoControlFile( ConsoleDeviceHandle,
NULL,
NULL,
NULL,
&Iosb,
IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
Buffer,
sizeof (COORD) + Title.Length,
NULL,
0);
if( !NT_SUCCESS( Status ) )
{
DPRINT1( "Error writing to console\n" );
}
RtlFreeHeap( CsrssApiHeap, 0, Buffer );
if( !SubmitKey ) continue;
er.EventType = KEY_EVENT;
er.Event.KeyEvent.bKeyDown = Down;
er.Event.KeyEvent.wRepeatCount = RepeatCount;
// er.Event.KeyEvent.uChar.AsciiChar = AsciiChar;
// er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar;
er.Event.KeyEvent.uChar.UnicodeChar = AsciiChar;
er.Event.KeyEvent.dwControlKeyState = ShiftState;
er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode;
er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode;
if (ShiftState & ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED )&&
VirtualKeyCode == VK_TAB )
{
if( Down == TRUE )
{
ANSI_STRING Title;
void * Buffer;
COORD *pos;
UNLOCK;
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
continue;
}
else {
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
continue;
}
else if( SwapConsole &&
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_MENU &&
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == FALSE )
{
// alt key released, swap consoles
PCSRSS_CONSOLE tmp;
LOCK;
if( SwapConsole != ActiveConsole )
{
// first remove swapconsole from the list
SwapConsole->Prev->Next = SwapConsole->Next;
SwapConsole->Next->Prev = SwapConsole->Prev;
// now insert before activeconsole
SwapConsole->Next = ActiveConsole;
SwapConsole->Prev = ActiveConsole->Prev;
ActiveConsole->Prev->Next = SwapConsole;
ActiveConsole->Prev = SwapConsole;
}
ActiveConsole = SwapConsole;
SwapConsole = 0;
CsrDrawConsole( ActiveConsole->ActiveBuffer );
UNLOCK;
}
/* process Ctrl-C and Ctrl-Break */
if (ActiveConsole->Mode & ENABLE_PROCESSED_INPUT &&
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown &&
((KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE) ||
(KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == 'C')) &&
(KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)))
{
PCSRSS_PROCESS_DATA current;
PLIST_ENTRY current_entry;
DPRINT1("Console_Api Ctrl-C\n");
/* alt-tab, swap consoles */
// move SwapConsole to next console, and print its title
LOCK;
current_entry = ActiveConsole->ProcessList.Flink;
while (current_entry != &ActiveConsole->ProcessList)
{
current = CONTAINING_RECORD(current_entry, CSRSS_PROCESS_DATA, ProcessEntry);
current_entry = current_entry->Flink;
CsrConsoleCtrlEvent((DWORD)CTRL_C_EVENT, current);
}
UNLOCK;
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
continue;
}
if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState &
( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) &&
( KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP ||
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) )
{
if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE )
{
/* scroll up or down */
LOCK;
if( ActiveConsole == 0 )
{
DbgPrint( "CSR: No Active Console!\n" );
UNLOCK;
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
continue;
}
if( KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP )
{
/* only scroll up if there is room to scroll up into */
if( ActiveConsole->ActiveBuffer->ShowY != ((ActiveConsole->ActiveBuffer->CurrentY + 1) %
ActiveConsole->ActiveBuffer->MaxY) )
ActiveConsole->ActiveBuffer->ShowY = (ActiveConsole->ActiveBuffer->ShowY +
ActiveConsole->ActiveBuffer->MaxY - 1) % ActiveConsole->ActiveBuffer->MaxY;
}
else if( ActiveConsole->ActiveBuffer->ShowY != ActiveConsole->ActiveBuffer->CurrentY )
/* only scroll down if there is room to scroll down into */
if( ActiveConsole->ActiveBuffer->ShowY % ActiveConsole->ActiveBuffer->MaxY !=
ActiveConsole->ActiveBuffer->CurrentY )
if( !SwapConsole )
{
SwapConsole = ActiveConsole;
}
if( ShiftState & SHIFT_PRESSED )
{
SwapConsole = SwapConsole->Prev;
}
else
{
SwapConsole = SwapConsole->Next;
}
Title.MaximumLength = RtlUnicodeStringToAnsiSize( &SwapConsole->Title );
Title.Length = 0;
Buffer = RtlAllocateHeap( CsrssApiHeap,
0,
sizeof( COORD ) + Title.MaximumLength);
pos = (COORD *)Buffer;
Title.Buffer = Buffer + sizeof( COORD );
if( ((ActiveConsole->ActiveBuffer->CurrentY + 1) % ActiveConsole->ActiveBuffer->MaxY) !=
(ActiveConsole->ActiveBuffer->ShowY + PhysicalConsoleSize.Y) % ActiveConsole->ActiveBuffer->MaxY )
ActiveConsole->ActiveBuffer->ShowY = (ActiveConsole->ActiveBuffer->ShowY + 1) %
ActiveConsole->ActiveBuffer->MaxY;
CsrDrawConsole( ActiveConsole->ActiveBuffer );
UNLOCK;
}
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
continue;
}
LOCK;
if( ActiveConsole == 0 )
{
DbgPrint( "CSR: No Active Console!\n" );
RtlUnicodeStringToAnsiString(&Title, &SwapConsole->Title, FALSE);
pos->Y = PhysicalConsoleSize.Y / 2;
pos->X = ( PhysicalConsoleSize.X - Title.Length ) / 2;
// redraw the console to clear off old title
CsrDrawConsole( ActiveConsole->ActiveBuffer );
Status = NtDeviceIoControlFile( ConsoleDeviceHandle,
NULL,
NULL,
NULL,
&Iosb,
IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
Buffer,
sizeof (COORD) + Title.Length,
NULL,
0);
if( !NT_SUCCESS( Status ) )
{
DPRINT1( "Error writing to console\n" );
}
RtlFreeHeap( CsrssApiHeap, 0, Buffer );
UNLOCK;
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
continue;
}
// process special keys if enabled
if( ActiveConsole->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT) )
switch( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar )
{
case '\r':
// add a \n to the queue as well
// first add the \r
updown = KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown;
KeyEventRecord->Echoed = FALSE;
KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\r';
InsertTailList(&ActiveConsole->InputEvents, &KeyEventRecord->ListEntry);
ActiveConsole->WaitingChars++;
KeyEventRecord = RtlAllocateHeap( CsrssApiHeap, 0, sizeof( ConsoleInput ) );
if( !KeyEventRecord )
{
DbgPrint( "CSR: Failed to allocate KeyEventRecord\n" );
UNLOCK;
continue;
}
KeyEventRecord->InputEvent.EventType = KEY_EVENT;
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown = updown;
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode = 0;
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualScanCode = 0;
KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\n';
}
// add event to the queue
InsertTailList(&ActiveConsole->InputEvents, &KeyEventRecord->ListEntry);
// if line input mode is enabled, only wake the client on enter key down
if( !(ActiveConsole->Mode & ENABLE_LINE_INPUT ) ||
ActiveConsole->EarlyReturn ||
( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' &&
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE ) )
{
NtSetEvent( ActiveConsole->ActiveEvent, 0 );
if( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' )
ActiveConsole->WaitingLines++;
}
KeyEventRecord->Echoed = FALSE;
if( ActiveConsole->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT) &&
KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\b' &&
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown )
{
// walk the input queue looking for a char to backspace
for( TempInput = (ConsoleInput *)ActiveConsole->InputEvents.Blink;
TempInput != (ConsoleInput *)&ActiveConsole->InputEvents &&
(TempInput->InputEvent.EventType != KEY_EVENT ||
TempInput->InputEvent.Event.KeyEvent.bKeyDown == FALSE ||
TempInput->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\b' );
TempInput = (ConsoleInput *)TempInput->ListEntry.Blink );
// if we found one, delete it, otherwise, wake the client
if( TempInput != (ConsoleInput *)&ActiveConsole->InputEvents )
{
// delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue
RemoveEntryList(&TempInput->ListEntry);
if( TempInput->Echoed )
CsrpWriteConsole( ActiveConsole->ActiveBuffer, &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE );
RtlFreeHeap( CsrssApiHeap, 0, TempInput );
RemoveEntryList(&KeyEventRecord->ListEntry);
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
ActiveConsole->WaitingChars -= 2;
}
else NtSetEvent( ActiveConsole->ActiveEvent, 0 );
}
else {
// echo chars if we are supposed to and client is waiting for some
if( ( ActiveConsole->Mode & ENABLE_ECHO_INPUT ) && ActiveConsole->EchoCount &&
KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar &&
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE &&
KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar != '\r' )
{
// mark the char as already echoed
CsrpWriteConsole( ActiveConsole->ActiveBuffer, &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE );
ActiveConsole->EchoCount--;
KeyEventRecord->Echoed = TRUE;
}
}
continue;
}
else if( SwapConsole && VirtualKeyCode == VK_MENU && !Down)
{
// alt key released, swap consoles
PCSRSS_CONSOLE tmp;
LOCK;
if( SwapConsole != ActiveConsole )
{
// first remove swapconsole from the list
SwapConsole->Prev->Next = SwapConsole->Next;
SwapConsole->Next->Prev = SwapConsole->Prev;
// now insert before activeconsole
SwapConsole->Next = ActiveConsole;
SwapConsole->Prev = ActiveConsole->Prev;
ActiveConsole->Prev->Next = SwapConsole;
ActiveConsole->Prev = SwapConsole;
}
ActiveConsole = SwapConsole;
SwapConsole = 0;
CsrDrawConsole( ActiveConsole->ActiveBuffer );
UNLOCK;
continue;
}
ActiveConsole->WaitingChars++;
if( !(ActiveConsole->Mode & ENABLE_LINE_INPUT) )
NtSetEvent( ActiveConsole->ActiveEvent, 0 );
UNLOCK;
}
LOCK;
if (ActiveConsole == NULL)
{
UNLOCK;
continue;
}
ConInRec = RtlAllocateHeap(CsrssApiHeap, 0, sizeof(ConsoleInput));
if(ConInRec == NULL)
{
UNLOCK;
break;
}
ConInRec->InputEvent = er;
ConInRec->Fake = FALSE;
ConInRec->Echoed = FALSE;
CsrpProcessChar( ActiveConsole, ConInRec );
UNLOCK;
}
NtUserAcquireOrReleaseInputOwnership( TRUE );
}
CSR_API(CsrGetScreenBufferInfo)
@ -1445,6 +1547,7 @@ CSR_API(CsrReadInputEvent)
PLIST_ENTRY CurrentEntry;
PCSRSS_CONSOLE Console;
NTSTATUS Status;
BOOLEAN Done = FALSE;
ConsoleInput *Input;
Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
@ -1462,50 +1565,36 @@ CSR_API(CsrReadInputEvent)
}
// only get input if there is any
if( Console->InputEvents.Flink != &Console->InputEvents )
while( Console->InputEvents.Flink != &Console->InputEvents &&
!Done )
{
CurrentEntry = RemoveHeadList(&Console->InputEvents);
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
Done = !Input->Fake;
Reply->Data.ReadInputReply.Input = Input->InputEvent;
if( Input->InputEvent.EventType == KEY_EVENT )
{
if( Console->Mode & ENABLE_LINE_INPUT &&
Input->InputEvent.Event.KeyEvent.bKeyDown == FALSE &&
Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' )
Input->InputEvent.Event.KeyEvent.bKeyDown == TRUE &&
Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\r' ) {
Console->WaitingLines--;
}
Console->WaitingChars--;
}
RtlFreeHeap( CsrssApiHeap, 0, Input );
if (Console->InputEvents.Flink != &Console->InputEvents &&
Reply->Data.ReadInputReply.Input.EventType == KEY_EVENT &&
Reply->Data.ReadInputReply.Input.Event.KeyEvent.uChar.AsciiChar == '\r')
{
Input = CONTAINING_RECORD(Console->InputEvents.Flink, ConsoleInput, ListEntry);
if (Input->InputEvent.EventType == KEY_EVENT &&
Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' &&
((Input->InputEvent.Event.KeyEvent.bKeyDown && Reply->Data.ReadInputReply.Input.Event.KeyEvent.bKeyDown) ||
(Input->InputEvent.Event.KeyEvent.bKeyDown==FALSE && Reply->Data.ReadInputReply.Input.Event.KeyEvent.bKeyDown==FALSE)))
{
if(Console->Mode & ENABLE_LINE_INPUT &&
Input->InputEvent.Event.KeyEvent.bKeyDown == FALSE &&
Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' )
Console->WaitingLines--;
Console->WaitingChars--;
RemoveHeadList(&Console->InputEvents);
RtlFreeHeap( CsrssApiHeap, 0, Input );
}
}
Reply->Data.ReadInputReply.MoreEvents = (Console->InputEvents.Flink != &Console->InputEvents) ? TRUE : FALSE;
Status = STATUS_SUCCESS;
Console->EarlyReturn = FALSE; // clear early return
}
else {
Status = STATUS_PENDING;
Console->EarlyReturn = TRUE; // mark for early return
}
if( !Done )
{
Status = STATUS_PENDING;
Console->EarlyReturn = TRUE; // mark for early return
}
UNLOCK;
return Reply->Status = Status;
}
@ -2424,14 +2513,14 @@ CSR_API(CsrReadConsoleOutput)
ReadRegion.Bottom = ReadRegion.Top + SizeY;
ReadRegion.Right = ReadRegion.Left + SizeX;
CsrpInitRect(ScreenRect, 0, 0, ScreenBuffer->MaxY - 1, ScreenBuffer->MaxX - 1);
CsrpInitRect(ScreenRect, 0, 0, ScreenBuffer->MaxY, ScreenBuffer->MaxX);
if (!CsrpGetIntersection(&ReadRegion, ScreenRect, ReadRegion))
{
UNLOCK;
Reply->Status = STATUS_SUCCESS;
return Reply->Status;
}
for(i = 0, Y = ReadRegion.Top; Y < ReadRegion.Bottom; ++i, ++Y)
{
CurCharInfo = CharInfo + (i * BufferSize.X);
@ -2509,9 +2598,13 @@ CSR_API(CsrWriteConsoleInput)
Reply->Status = STATUS_INSUFFICIENT_RESOURCES;
return Reply->Status;
}
Record->Echoed = FALSE;
Record->Fake = FALSE;
Record->InputEvent = *InputRecord++;
InsertTailList(&Console->InputEvents, &Record->ListEntry);
if( Record->InputEvent.EventType == KEY_EVENT ) {
CsrpProcessChar( Console, Record );
}
}
UNLOCK;
@ -2542,15 +2635,6 @@ static NTSTATUS FASTCALL SetConsoleHardwareState (PCSRSS_CONSOLE Console, DWORD
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 */

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: mem.c,v 1.12 2003/09/26 10:45:44 gvg Exp $
/* $Id: mem.c,v 1.13 2003/10/09 06:13:04 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -81,6 +81,7 @@ EngAllocUserMem(ULONG cj, ULONG Tag)
ULONG MemSize = sizeof(USERMEMHEADER) + cj;
PUSERMEMHEADER Header;
DbgPrint("EngAllocUserMem\n");
Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &NewMem, 0, &MemSize, MEM_COMMIT, PAGE_READWRITE);
if (! NT_SUCCESS(Status))

View file

@ -1,7 +1,12 @@
#ifndef __WIN32K_MOUSE_H
#define __WIN32K_MOUSE_H
#include <internal/kbd.h>
NTSTATUS FASTCALL
InitInputImpl(VOID);
PUSER_MESSAGE_QUEUE W32kGetPrimitiveMessageQueue(VOID);
PKBDTABLES W32kGetDefaultKeyLayout(VOID);
VOID FASTCALL W32kKeyProcessMessage(LPMSG Msg, PKBDTABLES KeyLayout);
#endif /* __WIN32K_MOUSE_H */

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: dllmain.c,v 1.44 2003/08/19 11:48:49 weiden Exp $
/* $Id: dllmain.c,v 1.45 2003/10/09 06:13:04 gvg Exp $
*
* Entry Point for win32k.sys
*/
@ -73,6 +73,7 @@ Win32kProcessCallback (struct _EPROCESS *Process,
InitializeListHead(&Win32Process->MenuListHead);
ExInitializeFastMutex(&Win32Process->MenuListLock);
Win32Process->KeyboardLayout = W32kGetDefaultKeyLayout();
Win32Process->WindowStation = NULL;
if (Process->Win32WindowStation != NULL)
{
@ -125,6 +126,7 @@ Win32kThreadCallback (struct _ETHREAD *Thread,
#endif
Win32Thread->MessageQueue = MsqCreateMessageQueue();
Win32Thread->KeyboardLayout = W32kGetDefaultKeyLayout();
InitializeListHead(&Win32Thread->WindowListHead);
ExInitializeFastMutex(&Win32Thread->WindowListLock);

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.13 2003/09/30 22:04:24 gvg Exp $
/* $Id: input.c,v 1.14 2003/10/09 06:13:04 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -50,6 +50,7 @@ static CLIENT_ID KeyboardThreadId;
static HANDLE KeyboardDeviceHandle;
static KEVENT InputThreadsStart;
static BOOLEAN InputThreadsRunning = FALSE;
PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue = 0;
/* FUNCTIONS *****************************************************************/
@ -84,11 +85,13 @@ KeyboardThreadMain(PVOID StartContext)
/*
* Wait to start input.
*/
DbgPrint( "Input Thread Waiting for start event\n" );
Status = KeWaitForSingleObject(&InputThreadsStart,
0,
UserMode,
TRUE,
NULL);
DbgPrint( "Input Thread Starting...\n" );
/*
* Receive and process keyboard input.
@ -96,8 +99,8 @@ KeyboardThreadMain(PVOID StartContext)
while (InputThreadsRunning)
{
KEY_EVENT_RECORD KeyEvent;
LPARAM lParam;
BOOLEAN SysKey;
LPARAM lParam = 0;
BOOLEAN SysKey;
Status = NtReadFile (KeyboardDeviceHandle,
NULL,
@ -144,8 +147,9 @@ 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,
lParam);
MsqPostKeyboardMessage(SysKey ? WM_SYSKEYDOWN : WM_KEYDOWN,
KeyEvent.wVirtualKeyCode,
lParam);
}
else
{
@ -166,16 +170,19 @@ KeyboardThreadMain(PVOID StartContext)
lParam);
}
}
DbgPrint( "Input Thread Stopped...\n" );
}
}
NTSTATUS STDCALL
NtUserAcquireOrReleaseInputOwnership(BOOLEAN Release)
{
if (Release && InputThreadsRunning)
if (Release && InputThreadsRunning && !pmPrimitiveMessageQueue)
{
DbgPrint( "Releasing input: PM = %08x\n", pmPrimitiveMessageQueue );
KeClearEvent(&InputThreadsStart);
InputThreadsRunning = FALSE;
NtAlertThread(KeyboardThreadHandle);
}
else if (!Release && !InputThreadsRunning)
@ -183,6 +190,7 @@ NtUserAcquireOrReleaseInputOwnership(BOOLEAN Release)
InputThreadsRunning = TRUE;
KeSetEvent(&InputThreadsStart, IO_NO_INCREMENT, FALSE);
}
return(STATUS_SUCCESS);
}
@ -304,5 +312,4 @@ NtUserDragDetect(
return 0;
}
/* 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: keyboard.c,v 1.9 2003/08/19 11:48:49 weiden Exp $
/* $Id: keyboard.c,v 1.10 2003/10/09 06:13:04 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -44,9 +44,8 @@
#define NDEBUG
#include <debug.h>
DWORD ModBits = 0;
BYTE QueueKeyStateTable[256];
static PVOID pkKeyboardLayout = 0;
PKBDTABLES pkKeyboardLayout = 0;
/* arty -- These should be phased out for the general kbdxx.dll tables */
@ -171,68 +170,141 @@ static const struct accent_char accent_chars[] =
/*** Statics used by TranslateMessage ***/
static UINT DontDistinguishShifts( UINT ret ) {
if( ret == VK_LSHIFT || ret == VK_RSHIFT ) ret = VK_SHIFT;
if( ret == VK_LCONTROL || ret == VK_RCONTROL ) ret = VK_CONTROL;
if( ret == VK_LMENU || ret == VK_RMENU ) ret = VK_MENU;
return ret;
}
static VOID STDCALL SetKeyState(DWORD key, BOOL down) {
if( key >= 'a' && key <= 'z' ) key += 'A' - 'a';
QueueKeyStateTable[key] = down;
QueueKeyStateTable[key] = down ? 0x80 : 0;
}
static BOOL SetModKey( PKBDTABLES pkKT, WORD wVK, BOOL down ) {
VOID DumpKeyState( PBYTE KeyState ) {
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;
DbgPrint( "KeyState { " );
for( i = 0; i < 0x100; i++ ) {
if( KeyState[i] ) DbgPrint( "%02x(%02x) ", i, KeyState[i] );
}
DbgPrint( "};\n" );
}
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;
static BYTE KeysSet( PKBDTABLES pkKT, PBYTE KeyState,
int Mod, int FakeModLeft, int FakeModRight ) {
int i;
for( i = 0;; i++ ) {
vkPtr = (PVK_TO_WCHARS10)
(((BYTE *)vtwTbl->pVkToWchars) + i * size_this_entry);
if( !KeyState || !pkKT ) return 0;
if( !vkPtr->VirtualKey ) return FALSE;
if( wVirtKey == vkPtr->VirtualKey ) {
for( j = 0; j < nStates; j++ ) {
if( j == (int) 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;
}
}
for( i = 0; i < pkKT->bMaxVSCtoVK; i++ ) {
if( KeyState[i] & 0xC0 &&
((pkKT->pusVSCtoVK[i] & 0xff) == Mod ||
(pkKT->pusVSCtoVK[i] & 0xff) == FakeModLeft ||
(pkKT->pusVSCtoVK[i] & 0xff) == FakeModRight ) ) {
return KeyState[i];
}
}
return 0;
}
static DWORD ModBits( PKBDTABLES pkKT, PBYTE KeyState ) {
int i;
DWORD ModBits = 0;
BYTE Mask;
if( !KeyState ) return 0;
/* DumpKeyState( KeyState ); */
for( i = 0; pkKT->pCharModifiers->pVkToBit[i].Vk; i++ ) {
int Vk = pkKT->pCharModifiers->pVkToBit[i].Vk;
switch(Vk)
{
case VK_SHIFT:
Mask = KeysSet( pkKT, KeyState, Vk, VK_LSHIFT, VK_RSHIFT );
if (Mask & 0xc0)
ModBits |= pkKT->pCharModifiers->pVkToBit[i].ModBits;
break;
case VK_CONTROL:
Mask = KeysSet( pkKT, KeyState, Vk, VK_LCONTROL, VK_RCONTROL );
if (Mask & 0xc0)
ModBits |= pkKT->pCharModifiers->pVkToBit[i].ModBits;
break;
case VK_MENU:
Mask = KeysSet( pkKT, KeyState, Vk, VK_LMENU, VK_RMENU );
if (Mask & 0xc0)
ModBits |= pkKT->pCharModifiers->pVkToBit[i].ModBits;
if (Mask & 0x40)
ModBits |= 0x02 /* KCTRL */;
break;
default:
Mask = KeysSet( pkKT, KeyState, Vk, 0, 0 );
if (Mask & 0x80)
ModBits |= pkKT->pCharModifiers->pVkToBit[i].ModBits;
break;
}
}
DPRINT( "Current Mod Bits: %x\n", ModBits );
return ModBits;
}
static BOOL TryToTranslateChar(WORD wVirtKey,
DWORD ModBits,
PBOOL pbDead,
PBOOL pbLigature,
PWCHAR pwcTranslatedChar,
PKBDTABLES keyLayout )
{
PVK_TO_WCHAR_TABLE vtwTbl;
PVK_TO_WCHARS10 vkPtr;
size_t size_this_entry;
int nMod, shift;
DPRINT ( "TryToTranslate: %04x %x\n", wVirtKey, ModBits );
if (ModBits > keyLayout->pCharModifiers->wMaxModBits)
{
return FALSE;
}
shift = keyLayout->pCharModifiers->ModNumber[ModBits];
for (nMod = 0; keyLayout->pVkToWcharTable[nMod].nModifications; nMod++)
{
if (shift >= keyLayout->pVkToWcharTable[nMod].nModifications)
{
continue;
}
vtwTbl = &keyLayout->pVkToWcharTable[nMod];
size_this_entry = vtwTbl->cbSize;
vkPtr = (PVK_TO_WCHARS10)((BYTE *)vtwTbl->pVkToWchars);
while(vkPtr->VirtualKey)
{
if( wVirtKey == vkPtr->VirtualKey )
{
*pbDead = vkPtr->wch[shift] == WCH_DEAD;
*pbLigature = vkPtr->wch[shift] == WCH_LGTR;
*pwcTranslatedChar = vkPtr->wch[shift];
if( *pbDead )
{
vkPtr = (PVK_TO_WCHARS10)(((BYTE *)vkPtr) + 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[shift];
}
return TRUE;
}
vkPtr = (PVK_TO_WCHARS10)(((BYTE *)vkPtr) + size_this_entry);
}
}
return FALSE;
}
static
@ -243,38 +315,32 @@ ToUnicodeInner(UINT wVirtKey,
LPWSTR pwszBuff,
int cchBuff,
UINT wFlags,
DWORD ModBits,
PKBDTABLES pkKT)
{
int i;
WCHAR wcTranslatedChar;
BOOL bDead;
BOOL bLigature;
DbgPrint("wVirtKey=%08x, wScanCode=%08x, lpKeyState=[], "
"pwszBuff=%S, cchBuff=%d, wFlags=%x\n",
wVirtKey, wScanCode, /* lpKeyState, */ pwszBuff,
cchBuff, wFlags );
if( !pkKT ) return 0;
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( TryToTranslateChar( wVirtKey,
ModBits( pkKT, lpKeyState ),
&bDead,
&bLigature,
&wcTranslatedChar,
pkKT ) )
{
if( bLigature )
{
DPRINT("Not handling ligature (yet)\n" );
return 0;
}
/* DbgPrint( "Trans: %04x\n", wcTranslatedChar ); */
if( cchBuff > 0 ) pwszBuff[0] = wcTranslatedChar;
if( bDead ) return -1;
else return 1;
return bDead ? -1 : 1;
}
}
return 0;
}
@ -286,11 +352,30 @@ NtUserGetKeyState(
{
DWORD ret;
if (key >= 'a' && key <= 'z') key += 'A' - 'a';
if( key < 0x100 ) {
ret = ((DWORD)(QueueKeyStateTable[key] & 0x80) << 8 ) |
(QueueKeyStateTable[key] & 0x80) |
(QueueKeyStateTable[key] & 0x01);
(QueueKeyStateTable[key] & 0x80) |
(QueueKeyStateTable[key] & 0x01);
return ret;
}
return 0;
}
int STDCALL ToUnicodeEx( UINT wVirtKey,
UINT wScanCode,
PBYTE lpKeyState,
LPWSTR pwszBuff,
int cchBuff,
UINT wFlags,
HKL dwhkl ) {
return ToUnicodeInner( wVirtKey,
wScanCode,
lpKeyState,
pwszBuff,
cchBuff,
wFlags,
PsGetWin32Thread() ?
PsGetWin32Thread()->KeyboardLayout : 0 );
}
int STDCALL ToUnicode( UINT wVirtKey,
@ -299,14 +384,13 @@ int STDCALL ToUnicode( UINT wVirtKey,
LPWSTR pwszBuff,
int cchBuff,
UINT wFlags ) {
return ToUnicodeInner( wVirtKey,
wScanCode,
QueueKeyStateTable,
pwszBuff,
cchBuff,
wFlags,
ModBits,
pkKeyboardLayout );
return ToUnicodeEx( wVirtKey,
wScanCode,
QueueKeyStateTable,
pwszBuff,
cchBuff,
wFlags,
0 );
}
typedef PVOID (*KbdLayerDescriptor)(VOID);
@ -339,56 +423,51 @@ void InitKbdLayout( PVOID *pkKeyboardLayout ) {
}
}
PKBDTABLES W32kGetDefaultKeyLayout() {
if( !pkKeyboardLayout ) InitKbdLayout( (PVOID) &pkKeyboardLayout );
return pkKeyboardLayout;
}
BOOL STDCALL
NtUserTranslateMessage(LPMSG lpMsg,
DWORD Unknown1) /* Used to pass the kbd layout */
HKL dwhkl) /* Used to pass the kbd layout */
{
static INT dead_char = 0;
UINT ScanCode = 0;
LONG UState = 0;
WCHAR wp[2] = { 0 };
MSG NewMsg = { 0 };
MSG InMsg = { 0 };
PUSER_MESSAGE UMsg;
PKBDTABLES keyLayout;
/* 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" );
if( !NT_SUCCESS(MmCopyFromCaller(&InMsg, lpMsg, sizeof(InMsg))) ) {
return FALSE;
}
if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN)
keyLayout = PsGetWin32Thread()->KeyboardLayout;
if( !keyLayout ) return 0;
ScanCode = (InMsg.lParam >> 16) & 0xff;
if (InMsg.message != WM_KEYDOWN && InMsg.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" );
if (InMsg.message == WM_KEYUP) {
SetKeyState( ScanCode, FALSE ); /* Release key */
}
return(FALSE);
}
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" );
SetKeyState( ScanCode, TRUE ); /* Strike key */
/* Pass 2: Get Unicode Character */
DbgPrint( "Calling ToUnicodeString()\n" );
UState = ToUnicodeInner(lpMsg->wParam, HIWORD(lpMsg->lParam),
QueueKeyStateTable, wp, 2, 0, ModBits,
pkKeyboardLayout);
UState = ToUnicodeInner(InMsg.wParam, HIWORD(InMsg.lParam) & 0xff,
QueueKeyStateTable, wp, 2, 0,
keyLayout );
DbgPrint( "UState is %d after key %04x\n", UState, wp[0] );
if (UState == 1)
{
NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
NewMsg.message = (InMsg.message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
if (dead_char)
{
ULONG i;
@ -412,21 +491,21 @@ NtUserTranslateMessage(LPMSG lpMsg,
dead_char = 0;
}
}
NewMsg.hwnd = lpMsg->hwnd;
NewMsg.hwnd = InMsg.hwnd;
NewMsg.wParam = wp[0];
NewMsg.lParam = lpMsg->lParam;
NewMsg.lParam = InMsg.lParam;
UMsg = MsqCreateMessage(&NewMsg);
DbgPrint( "CHAR='%c' %04x %08x\n", wp[0], wp[0], lpMsg->lParam );
DPRINT( "CHAR='%c' %04x %08x\n", wp[0], wp[0], InMsg.lParam );
MsqPostMessage(PsGetWin32Thread()->MessageQueue, UMsg);
return(TRUE);
}
else if (UState == -1)
{
NewMsg.message =
(lpMsg->message == WM_KEYDOWN) ? WM_DEADCHAR : WM_SYSDEADCHAR;
NewMsg.hwnd = lpMsg->hwnd;
(InMsg.message == WM_KEYDOWN) ? WM_DEADCHAR : WM_SYSDEADCHAR;
NewMsg.hwnd = InMsg.hwnd;
NewMsg.wParam = wp[0];
NewMsg.lParam = lpMsg->lParam;
NewMsg.lParam = InMsg.lParam;
dead_char = wp[0];
UMsg = MsqCreateMessage(&NewMsg);
MsqPostMessage(PsGetWin32Thread()->MessageQueue, UMsg);
@ -465,5 +544,221 @@ NtUserSetKeyboardState(
return TRUE;
}
static UINT VkToScan( UINT Code, BOOL ExtCode, PKBDTABLES pkKT ) {
int i;
for( i = 0; i < pkKT->bMaxVSCtoVK; i++ ) {
if( pkKT->pusVSCtoVK[i] == Code ) { return i; }
}
return 0;
}
UINT ScanToVk( UINT Code, BOOL ExtKey, PKBDTABLES pkKT ) {
if( ExtKey ) {
int i;
for( i = 0; pkKT->pVSCtoVK_E0[i].Vsc; i++ ) {
if( pkKT->pVSCtoVK_E0[i].Vsc == Code )
return pkKT->pVSCtoVK_E0[i].Vk & 0xff;
}
for( i = 0; pkKT->pVSCtoVK_E1[i].Vsc; i++ ) {
if( pkKT->pVSCtoVK_E1[i].Vsc == Code )
return pkKT->pVSCtoVK_E1[i].Vk & 0xff;
}
return 0;
} else {
if( Code >= pkKT->bMaxVSCtoVK ) { return 0; }
return pkKT->pusVSCtoVK[Code] & 0xff;
}
}
/*
* Map a virtual key code, or virtual scan code, to a scan code, key code,
* or unshifted unicode character.
*
* Code: See Below
* Type:
* 0 -- Code is a virtual key code that is converted into a virtual scan code
* that does not distinguish between left and right shift keys.
* 1 -- Code is a virtual scan code that is converted into a virtual key code
* that does not distinguish between left and right shift keys.
* 2 -- Code is a virtual key code that is converted into an unshifted unicode
* character.
* 3 -- Code is a virtual scan code that is converted into a virtual key code
* that distinguishes left and right shift keys.
* KeyLayout: Keyboard layout handle (currently, unused)
*
* @implemented
*/
UINT
STDCALL
NtUserMapVirtualKeyEx( UINT Code, UINT Type, DWORD keyboardId, HKL dwhkl ) {
UINT ret = 0;
PKBDTABLES keyLayout = PsGetWin32Thread()->KeyboardLayout;
if( !keyLayout ) return 0;
switch( Type ) {
case 0:
if( Code == VK_RSHIFT ) Code = VK_LSHIFT;
if( Code == VK_RMENU ) Code = VK_LMENU;
if( Code == VK_RCONTROL ) Code = VK_LCONTROL;
ret = VkToScan( Code, FALSE, keyLayout );
break;
case 1:
ret =
DontDistinguishShifts
(NtUserMapVirtualKeyEx( Code, 3, keyboardId, dwhkl ) );
break;
case 2: {
WCHAR wp[2];
ret = VkToScan( Code, FALSE, keyLayout );
ToUnicodeInner( Code, ret, 0, wp, 2, 0, keyLayout );
ret = wp[0];
} break;
case 3:
ret = ScanToVk( Code, FALSE, keyLayout );
break;
}
return ret;
}
int
STDCALL
NtUserToUnicodeEx(
UINT wVirtKey,
UINT wScanCode,
PBYTE lpKeyState,
LPWSTR pwszBuff,
int cchBuff,
UINT wFlags,
HKL dwhkl ) {
BYTE KeyStateBuf[0x100];
PWCHAR OutPwszBuff = 0;
int ret = 0;
if( !NT_SUCCESS(MmCopyFromCaller(KeyStateBuf,
lpKeyState,
sizeof(KeyStateBuf))) ) {
DbgPrint( "Couldn't copy key state from caller.\n" );
return 0;
}
OutPwszBuff = ExAllocatePool(NonPagedPool,sizeof(WCHAR) * cchBuff);
if( !OutPwszBuff ) {
DbgPrint( "ExAllocatePool(%d) failed\n", sizeof(WCHAR) * cchBuff);
return 0;
}
RtlZeroMemory( OutPwszBuff, sizeof( WCHAR ) * cchBuff );
ret = ToUnicodeEx( wVirtKey,
wScanCode,
KeyStateBuf,
OutPwszBuff,
cchBuff,
wFlags,
dwhkl );
MmCopyToCaller(pwszBuff,OutPwszBuff,sizeof(WCHAR)*cchBuff);
ExFreePool(OutPwszBuff);
return ret;
}
static int W32kSimpleToupper( int ch ) {
if( ch >= 'a' && ch <= 'z' ) ch = ch - 'a' + 'A';
return ch;
}
DWORD
STDCALL
NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize ) {
int i;
DWORD ret = 0;
UINT CareVk = 0;
UINT VkCode = 0;
UINT ScanCode = (lParam >> 16) & 0xff;
BOOL ExtKey = lParam & (1<<24) ? TRUE : FALSE;
PKBDTABLES keyLayout =
PsGetWin32Thread() ?
PsGetWin32Thread()->KeyboardLayout : 0;
if( !keyLayout || nSize < 1 ) return 0;
if( lParam & (1<<25) ) {
CareVk = VkCode = ScanToVk( ScanCode, ExtKey, keyLayout );
if( VkCode == VK_LSHIFT || VkCode == VK_RSHIFT )
VkCode = VK_LSHIFT;
if( VkCode == VK_LCONTROL || VkCode == VK_RCONTROL )
VkCode = VK_LCONTROL;
if( VkCode == VK_LMENU || VkCode == VK_RMENU )
VkCode = VK_LMENU;
} else {
VkCode = ScanToVk( ScanCode, ExtKey, keyLayout );
}
VSC_LPWSTR *KeyNames = 0;
if( CareVk != VkCode )
ScanCode = VkToScan( VkCode, ExtKey, keyLayout );
if( ExtKey )
KeyNames = keyLayout->pKeyNamesExt;
else
KeyNames = keyLayout->pKeyNames;
for( i = 0; KeyNames[i].pwsz; i++ ) {
if( KeyNames[i].vsc == ScanCode ) {
UINT StrLen = wcslen(KeyNames[i].pwsz);
UINT StrMax = StrLen > (nSize - 1) ? (nSize - 1) : StrLen;
WCHAR null_wc = 0;
if( NT_SUCCESS( MmCopyToCaller( lpString,
KeyNames[i].pwsz,
StrMax * sizeof(WCHAR) ) ) &&
NT_SUCCESS( MmCopyToCaller( lpString + StrMax,
&null_wc,
sizeof( WCHAR ) ) ) ) {
ret = StrMax;
break;
}
}
}
if( ret == 0 ) {
WCHAR UCName[2];
UCName[0] = W32kSimpleToupper(NtUserMapVirtualKeyEx( VkCode, 2, 0, 0 ));
UCName[1] = 0;
ret = 1;
if( !NT_SUCCESS(MmCopyToCaller( lpString, UCName, 2 * sizeof(WCHAR) )) )
return 0;
}
return ret;
}
/*
* Filter this message according to the current key layout, setting wParam
* appropriately.
*/
VOID FASTCALL W32kKeyProcessMessage(LPMSG Msg, PKBDTABLES KeyboardLayout) {
if( !KeyboardLayout || !Msg) return;
if( Msg->message != WM_KEYDOWN && Msg->message != WM_SYSKEYDOWN &&
Msg->message != WM_KEYUP && Msg->message != WM_SYSKEYUP ) {
return;
}
Msg->wParam = NtUserMapVirtualKeyEx( (Msg->lParam >> 16) & 0xff, 1, 0, 0 );
}
/* 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: message.c,v 1.29 2003/09/27 15:41:54 gvg Exp $
/* $Id: message.c,v 1.30 2003/10/09 06:13:04 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -39,6 +39,7 @@
#include <include/winsta.h>
#include <include/callback.h>
#include <include/painting.h>
#include <include/input.h>
#include <internal/safe.h>
#define NDEBUG
@ -91,6 +92,8 @@ NtUserDispatchMessage(CONST MSG* UnsafeMsg)
}
}
if( Msg.hwnd == 0 ) return 0;
/* Get the window object. */
Status =
ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
@ -184,6 +187,7 @@ IntPeekMessage(LPMSG Msg,
{
MsqDestroyMessage(Message);
}
W32kKeyProcessMessage(Msg,PsGetWin32Thread()->KeyboardLayout);
return TRUE;
}
@ -536,7 +540,7 @@ IntSendMessage(HWND hWnd,
{
Result = IntCallWindowProc(Window->WndProcA, hWnd, Msg, wParam, lParam);
}
return Result;
return Result;
}
}
else
@ -615,7 +619,6 @@ NtUserWaitMessage(VOID)
return IntWaitMessage(NULL, 0, 0);
}
DWORD STDCALL
NtUserGetQueueStatus(BOOL ClearChanges)
{

View file

@ -1,4 +1,4 @@
/* $Id: misc.c,v 1.18 2003/09/24 21:09:22 weiden Exp $
/* $Id: misc.c,v 1.19 2003/10/09 06:13:05 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -23,27 +23,48 @@
#define NDEBUG
#include <debug.h>
void W32kRegisterPrimitiveMessageQueue() {
extern PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue;
if( !pmPrimitiveMessageQueue ) {
PW32THREAD pThread;
pThread = PsGetWin32Thread();
if( pThread && pThread->MessageQueue ) {
pmPrimitiveMessageQueue = pThread->MessageQueue;
DbgPrint( "Installed primitive input queue.\n" );
}
} else {
DbgPrint( "Alert! Someone is trying to steal the primitive queue.\n" );
}
}
PUSER_MESSAGE_QUEUE W32kGetPrimitiveMessageQueue() {
extern PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue;
return pmPrimitiveMessageQueue;
}
/*
* @unimplemented
*/
DWORD
STDCALL
NtUserCallNoParam(
DWORD Routine)
NtUserCallNoParam(DWORD Routine)
{
/*
switch(Routine)
{
case 0:
break;
}
*/
DPRINT1("Calling invalid routine number 0x%x in NtUserCallNoParam()\n", Routine);
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return 0;
}
DWORD Result;
switch(Routine) {
case NOPARAM_ROUTINE_REGISTER_PRIMITIVE:
W32kRegisterPrimitiveMessageQueue();
Result = TRUE;
break;
default:
DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam\n");
SetLastWin32Error(ERROR_INVALID_PARAMETER);
Result = 0;
break;
}
return 0;
}
/*
* @implemented

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: msgqueue.c,v 1.25 2003/09/29 19:38:30 weiden Exp $
/* $Id: msgqueue.c,v 1.26 2003/10/09 06:13:05 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -37,6 +37,7 @@
#include <include/winpos.h>
#include <include/class.h>
#include <include/object.h>
#include <include/input.h>
#define NDEBUG
#include <win32k/debug1.h>
@ -299,6 +300,9 @@ MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, HWND hWnd,
ULONG ActiveStamp;
PWINDOW_OBJECT DesktopWindow;
if( !IntGetScreenDC() ||
PsGetWin32Thread()->MessageQueue == W32kGetPrimitiveMessageQueue() )
return FALSE;
DesktopWindow = IntGetWindowObject(IntGetDesktopWindow());
/* Process messages in the message queue itself. */
@ -433,27 +437,45 @@ MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
uMsg, wParam, lParam);
FocusMessageQueue = IntGetFocusMessageQueue();
if (FocusMessageQueue == NULL)
{
DPRINT("No focus message queue\n");
return;
}
if( !IntGetScreenDC() ) {
Msg.hwnd = 0;
Msg.message = uMsg;
Msg.wParam = wParam;
Msg.lParam = lParam;
/* FIXME: Initialize time and point. */
if (FocusMessageQueue->FocusWindow != (HWND)0)
{
Msg.hwnd = FocusMessageQueue->FocusWindow;
if( W32kGetPrimitiveMessageQueue() ) {
Msg.hwnd = 0;
Msg.message = uMsg;
Msg.wParam = wParam;
Msg.lParam = lParam;
/* FIXME: Initialize time and point. */
Message = MsqCreateMessage(&Msg);
MsqPostMessage(FocusMessageQueue, Message);
}
else
{
DPRINT("Invalid focus window handle\n");
MsqPostMessage(W32kGetPrimitiveMessageQueue(), Message);
}
} else {
if (FocusMessageQueue == NULL)
{
DPRINT("No focus message queue\n");
return;
}
if (FocusMessageQueue->FocusWindow != (HWND)0)
{
Msg.hwnd = FocusMessageQueue->FocusWindow;
Msg.message = uMsg;
Msg.wParam = wParam;
Msg.lParam = lParam;
/* FIXME: Initialize time and point. */
Message = MsqCreateMessage(&Msg);
MsqPostMessage(FocusMessageQueue, Message);
}
else
{
DPRINT("Invalid focus window handle\n");
}
}
}
VOID FASTCALL

View file

@ -1,4 +1,4 @@
/* $Id: stubs.c,v 1.28 2003/09/12 12:54:26 weiden Exp $
/* $Id: stubs.c,v 1.29 2003/10/09 06:13:05 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -643,18 +643,6 @@ NtUserGetKeyboardLayoutName(
return 0;
}
DWORD
STDCALL
NtUserGetKeyNameText(
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2)
{
UNIMPLEMENTED
return 0;
}
DWORD
STDCALL
NtUserGetListBoxInfo(
@ -811,19 +799,6 @@ NtUserLockWorkStation(VOID)
return 0;
}
DWORD
STDCALL
NtUserMapVirtualKeyEx(
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3)
{
UNIMPLEMENTED
return 0;
}
DWORD
STDCALL
NtUserMinMaximize(
@ -1070,22 +1045,6 @@ NtUserShowCaret(
return 0;
}
DWORD
STDCALL
NtUserToUnicodeEx(
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3,
DWORD Unknown4,
DWORD Unknown5,
DWORD Unknown6)
{
UNIMPLEMENTED
return 0;
}
DWORD
STDCALL
NtUserTrackMouseEvent(

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: winsta.c,v 1.36 2003/09/25 20:09:56 ekohl Exp $
/* $Id: winsta.c,v 1.37 2003/10/09 06:13:05 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -714,6 +714,7 @@ NtUserCreateDesktop(PUNICODE_STRING lpszDesktopName,
IntCreateDesktopWindow(DesktopObject->WindowStation,
DesktopWindowClass,
640, 480);
DbgPrint( "Created Desktop Window: %08x\n", DesktopObject->DesktopWindow );
Status = ObInsertObject ((PVOID)DesktopObject,
NULL,