2010-05-31 06:28:55 +00:00
|
|
|
/*
|
2012-10-25 20:40:41 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS Console Server DLL
|
|
|
|
* FILE: win32ss/user/consrv/coninput.c
|
|
|
|
* PURPOSE: Console I/O functions
|
|
|
|
* PROGRAMMERS:
|
2010-05-31 06:28:55 +00:00
|
|
|
*/
|
|
|
|
|
2012-11-17 15:41:31 +00:00
|
|
|
/* INCLUDES *******************************************************************/
|
2010-05-31 06:28:55 +00:00
|
|
|
|
2012-10-23 22:31:36 +00:00
|
|
|
#include "consrv.h"
|
|
|
|
#include "conio.h"
|
|
|
|
#include "tuiconsole.h"
|
|
|
|
|
2010-05-31 06:28:55 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
2012-11-17 15:41:31 +00:00
|
|
|
|
|
|
|
/* GLOBALS ********************************************************************/
|
2010-05-31 06:28:55 +00:00
|
|
|
|
|
|
|
#define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
|
|
|
|
WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
|
|
|
|
|
|
|
|
#define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \
|
|
|
|
MultiByteToWideChar((Console)->CodePage, 0, (sChar), 1, (dWChar), 1)
|
|
|
|
|
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
typedef struct _GET_INPUT_INFO
|
|
|
|
{
|
|
|
|
PCONSOLE_PROCESS_DATA ProcessData;
|
|
|
|
PCSRSS_CONSOLE Console;
|
|
|
|
} GET_INPUT_INFO, *PGET_INPUT_INFO;
|
|
|
|
|
|
|
|
|
2012-11-17 15:41:31 +00:00
|
|
|
/* PRIVATE FUNCTIONS **********************************************************/
|
2010-05-31 06:28:55 +00:00
|
|
|
|
|
|
|
static VOID FASTCALL
|
|
|
|
ConioInputEventToAnsi(PCSRSS_CONSOLE Console, PINPUT_RECORD InputEvent)
|
|
|
|
{
|
|
|
|
if (InputEvent->EventType == KEY_EVENT)
|
|
|
|
{
|
|
|
|
WCHAR UnicodeChar = InputEvent->Event.KeyEvent.uChar.UnicodeChar;
|
|
|
|
InputEvent->Event.KeyEvent.uChar.UnicodeChar = 0;
|
|
|
|
ConsoleInputUnicodeCharToAnsiChar(Console,
|
|
|
|
&InputEvent->Event.KeyEvent.uChar.AsciiChar,
|
|
|
|
&UnicodeChar);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-04 18:26:22 +00:00
|
|
|
static NTSTATUS FASTCALL
|
2010-05-31 06:28:55 +00:00
|
|
|
ConioProcessChar(PCSRSS_CONSOLE Console,
|
2010-06-04 18:26:22 +00:00
|
|
|
PINPUT_RECORD InputEvent)
|
2010-05-31 06:28:55 +00:00
|
|
|
{
|
2010-07-29 10:20:41 +00:00
|
|
|
ConsoleInput *ConInRec;
|
|
|
|
|
2010-06-04 18:26:22 +00:00
|
|
|
/* Check for pause or unpause */
|
|
|
|
if (InputEvent->EventType == KEY_EVENT && InputEvent->Event.KeyEvent.bKeyDown)
|
2010-05-31 06:28:55 +00:00
|
|
|
{
|
2010-06-04 18:26:22 +00:00
|
|
|
WORD vk = InputEvent->Event.KeyEvent.wVirtualKeyCode;
|
2010-05-31 06:28:55 +00:00
|
|
|
if (!(Console->PauseFlags & PAUSED_FROM_KEYBOARD))
|
|
|
|
{
|
2010-06-04 18:26:22 +00:00
|
|
|
DWORD cks = InputEvent->Event.KeyEvent.dwControlKeyState;
|
2010-05-31 06:28:55 +00:00
|
|
|
if (Console->Mode & ENABLE_LINE_INPUT &&
|
|
|
|
(vk == VK_PAUSE || (vk == 'S' &&
|
|
|
|
(cks & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) &&
|
|
|
|
!(cks & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)))))
|
|
|
|
{
|
|
|
|
ConioPause(Console, PAUSED_FROM_KEYBOARD);
|
2010-06-04 18:26:22 +00:00
|
|
|
return STATUS_SUCCESS;
|
2010-05-31 06:28:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((vk < VK_SHIFT || vk > VK_CAPITAL) && vk != VK_LWIN &&
|
|
|
|
vk != VK_RWIN && vk != VK_NUMLOCK && vk != VK_SCROLL)
|
|
|
|
{
|
|
|
|
ConioUnpause(Console, PAUSED_FROM_KEYBOARD);
|
2010-06-04 18:26:22 +00:00
|
|
|
return STATUS_SUCCESS;
|
2010-05-31 06:28:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add event to the queue */
|
2012-10-22 23:55:51 +00:00
|
|
|
ConInRec = RtlAllocateHeap(ConSrvHeap, 0, sizeof(ConsoleInput));
|
2010-06-04 18:26:22 +00:00
|
|
|
if (ConInRec == NULL)
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
ConInRec->InputEvent = *InputEvent;
|
|
|
|
InsertTailList(&Console->InputEvents, &ConInRec->ListEntry);
|
2012-12-08 00:39:24 +00:00
|
|
|
|
2010-05-31 06:28:55 +00:00
|
|
|
SetEvent(Console->ActiveEvent);
|
2012-12-08 00:39:24 +00:00
|
|
|
CsrNotifyWait(&Console->ReadWaitQueue,
|
|
|
|
WaitAny,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
2010-06-04 18:26:22 +00:00
|
|
|
return STATUS_SUCCESS;
|
2010-05-31 06:28:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD FASTCALL
|
|
|
|
ConioGetShiftState(PBYTE KeyState)
|
|
|
|
{
|
|
|
|
DWORD ssOut = 0;
|
|
|
|
|
|
|
|
if (KeyState[VK_CAPITAL] & 1)
|
|
|
|
ssOut |= CAPSLOCK_ON;
|
|
|
|
|
|
|
|
if (KeyState[VK_NUMLOCK] & 1)
|
|
|
|
ssOut |= NUMLOCK_ON;
|
|
|
|
|
|
|
|
if (KeyState[VK_SCROLL] & 1)
|
|
|
|
ssOut |= SCROLLLOCK_ON;
|
|
|
|
|
|
|
|
if (KeyState[VK_SHIFT] & 0x80)
|
|
|
|
ssOut |= SHIFT_PRESSED;
|
|
|
|
|
|
|
|
if (KeyState[VK_LCONTROL] & 0x80)
|
|
|
|
ssOut |= LEFT_CTRL_PRESSED;
|
|
|
|
if (KeyState[VK_RCONTROL] & 0x80)
|
|
|
|
ssOut |= RIGHT_CTRL_PRESSED;
|
|
|
|
|
|
|
|
if (KeyState[VK_LMENU] & 0x80)
|
|
|
|
ssOut |= LEFT_ALT_PRESSED;
|
|
|
|
if (KeyState[VK_RMENU] & 0x80)
|
|
|
|
ssOut |= RIGHT_ALT_PRESSED;
|
|
|
|
|
|
|
|
return ssOut;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID WINAPI
|
|
|
|
ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode)
|
|
|
|
{
|
|
|
|
static BYTE KeyState[256] = { 0 };
|
|
|
|
/* MSDN mentions that you should use the last virtual key code received
|
|
|
|
* when putting a virtual key identity to a WM_CHAR message since multiple
|
|
|
|
* or translated keys may be involved. */
|
|
|
|
static UINT LastVirtualKey = 0;
|
|
|
|
DWORD ShiftState;
|
|
|
|
UINT RepeatCount;
|
|
|
|
WCHAR UnicodeChar;
|
|
|
|
UINT VirtualKeyCode;
|
|
|
|
UINT VirtualScanCode;
|
|
|
|
BOOL Down = FALSE;
|
|
|
|
INPUT_RECORD er;
|
2010-06-04 18:26:22 +00:00
|
|
|
BOOLEAN Fake; // synthesized, not a real event
|
|
|
|
BOOLEAN NotChar; // message should not be used to return a character
|
2010-05-31 06:28:55 +00:00
|
|
|
|
|
|
|
RepeatCount = 1;
|
|
|
|
VirtualScanCode = (msg->lParam >> 16) & 0xff;
|
|
|
|
Down = msg->message == WM_KEYDOWN || msg->message == WM_CHAR ||
|
|
|
|
msg->message == WM_SYSKEYDOWN || msg->message == WM_SYSCHAR;
|
|
|
|
|
|
|
|
GetKeyboardState(KeyState);
|
|
|
|
ShiftState = ConioGetShiftState(KeyState);
|
|
|
|
|
|
|
|
if (msg->message == WM_CHAR || msg->message == WM_SYSCHAR)
|
|
|
|
{
|
|
|
|
VirtualKeyCode = LastVirtualKey;
|
|
|
|
UnicodeChar = msg->wParam;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WCHAR Chars[2];
|
|
|
|
INT RetChars = 0;
|
|
|
|
|
|
|
|
VirtualKeyCode = msg->wParam;
|
|
|
|
RetChars = ToUnicodeEx(VirtualKeyCode,
|
|
|
|
VirtualScanCode,
|
|
|
|
KeyState,
|
|
|
|
Chars,
|
|
|
|
2,
|
|
|
|
0,
|
|
|
|
0);
|
|
|
|
UnicodeChar = (1 == RetChars ? Chars[0] : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
er.EventType = KEY_EVENT;
|
|
|
|
er.Event.KeyEvent.bKeyDown = Down;
|
|
|
|
er.Event.KeyEvent.wRepeatCount = RepeatCount;
|
|
|
|
er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar;
|
|
|
|
er.Event.KeyEvent.dwControlKeyState = ShiftState;
|
|
|
|
er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode;
|
|
|
|
er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode;
|
|
|
|
|
|
|
|
if (TextMode)
|
|
|
|
{
|
|
|
|
if (0 != (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
|
|
|
|
&& VK_TAB == VirtualKeyCode)
|
|
|
|
{
|
|
|
|
if (Down)
|
|
|
|
{
|
|
|
|
TuiSwapConsole(ShiftState & SHIFT_PRESSED ? -1 : 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (VK_MENU == VirtualKeyCode && ! Down)
|
|
|
|
{
|
|
|
|
if (TuiSwapConsole(0))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-05-21 00:35:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED) || KeyState[VK_MENU] & 0x80) &&
|
|
|
|
(VirtualKeyCode == VK_ESCAPE || VirtualKeyCode == VK_TAB || VirtualKeyCode == VK_SPACE))
|
|
|
|
{
|
|
|
|
DefWindowProcW( msg->hwnd, msg->message, msg->wParam, msg->lParam);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2010-05-31 06:28:55 +00:00
|
|
|
|
|
|
|
if (NULL == Console)
|
|
|
|
{
|
|
|
|
DPRINT1("No Active Console!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-06-04 18:26:22 +00:00
|
|
|
Fake = UnicodeChar &&
|
|
|
|
(msg->message != WM_CHAR && msg->message != WM_SYSCHAR &&
|
|
|
|
msg->message != WM_KEYUP && msg->message != WM_SYSKEYUP);
|
|
|
|
NotChar = (msg->message != WM_CHAR && msg->message != WM_SYSCHAR);
|
|
|
|
if (NotChar)
|
2010-05-31 06:28:55 +00:00
|
|
|
LastVirtualKey = msg->wParam;
|
|
|
|
|
2012-11-17 21:39:41 +00:00
|
|
|
DPRINT("CONSRV: %s %s %s %s %02x %02x '%lc' %04x\n",
|
|
|
|
Down ? "down" : "up ",
|
|
|
|
(msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ?
|
|
|
|
"char" : "key ",
|
|
|
|
Fake ? "fake" : "real",
|
|
|
|
NotChar ? "notc" : "char",
|
|
|
|
VirtualScanCode,
|
|
|
|
VirtualKeyCode,
|
|
|
|
(UnicodeChar >= L' ') ? UnicodeChar : L'.',
|
|
|
|
ShiftState);
|
2010-05-31 06:28:55 +00:00
|
|
|
|
2010-06-04 18:26:22 +00:00
|
|
|
if (Fake)
|
2010-05-31 06:28:55 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* process Ctrl-C and Ctrl-Break */
|
|
|
|
if (Console->Mode & ENABLE_PROCESSED_INPUT &&
|
|
|
|
er.Event.KeyEvent.bKeyDown &&
|
|
|
|
((er.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE) ||
|
|
|
|
(er.Event.KeyEvent.wVirtualKeyCode == 'C')) &&
|
2011-05-21 00:35:53 +00:00
|
|
|
(er.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyState[VK_CONTROL] & 0x80))
|
2010-05-31 06:28:55 +00:00
|
|
|
{
|
2012-11-17 21:39:41 +00:00
|
|
|
PCONSOLE_PROCESS_DATA current;
|
2010-05-31 06:28:55 +00:00
|
|
|
PLIST_ENTRY current_entry;
|
2012-11-17 21:39:41 +00:00
|
|
|
|
2010-05-31 06:28:55 +00:00
|
|
|
DPRINT1("Console_Api Ctrl-C\n");
|
2012-11-17 21:39:41 +00:00
|
|
|
|
2010-05-31 06:28:55 +00:00
|
|
|
current_entry = Console->ProcessList.Flink;
|
|
|
|
while (current_entry != &Console->ProcessList)
|
|
|
|
{
|
2012-11-17 21:39:41 +00:00
|
|
|
current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
|
2010-05-31 06:28:55 +00:00
|
|
|
current_entry = current_entry->Flink;
|
2013-01-03 17:47:34 +00:00
|
|
|
ConioConsoleCtrlEvent((DWORD)CTRL_C_EVENT, current);
|
2010-05-31 06:28:55 +00:00
|
|
|
}
|
2010-06-08 06:38:14 +00:00
|
|
|
if (Console->LineBuffer && !Console->LineComplete)
|
|
|
|
{
|
|
|
|
/* Line input is in progress; end it */
|
|
|
|
Console->LinePos = Console->LineSize = 0;
|
|
|
|
Console->LineComplete = TRUE;
|
|
|
|
}
|
2010-05-31 06:28:55 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (0 != (er.Event.KeyEvent.dwControlKeyState
|
|
|
|
& (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
|
|
|
|
&& (VK_UP == er.Event.KeyEvent.wVirtualKeyCode
|
|
|
|
|| VK_DOWN == er.Event.KeyEvent.wVirtualKeyCode))
|
|
|
|
{
|
|
|
|
if (er.Event.KeyEvent.bKeyDown)
|
|
|
|
{
|
|
|
|
/* scroll up or down */
|
|
|
|
if (VK_UP == er.Event.KeyEvent.wVirtualKeyCode)
|
|
|
|
{
|
|
|
|
/* only scroll up if there is room to scroll up into */
|
|
|
|
if (Console->ActiveBuffer->CurrentY != Console->ActiveBuffer->MaxY - 1)
|
|
|
|
{
|
|
|
|
Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY +
|
|
|
|
Console->ActiveBuffer->MaxY - 1) %
|
|
|
|
Console->ActiveBuffer->MaxY;
|
|
|
|
Console->ActiveBuffer->CurrentY++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* only scroll down if there is room to scroll down into */
|
|
|
|
if (Console->ActiveBuffer->CurrentY != 0)
|
|
|
|
{
|
|
|
|
Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 1) %
|
|
|
|
Console->ActiveBuffer->MaxY;
|
|
|
|
Console->ActiveBuffer->CurrentY--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ConioDrawConsole(Console);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2010-06-04 18:26:22 +00:00
|
|
|
ConioProcessChar(Console, &er);
|
2010-05-31 06:28:55 +00:00
|
|
|
}
|
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
static NTSTATUS
|
|
|
|
WaitBeforeReading(IN PGET_INPUT_INFO InputInfo,
|
|
|
|
IN PCSR_API_MESSAGE ApiMessage,
|
|
|
|
IN CSR_WAIT_FUNCTION WaitFunction OPTIONAL,
|
|
|
|
IN BOOL CreateWaitBlock OPTIONAL)
|
|
|
|
{
|
|
|
|
if (CreateWaitBlock)
|
|
|
|
{
|
|
|
|
PGET_INPUT_INFO CapturedInputInfo;
|
2012-11-17 15:41:31 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
CapturedInputInfo = HeapAlloc(ConSrvHeap, 0, sizeof(GET_INPUT_INFO));
|
|
|
|
if (!CapturedInputInfo) return STATUS_NO_MEMORY;
|
2012-11-17 15:41:31 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
memmove(CapturedInputInfo, InputInfo, sizeof(GET_INPUT_INFO));
|
2012-11-17 21:39:41 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
if (!CsrCreateWait(&InputInfo->Console->ReadWaitQueue,
|
|
|
|
WaitFunction,
|
|
|
|
CsrGetClientThread(),
|
|
|
|
ApiMessage,
|
|
|
|
CapturedInputInfo,
|
|
|
|
NULL))
|
|
|
|
{
|
|
|
|
HeapFree(ConSrvHeap, 0, CapturedInputInfo);
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
2012-11-17 15:41:31 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
/* Wait for input */
|
|
|
|
return STATUS_PENDING;
|
|
|
|
}
|
2012-11-17 15:41:31 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
static NTSTATUS
|
|
|
|
ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
|
|
|
|
IN BOOL Wait,
|
|
|
|
IN PCSR_API_MESSAGE ApiMessage,
|
|
|
|
IN BOOL CreateWaitBlock OPTIONAL);
|
|
|
|
|
|
|
|
// Wait function CSR_WAIT_FUNCTION
|
|
|
|
static BOOLEAN
|
|
|
|
ReadInputBufferThread(IN PLIST_ENTRY WaitList,
|
|
|
|
IN PCSR_THREAD WaitThread,
|
|
|
|
IN PCSR_API_MESSAGE WaitApiMessage,
|
|
|
|
IN PVOID WaitContext,
|
|
|
|
IN PVOID WaitArgument1,
|
|
|
|
IN PVOID WaitArgument2,
|
|
|
|
IN ULONG WaitFlags)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
2013-01-05 23:10:12 +00:00
|
|
|
PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)WaitApiMessage)->Data.GetInputRequest;
|
2012-12-08 00:39:24 +00:00
|
|
|
PGET_INPUT_INFO InputInfo = (PGET_INPUT_INFO)WaitContext;
|
2012-11-17 21:39:41 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
Status = ReadInputBuffer(InputInfo,
|
2013-01-05 23:10:12 +00:00
|
|
|
GetInputRequest->bRead,
|
2012-12-08 00:39:24 +00:00
|
|
|
WaitApiMessage,
|
|
|
|
FALSE);
|
|
|
|
|
|
|
|
if (Status != STATUS_PENDING)
|
2012-11-17 15:41:31 +00:00
|
|
|
{
|
2012-12-08 00:39:24 +00:00
|
|
|
WaitApiMessage->Status = Status;
|
|
|
|
HeapFree(ConSrvHeap, 0, InputInfo);
|
2012-11-17 15:41:31 +00:00
|
|
|
}
|
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
return (Status == STATUS_PENDING ? FALSE : TRUE);
|
|
|
|
}
|
2012-11-17 15:41:31 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
static NTSTATUS
|
|
|
|
ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
|
|
|
|
IN BOOL Wait, // TRUE --> Read ; FALSE --> Peek
|
|
|
|
IN PCSR_API_MESSAGE ApiMessage,
|
|
|
|
IN BOOL CreateWaitBlock OPTIONAL)
|
|
|
|
{
|
|
|
|
if (IsListEmpty(&InputInfo->Console->InputEvents))
|
2012-11-17 15:41:31 +00:00
|
|
|
{
|
2012-12-08 00:39:24 +00:00
|
|
|
if (Wait)
|
|
|
|
{
|
|
|
|
return WaitBeforeReading(InputInfo,
|
|
|
|
ApiMessage,
|
|
|
|
ReadInputBufferThread,
|
|
|
|
CreateWaitBlock);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* No input available and we don't wait, so we return success */
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2012-11-17 15:41:31 +00:00
|
|
|
}
|
2012-12-08 00:39:24 +00:00
|
|
|
else
|
2012-11-17 15:41:31 +00:00
|
|
|
{
|
2013-01-05 23:10:12 +00:00
|
|
|
PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest;
|
2012-12-08 00:39:24 +00:00
|
|
|
PLIST_ENTRY CurrentInput;
|
|
|
|
ConsoleInput* Input;
|
2013-01-05 23:10:12 +00:00
|
|
|
ULONG Length = GetInputRequest->Length;
|
|
|
|
PINPUT_RECORD InputRecord = GetInputRequest->InputRecord;
|
2012-12-08 00:39:24 +00:00
|
|
|
|
|
|
|
/* Only get input if there is any */
|
|
|
|
CurrentInput = InputInfo->Console->InputEvents.Flink;
|
2012-11-17 15:41:31 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
while ( CurrentInput != &InputInfo->Console->InputEvents &&
|
2013-01-05 23:10:12 +00:00
|
|
|
GetInputRequest->InputsRead < Length )
|
2012-11-17 15:41:31 +00:00
|
|
|
{
|
2012-12-08 00:39:24 +00:00
|
|
|
Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry);
|
2012-11-17 21:39:41 +00:00
|
|
|
|
2013-01-05 23:10:12 +00:00
|
|
|
GetInputRequest->InputsRead++;
|
2012-12-08 00:39:24 +00:00
|
|
|
*InputRecord = Input->InputEvent;
|
2012-11-17 21:39:41 +00:00
|
|
|
|
2013-01-05 23:10:12 +00:00
|
|
|
if (GetInputRequest->Unicode == FALSE)
|
2012-11-17 21:39:41 +00:00
|
|
|
{
|
2012-12-08 00:39:24 +00:00
|
|
|
ConioInputEventToAnsi(InputInfo->Console, InputRecord);
|
|
|
|
}
|
2012-11-17 21:39:41 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
InputRecord++;
|
|
|
|
CurrentInput = CurrentInput->Flink;
|
2012-11-17 21:39:41 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
if (Wait) // TRUE --> Read, we remove inputs from the buffer ; FALSE --> Peek, we keep inputs.
|
|
|
|
{
|
2012-11-17 21:39:41 +00:00
|
|
|
RemoveEntryList(&Input->ListEntry);
|
2012-12-08 00:39:24 +00:00
|
|
|
HeapFree(ConSrvHeap, 0, Input);
|
|
|
|
}
|
|
|
|
}
|
2012-11-17 15:41:31 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
if (IsListEmpty(&InputInfo->Console->InputEvents))
|
|
|
|
{
|
|
|
|
ResetEvent(InputInfo->Console->ActiveEvent);
|
|
|
|
}
|
2012-11-17 21:39:41 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
/* We read all the inputs available, we return success */
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static NTSTATUS
|
|
|
|
ReadChars(IN PGET_INPUT_INFO InputInfo,
|
|
|
|
IN PCSR_API_MESSAGE ApiMessage,
|
|
|
|
IN BOOL CreateWaitBlock OPTIONAL);
|
|
|
|
|
|
|
|
// Wait function CSR_WAIT_FUNCTION
|
|
|
|
static BOOLEAN
|
|
|
|
ReadCharsThread(IN PLIST_ENTRY WaitList,
|
|
|
|
IN PCSR_THREAD WaitThread,
|
|
|
|
IN PCSR_API_MESSAGE WaitApiMessage,
|
|
|
|
IN PVOID WaitContext,
|
|
|
|
IN PVOID WaitArgument1,
|
|
|
|
IN PVOID WaitArgument2,
|
|
|
|
IN ULONG WaitFlags)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
PGET_INPUT_INFO InputInfo = (PGET_INPUT_INFO)WaitContext;
|
|
|
|
|
|
|
|
Status = ReadChars(InputInfo,
|
|
|
|
WaitApiMessage,
|
|
|
|
FALSE);
|
|
|
|
|
|
|
|
if (Status != STATUS_PENDING)
|
|
|
|
{
|
|
|
|
WaitApiMessage->Status = Status;
|
|
|
|
HeapFree(ConSrvHeap, 0, InputInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (Status == STATUS_PENDING ? FALSE : TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static NTSTATUS
|
|
|
|
ReadChars(IN PGET_INPUT_INFO InputInfo,
|
|
|
|
IN PCSR_API_MESSAGE ApiMessage,
|
|
|
|
IN BOOL CreateWaitBlock OPTIONAL)
|
|
|
|
{
|
|
|
|
BOOL WaitForMoreToRead = TRUE; // TRUE : Wait if more to read ; FALSE : Don't wait.
|
|
|
|
|
2013-01-05 23:10:12 +00:00
|
|
|
PCONSOLE_READCONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
|
2012-12-08 00:39:24 +00:00
|
|
|
PLIST_ENTRY CurrentEntry;
|
|
|
|
ConsoleInput *Input;
|
|
|
|
PCHAR Buffer = (PCHAR)ReadConsoleRequest->Buffer;
|
|
|
|
PWCHAR UnicodeBuffer = (PWCHAR)Buffer;
|
|
|
|
ULONG nNumberOfCharsToRead = ReadConsoleRequest->NrCharactersToRead;
|
|
|
|
|
|
|
|
/* We haven't read anything (yet) */
|
|
|
|
|
|
|
|
if (InputInfo->Console->Mode & ENABLE_LINE_INPUT)
|
|
|
|
{
|
|
|
|
if (InputInfo->Console->LineBuffer == NULL)
|
|
|
|
{
|
|
|
|
/* Starting a new line */
|
|
|
|
InputInfo->Console->LineMaxSize = max(256, nNumberOfCharsToRead);
|
|
|
|
InputInfo->Console->LineBuffer = HeapAlloc(ConSrvHeap, 0, InputInfo->Console->LineMaxSize * sizeof(WCHAR));
|
|
|
|
if (InputInfo->Console->LineBuffer == NULL)
|
|
|
|
{
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
}
|
|
|
|
InputInfo->Console->LineComplete = FALSE;
|
|
|
|
InputInfo->Console->LineUpPressed = FALSE;
|
|
|
|
InputInfo->Console->LineInsertToggle = 0;
|
|
|
|
InputInfo->Console->LineWakeupMask = ReadConsoleRequest->CtrlWakeupMask;
|
|
|
|
InputInfo->Console->LineSize = ReadConsoleRequest->NrCharactersRead;
|
|
|
|
InputInfo->Console->LinePos = InputInfo->Console->LineSize;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Pre-filling the buffer is only allowed in the Unicode API,
|
|
|
|
* so we don't need to worry about ANSI <-> Unicode conversion.
|
|
|
|
*/
|
|
|
|
memcpy(InputInfo->Console->LineBuffer, Buffer, InputInfo->Console->LineSize * sizeof(WCHAR));
|
|
|
|
if (InputInfo->Console->LineSize == InputInfo->Console->LineMaxSize)
|
|
|
|
{
|
|
|
|
InputInfo->Console->LineComplete = TRUE;
|
|
|
|
InputInfo->Console->LinePos = 0;
|
2012-11-17 21:39:41 +00:00
|
|
|
}
|
2012-12-08 00:39:24 +00:00
|
|
|
}
|
2012-11-17 21:39:41 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
/* If we don't have a complete line yet, process the pending input */
|
|
|
|
while ( !InputInfo->Console->LineComplete &&
|
|
|
|
!IsListEmpty(&InputInfo->Console->InputEvents) )
|
|
|
|
{
|
|
|
|
/* Remove input event from queue */
|
|
|
|
CurrentEntry = RemoveHeadList(&InputInfo->Console->InputEvents);
|
|
|
|
if (IsListEmpty(&InputInfo->Console->InputEvents))
|
|
|
|
{
|
|
|
|
ResetEvent(InputInfo->Console->ActiveEvent);
|
|
|
|
}
|
|
|
|
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
2012-11-17 21:39:41 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
/* Only pay attention to key down */
|
|
|
|
if (KEY_EVENT == Input->InputEvent.EventType
|
|
|
|
&& Input->InputEvent.Event.KeyEvent.bKeyDown)
|
2012-11-17 21:39:41 +00:00
|
|
|
{
|
2012-12-08 00:39:24 +00:00
|
|
|
LineInputKeyDown(InputInfo->Console, &Input->InputEvent.Event.KeyEvent);
|
|
|
|
ReadConsoleRequest->ControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState;
|
2012-11-17 21:39:41 +00:00
|
|
|
}
|
2012-12-08 00:39:24 +00:00
|
|
|
HeapFree(ConSrvHeap, 0, Input);
|
|
|
|
}
|
2012-11-17 15:41:31 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
/* Check if we have a complete line to read from */
|
|
|
|
if (InputInfo->Console->LineComplete)
|
|
|
|
{
|
|
|
|
while ( ReadConsoleRequest->NrCharactersRead < nNumberOfCharsToRead &&
|
|
|
|
InputInfo->Console->LinePos != InputInfo->Console->LineSize )
|
2012-11-17 21:39:41 +00:00
|
|
|
{
|
2012-12-08 00:39:24 +00:00
|
|
|
WCHAR Char = InputInfo->Console->LineBuffer[InputInfo->Console->LinePos++];
|
|
|
|
|
|
|
|
if (ReadConsoleRequest->Unicode)
|
2012-11-17 21:39:41 +00:00
|
|
|
{
|
2012-12-08 00:39:24 +00:00
|
|
|
UnicodeBuffer[ReadConsoleRequest->NrCharactersRead] = Char;
|
2012-11-17 21:39:41 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-12-08 00:39:24 +00:00
|
|
|
ConsoleInputUnicodeCharToAnsiChar(InputInfo->Console,
|
|
|
|
&Buffer[ReadConsoleRequest->NrCharactersRead],
|
|
|
|
&Char);
|
2012-11-17 21:39:41 +00:00
|
|
|
}
|
2012-12-08 00:39:24 +00:00
|
|
|
|
|
|
|
ReadConsoleRequest->NrCharactersRead++;
|
2012-11-17 21:39:41 +00:00
|
|
|
}
|
2012-12-08 00:39:24 +00:00
|
|
|
|
|
|
|
if (InputInfo->Console->LinePos == InputInfo->Console->LineSize)
|
2012-11-17 15:41:31 +00:00
|
|
|
{
|
2012-12-08 00:39:24 +00:00
|
|
|
/* Entire line has been read */
|
|
|
|
HeapFree(ConSrvHeap, 0, InputInfo->Console->LineBuffer);
|
|
|
|
InputInfo->Console->LineBuffer = NULL;
|
2012-11-17 15:41:31 +00:00
|
|
|
}
|
2012-12-08 00:39:24 +00:00
|
|
|
|
|
|
|
WaitForMoreToRead = FALSE;
|
2012-11-17 21:39:41 +00:00
|
|
|
}
|
|
|
|
}
|
2013-01-03 17:47:34 +00:00
|
|
|
else
|
2012-11-17 21:39:41 +00:00
|
|
|
{
|
2012-12-08 00:39:24 +00:00
|
|
|
/* Character input */
|
|
|
|
while ( ReadConsoleRequest->NrCharactersRead < nNumberOfCharsToRead &&
|
|
|
|
!IsListEmpty(&InputInfo->Console->InputEvents) )
|
2012-11-17 21:39:41 +00:00
|
|
|
{
|
2012-12-08 00:39:24 +00:00
|
|
|
/* Remove input event from queue */
|
|
|
|
CurrentEntry = RemoveHeadList(&InputInfo->Console->InputEvents);
|
|
|
|
if (IsListEmpty(&InputInfo->Console->InputEvents))
|
2012-11-17 21:39:41 +00:00
|
|
|
{
|
2012-12-08 00:39:24 +00:00
|
|
|
ResetEvent(InputInfo->Console->ActiveEvent);
|
|
|
|
}
|
|
|
|
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
2012-11-17 21:39:41 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
/* Only pay attention to valid ascii chars, on key down */
|
|
|
|
if (KEY_EVENT == Input->InputEvent.EventType
|
|
|
|
&& Input->InputEvent.Event.KeyEvent.bKeyDown
|
|
|
|
&& Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar != L'\0')
|
|
|
|
{
|
|
|
|
WCHAR Char = Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar;
|
2012-11-17 15:41:31 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
if (ReadConsoleRequest->Unicode)
|
2012-11-17 21:39:41 +00:00
|
|
|
{
|
2012-12-08 00:39:24 +00:00
|
|
|
UnicodeBuffer[ReadConsoleRequest->NrCharactersRead] = Char;
|
2012-11-17 21:39:41 +00:00
|
|
|
}
|
2012-12-08 00:39:24 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ConsoleInputUnicodeCharToAnsiChar(InputInfo->Console,
|
|
|
|
&Buffer[ReadConsoleRequest->NrCharactersRead],
|
|
|
|
&Char);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReadConsoleRequest->NrCharactersRead++;
|
2012-11-17 21:39:41 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
/* Did read something */
|
|
|
|
WaitForMoreToRead = FALSE;
|
2012-11-17 21:39:41 +00:00
|
|
|
}
|
2012-12-08 00:39:24 +00:00
|
|
|
HeapFree(ConSrvHeap, 0, Input);
|
2012-11-17 15:41:31 +00:00
|
|
|
}
|
2012-12-08 00:39:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* We haven't completed a read, so start a wait */
|
|
|
|
if (WaitForMoreToRead == TRUE)
|
|
|
|
{
|
|
|
|
return WaitBeforeReading(InputInfo,
|
|
|
|
ApiMessage,
|
|
|
|
ReadCharsThread,
|
|
|
|
CreateWaitBlock);
|
|
|
|
}
|
|
|
|
else /* We read all what we wanted, we return success */
|
|
|
|
{
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
2012-11-17 21:39:41 +00:00
|
|
|
|
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
/* PUBLIC APIS ****************************************************************/
|
|
|
|
|
|
|
|
CSR_API(SrvGetConsoleInput)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
2013-01-05 23:10:12 +00:00
|
|
|
PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest;
|
2012-12-08 00:39:24 +00:00
|
|
|
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
|
|
|
PCSRSS_CONSOLE Console;
|
|
|
|
GET_INPUT_INFO InputInfo;
|
|
|
|
|
|
|
|
DPRINT("SrvGetConsoleInput\n");
|
|
|
|
|
|
|
|
if (!CsrValidateMessageBuffer(ApiMessage,
|
2013-01-05 23:10:12 +00:00
|
|
|
(PVOID*)&GetInputRequest->InputRecord,
|
|
|
|
GetInputRequest->Length,
|
2012-12-08 00:39:24 +00:00
|
|
|
sizeof(INPUT_RECORD)))
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
2012-11-17 15:41:31 +00:00
|
|
|
}
|
|
|
|
|
2013-01-05 23:10:12 +00:00
|
|
|
Status = ConioLockConsole(ProcessData, GetInputRequest->InputHandle, &Console, GENERIC_READ);
|
2012-12-08 00:39:24 +00:00
|
|
|
if(!NT_SUCCESS(Status)) return Status;
|
|
|
|
|
2013-01-05 23:10:12 +00:00
|
|
|
GetInputRequest->InputsRead = 0;
|
2012-12-08 00:39:24 +00:00
|
|
|
|
|
|
|
InputInfo.ProcessData = ProcessData; // ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
|
|
|
InputInfo.Console = Console;
|
|
|
|
|
|
|
|
Status = ReadInputBuffer(&InputInfo,
|
2013-01-05 23:10:12 +00:00
|
|
|
GetInputRequest->bRead,
|
2012-12-08 00:39:24 +00:00
|
|
|
ApiMessage,
|
|
|
|
TRUE);
|
|
|
|
|
2012-11-17 15:41:31 +00:00
|
|
|
ConioUnlockConsole(Console);
|
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
if (Status == STATUS_PENDING)
|
|
|
|
*ReplyCode = CsrReplyPending;
|
|
|
|
|
2012-11-17 21:39:41 +00:00
|
|
|
return Status;
|
2012-11-17 15:41:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CSR_API(SrvWriteConsoleInput)
|
|
|
|
{
|
2012-11-17 21:39:41 +00:00
|
|
|
NTSTATUS Status;
|
2013-01-05 23:10:12 +00:00
|
|
|
PCONSOLE_WRITEINPUT WriteInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteInputRequest;
|
2012-11-17 15:41:31 +00:00
|
|
|
PINPUT_RECORD InputRecord;
|
2012-11-17 21:39:41 +00:00
|
|
|
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
2012-11-17 15:41:31 +00:00
|
|
|
PCSRSS_CONSOLE Console;
|
|
|
|
DWORD Length;
|
|
|
|
DWORD i;
|
|
|
|
|
|
|
|
DPRINT("SrvWriteConsoleInput\n");
|
|
|
|
|
2012-11-18 13:54:32 +00:00
|
|
|
if (!CsrValidateMessageBuffer(ApiMessage,
|
2013-01-05 23:10:12 +00:00
|
|
|
(PVOID*)&WriteInputRequest->InputRecord,
|
|
|
|
WriteInputRequest->Length,
|
2012-11-18 13:54:32 +00:00
|
|
|
sizeof(INPUT_RECORD)))
|
2012-11-17 15:41:31 +00:00
|
|
|
{
|
2012-11-18 13:54:32 +00:00
|
|
|
return STATUS_INVALID_PARAMETER;
|
2012-11-17 15:41:31 +00:00
|
|
|
}
|
|
|
|
|
2013-01-05 23:10:12 +00:00
|
|
|
Status = ConioLockConsole(ProcessData, WriteInputRequest->InputHandle, &Console, GENERIC_WRITE);
|
2012-11-18 13:54:32 +00:00
|
|
|
if (!NT_SUCCESS(Status)) return Status;
|
|
|
|
|
2013-01-05 23:10:12 +00:00
|
|
|
InputRecord = WriteInputRequest->InputRecord;
|
|
|
|
Length = WriteInputRequest->Length;
|
2012-11-17 15:41:31 +00:00
|
|
|
|
|
|
|
for (i = 0; i < Length && NT_SUCCESS(Status); i++)
|
|
|
|
{
|
2013-01-05 23:10:12 +00:00
|
|
|
if (!WriteInputRequest->Unicode &&
|
2012-11-17 15:41:31 +00:00
|
|
|
InputRecord->EventType == KEY_EVENT)
|
|
|
|
{
|
|
|
|
CHAR AsciiChar = InputRecord->Event.KeyEvent.uChar.AsciiChar;
|
|
|
|
ConsoleInputAnsiCharToUnicodeChar(Console,
|
|
|
|
&InputRecord->Event.KeyEvent.uChar.UnicodeChar,
|
|
|
|
&AsciiChar);
|
|
|
|
}
|
2012-11-18 13:54:32 +00:00
|
|
|
|
2012-11-17 15:41:31 +00:00
|
|
|
Status = ConioProcessChar(Console, InputRecord++);
|
|
|
|
}
|
|
|
|
|
|
|
|
ConioUnlockConsole(Console);
|
|
|
|
|
2013-01-05 23:10:12 +00:00
|
|
|
WriteInputRequest->Length = i;
|
2012-11-17 15:41:31 +00:00
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
CSR_API(SrvReadConsole)
|
|
|
|
{
|
2012-11-17 21:39:41 +00:00
|
|
|
NTSTATUS Status;
|
2013-01-05 23:10:12 +00:00
|
|
|
PCONSOLE_READCONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
|
2012-11-17 21:39:41 +00:00
|
|
|
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
2012-11-17 15:41:31 +00:00
|
|
|
PCSRSS_CONSOLE Console;
|
2012-12-08 00:39:24 +00:00
|
|
|
GET_INPUT_INFO InputInfo;
|
2012-11-17 15:41:31 +00:00
|
|
|
|
|
|
|
DPRINT("SrvReadConsole\n");
|
|
|
|
|
2012-11-17 21:39:41 +00:00
|
|
|
if (!CsrValidateMessageBuffer(ApiMessage,
|
|
|
|
(PVOID*)&ReadConsoleRequest->Buffer,
|
|
|
|
ReadConsoleRequest->BufferSize,
|
|
|
|
sizeof(BYTE)))
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
// if (Request->Data.ReadConsoleRequest.NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize)
|
|
|
|
if (ReadConsoleRequest->NrCharactersRead > ReadConsoleRequest->NrCharactersToRead)
|
2012-11-17 21:39:41 +00:00
|
|
|
{
|
2012-12-08 00:39:24 +00:00
|
|
|
return STATUS_INVALID_PARAMETER;
|
2012-11-17 21:39:41 +00:00
|
|
|
}
|
|
|
|
|
2013-01-05 23:10:12 +00:00
|
|
|
Status = ConioLockConsole(ProcessData, ReadConsoleRequest->InputHandle, &Console, GENERIC_READ);
|
2012-12-08 00:39:24 +00:00
|
|
|
if (!NT_SUCCESS(Status)) return Status;
|
2012-11-17 15:41:31 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
ReadConsoleRequest->NrCharactersRead = 0;
|
2012-11-17 15:41:31 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
InputInfo.ProcessData = ProcessData; // ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
|
|
|
InputInfo.Console = Console;
|
2012-11-17 15:41:31 +00:00
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
Status = ReadChars(&InputInfo,
|
|
|
|
ApiMessage,
|
|
|
|
TRUE);
|
2010-05-31 06:28:55 +00:00
|
|
|
|
|
|
|
ConioUnlockConsole(Console);
|
|
|
|
|
2012-12-08 00:39:24 +00:00
|
|
|
if (Status == STATUS_PENDING)
|
|
|
|
*ReplyCode = CsrReplyPending;
|
|
|
|
|
2010-05-31 06:28:55 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2012-10-22 23:55:51 +00:00
|
|
|
CSR_API(SrvFlushConsoleInputBuffer)
|
2010-05-31 06:28:55 +00:00
|
|
|
{
|
2012-11-17 21:39:41 +00:00
|
|
|
NTSTATUS Status;
|
2013-01-05 23:10:12 +00:00
|
|
|
PCONSOLE_FLUSHINPUTBUFFER FlushInputBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FlushInputBufferRequest;
|
2010-05-31 06:28:55 +00:00
|
|
|
PLIST_ENTRY CurrentEntry;
|
|
|
|
PCSRSS_CONSOLE Console;
|
|
|
|
ConsoleInput* Input;
|
|
|
|
|
2012-10-22 23:55:51 +00:00
|
|
|
DPRINT("SrvFlushConsoleInputBuffer\n");
|
2010-05-31 06:28:55 +00:00
|
|
|
|
2012-11-17 21:39:41 +00:00
|
|
|
Status = ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
2013-01-05 23:10:12 +00:00
|
|
|
FlushInputBufferRequest->InputHandle,
|
2010-05-31 06:28:55 +00:00
|
|
|
&Console,
|
|
|
|
GENERIC_WRITE);
|
2012-11-17 21:39:41 +00:00
|
|
|
if(!NT_SUCCESS(Status)) return Status;
|
2010-05-31 06:28:55 +00:00
|
|
|
|
|
|
|
/* Discard all entries in the input event queue */
|
|
|
|
while (!IsListEmpty(&Console->InputEvents))
|
|
|
|
{
|
|
|
|
CurrentEntry = RemoveHeadList(&Console->InputEvents);
|
|
|
|
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
|
|
|
/* Destroy the event */
|
2012-10-22 23:55:51 +00:00
|
|
|
HeapFree(ConSrvHeap, 0, Input);
|
2010-05-31 06:28:55 +00:00
|
|
|
}
|
|
|
|
ResetEvent(Console->ActiveEvent);
|
|
|
|
|
|
|
|
ConioUnlockConsole(Console);
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-10-22 23:55:51 +00:00
|
|
|
CSR_API(SrvGetConsoleNumberOfInputEvents)
|
2010-05-31 06:28:55 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
2013-01-05 23:10:12 +00:00
|
|
|
PCONSOLE_GETNUMINPUTEVENTS GetNumInputEventsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetNumInputEventsRequest;
|
2010-05-31 06:28:55 +00:00
|
|
|
PCSRSS_CONSOLE Console;
|
2012-11-17 21:39:41 +00:00
|
|
|
PLIST_ENTRY CurrentInput;
|
2010-05-31 06:28:55 +00:00
|
|
|
DWORD NumEvents;
|
|
|
|
|
2012-10-22 23:55:51 +00:00
|
|
|
DPRINT("SrvGetConsoleNumberOfInputEvents\n");
|
2010-05-31 06:28:55 +00:00
|
|
|
|
2013-01-05 23:10:12 +00:00
|
|
|
Status = ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), GetNumInputEventsRequest->InputHandle, &Console, GENERIC_READ);
|
2012-11-17 21:39:41 +00:00
|
|
|
if (!NT_SUCCESS(Status)) return Status;
|
2010-05-31 06:28:55 +00:00
|
|
|
|
2012-11-17 21:39:41 +00:00
|
|
|
CurrentInput = Console->InputEvents.Flink;
|
2010-05-31 06:28:55 +00:00
|
|
|
NumEvents = 0;
|
|
|
|
|
|
|
|
/* If there are any events ... */
|
2012-11-17 21:39:41 +00:00
|
|
|
while (CurrentInput != &Console->InputEvents)
|
2010-05-31 06:28:55 +00:00
|
|
|
{
|
2012-11-17 21:39:41 +00:00
|
|
|
CurrentInput = CurrentInput->Flink;
|
2010-06-04 18:26:22 +00:00
|
|
|
NumEvents++;
|
2010-05-31 06:28:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ConioUnlockConsole(Console);
|
|
|
|
|
2012-10-23 22:31:36 +00:00
|
|
|
GetNumInputEventsRequest->NumInputEvents = NumEvents;
|
2010-05-31 06:28:55 +00:00
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|