mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
Keyboard sync between gui and text modes, patch by Art Yerkes and
Hartmut Birr svn path=/trunk/; revision=6271
This commit is contained in:
parent
511fc18181
commit
3f52e9d728
20 changed files with 1027 additions and 620 deletions
|
@ -8360,8 +8360,7 @@ ToAsciiEx(
|
|||
|
||||
int
|
||||
STDCALL
|
||||
ToUnicode(
|
||||
UINT wVirtKey,
|
||||
ToUnicode(UINT wVirtKey,
|
||||
UINT wScanCode,
|
||||
PBYTE lpKeyState,
|
||||
LPWSTR pwszBuff,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/* --- --- --- */
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
typedef struct _USER32_THREAD_DATA
|
||||
{
|
||||
MSG LastMessage;
|
||||
HKL KeyboardLayoutHandle;
|
||||
} USER32_THREAD_DATA, *PUSER32_THREAD_DATA;
|
||||
|
||||
PUSER32_THREAD_DATA User32GetThreadData();
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue