MultiByteToWideChar((Console)->CodePage, 0, (sChar), 1, (dWChar), 1)
+typedef struct _GET_INPUT_INFO
+{
+ PCONSOLE_PROCESS_DATA ProcessData;
+ PCSRSS_CONSOLE Console;
+} GET_INPUT_INFO, *PGET_INPUT_INFO;
+
+
/* PRIVATE FUNCTIONS **********************************************************/
static VOID FASTCALL
return STATUS_INSUFFICIENT_RESOURCES;
ConInRec->InputEvent = *InputEvent;
InsertTailList(&Console->InputEvents, &ConInRec->ListEntry);
+
SetEvent(Console->ActiveEvent);
+ CsrNotifyWait(&Console->ReadWaitQueue,
+ WaitAny,
+ NULL,
+ NULL);
+
return STATUS_SUCCESS;
}
ConioProcessChar(Console, &er);
}
+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;
-/* PUBLIC APIS ****************************************************************/
+ CapturedInputInfo = HeapAlloc(ConSrvHeap, 0, sizeof(GET_INPUT_INFO));
+ if (!CapturedInputInfo) return STATUS_NO_MEMORY;
-CSR_API(SrvGetConsoleInput)
-{
- NTSTATUS Status;
- PCSRSS_GET_CONSOLE_INPUT GetConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputRequest;
- PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
- PCSRSS_CONSOLE Console;
- PLIST_ENTRY CurrentInput;
- ConsoleInput* Input;
+ memmove(CapturedInputInfo, InputInfo, sizeof(GET_INPUT_INFO));
- DWORD Length;
- PINPUT_RECORD InputRecord;
+ if (!CsrCreateWait(&InputInfo->Console->ReadWaitQueue,
+ WaitFunction,
+ CsrGetClientThread(),
+ ApiMessage,
+ CapturedInputInfo,
+ NULL))
+ {
+ HeapFree(ConSrvHeap, 0, CapturedInputInfo);
+ return STATUS_NO_MEMORY;
+ }
+ }
- DPRINT("SrvGetConsoleInput\n");
+ /* Wait for input */
+ return STATUS_PENDING;
+}
- Status = ConioLockConsole(ProcessData, GetConsoleInputRequest->ConsoleHandle, &Console, GENERIC_READ);
- if(!NT_SUCCESS(Status)) return Status;
+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;
- if (!CsrValidateMessageBuffer(ApiMessage,
- (PVOID*)&GetConsoleInputRequest->InputRecord,
- GetConsoleInputRequest->Length,
- sizeof(INPUT_RECORD)))
+ Status = ReadInputBuffer(InputInfo,
+ GetConsoleInputRequest->bRead,
+ WaitApiMessage,
+ FALSE);
+
+ if (Status != STATUS_PENDING)
{
- return STATUS_INVALID_PARAMETER;
+ WaitApiMessage->Status = Status;
+ HeapFree(ConSrvHeap, 0, InputInfo);
}
- InputRecord = GetConsoleInputRequest->InputRecord;
- Length = GetConsoleInputRequest->Length;
+ return (Status == STATUS_PENDING ? FALSE : TRUE);
+}
-/*
- if (!Win32CsrValidateBuffer(ProcessData->Process, InputRecord, Length, sizeof(INPUT_RECORD)))
+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))
{
- ConioUnlockConsole(Console);
- return STATUS_ACCESS_VIOLATION;
+ if (Wait)
+ {
+ return WaitBeforeReading(InputInfo,
+ ApiMessage,
+ ReadInputBufferThread,
+ CreateWaitBlock);
+ }
+ else
+ {
+ /* No input available and we don't wait, so we return success */
+ return STATUS_SUCCESS;
+ }
}
-*/
-
- if (GetConsoleInputRequest->bRead) // Read input.
+ else
{
- GetConsoleInputRequest->Event = ProcessData->ConsoleEvent;
+ 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;
- while (Length > 0)
+ /* Only get input if there is any */
+ CurrentInput = InputInfo->Console->InputEvents.Flink;
+
+ while ( CurrentInput != &InputInfo->Console->InputEvents &&
+ GetConsoleInputRequest->InputsRead < Length )
{
- BOOLEAN Done = FALSE;
+ Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry);
- // GetConsoleInputRequest->Event = ProcessData->ConsoleEvent;
+ GetConsoleInputRequest->InputsRead++;
+ *InputRecord = Input->InputEvent;
- /* only get input if there is any */
- CurrentInput = Console->InputEvents.Flink;
- while (CurrentInput != &Console->InputEvents)
+ if (GetConsoleInputRequest->Unicode == FALSE)
{
- Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry);
- CurrentInput = CurrentInput->Flink;
+ ConioInputEventToAnsi(InputInfo->Console, InputRecord);
+ }
- if (Done)
- {
- GetConsoleInputRequest->MoreEvents = TRUE;
- break;
- }
+ 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);
+ }
+ }
- if (!Done)
- {
- GetConsoleInputRequest->InputsRead++;
- *InputRecord = Input->InputEvent;
- /* HACK */ Length--;
-
- // GetConsoleInputRequest->Input = Input->InputEvent;
- if (GetConsoleInputRequest->Unicode == FALSE)
- {
- // ConioInputEventToAnsi(Console, &GetConsoleInputRequest->Input);
- ConioInputEventToAnsi(Console, InputRecord);
- }
-
- InputRecord++;
- Done = TRUE;
- }
+ if (IsListEmpty(&InputInfo->Console->InputEvents))
+ {
+ ResetEvent(InputInfo->Console->ActiveEvent);
+ }
- HeapFree(ConSrvHeap, 0, Input);
+ /* 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.
+
+ PCSRSS_READ_CONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
+ 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;
+ }
+ }
- if (Done)
- Status = STATUS_SUCCESS;
- else
- Status = STATUS_PENDING;
+ /* 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);
- if (IsListEmpty(&Console->InputEvents))
+ /* Only pay attention to key down */
+ if (KEY_EVENT == Input->InputEvent.EventType
+ && Input->InputEvent.Event.KeyEvent.bKeyDown)
{
- ResetEvent(Console->ActiveEvent);
+ LineInputKeyDown(InputInfo->Console, &Input->InputEvent.Event.KeyEvent);
+ ReadConsoleRequest->ControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState;
}
+ HeapFree(ConSrvHeap, 0, Input);
+ }
- if (Status == STATUS_PENDING)
+ /* Check if we have a complete line to read from */
+ if (InputInfo->Console->LineComplete)
+ {
+ while ( ReadConsoleRequest->NrCharactersRead < nNumberOfCharsToRead &&
+ InputInfo->Console->LinePos != InputInfo->Console->LineSize )
{
- if (GetConsoleInputRequest->InputsRead == 0)
+ WCHAR Char = InputInfo->Console->LineBuffer[InputInfo->Console->LinePos++];
+
+ if (ReadConsoleRequest->Unicode)
{
- Status = NtWaitForSingleObject(GetConsoleInputRequest->Event, FALSE, 0);
- if (!NT_SUCCESS(Status))
- {
- // BaseSetLastNTError(Status);
- break;
- }
+ UnicodeBuffer[ReadConsoleRequest->NrCharactersRead] = Char;
}
else
{
- /* nothing more to read (waiting for more input??), let's just bail */
- break;
+ ConsoleInputUnicodeCharToAnsiChar(InputInfo->Console,
+ &Buffer[ReadConsoleRequest->NrCharactersRead],
+ &Char);
}
+
+ ReadConsoleRequest->NrCharactersRead++;
}
- else // Status != STATUS_PENDING ; == STATUS_SUCCESS
+
+ if (InputInfo->Console->LinePos == InputInfo->Console->LineSize)
{
- if (!GetConsoleInputRequest->MoreEvents)
- {
- /* nothing more to read, bail */
- break;
- }
+ /* Entire line has been read */
+ HeapFree(ConSrvHeap, 0, InputInfo->Console->LineBuffer);
+ InputInfo->Console->LineBuffer = NULL;
}
+
+ WaitForMoreToRead = FALSE;
}
}
- else // Peek input.
+ else
{
- UINT NumInputs = 0;
-
- if (!IsListEmpty(&Console->InputEvents))
+ /* Character input */
+ while ( ReadConsoleRequest->NrCharactersRead < nNumberOfCharsToRead &&
+ !IsListEmpty(&InputInfo->Console->InputEvents) )
{
- CurrentInput = Console->InputEvents.Flink;
-
- while (CurrentInput != &Console->InputEvents && NumInputs < Length)
+ /* Remove input event from queue */
+ CurrentEntry = RemoveHeadList(&InputInfo->Console->InputEvents);
+ if (IsListEmpty(&InputInfo->Console->InputEvents))
{
- Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry);
+ ResetEvent(InputInfo->Console->ActiveEvent);
+ }
+ Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
- ++NumInputs;
- *InputRecord = Input->InputEvent;
+ /* 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 (GetConsoleInputRequest->Unicode == FALSE)
+ if (ReadConsoleRequest->Unicode)
{
- ConioInputEventToAnsi(Console, InputRecord);
+ UnicodeBuffer[ReadConsoleRequest->NrCharactersRead] = Char;
}
+ else
+ {
+ ConsoleInputUnicodeCharToAnsiChar(InputInfo->Console,
+ &Buffer[ReadConsoleRequest->NrCharactersRead],
+ &Char);
+ }
+
+ ReadConsoleRequest->NrCharactersRead++;
- InputRecord++;
- CurrentInput = CurrentInput->Flink;
+ /* Did read something */
+ WaitForMoreToRead = FALSE;
}
+ HeapFree(ConSrvHeap, 0, Input);
}
+ }
+
+ /* 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;
+ }
+}
- GetConsoleInputRequest->Length = NumInputs;
- Status = STATUS_SUCCESS;
+/* PUBLIC APIS ****************************************************************/
+
+CSR_API(SrvGetConsoleInput)
+{
+ NTSTATUS Status;
+ PCSRSS_GET_CONSOLE_INPUT GetConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputRequest;
+ PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+ PCSRSS_CONSOLE Console;
+ GET_INPUT_INFO InputInfo;
+
+ DPRINT("SrvGetConsoleInput\n");
+
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&GetConsoleInputRequest->InputRecord,
+ GetConsoleInputRequest->Length,
+ sizeof(INPUT_RECORD)))
+ {
+ return STATUS_INVALID_PARAMETER;
}
+ Status = ConioLockConsole(ProcessData, GetConsoleInputRequest->ConsoleHandle, &Console, GENERIC_READ);
+ if(!NT_SUCCESS(Status)) return Status;
+
+ GetConsoleInputRequest->InputsRead = 0;
+
+ InputInfo.ProcessData = ProcessData; // ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+ InputInfo.Console = Console;
+
+ Status = ReadInputBuffer(&InputInfo,
+ GetConsoleInputRequest->bRead,
+ ApiMessage,
+ TRUE);
+
ConioUnlockConsole(Console);
+ if (Status == STATUS_PENDING)
+ *ReplyCode = CsrReplyPending;
+
return Status;
}
InputRecord = WriteConsoleInputRequest->InputRecord;
Length = WriteConsoleInputRequest->Length;
-/*
- if (!Win32CsrValidateBuffer(ProcessData->Process, InputRecord, Length, sizeof(INPUT_RECORD)))
- {
- ConioUnlockConsole(Console);
- return STATUS_ACCESS_VIOLATION;
- }
-*/
-
for (i = 0; i < Length && NT_SUCCESS(Status); i++)
{
if (!WriteConsoleInputRequest->Unicode &&
{
NTSTATUS Status;
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;
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
PCSRSS_CONSOLE Console;
+ GET_INPUT_INFO InputInfo;
DPRINT("SrvReadConsole\n");
- CharSize = (ReadConsoleRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
-
- nNumberOfCharsToRead = ReadConsoleRequest->NrCharactersToRead;
-
if (!CsrValidateMessageBuffer(ApiMessage,
(PVOID*)&ReadConsoleRequest->Buffer,
ReadConsoleRequest->BufferSize,
return STATUS_INVALID_PARAMETER;
}
- Buffer = (PCHAR)ReadConsoleRequest->Buffer;
- UnicodeBuffer = (PWCHAR)Buffer;
-
-/*
- if (!Win32CsrValidateBuffer(ProcessData->Process, Buffer, nNumberOfCharsToRead, CharSize))
- return STATUS_ACCESS_VIOLATION;
-*/
-
- Status = ConioLockConsole(ProcessData, ReadConsoleRequest->ConsoleHandle,
- &Console, GENERIC_READ);
- if (!NT_SUCCESS(Status)) return Status;
-
- Status = STATUS_SUCCESS;
- ReadConsoleRequest->EventHandle = ProcessData->ConsoleEvent;
-
-/*** HACK: Enclosing do { ... } while (...) loop coming from kernel32 ***/
-do
-{
- if (Status == STATUS_PENDING)
- {
- Status = NtWaitForSingleObject(ReadConsoleRequest->EventHandle,
- FALSE,
- 0);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Wait for console input failed!\n");
- break;
- }
- }
-/******/
-
- if (ReadConsoleRequest->NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize)
+ // if (Request->Data.ReadConsoleRequest.NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize)
+ if (ReadConsoleRequest->NrCharactersRead > ReadConsoleRequest->NrCharactersToRead)
{
- // return STATUS_INVALID_PARAMETER;
- Status = STATUS_INVALID_PARAMETER;
- break;
- // goto done;
+ return STATUS_INVALID_PARAMETER;
}
- // ReadConsoleRequest->EventHandle = ProcessData->ConsoleEvent;
+ Status = ConioLockConsole(ProcessData, ReadConsoleRequest->ConsoleHandle, &Console, GENERIC_READ);
+ if (!NT_SUCCESS(Status)) return Status;
- 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;
- }
- }
+ ReadConsoleRequest->NrCharactersRead = 0;
- /* 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);
+ InputInfo.ProcessData = ProcessData; // ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+ InputInfo.Console = Console;
- /* 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;
-
-/******/
-}
-while (Status == STATUS_PENDING);
-/*** HACK: Enclosing do { ... } while (...) loop coming from kernel32 ***/
+ Status = ReadChars(&InputInfo,
+ ApiMessage,
+ TRUE);
ConioUnlockConsole(Console);
+ if (Status == STATUS_PENDING)
+ *ReplyCode = CsrReplyPending;
+
return Status;
}