NTSTATUS NTAPI ConDrvGetConsoleInput(IN PCONSOLE Console, IN PCONSOLE_INPUT_BUFFER InputBuffer, IN BOOLEAN KeepEvents, IN BOOLEAN WaitForMoreEvents, IN BOOLEAN Unicode, OUT PINPUT_RECORD InputRecord, IN ULONG NumEventsToRead, OUT PULONG NumEventsRead OPTIONAL) { PLIST_ENTRY CurrentInput; ConsoleInput* Input; ULONG i = 0; if (Console == NULL || InputBuffer == NULL /* || InputRecord == NULL */) return STATUS_INVALID_PARAMETER; /* Validity checks */ ASSERT(Console == InputBuffer->Header.Console); ASSERT( (InputRecord != NULL && NumEventsToRead >= 0) || (InputRecord == NULL && NumEventsToRead == 0) ); // Do NOT do that !! Use the existing number of events already read, if any... // if (NumEventsRead) *NumEventsRead = 0; if (IsListEmpty(&InputBuffer->InputEvents)) { /* * No input is available. Wait for more input if requested, * otherwise, we don't wait, so we return success. */ return (WaitForMoreEvents ? STATUS_PENDING : STATUS_SUCCESS); } /* Only get input if there is any */ CurrentInput = InputBuffer->InputEvents.Flink; if (NumEventsRead) i = *NumEventsRead; // We will read the remaining events... while ((CurrentInput != &InputBuffer->InputEvents) && (i < NumEventsToRead)) { Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry); *InputRecord = Input->InputEvent; if (!Unicode) { ConioInputEventToAnsi(InputBuffer->Header.Console, InputRecord); } ++InputRecord; ++i; CurrentInput = CurrentInput->Flink; /* Remove the events from the queue if needed */ if (!KeepEvents) { RemoveEntryList(&Input->ListEntry); ConsoleFreeHeap(Input); } } if (NumEventsRead) *NumEventsRead = i; if (IsListEmpty(&InputBuffer->InputEvents)) { ResetEvent(InputBuffer->ActiveEvent); } /* We read all the inputs available, we return success */ return STATUS_SUCCESS; }
static NTSTATUS ReadInputBuffer(IN PGET_INPUT_INFO InputInfo, IN PCSR_API_MESSAGE ApiMessage, IN BOOLEAN CreateWaitBlock OPTIONAL) { NTSTATUS Status; PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest; PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer; ULONG NumEventsRead; PINPUT_RECORD InputRecord; /* * For optimization purposes, Windows (and hence ReactOS, too, for * compatibility reasons) uses a static buffer if no more than five * input records are read. Otherwise a new buffer is used. * The client-side expects that we know this behaviour. */ if (GetInputRequest->NumRecords <= sizeof(GetInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD)) { /* * Adjust the internal pointer, because its old value points to * the static buffer in the original ApiMessage structure. */ // GetInputRequest->RecordBufPtr = GetInputRequest->RecordStaticBuffer; InputRecord = GetInputRequest->RecordStaticBuffer; } else { InputRecord = GetInputRequest->RecordBufPtr; } NumEventsRead = 0; Status = ConDrvGetConsoleInput(InputBuffer->Header.Console, InputBuffer, (GetInputRequest->Flags & CONSOLE_READ_KEEPEVENT) != 0, (GetInputRequest->Flags & CONSOLE_READ_CONTINUE ) == 0, InputRecord, GetInputRequest->NumRecords, &NumEventsRead); if (Status == STATUS_PENDING) { /* We haven't completed a read, so start a wait */ return WaitBeforeReading(InputInfo, ApiMessage, ReadInputBufferThread, CreateWaitBlock); } else { /* * We read all what we wanted. Set the number of events read and * return the error code we were given. */ GetInputRequest->NumRecords = NumEventsRead; if (NT_SUCCESS(Status)) { /* Now translate everything to ANSI */ if (!GetInputRequest->Unicode) { for (; NumEventsRead > 0; --NumEventsRead) { ConioInputEventToAnsi(InputBuffer->Header.Console, --InputRecord); } } } return Status; // return STATUS_SUCCESS; } }