[WIN32CSR] Console input simplification:

- Put code for processing events for line input in one place, instead of duplicating it everywhere
- Remove "Fake" and "NotChar" fields from ConsoleInput struct. ConioProcessKey didn't actually add Fake events; they were used for the \n when converting \r to \r\n, but this is better done by the line input code.
- Build an input line completely on the server side; this will make it practical to add history and more sophisticated editing later

svn path=/trunk/; revision=47572
This commit is contained in:
Jeffrey Morlan
2010-06-04 18:26:22 +00:00
parent d3c4ade827
commit 6659ae1d98
5 changed files with 173 additions and 308 deletions
+3 -13
View File
@@ -1566,6 +1566,9 @@ IntReadConsole(HANDLE hConsoleInput,
}
Request->Status = STATUS_SUCCESS;
Request->Data.ReadConsoleRequest.ConsoleHandle = hConsoleInput;
Request->Data.ReadConsoleRequest.Unicode = bUnicode;
Request->Data.ReadConsoleRequest.FullReadSize = (WORD)nNumberOfCharsToRead;
CsrRequest = MAKE_CSR_API(READ_CONSOLE, CSR_CONSOLE);
do
@@ -1582,10 +1585,7 @@ IntReadConsole(HANDLE hConsoleInput,
}
}
Request->Data.ReadConsoleRequest.ConsoleHandle = hConsoleInput;
Request->Data.ReadConsoleRequest.Unicode = bUnicode;
Request->Data.ReadConsoleRequest.NrCharactersToRead = (WORD)min(nNumberOfCharsToRead, CSRSS_MAX_READ_CONSOLE / CharSize);
Request->Data.ReadConsoleRequest.nCharsCanBeDeleted = (WORD)CharsRead;
Status = CsrClientCallServer(Request,
NULL,
@@ -1607,16 +1607,6 @@ IntReadConsole(HANDLE hConsoleInput,
Request->Data.ReadConsoleRequest.Buffer,
Request->Data.ReadConsoleRequest.NrCharactersRead * CharSize);
CharsRead += Request->Data.ReadConsoleRequest.NrCharactersRead;
if (Request->Status == STATUS_NOTIFY_CLEANUP)
{
if(CharsRead > 0)
{
CharsRead--;
nNumberOfCharsToRead++;
}
Request->Status = STATUS_PENDING;
}
}
while (Request->Status == STATUS_PENDING && nNumberOfCharsToRead > 0);
+1 -1
View File
@@ -70,8 +70,8 @@ typedef struct
{
HANDLE ConsoleHandle;
BOOL Unicode;
WORD FullReadSize;
WORD NrCharactersToRead;
WORD nCharsCanBeDeleted; /* number of chars already in buffer that can be backspaced */
HANDLE EventHandle;
ULONG NrCharactersRead;
BYTE Buffer[0];
+161 -283
View File
@@ -22,13 +22,62 @@
/* FUNCTIONS *****************************************************************/
static VOID
ConioLineInputKeyDown(PCSRSS_CONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
{
if (KeyEvent->uChar.UnicodeChar == L'\b' && Console->Mode & ENABLE_PROCESSED_INPUT)
{
/* backspace handling - if we are in charge of echoing it then we handle it here
* otherwise we treat it like a normal char.
*/
if (Console->LineSize > 0)
{
Console->LineSize--;
if (Console->Mode & ENABLE_ECHO_INPUT)
ConioWriteConsole(Console, Console->ActiveBuffer, "\b", 1, TRUE);
}
}
else if (KeyEvent->uChar.UnicodeChar == L'\r')
{
/* TODO: add line to history */
Console->LineBuffer[Console->LineSize++] = L'\r';
if (Console->Mode & ENABLE_ECHO_INPUT)
ConioWriteConsole(Console, Console->ActiveBuffer, "\r", 1, TRUE);
if (Console->Mode & ENABLE_PROCESSED_INPUT)
{
Console->LineBuffer[Console->LineSize++] = L'\n';
if (Console->Mode & ENABLE_ECHO_INPUT)
ConioWriteConsole(Console, Console->ActiveBuffer, "\n", 1, TRUE);
}
Console->LineComplete = TRUE;
Console->LinePos = 0;
}
else if (KeyEvent->uChar.UnicodeChar != L'\0')
{
if (Console->LineSize + 2 < Console->LineMaxSize)
{
Console->LineBuffer[Console->LineSize++] = KeyEvent->uChar.UnicodeChar;
/* echo to screen if enabled */
if (Console->Mode & ENABLE_ECHO_INPUT)
{
CHAR AsciiChar;
WideCharToMultiByte(Console->OutputCodePage, 0,
&KeyEvent->uChar.UnicodeChar, 1,
&AsciiChar, 1, NULL, NULL);
ConioWriteConsole(Console, Console->ActiveBuffer, &AsciiChar, 1, TRUE);
}
}
}
}
CSR_API(CsrReadConsole)
{
PLIST_ENTRY CurrentEntry;
ConsoleInput *Input;
PCHAR Buffer;
PWCHAR UnicodeBuffer;
ULONG i;
ULONG i = 0;
ULONG nNumberOfCharsToRead, CharSize;
PCSRSS_CONSOLE Console;
NTSTATUS Status;
@@ -51,110 +100,94 @@ CSR_API(CsrReadConsole)
return Status;
}
Request->Data.ReadConsoleRequest.EventHandle = ProcessData->ConsoleEvent;
for (i = 0; i < nNumberOfCharsToRead && Console->InputEvents.Flink != &Console->InputEvents; i++)
Status = STATUS_PENDING; /* we haven't read anything (yet) */
if (Console->Mode & ENABLE_LINE_INPUT)
{
/* remove input event from queue */
CurrentEntry = RemoveHeadList(&Console->InputEvents);
if (IsListEmpty(&Console->InputEvents))
if (Console->LineBuffer == NULL)
{
ResetEvent(Console->ActiveEvent);
/* Starting a new line */
Console->LineMaxSize = max(256, Request->Data.ReadConsoleRequest.FullReadSize);
Console->LineBuffer = HeapAlloc(Win32CsrApiHeap, 0, Console->LineMaxSize * sizeof(WCHAR));
if (Console->LineBuffer == NULL)
{
Status = STATUS_NO_MEMORY;
goto done;
}
Console->LineComplete = FALSE;
Console->LineSize = 0;
Console->LinePos = 0;
}
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')
/* If we don't have a complete line yet, process the pending input */
while (!Console->LineComplete && !IsListEmpty(&Console->InputEvents))
{
/*
* backspace handling - if we are in charge of echoing it then we handle it here
* otherwise we treat it like a normal char.
*/
if (L'\b' == Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar && 0
!= (Console->Mode & ENABLE_ECHO_INPUT))
/* remove input event from queue */
CurrentEntry = RemoveHeadList(&Console->InputEvents);
if (IsListEmpty(&Console->InputEvents))
{
/* echo if it has not already been done, and either we or the client has chars to be deleted */
if (! Input->Echoed
&& (0 != i || Request->Data.ReadConsoleRequest.nCharsCanBeDeleted))
{
ConioWriteConsole(Console, Console->ActiveBuffer, "\b", 1, TRUE);
}
if (0 != i)
{
i -= 2; /* if we already have something to return, just back it up by 2 */
}
else
{
/* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
Console->WaitingChars--;
ConioUnlockConsole(Console);
HeapFree(Win32CsrApiHeap, 0, Input);
Request->Data.ReadConsoleRequest.NrCharactersRead = 0;
return STATUS_NOTIFY_CLEANUP;
ResetEvent(Console->ActiveEvent);
}
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
}
Request->Data.ReadConsoleRequest.nCharsCanBeDeleted--;
Input->Echoed = TRUE; /* mark as echoed so we don't echo it below */
}
/* do not copy backspace to buffer */
else
/* only pay attention to key down */
if (KEY_EVENT == Input->InputEvent.EventType
&& Input->InputEvent.Event.KeyEvent.bKeyDown)
{
if(Request->Data.ReadConsoleRequest.Unicode)
UnicodeBuffer[i] = Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar;
else
ConsoleInputUnicodeCharToAnsiChar(Console, &Buffer[i], &Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar);
}
/* echo to screen if enabled and we did not already echo the char */
if (0 != (Console->Mode & ENABLE_ECHO_INPUT)
&& ! Input->Echoed
&& L'\r' != Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar)
{
CHAR AsciiChar;
WideCharToMultiByte(Console->OutputCodePage, 0,
&Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar, 1,
&AsciiChar, 1, NULL, NULL);
ConioWriteConsole(Console, Console->ActiveBuffer, &AsciiChar, 1, TRUE);
ConioLineInputKeyDown(Console, &Input->InputEvent.Event.KeyEvent);
}
HeapFree(Win32CsrApiHeap, 0, Input);
}
else
/* Check if we have a complete line to read from */
if (Console->LineComplete)
{
i--;
while (i < nNumberOfCharsToRead && Console->LinePos != Console->LineSize)
{
WCHAR Char = Console->LineBuffer[Console->LinePos++];
if (Request->Data.ReadConsoleRequest.Unicode)
UnicodeBuffer[i++] = Char;
else
ConsoleInputUnicodeCharToAnsiChar(Console, &Buffer[i++], &Char);
}
if (Console->LinePos == Console->LineSize)
{
HeapFree(Win32CsrApiHeap, 0, Console->LineBuffer);
Console->LineBuffer = NULL;
Status = STATUS_SUCCESS; /* Entire line has been read */
}
}
Console->WaitingChars--;
HeapFree(Win32CsrApiHeap, 0, Input);
}
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 (Request->Data.ReadConsoleRequest.Unicode)
UnicodeBuffer[i++] = Char;
else
ConsoleInputUnicodeCharToAnsiChar(Console, &Buffer[i++], &Char);
Status = STATUS_SUCCESS; /* did read something */
}
HeapFree(Win32CsrApiHeap, 0, Input);
}
}
done:
Request->Data.ReadConsoleRequest.NrCharactersRead = i;
if (0 == i)
{
Status = STATUS_PENDING; /* we didn't read anything */
}
else if (0 != (Console->Mode & ENABLE_LINE_INPUT))
{
if (0 == Console->WaitingLines ||
(Request->Data.ReadConsoleRequest.Unicode ? (L'\n' != UnicodeBuffer[i - 1]) : ('\n' != Buffer[i - 1])))
{
Status = STATUS_PENDING; /* line buffered, didn't get a complete line */
}
else
{
Console->WaitingLines--;
Status = STATUS_SUCCESS; /* line buffered, did get a complete line */
}
}
else
{
Status = STATUS_SUCCESS; /* not line buffered, did read something */
}
if (Status == STATUS_PENDING)
{
Console->EchoCount = nNumberOfCharsToRead - i;
}
else
{
Console->EchoCount = 0; /* if the client is no longer waiting on input, do not echo */
}
ConioUnlockConsole(Console);
if (CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE) + i * CharSize > sizeof(CSR_API_MESSAGE))
@@ -179,28 +212,24 @@ ConioInputEventToAnsi(PCSRSS_CONSOLE Console, PINPUT_RECORD InputEvent)
}
}
static VOID FASTCALL
static NTSTATUS FASTCALL
ConioProcessChar(PCSRSS_CONSOLE Console,
ConsoleInput *KeyEventRecord)
PINPUT_RECORD InputEvent)
{
BOOL updown;
ConsoleInput *TempInput;
if (KeyEventRecord->InputEvent.EventType == KEY_EVENT &&
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown)
/* Check for pause or unpause */
if (InputEvent->EventType == KEY_EVENT && InputEvent->Event.KeyEvent.bKeyDown)
{
WORD vk = KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode;
WORD vk = InputEvent->Event.KeyEvent.wVirtualKeyCode;
if (!(Console->PauseFlags & PAUSED_FROM_KEYBOARD))
{
DWORD cks = KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState;
DWORD cks = InputEvent->Event.KeyEvent.dwControlKeyState;
if (Console->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);
HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
return;
return STATUS_SUCCESS;
}
}
else
@@ -209,110 +238,19 @@ ConioProcessChar(PCSRSS_CONSOLE Console,
vk != VK_RWIN && vk != VK_NUMLOCK && vk != VK_SCROLL)
{
ConioUnpause(Console, PAUSED_FROM_KEYBOARD);
HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
return;
return STATUS_SUCCESS;
}
}
}
if (0 != (Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT)))
{
switch(KeyEventRecord->InputEvent.Event.KeyEvent.uChar.UnicodeChar)
{
case L'\r':
/* first add the \r */
KeyEventRecord->InputEvent.EventType = KEY_EVENT;
updown = KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown;
KeyEventRecord->Echoed = FALSE;
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
KeyEventRecord->InputEvent.Event.KeyEvent.uChar.UnicodeChar = L'\r';
InsertTailList(&Console->InputEvents, &KeyEventRecord->ListEntry);
Console->WaitingChars++;
KeyEventRecord = HeapAlloc(Win32CsrApiHeap, 0, sizeof(ConsoleInput));
if (NULL == KeyEventRecord)
{
DPRINT1("Failed to allocate KeyEventRecord\n");
return;
}
KeyEventRecord->InputEvent.EventType = KEY_EVENT;
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown = updown;
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode = 0;
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualScanCode = 0;
KeyEventRecord->InputEvent.Event.KeyEvent.uChar.UnicodeChar = L'\n';
KeyEventRecord->Fake = TRUE;
break;
}
}
/* add event to the queue */
InsertTailList(&Console->InputEvents, &KeyEventRecord->ListEntry);
Console->WaitingChars++;
/* if line input mode is enabled, only wake the client on enter key down */
if (0 == (Console->Mode & ENABLE_LINE_INPUT)
|| Console->EarlyReturn
|| (L'\n' == KeyEventRecord->InputEvent.Event.KeyEvent.uChar.UnicodeChar
&& KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown))
{
if (L'\n' == KeyEventRecord->InputEvent.Event.KeyEvent.uChar.UnicodeChar)
{
Console->WaitingLines++;
}
}
KeyEventRecord->Echoed = FALSE;
if (0 != (Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT))
&& L'\b' == KeyEventRecord->InputEvent.Event.KeyEvent.uChar.UnicodeChar
&& KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown)
{
/* walk the input queue looking for a char to backspace */
for (TempInput = (ConsoleInput *) Console->InputEvents.Blink;
TempInput != (ConsoleInput *) &Console->InputEvents
&& (KEY_EVENT == TempInput->InputEvent.EventType
|| ! TempInput->InputEvent.Event.KeyEvent.bKeyDown
|| L'\b' == TempInput->InputEvent.Event.KeyEvent.uChar.UnicodeChar);
TempInput = (ConsoleInput *) TempInput->ListEntry.Blink)
{
/* NOP */;
}
/* if we found one, delete it, otherwise, wake the client */
if (TempInput != (ConsoleInput *) &Console->InputEvents)
{
/* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
RemoveEntryList(&TempInput->ListEntry);
if (TempInput->Echoed)
{
CHAR AsciiChar;
WideCharToMultiByte(Console->OutputCodePage, 0,
&KeyEventRecord->InputEvent.Event.KeyEvent.uChar.UnicodeChar, 1,
&AsciiChar, 1, NULL, NULL);
ConioWriteConsole(Console, Console->ActiveBuffer, &AsciiChar, 1, TRUE);
}
HeapFree(Win32CsrApiHeap, 0, TempInput);
RemoveEntryList(&KeyEventRecord->ListEntry);
HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
Console->WaitingChars -= 2;
return;
}
}
else
{
/* echo chars if we are supposed to and client is waiting for some */
if (0 != (Console->Mode & ENABLE_ECHO_INPUT) && Console->EchoCount
&& KeyEventRecord->InputEvent.Event.KeyEvent.uChar.UnicodeChar
&& KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown
&& L'\r' != KeyEventRecord->InputEvent.Event.KeyEvent.uChar.UnicodeChar)
{
/* mark the char as already echoed */
CHAR AsciiChar;
WideCharToMultiByte(Console->OutputCodePage, 0,
&KeyEventRecord->InputEvent.Event.KeyEvent.uChar.UnicodeChar, 1,
&AsciiChar, 1, NULL, NULL);
ConioWriteConsole(Console, Console->ActiveBuffer, &AsciiChar, 1, TRUE);
Console->EchoCount--;
KeyEventRecord->Echoed = TRUE;
}
}
/* Console->WaitingChars++; */
ConsoleInput *ConInRec = RtlAllocateHeap(Win32CsrApiHeap, 0, sizeof(ConsoleInput));
if (ConInRec == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
ConInRec->InputEvent = *InputEvent;
InsertTailList(&Console->InputEvents, &ConInRec->ListEntry);
SetEvent(Console->ActiveEvent);
return STATUS_SUCCESS;
}
static DWORD FASTCALL
@@ -354,15 +292,14 @@ ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode)
* or translated keys may be involved. */
static UINT LastVirtualKey = 0;
DWORD ShiftState;
ConsoleInput *ConInRec;
UINT RepeatCount;
CHAR AsciiChar;
WCHAR UnicodeChar;
UINT VirtualKeyCode;
UINT VirtualScanCode;
BOOL Down = FALSE;
INPUT_RECORD er;
ULONG ResultSize = 0;
BOOLEAN Fake; // synthesized, not a real event
BOOLEAN NotChar; // message should not be used to return a character
RepeatCount = 1;
VirtualScanCode = (msg->lParam >> 16) & 0xff;
@@ -393,11 +330,6 @@ ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode)
UnicodeChar = (1 == RetChars ? Chars[0] : 0);
}
if (0 == ResultSize)
{
AsciiChar = 0;
}
er.EventType = KEY_EVENT;
er.Event.KeyEvent.bKeyDown = Down;
er.Event.KeyEvent.wRepeatCount = RepeatCount;
@@ -433,38 +365,26 @@ ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode)
return;
}
ConInRec = HeapAlloc(Win32CsrApiHeap, 0, sizeof(ConsoleInput));
if (NULL == ConInRec)
{
return;
}
ConInRec->InputEvent = er;
ConInRec->Fake = UnicodeChar &&
(msg->message != WM_CHAR && msg->message != WM_SYSCHAR &&
msg->message != WM_KEYUP && msg->message != WM_SYSKEYUP);
ConInRec->NotChar = (msg->message != WM_CHAR && msg->message != WM_SYSCHAR);
ConInRec->Echoed = FALSE;
if (ConInRec->NotChar)
Fake = UnicodeChar &&
(msg->message != WM_CHAR && msg->message != WM_SYSCHAR &&
msg->message != WM_KEYUP && msg->message != WM_SYSKEYUP);
NotChar = (msg->message != WM_CHAR && msg->message != WM_SYSCHAR);
if (NotChar)
LastVirtualKey = msg->wParam;
DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
DPRINT ("csrss: %s %s %s %s %02x %02x '%lc' %04x\n",
Down ? "down" : "up ",
(msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ?
"char" : "key ",
ConInRec->Fake ? "fake" : "real",
ConInRec->NotChar ? "notc" : "char",
Fake ? "fake" : "real",
NotChar ? "notc" : "char",
VirtualScanCode,
VirtualKeyCode,
(AsciiChar >= ' ') ? AsciiChar : '.',
(UnicodeChar >= L' ') ? UnicodeChar : L'.',
ShiftState);
if (ConInRec->Fake && ConInRec->NotChar)
{
HeapFree(Win32CsrApiHeap, 0, ConInRec);
if (Fake)
return;
}
/* process Ctrl-C and Ctrl-Break */
if (Console->Mode & ENABLE_PROCESSED_INPUT &&
@@ -483,7 +403,6 @@ ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode)
current_entry = current_entry->Flink;
ConioConsoleCtrlEvent((DWORD)CTRL_C_EVENT, current);
}
HeapFree(Win32CsrApiHeap, 0, ConInRec);
return;
}
@@ -518,10 +437,9 @@ ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode)
}
ConioDrawConsole(Console);
}
HeapFree(Win32CsrApiHeap, 0, ConInRec);
return;
}
ConioProcessChar(Console, ConInRec);
ConioProcessChar(Console, &er);
}
CSR_API(CsrReadInputEvent)
@@ -551,7 +469,7 @@ CSR_API(CsrReadInputEvent)
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
CurrentEntry = CurrentEntry->Flink;
if (Done && !Input->Fake)
if (Done)
{
Request->Data.ReadInputRequest.MoreEvents = TRUE;
break;
@@ -559,7 +477,7 @@ CSR_API(CsrReadInputEvent)
RemoveEntryList(&Input->ListEntry);
if (!Done && !Input->Fake)
if (!Done)
{
Request->Data.ReadInputRequest.Input = Input->InputEvent;
if (Request->Data.ReadInputRequest.Unicode == FALSE)
@@ -569,29 +487,13 @@ CSR_API(CsrReadInputEvent)
Done = TRUE;
}
if (Input->InputEvent.EventType == KEY_EVENT)
{
if (0 != (Console->Mode & ENABLE_LINE_INPUT)
&& Input->InputEvent.Event.KeyEvent.bKeyDown
&& L'\r' == Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar)
{
Console->WaitingLines--;
}
Console->WaitingChars--;
}
HeapFree(Win32CsrApiHeap, 0, Input);
}
if (Done)
{
Status = STATUS_SUCCESS;
Console->EarlyReturn = FALSE;
}
else
{
Status = STATUS_PENDING;
Console->EarlyReturn = TRUE; /* mark for early return */
}
if (IsListEmpty(&Console->InputEvents))
{
@@ -632,7 +534,6 @@ CSR_API(CsrFlushInputBuffer)
HeapFree(Win32CsrApiHeap, 0, Input);
}
ResetEvent(Console->ActiveEvent);
Console->WaitingChars=0;
ConioUnlockConsole(Console);
@@ -645,7 +546,6 @@ CSR_API(CsrGetNumberOfConsoleInputEvents)
PCSRSS_CONSOLE Console;
PLIST_ENTRY CurrentItem;
DWORD NumEvents;
ConsoleInput *Input;
DPRINT("CsrGetNumberOfConsoleInputEvents\n");
@@ -664,12 +564,8 @@ CSR_API(CsrGetNumberOfConsoleInputEvents)
/* If there are any events ... */
while (CurrentItem != &Console->InputEvents)
{
Input = CONTAINING_RECORD(CurrentItem, ConsoleInput, ListEntry);
CurrentItem = CurrentItem->Flink;
if (!Input->Fake)
{
NumEvents++;
}
NumEvents++;
}
ConioUnlockConsole(Console);
@@ -719,16 +615,10 @@ CSR_API(CsrPeekConsoleInput)
{
Item = CONTAINING_RECORD(CurrentItem, ConsoleInput, ListEntry);
if (Item->Fake)
{
CurrentItem = CurrentItem->Flink;
continue;
}
++NumItems;
*InputRecord = Item->InputEvent;
if (Request->Data.ReadInputRequest.Unicode == FALSE)
if (Request->Data.PeekConsoleInputRequest.Unicode == FALSE)
{
ConioInputEventToAnsi(Console, InputRecord);
}
@@ -752,7 +642,6 @@ CSR_API(CsrWriteConsoleInput)
NTSTATUS Status;
DWORD Length;
DWORD i;
ConsoleInput* Record;
DPRINT("CsrWriteConsoleInput\n");
@@ -774,35 +663,24 @@ CSR_API(CsrWriteConsoleInput)
return STATUS_ACCESS_VIOLATION;
}
for (i = 0; i < Length; i++)
for (i = 0; i < Length && NT_SUCCESS(Status); i++)
{
Record = HeapAlloc(Win32CsrApiHeap, 0, sizeof(ConsoleInput));
if (NULL == Record)
{
ConioUnlockConsole(Console);
return STATUS_INSUFFICIENT_RESOURCES;
}
Record->Echoed = FALSE;
Record->Fake = FALSE;
//Record->InputEvent = *InputRecord++;
memcpy(&Record->InputEvent, &InputRecord[i], sizeof(INPUT_RECORD));
if (!Request->Data.WriteConsoleInputRequest.Unicode &&
Record->InputEvent.EventType == KEY_EVENT)
InputRecord->EventType == KEY_EVENT)
{
CHAR AsciiChar = Record->InputEvent.Event.KeyEvent.uChar.AsciiChar;
CHAR AsciiChar = InputRecord->Event.KeyEvent.uChar.AsciiChar;
ConsoleInputAnsiCharToUnicodeChar(Console,
&Record->InputEvent.Event.KeyEvent.uChar.UnicodeChar,
&InputRecord->Event.KeyEvent.uChar.UnicodeChar,
&AsciiChar);
}
ConioProcessChar(Console, Record);
Status = ConioProcessChar(Console, InputRecord++);
}
ConioUnlockConsole(Console);
Request->Data.WriteConsoleInputRequest.Length = i;
return STATUS_SUCCESS;
return Status;
}
/* EOF */
@@ -75,14 +75,15 @@ typedef struct tagCSRSS_CONSOLE
PCSRSS_CONSOLE Prev, Next; /* Next and Prev consoles in console wheel */
HANDLE ActiveEvent;
LIST_ENTRY InputEvents; /* List head for input event queue */
WORD WaitingChars;
WORD WaitingLines; /* number of chars and lines in input queue */
PWCHAR LineBuffer; /* current line being input, in line buffered mode */
WORD LineMaxSize; /* maximum size of line in characters (including CR+LF) */
WORD LineSize; /* current size of line */
WORD LinePos; /* current position within line */
BOOLEAN LineComplete; /* user pressed enter, ready to send back to client */
LIST_ENTRY BufferList; /* List of all screen buffers for this console */
PCSRSS_SCREEN_BUFFER ActiveBuffer; /* Pointer to currently active screen buffer */
WORD Mode; /* Console mode flags */
WORD EchoCount; /* count of chars to echo, in line buffered mode */
UNICODE_STRING Title; /* Title of console */
BOOL EarlyReturn; /* wake client and return data, even if we are in line buffered mode, and we don't have a complete line */
DWORD HardwareState; /* _GDI_MANAGED, _DIRECT */
HWND hWindow;
COORD Size;
@@ -101,9 +102,6 @@ typedef struct ConsoleInput_t
{
LIST_ENTRY ListEntry;
INPUT_RECORD InputEvent;
BOOLEAN Echoed; // already been echoed or not
BOOLEAN Fake; // synthesized, not a real event
BOOLEAN NotChar; // message should not be used to return a character
} ConsoleInput;
/* CONSOLE_SELECTION_INFO dwFlags values */
@@ -81,13 +81,10 @@ CsrInitConsole(PCSRSS_CONSOLE Console, BOOL Visible)
RtlCreateUnicodeString(&Console->Title, L"Command Prompt");
Console->ReferenceCount = 0;
Console->WaitingChars = 0;
Console->WaitingLines = 0;
Console->EchoCount = 0;
Console->LineBuffer = NULL;
Console->Header.Type = CONIO_CONSOLE_MAGIC;
Console->Header.Console = Console;
Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
Console->EarlyReturn = FALSE;
InitializeListHead(&Console->BufferList);
Console->ActiveBuffer = NULL;
InitializeListHead(&Console->InputEvents);
@@ -333,6 +330,8 @@ ConioDeleteConsole(Object_t *Object)
}
ConioCleanupConsole(Console);
if (Console->LineBuffer)
RtlFreeHeap(Win32CsrApiHeap, 0, Console->LineBuffer);
ConioDeleteScreenBuffer(Console->ActiveBuffer);
if (!IsListEmpty(&Console->BufferList))
{