static VOID ConioInputEventToAnsi(PCONSOLE 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); } }
static NTSTATUS NTAPI ConSrvTermReadStream(IN OUT PTERMINAL This, IN BOOLEAN Unicode, /**PWCHAR Buffer,**/ OUT PVOID Buffer, IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl, IN PVOID Parameter OPTIONAL, IN ULONG NumCharsToRead, OUT PULONG NumCharsRead OPTIONAL) { PFRONTEND FrontEnd = This->Context; PCONSRV_CONSOLE Console = FrontEnd->Console; PCONSOLE_INPUT_BUFFER InputBuffer = &Console->InputBuffer; PUNICODE_STRING ExeName = Parameter; // STATUS_PENDING : Wait if more to read ; STATUS_SUCCESS : Don't wait. NTSTATUS Status = STATUS_PENDING; PLIST_ENTRY CurrentEntry; ConsoleInput *Input; ULONG i; /* Validity checks */ // ASSERT(Console == InputBuffer->Header.Console); ASSERT((Buffer != NULL) || (Buffer == NULL && NumCharsToRead == 0)); /* We haven't read anything (yet) */ i = ReadControl->nInitialChars; if (InputBuffer->Mode & ENABLE_LINE_INPUT) { /* COOKED mode, call the line discipline */ if (Console->LineBuffer == NULL) { /* Starting a new line */ Console->LineMaxSize = max(256, NumCharsToRead); Console->LineBuffer = ConsoleAllocHeap(0, Console->LineMaxSize * sizeof(WCHAR)); if (Console->LineBuffer == NULL) return STATUS_NO_MEMORY; Console->LinePos = Console->LineSize = ReadControl->nInitialChars; Console->LineComplete = Console->LineUpPressed = FALSE; Console->LineInsertToggle = Console->InsertMode; Console->LineWakeupMask = ReadControl->dwCtrlWakeupMask; /* * Pre-filling the buffer is only allowed in the Unicode API, * so we don't need to worry about ANSI <-> Unicode conversion. */ memcpy(Console->LineBuffer, Buffer, Console->LineSize * sizeof(WCHAR)); if (Console->LineSize == Console->LineMaxSize) { Console->LineComplete = TRUE; Console->LinePos = 0; } } /* If we don't have a complete line yet, process the pending input */ while (!Console->LineComplete && !IsListEmpty(&InputBuffer->InputEvents)) { /* Remove input event from queue */ CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents); if (IsListEmpty(&InputBuffer->InputEvents)) { ResetEvent(InputBuffer->ActiveEvent); } Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); /* Only pay attention to key down */ if (Input->InputEvent.EventType == KEY_EVENT && Input->InputEvent.Event.KeyEvent.bKeyDown) { LineInputKeyDown(Console, ExeName, &Input->InputEvent.Event.KeyEvent); ReadControl->dwControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState; } ConsoleFreeHeap(Input); } /* Check if we have a complete line to read from */ if (Console->LineComplete) { while (i < NumCharsToRead && Console->LinePos != Console->LineSize) { WCHAR Char = Console->LineBuffer[Console->LinePos++]; if (Unicode) { ((PWCHAR)Buffer)[i] = Char; } else { ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char); } ++i; } if (Console->LinePos == Console->LineSize) { /* Entire line has been read */ ConsoleFreeHeap(Console->LineBuffer); Console->LineBuffer = NULL; } Status = STATUS_SUCCESS; } } else { /* RAW mode */ /* Character input */ while (i < NumCharsToRead && !IsListEmpty(&InputBuffer->InputEvents)) { /* Remove input event from queue */ CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents); if (IsListEmpty(&InputBuffer->InputEvents)) { ResetEvent(InputBuffer->ActiveEvent); } Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); /* Only pay attention to valid characters, on key down */ if (Input->InputEvent.EventType == KEY_EVENT && Input->InputEvent.Event.KeyEvent.bKeyDown && Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar != L'\0') { WCHAR Char = Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar; if (Unicode) { ((PWCHAR)Buffer)[i] = Char; } else { ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char); } ++i; /* Did read something */ Status = STATUS_SUCCESS; } ConsoleFreeHeap(Input); } } // FIXME: Only set if Status == STATUS_SUCCESS ??? if (NumCharsRead) *NumCharsRead = i; return Status; }
NTSTATUS NTAPI ConDrvReadConsole(IN PCONSOLE Console, IN PCONSOLE_INPUT_BUFFER InputBuffer, IN BOOLEAN Unicode, OUT PVOID Buffer, IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl, IN ULONG NumCharsToRead, OUT PULONG NumCharsRead OPTIONAL) { // STATUS_PENDING : Wait if more to read ; STATUS_SUCCESS : Don't wait. NTSTATUS Status = STATUS_PENDING; PLIST_ENTRY CurrentEntry; ConsoleInput *Input; ULONG i = ReadControl->nInitialChars; if (Console == NULL || InputBuffer == NULL || /* Buffer == NULL || */ ReadControl == NULL || ReadControl->nLength != sizeof(CONSOLE_READCONSOLE_CONTROL)) { return STATUS_INVALID_PARAMETER; } /* Validity checks */ ASSERT(Console == InputBuffer->Header.Console); ASSERT( (Buffer != NULL && NumCharsToRead >= 0) || (Buffer == NULL && NumCharsToRead == 0) ); /* We haven't read anything (yet) */ if (InputBuffer->Mode & ENABLE_LINE_INPUT) { if (Console->LineBuffer == NULL) { /* Starting a new line */ Console->LineMaxSize = (WORD)max(256, NumCharsToRead); Console->LineBuffer = ConsoleAllocHeap(0, Console->LineMaxSize * sizeof(WCHAR)); if (Console->LineBuffer == NULL) return STATUS_NO_MEMORY; Console->LineComplete = FALSE; Console->LineUpPressed = FALSE; Console->LineInsertToggle = 0; Console->LineWakeupMask = ReadControl->dwCtrlWakeupMask; Console->LineSize = ReadControl->nInitialChars; Console->LinePos = 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(Console->LineBuffer, Buffer, Console->LineSize * sizeof(WCHAR)); if (Console->LineSize == Console->LineMaxSize) { Console->LineComplete = TRUE; Console->LinePos = 0; } } /* If we don't have a complete line yet, process the pending input */ while (!Console->LineComplete && !IsListEmpty(&InputBuffer->InputEvents)) { /* Remove input event from queue */ CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents); if (IsListEmpty(&InputBuffer->InputEvents)) { ResetEvent(InputBuffer->ActiveEvent); } Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); /* Only pay attention to key down */ if (Input->InputEvent.EventType == KEY_EVENT && Input->InputEvent.Event.KeyEvent.bKeyDown) { LineInputKeyDown(Console, &Input->InputEvent.Event.KeyEvent); ReadControl->dwControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState; } ConsoleFreeHeap(Input); } /* Check if we have a complete line to read from */ if (Console->LineComplete) { while (i < NumCharsToRead && Console->LinePos != Console->LineSize) { WCHAR Char = Console->LineBuffer[Console->LinePos++]; if (Unicode) { ((PWCHAR)Buffer)[i] = Char; } else { ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char); } ++i; } if (Console->LinePos == Console->LineSize) { /* Entire line has been read */ ConsoleFreeHeap(Console->LineBuffer); Console->LineBuffer = NULL; } Status = STATUS_SUCCESS; } } else { /* Character input */ while (i < NumCharsToRead && !IsListEmpty(&InputBuffer->InputEvents)) { /* Remove input event from queue */ CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents); if (IsListEmpty(&InputBuffer->InputEvents)) { ResetEvent(InputBuffer->ActiveEvent); } Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); /* Only pay attention to valid ASCII chars, on key down */ if (Input->InputEvent.EventType == KEY_EVENT && Input->InputEvent.Event.KeyEvent.bKeyDown && Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar != L'\0') { WCHAR Char = Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar; if (Unicode) { ((PWCHAR)Buffer)[i] = Char; } else { ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char); } ++i; /* Did read something */ Status = STATUS_SUCCESS; } ConsoleFreeHeap(Input); } } if (NumCharsRead) *NumCharsRead = i; return Status; }