+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;
+ ConsoleInputUnicodeToAnsiChar(Console,
+ &InputEvent->Event.KeyEvent.uChar.AsciiChar,
+ &UnicodeChar);
+ }
+}
+
+static VOID
+ConioInputEventToUnicode(PCONSOLE Console, PINPUT_RECORD InputEvent)
+{
+ if (InputEvent->EventType == KEY_EVENT)
+ {
+ CHAR AsciiChar = InputEvent->Event.KeyEvent.uChar.AsciiChar;
+ InputEvent->Event.KeyEvent.uChar.AsciiChar = 0;
+ ConsoleInputAnsiToUnicodeChar(Console,
+ &InputEvent->Event.KeyEvent.uChar.UnicodeChar,
+ &AsciiChar);
+ }
+}
+
+static ULONG
+PreprocessInput(PCONSRV_CONSOLE Console,
+ PINPUT_RECORD InputEvent,
+ ULONG NumEventsToWrite)
+{
+ ULONG NumEvents;
+
+ /*
+ * Loop each event, and for each, check for pause or unpause
+ * and perform adequate behaviour.
+ */
+ for (NumEvents = NumEventsToWrite; NumEvents > 0; --NumEvents)
+ {
+ /* Check for pause or unpause */
+ if (InputEvent->EventType == KEY_EVENT && InputEvent->Event.KeyEvent.bKeyDown)
+ {
+ WORD vk = InputEvent->Event.KeyEvent.wVirtualKeyCode;
+ if (!(Console->PauseFlags & PAUSED_FROM_KEYBOARD))
+ {
+ DWORD cks = InputEvent->Event.KeyEvent.dwControlKeyState;
+ if (Console->InputBuffer.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);
+
+ /* Skip the event */
+ RtlMoveMemory(InputEvent,
+ InputEvent + 1,
+ (NumEvents - 1) * sizeof(INPUT_RECORD));
+ --NumEventsToWrite;
+ continue;
+ }
+ }
+ 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);
+
+ /* Skip the event */
+ RtlMoveMemory(InputEvent,
+ InputEvent + 1,
+ (NumEvents - 1) * sizeof(INPUT_RECORD));
+ --NumEventsToWrite;
+ continue;
+ }
+ }
+ }
+
+ /* Go to the next event */
+ ++InputEvent;
+ }
+
+ return NumEventsToWrite;
+}
+
+static VOID
+PostprocessInput(PCONSRV_CONSOLE Console)
+{
+ CsrNotifyWait(&Console->ReadWaitQueue,
+ FALSE,
+ NULL,
+ NULL);
+ if (!IsListEmpty(&Console->ReadWaitQueue))
+ {
+ CsrDereferenceWait(&Console->ReadWaitQueue);
+ }
+}
+
+
+NTSTATUS NTAPI
+ConDrvWriteConsoleInput(IN PCONSOLE Console,
+ IN PCONSOLE_INPUT_BUFFER InputBuffer,
+ IN BOOLEAN AppendToEnd,
+ IN PINPUT_RECORD InputRecord,
+ IN ULONG NumEventsToWrite,
+ OUT PULONG NumEventsWritten OPTIONAL);
+static NTSTATUS
+ConioAddInputEvents(PCONSOLE Console,
+ PINPUT_RECORD InputRecords, // InputEvent
+ ULONG NumEventsToWrite,
+ PULONG NumEventsWritten,
+ BOOLEAN AppendToEnd)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ if (NumEventsWritten) *NumEventsWritten = 0;
+
+ NumEventsToWrite = PreprocessInput(Console, InputRecords, NumEventsToWrite);
+ if (NumEventsToWrite == 0) return STATUS_SUCCESS;
+
+ // Status = ConDrvAddInputEvents(Console,
+ // InputRecords,
+ // NumEventsToWrite,
+ // NumEventsWritten,
+ // AppendToEnd);
+
+ Status = ConDrvWriteConsoleInput(Console,
+ &Console->InputBuffer,
+ AppendToEnd,
+ InputRecords,
+ NumEventsToWrite,
+ NumEventsWritten);
+
+ // if (NT_SUCCESS(Status))
+ if (Status == STATUS_SUCCESS) PostprocessInput(Console);
+
+ return Status;
+}
+
+/* FIXME: This function can be called by CONDRV, in ConioResizeBuffer() in text.c */
+NTSTATUS
+ConioProcessInputEvent(PCONSOLE Console,
+ PINPUT_RECORD InputEvent)
+{
+ ULONG NumEventsWritten;
+ return ConioAddInputEvents(Console,
+ InputEvent,
+ 1,
+ &NumEventsWritten,
+ TRUE);
+}
+
+