* PROGRAMMERS:
*/
-/* INCLUDES ******************************************************************/
+/* INCLUDES *******************************************************************/
#include "consrv.h"
#include "conio.h"
#define NDEBUG
#include <debug.h>
-/* GLOBALS *******************************************************************/
+
+/* GLOBALS ********************************************************************/
#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)
-/* FUNCTIONS *****************************************************************/
-CSR_API(SrvReadConsole)
+typedef struct _GET_INPUT_INFO
{
- PCSRSS_READ_CONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
- PLIST_ENTRY CurrentEntry;
- ConsoleInput *Input;
- PCHAR Buffer;
- PWCHAR UnicodeBuffer;
- ULONG i = 0;
- ULONG nNumberOfCharsToRead, CharSize;
- PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
+ PCONSOLE_PROCESS_DATA ProcessData;
PCSRSS_CONSOLE Console;
- NTSTATUS Status;
-
- DPRINT("SrvReadConsole\n");
-
- CharSize = (ReadConsoleRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
-
- nNumberOfCharsToRead = ReadConsoleRequest->NrCharactersToRead;
-
- Buffer = (PCHAR)ReadConsoleRequest->Buffer;
- UnicodeBuffer = (PWCHAR)Buffer;
- if (!Win32CsrValidateBuffer(ProcessData, Buffer, nNumberOfCharsToRead, CharSize))
- return STATUS_ACCESS_VIOLATION;
-
- if (ReadConsoleRequest->NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize)
- return STATUS_INVALID_PARAMETER;
-
- Status = ConioLockConsole(ProcessData, ReadConsoleRequest->ConsoleHandle,
- &Console, GENERIC_READ);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
- ReadConsoleRequest->EventHandle = ProcessData->ConsoleEvent;
-
- Status = STATUS_PENDING; /* we haven't read anything (yet) */
- if (Console->Mode & ENABLE_LINE_INPUT)
- {
- if (Console->LineBuffer == NULL)
- {
- /* Starting a new line */
- Console->LineMaxSize = max(256, nNumberOfCharsToRead);
- Console->LineBuffer = HeapAlloc(ConSrvHeap, 0, Console->LineMaxSize * sizeof(WCHAR));
- if (Console->LineBuffer == NULL)
- {
- Status = STATUS_NO_MEMORY;
- goto done;
- }
- Console->LineComplete = FALSE;
- Console->LineUpPressed = FALSE;
- Console->LineInsertToggle = 0;
- Console->LineWakeupMask = ReadConsoleRequest->CtrlWakeupMask;
- Console->LineSize = ReadConsoleRequest->NrCharactersRead;
- Console->LinePos = Console->LineSize;
- /* pre-filling the buffer is only allowed in the Unicode API,
- * so we don't need to worry about conversion */
- memcpy(Console->LineBuffer, Buffer, Console->LineSize * sizeof(WCHAR));
- if (Console->LineSize == Console->LineMaxSize)
- {
- Console->LineComplete = TRUE;
- Console->LinePos = 0;
- }
- }
+} GET_INPUT_INFO, *PGET_INPUT_INFO;
- /* If we don't have a complete line yet, process the pending input */
- while (!Console->LineComplete && !IsListEmpty(&Console->InputEvents))
- {
- /* remove input event from queue */
- CurrentEntry = RemoveHeadList(&Console->InputEvents);
- if (IsListEmpty(&Console->InputEvents))
- {
- ResetEvent(Console->ActiveEvent);
- }
- Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
- /* only pay attention to key down */
- if (KEY_EVENT == Input->InputEvent.EventType
- && Input->InputEvent.Event.KeyEvent.bKeyDown)
- {
- LineInputKeyDown(Console, &Input->InputEvent.Event.KeyEvent);
- ReadConsoleRequest->ControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState;
- }
- HeapFree(ConSrvHeap, 0, Input);
- }
-
- /* Check if we have a complete line to read from */
- if (Console->LineComplete)
- {
- while (i < nNumberOfCharsToRead && Console->LinePos != Console->LineSize)
- {
- WCHAR Char = Console->LineBuffer[Console->LinePos++];
- if (ReadConsoleRequest->Unicode)
- UnicodeBuffer[i++] = Char;
- else
- ConsoleInputUnicodeCharToAnsiChar(Console, &Buffer[i++], &Char);
- }
- if (Console->LinePos == Console->LineSize)
- {
- /* Entire line has been read */
- HeapFree(ConSrvHeap, 0, Console->LineBuffer);
- Console->LineBuffer = NULL;
- }
- Status = STATUS_SUCCESS;
- }
- }
- else
- {
- /* Character input */
- while (i < nNumberOfCharsToRead && !IsListEmpty(&Console->InputEvents))
- {
- /* remove input event from queue */
- CurrentEntry = RemoveHeadList(&Console->InputEvents);
- if (IsListEmpty(&Console->InputEvents))
- {
- ResetEvent(Console->ActiveEvent);
- }
- Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
-
- /* 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;
- if (ReadConsoleRequest->Unicode)
- UnicodeBuffer[i++] = Char;
- else
- ConsoleInputUnicodeCharToAnsiChar(Console, &Buffer[i++], &Char);
- Status = STATUS_SUCCESS; /* did read something */
- }
- HeapFree(ConSrvHeap, 0, Input);
- }
- }
-done:
- ReadConsoleRequest->NrCharactersRead = i;
- ConioUnlockConsole(Console);
-
- return Status;
-}
+/* PRIVATE FUNCTIONS **********************************************************/
static VOID FASTCALL
ConioInputEventToAnsi(PCSRSS_CONSOLE Console, PINPUT_RECORD InputEvent)
return STATUS_INSUFFICIENT_RESOURCES;
ConInRec->InputEvent = *InputEvent;
InsertTailList(&Console->InputEvents, &ConInRec->ListEntry);
+
SetEvent(Console->ActiveEvent);
+ CsrNotifyWait(&Console->ReadWaitQueue,
+ WaitAny,
+ NULL,
+ NULL);
+
return STATUS_SUCCESS;
}
if (NotChar)
LastVirtualKey = msg->wParam;
- DPRINT ("csrss: %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);
+ 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);
if (Fake)
return;
(er.Event.KeyEvent.wVirtualKeyCode == 'C')) &&
(er.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyState[VK_CONTROL] & 0x80))
{
- PCSR_PROCESS current;
+ PCONSOLE_PROCESS_DATA current;
PLIST_ENTRY current_entry;
+
DPRINT1("Console_Api Ctrl-C\n");
+
current_entry = Console->ProcessList.Flink;
while (current_entry != &Console->ProcessList)
{
- current = CONTAINING_RECORD(current_entry, CSR_PROCESS, ConsoleLink);
+ current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
current_entry = current_entry->Flink;
ConioConsoleCtrlEvent((DWORD)CTRL_C_EVENT, current);
}
ConioProcessChar(Console, &er);
}
-CSR_API(CsrReadInputEvent)
+static NTSTATUS
+WaitBeforeReading(IN PGET_INPUT_INFO InputInfo,
+ IN PCSR_API_MESSAGE ApiMessage,
+ IN CSR_WAIT_FUNCTION WaitFunction OPTIONAL,
+ IN BOOL CreateWaitBlock OPTIONAL)
{
- PCSRSS_READ_INPUT ReadInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadInputRequest;
- PLIST_ENTRY CurrentEntry;
- PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
- PCSRSS_CONSOLE Console;
- NTSTATUS Status;
- BOOLEAN Done = FALSE;
- ConsoleInput *Input;
+ if (CreateWaitBlock)
+ {
+ PGET_INPUT_INFO CapturedInputInfo;
- DPRINT("CsrReadInputEvent\n");
+ CapturedInputInfo = HeapAlloc(ConSrvHeap, 0, sizeof(GET_INPUT_INFO));
+ if (!CapturedInputInfo) return STATUS_NO_MEMORY;
- ReadInputRequest->Event = ProcessData->ConsoleEvent;
+ memmove(CapturedInputInfo, InputInfo, sizeof(GET_INPUT_INFO));
- Status = ConioLockConsole(ProcessData, ReadInputRequest->ConsoleHandle, &Console, GENERIC_READ);
- if (! NT_SUCCESS(Status))
- {
- return Status;
+ if (!CsrCreateWait(&InputInfo->Console->ReadWaitQueue,
+ WaitFunction,
+ CsrGetClientThread(),
+ ApiMessage,
+ CapturedInputInfo,
+ NULL))
+ {
+ HeapFree(ConSrvHeap, 0, CapturedInputInfo);
+ return STATUS_NO_MEMORY;
+ }
}
- /* only get input if there is any */
- CurrentEntry = Console->InputEvents.Flink;
- while (CurrentEntry != &Console->InputEvents)
+ /* Wait for input */
+ return STATUS_PENDING;
+}
+
+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;
+ PCSRSS_GET_CONSOLE_INPUT GetConsoleInputRequest = &((PCONSOLE_API_MESSAGE)WaitApiMessage)->Data.GetConsoleInputRequest;
+ PGET_INPUT_INFO InputInfo = (PGET_INPUT_INFO)WaitContext;
+
+ Status = ReadInputBuffer(InputInfo,
+ GetConsoleInputRequest->bRead,
+ WaitApiMessage,
+ FALSE);
+
+ if (Status != STATUS_PENDING)
{
- Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
- CurrentEntry = CurrentEntry->Flink;
+ WaitApiMessage->Status = Status;
+ HeapFree(ConSrvHeap, 0, InputInfo);
+ }
+
+ return (Status == STATUS_PENDING ? FALSE : TRUE);
+}
- if (Done)
+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))
+ {
+ if (Wait)
+ {
+ return WaitBeforeReading(InputInfo,
+ ApiMessage,
+ ReadInputBufferThread,
+ CreateWaitBlock);
+ }
+ else
{
- ReadInputRequest->MoreEvents = TRUE;
- break;
+ /* No input available and we don't wait, so we return success */
+ return STATUS_SUCCESS;
}
+ }
+ else
+ {
+ PCSRSS_GET_CONSOLE_INPUT GetConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputRequest;
+ PLIST_ENTRY CurrentInput;
+ ConsoleInput* Input;
+ ULONG Length = GetConsoleInputRequest->Length;
+ PINPUT_RECORD InputRecord = GetConsoleInputRequest->InputRecord;
- RemoveEntryList(&Input->ListEntry);
+ /* Only get input if there is any */
+ CurrentInput = InputInfo->Console->InputEvents.Flink;
- if (!Done)
+ while ( CurrentInput != &InputInfo->Console->InputEvents &&
+ GetConsoleInputRequest->InputsRead < Length )
{
- ReadInputRequest->Input = Input->InputEvent;
- if (ReadInputRequest->Unicode == FALSE)
+ Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry);
+
+ GetConsoleInputRequest->InputsRead++;
+ *InputRecord = Input->InputEvent;
+
+ if (GetConsoleInputRequest->Unicode == FALSE)
{
- ConioInputEventToAnsi(Console, &ReadInputRequest->Input);
+ ConioInputEventToAnsi(InputInfo->Console, InputRecord);
+ }
+
+ InputRecord++;
+ CurrentInput = CurrentInput->Flink;
+
+ if (Wait) // TRUE --> Read, we remove inputs from the buffer ; FALSE --> Peek, we keep inputs.
+ {
+ RemoveEntryList(&Input->ListEntry);
+ HeapFree(ConSrvHeap, 0, Input);
}
- Done = TRUE;
}
- HeapFree(ConSrvHeap, 0, Input);
+ if (IsListEmpty(&InputInfo->Console->InputEvents))
+ {
+ ResetEvent(InputInfo->Console->ActiveEvent);
+ }
+
+ /* We read all the inputs available, we return success */
+ return STATUS_SUCCESS;
}
+}
- if (Done)
- Status = STATUS_SUCCESS;
- else
- Status = STATUS_PENDING;
+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 (IsListEmpty(&Console->InputEvents))
+ if (Status != STATUS_PENDING)
{
- ResetEvent(Console->ActiveEvent);
+ WaitApiMessage->Status = Status;
+ HeapFree(ConSrvHeap, 0, InputInfo);
}
- ConioUnlockConsole(Console);
-
- return Status;
+ return (Status == STATUS_PENDING ? FALSE : TRUE);
}
-CSR_API(SrvFlushConsoleInputBuffer)
+static NTSTATUS
+ReadChars(IN PGET_INPUT_INFO InputInfo,
+ IN PCSR_API_MESSAGE ApiMessage,
+ IN BOOL CreateWaitBlock OPTIONAL)
{
- PCSRSS_FLUSH_INPUT_BUFFER FlushInputBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FlushInputBufferRequest;
+ BOOL WaitForMoreToRead = TRUE; // TRUE : Wait if more to read ; FALSE : Don't wait.
+
+ PCSRSS_READ_CONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
PLIST_ENTRY CurrentEntry;
- PCSRSS_CONSOLE Console;
- ConsoleInput* Input;
- NTSTATUS Status;
+ ConsoleInput *Input;
+ PCHAR Buffer = (PCHAR)ReadConsoleRequest->Buffer;
+ PWCHAR UnicodeBuffer = (PWCHAR)Buffer;
+ ULONG nNumberOfCharsToRead = ReadConsoleRequest->NrCharactersToRead;
- DPRINT("SrvFlushConsoleInputBuffer\n");
+ /* We haven't read anything (yet) */
- Status = ConioLockConsole(CsrGetClientThread()->Process,
- FlushInputBufferRequest->ConsoleInput,
- &Console,
- GENERIC_WRITE);
- if(! NT_SUCCESS(Status))
+ if (InputInfo->Console->Mode & ENABLE_LINE_INPUT)
{
- return Status;
- }
+ 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;
+ }
+ }
- /* 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 */
- HeapFree(ConSrvHeap, 0, Input);
- }
- ResetEvent(Console->ActiveEvent);
+ /* 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);
- ConioUnlockConsole(Console);
+ /* Only pay attention to key down */
+ if (KEY_EVENT == Input->InputEvent.EventType
+ && Input->InputEvent.Event.KeyEvent.bKeyDown)
+ {
+ LineInputKeyDown(InputInfo->Console, &Input->InputEvent.Event.KeyEvent);
+ ReadConsoleRequest->ControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState;
+ }
+ HeapFree(ConSrvHeap, 0, Input);
+ }
- return STATUS_SUCCESS;
-}
+ /* Check if we have a complete line to read from */
+ if (InputInfo->Console->LineComplete)
+ {
+ while ( ReadConsoleRequest->NrCharactersRead < nNumberOfCharsToRead &&
+ InputInfo->Console->LinePos != InputInfo->Console->LineSize )
+ {
+ WCHAR Char = InputInfo->Console->LineBuffer[InputInfo->Console->LinePos++];
-CSR_API(SrvGetConsoleNumberOfInputEvents)
-{
- NTSTATUS Status;
- PCSRSS_GET_NUM_INPUT_EVENTS GetNumInputEventsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetNumInputEventsRequest;
- PCSRSS_CONSOLE Console;
- PLIST_ENTRY CurrentItem;
- DWORD NumEvents;
+ if (ReadConsoleRequest->Unicode)
+ {
+ UnicodeBuffer[ReadConsoleRequest->NrCharactersRead] = Char;
+ }
+ else
+ {
+ ConsoleInputUnicodeCharToAnsiChar(InputInfo->Console,
+ &Buffer[ReadConsoleRequest->NrCharactersRead],
+ &Char);
+ }
- DPRINT("SrvGetConsoleNumberOfInputEvents\n");
+ ReadConsoleRequest->NrCharactersRead++;
+ }
- Status = ConioLockConsole(CsrGetClientThread()->Process, GetNumInputEventsRequest->ConsoleHandle, &Console, GENERIC_READ);
- if (! NT_SUCCESS(Status))
- {
- return Status;
+ if (InputInfo->Console->LinePos == InputInfo->Console->LineSize)
+ {
+ /* Entire line has been read */
+ HeapFree(ConSrvHeap, 0, InputInfo->Console->LineBuffer);
+ InputInfo->Console->LineBuffer = NULL;
+ }
+
+ WaitForMoreToRead = FALSE;
+ }
}
+ else
+ {
+ /* Character input */
+ while ( ReadConsoleRequest->NrCharactersRead < nNumberOfCharsToRead &&
+ !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);
- CurrentItem = Console->InputEvents.Flink;
- NumEvents = 0;
+ /* 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;
- /* If there are any events ... */
- while (CurrentItem != &Console->InputEvents)
- {
- CurrentItem = CurrentItem->Flink;
- NumEvents++;
- }
+ if (ReadConsoleRequest->Unicode)
+ {
+ UnicodeBuffer[ReadConsoleRequest->NrCharactersRead] = Char;
+ }
+ else
+ {
+ ConsoleInputUnicodeCharToAnsiChar(InputInfo->Console,
+ &Buffer[ReadConsoleRequest->NrCharactersRead],
+ &Char);
+ }
- ConioUnlockConsole(Console);
+ ReadConsoleRequest->NrCharactersRead++;
- GetNumInputEventsRequest->NumInputEvents = NumEvents;
+ /* Did read something */
+ WaitForMoreToRead = FALSE;
+ }
+ HeapFree(ConSrvHeap, 0, Input);
+ }
+ }
- return STATUS_SUCCESS;
+ /* 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;
+ }
}
+
+/* PUBLIC APIS ****************************************************************/
+
CSR_API(SrvGetConsoleInput)
{
NTSTATUS Status;
- PCSRSS_PEEK_CONSOLE_INPUT PeekConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.PeekConsoleInputRequest;
- PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
+ PCSRSS_GET_CONSOLE_INPUT GetConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputRequest;
+ PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
PCSRSS_CONSOLE Console;
- DWORD Length;
- PLIST_ENTRY CurrentItem;
- PINPUT_RECORD InputRecord;
- ConsoleInput* Item;
- UINT NumItems;
+ GET_INPUT_INFO InputInfo;
DPRINT("SrvGetConsoleInput\n");
- Status = ConioLockConsole(ProcessData, PeekConsoleInputRequest->ConsoleHandle, &Console, GENERIC_READ);
- if(! NT_SUCCESS(Status))
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&GetConsoleInputRequest->InputRecord,
+ GetConsoleInputRequest->Length,
+ sizeof(INPUT_RECORD)))
{
- return Status;
- }
-
- InputRecord = PeekConsoleInputRequest->InputRecord;
- Length = PeekConsoleInputRequest->Length;
-
- if (!Win32CsrValidateBuffer(ProcessData, InputRecord, Length, sizeof(INPUT_RECORD)))
- {
- ConioUnlockConsole(Console);
- return STATUS_ACCESS_VIOLATION;
+ return STATUS_INVALID_PARAMETER;
}
- NumItems = 0;
-
- if (! IsListEmpty(&Console->InputEvents))
- {
- CurrentItem = Console->InputEvents.Flink;
-
- while (CurrentItem != &Console->InputEvents && NumItems < Length)
- {
- Item = CONTAINING_RECORD(CurrentItem, ConsoleInput, ListEntry);
+ Status = ConioLockConsole(ProcessData, GetConsoleInputRequest->ConsoleHandle, &Console, GENERIC_READ);
+ if(!NT_SUCCESS(Status)) return Status;
- ++NumItems;
- *InputRecord = Item->InputEvent;
+ GetConsoleInputRequest->InputsRead = 0;
- if (PeekConsoleInputRequest->Unicode == FALSE)
- {
- ConioInputEventToAnsi(Console, InputRecord);
- }
+ InputInfo.ProcessData = ProcessData; // ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+ InputInfo.Console = Console;
- InputRecord++;
- CurrentItem = CurrentItem->Flink;
- }
- }
+ Status = ReadInputBuffer(&InputInfo,
+ GetConsoleInputRequest->bRead,
+ ApiMessage,
+ TRUE);
ConioUnlockConsole(Console);
- PeekConsoleInputRequest->Length = NumItems;
+ if (Status == STATUS_PENDING)
+ *ReplyCode = CsrReplyPending;
- return STATUS_SUCCESS;
+ return Status;
}
CSR_API(SrvWriteConsoleInput)
{
+ NTSTATUS Status;
PCSRSS_WRITE_CONSOLE_INPUT WriteConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleInputRequest;
PINPUT_RECORD InputRecord;
- PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
+ PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
PCSRSS_CONSOLE Console;
- NTSTATUS Status;
DWORD Length;
DWORD i;
DPRINT("SrvWriteConsoleInput\n");
- Status = ConioLockConsole(ProcessData, WriteConsoleInputRequest->ConsoleHandle, &Console, GENERIC_WRITE);
- if (! NT_SUCCESS(Status))
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&WriteConsoleInputRequest->InputRecord,
+ WriteConsoleInputRequest->Length,
+ sizeof(INPUT_RECORD)))
{
- return Status;
+ return STATUS_INVALID_PARAMETER;
}
+ Status = ConioLockConsole(ProcessData, WriteConsoleInputRequest->ConsoleHandle, &Console, GENERIC_WRITE);
+ if (!NT_SUCCESS(Status)) return Status;
+
InputRecord = WriteConsoleInputRequest->InputRecord;
Length = WriteConsoleInputRequest->Length;
- if (!Win32CsrValidateBuffer(ProcessData, InputRecord, Length, sizeof(INPUT_RECORD)))
- {
- ConioUnlockConsole(Console);
- return STATUS_ACCESS_VIOLATION;
- }
-
for (i = 0; i < Length && NT_SUCCESS(Status); i++)
{
if (!WriteConsoleInputRequest->Unicode &&
&InputRecord->Event.KeyEvent.uChar.UnicodeChar,
&AsciiChar);
}
+
Status = ConioProcessChar(Console, InputRecord++);
}
return Status;
}
+CSR_API(SrvReadConsole)
+{
+ NTSTATUS Status;
+ PCSRSS_READ_CONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
+ PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+ PCSRSS_CONSOLE Console;
+ GET_INPUT_INFO InputInfo;
+
+ DPRINT("SrvReadConsole\n");
+
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&ReadConsoleRequest->Buffer,
+ ReadConsoleRequest->BufferSize,
+ sizeof(BYTE)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ // if (Request->Data.ReadConsoleRequest.NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize)
+ if (ReadConsoleRequest->NrCharactersRead > ReadConsoleRequest->NrCharactersToRead)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Status = ConioLockConsole(ProcessData, ReadConsoleRequest->ConsoleHandle, &Console, GENERIC_READ);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ ReadConsoleRequest->NrCharactersRead = 0;
+
+ InputInfo.ProcessData = ProcessData; // ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+ InputInfo.Console = Console;
+
+ Status = ReadChars(&InputInfo,
+ ApiMessage,
+ TRUE);
+
+ ConioUnlockConsole(Console);
+
+ if (Status == STATUS_PENDING)
+ *ReplyCode = CsrReplyPending;
+
+ return Status;
+}
+
+CSR_API(SrvFlushConsoleInputBuffer)
+{
+ NTSTATUS Status;
+ PCSRSS_FLUSH_INPUT_BUFFER FlushInputBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FlushInputBufferRequest;
+ PLIST_ENTRY CurrentEntry;
+ PCSRSS_CONSOLE Console;
+ ConsoleInput* Input;
+
+ DPRINT("SrvFlushConsoleInputBuffer\n");
+
+ Status = ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ FlushInputBufferRequest->ConsoleInput,
+ &Console,
+ GENERIC_WRITE);
+ if(!NT_SUCCESS(Status)) return Status;
+
+ /* 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 */
+ HeapFree(ConSrvHeap, 0, Input);
+ }
+ ResetEvent(Console->ActiveEvent);
+
+ ConioUnlockConsole(Console);
+
+ return STATUS_SUCCESS;
+}
+
+CSR_API(SrvGetConsoleNumberOfInputEvents)
+{
+ NTSTATUS Status;
+ PCSRSS_GET_NUM_INPUT_EVENTS GetNumInputEventsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetNumInputEventsRequest;
+ PCSRSS_CONSOLE Console;
+ PLIST_ENTRY CurrentInput;
+ DWORD NumEvents;
+
+ DPRINT("SrvGetConsoleNumberOfInputEvents\n");
+
+ Status = ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), GetNumInputEventsRequest->ConsoleHandle, &Console, GENERIC_READ);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ CurrentInput = Console->InputEvents.Flink;
+ NumEvents = 0;
+
+ /* If there are any events ... */
+ while (CurrentInput != &Console->InputEvents)
+ {
+ CurrentInput = CurrentInput->Flink;
+ NumEvents++;
+ }
+
+ ConioUnlockConsole(Console);
+
+ GetNumInputEventsRequest->NumInputEvents = NumEvents;
+
+ return STATUS_SUCCESS;
+}
+
/* EOF */