Author: hbelusca
Date: Thu Jun 27 00:20:58 2013
New Revision: 59345
URL:
http://svn.reactos.org/svn/reactos?rev=59345&view=rev
Log:
[KERNEL32]
Remove a spurious cast, and add a note for the pInputControl parameter of ReadConsole.
[CONSRV]
- Move some input/output console function helpers to condrv.
- The way we notify for the presence of new input data, or for console pausing/unpausing,
should be reconsidered (who should do this? The console driver? The active front-end?)
Modified:
trunk/reactos/dll/win32/kernel32/client/console/readwrite.c
trunk/reactos/include/reactos/subsys/win/conmsg.h
trunk/reactos/win32ss/user/consrv/condrv/coninput.c
trunk/reactos/win32ss/user/consrv/condrv/text.c
trunk/reactos/win32ss/user/consrv/coninput.c
trunk/reactos/win32ss/user/consrv/conoutput.c
Modified: trunk/reactos/dll/win32/kernel32/client/console/readwrite.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/console/readwrite.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/console/readwrite.c [iso-8859-1] Thu Jun 27
00:20:58 2013
@@ -60,11 +60,17 @@
/* Set up the data to send to the Console Server */
ReadConsoleRequest->InputHandle = hConsoleInput;
ReadConsoleRequest->Unicode = bUnicode;
- ReadConsoleRequest->NrCharactersToRead = (WORD)nNumberOfCharsToRead;
+ ReadConsoleRequest->NrCharactersToRead = nNumberOfCharsToRead;
ReadConsoleRequest->NrCharactersRead = 0;
ReadConsoleRequest->CtrlWakeupMask = 0;
if (pInputControl && pInputControl->nLength ==
sizeof(CONSOLE_READCONSOLE_CONTROL))
{
+ /*
+ * From MSDN (ReadConsole function), the description
+ * for pInputControl says:
+ * "This parameter requires Unicode input by default.
+ * For ANSI mode, set this parameter to NULL."
+ */
ReadConsoleRequest->NrCharactersRead = pInputControl->nInitialChars;
memcpy(ReadConsoleRequest->Buffer,
lpBuffer,
Modified: trunk/reactos/include/reactos/subsys/win/conmsg.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/subsys/win…
==============================================================================
--- trunk/reactos/include/reactos/subsys/win/conmsg.h [iso-8859-1] (original)
+++ trunk/reactos/include/reactos/subsys/win/conmsg.h [iso-8859-1] Thu Jun 27 00:20:58
2013
@@ -167,8 +167,8 @@
HANDLE InputHandle;
BOOL Unicode;
- WORD NrCharactersToRead;
- WORD NrCharactersRead;
+ ULONG NrCharactersToRead;
+ ULONG NrCharactersRead;
UNICODE_STRING ExeName;
DWORD CtrlWakeupMask;
Modified: trunk/reactos/win32ss/user/consrv/condrv/coninput.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/consrv/condrv…
==============================================================================
--- trunk/reactos/win32ss/user/consrv/condrv/coninput.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/consrv/condrv/coninput.c [iso-8859-1] Thu Jun 27 00:20:58
2013
@@ -43,17 +43,9 @@
INPUT_RECORD InputEvent;
} ConsoleInput;
-typedef struct _GET_INPUT_INFO
-{
- PCSR_THREAD CallingThread; // The thread which called the input API.
- PVOID HandleEntry; // The handle data associated with the wait
thread.
- PCONSOLE_INPUT_BUFFER InputBuffer; // The input buffer corresponding to the
handle.
-} GET_INPUT_INFO, *PGET_INPUT_INFO;
-
/* PRIVATE FUNCTIONS **********************************************************/
-#if 0
static VOID FASTCALL
ConioInputEventToAnsi(PCONSOLE Console, PINPUT_RECORD InputEvent)
{
@@ -66,7 +58,6 @@
&UnicodeChar);
}
}
-#endif
NTSTATUS FASTCALL
ConioProcessInputEvent(PCONSOLE Console,
@@ -212,12 +203,230 @@
/* PUBLIC SERVER APIS *********************************************************/
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;
+}
+
+NTSTATUS NTAPI
+ConDrvGetConsoleInput(IN PCONSOLE Console,
+ IN PCONSOLE_INPUT_BUFFER InputBuffer,
+ 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;
+
+ if (WaitForMoreEvents) // TRUE --> Read, we remove inputs from the buffer ;
FALSE --> Peek, we keep inputs.
+ {
+ 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;
+}
+
+NTSTATUS NTAPI
ConDrvWriteConsoleInput(IN PCONSOLE Console,
IN PCONSOLE_INPUT_BUFFER InputBuffer,
IN BOOLEAN Unicode,
IN PINPUT_RECORD InputRecord,
IN ULONG NumEventsToWrite,
- OUT PULONG NumEventsWritten)
+ OUT PULONG NumEventsWritten OPTIONAL)
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG i;
@@ -230,9 +439,10 @@
ASSERT( (InputRecord != NULL && NumEventsToWrite >= 0) ||
(InputRecord == NULL && NumEventsToWrite == 0) );
- if (NumEventsWritten) *NumEventsWritten = 0;
-
- for (i = 0; i < NumEventsToWrite && NT_SUCCESS(Status); ++i)
+ // Do NOT do that !! Use the existing number of events already written, if any...
+ // if (NumEventsWritten) *NumEventsWritten = 0;
+
+ for (i = (NumEventsWritten ? *NumEventsWritten : 0); i < NumEventsToWrite
&& NT_SUCCESS(Status); ++i)
{
if (InputRecord->EventType == KEY_EVENT && !Unicode)
{
Modified: trunk/reactos/win32ss/user/consrv/condrv/text.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/consrv/condrv…
==============================================================================
--- trunk/reactos/win32ss/user/consrv/condrv/text.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/consrv/condrv/text.c [iso-8859-1] Thu Jun 27 00:20:58 2013
@@ -751,9 +751,77 @@
}
NTSTATUS NTAPI
-ConDrvWriteConsole(IN PCONSOLE Console)
-{
- return STATUS_NOT_IMPLEMENTED;
+ConDrvWriteConsole(IN PCONSOLE Console,
+ IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
+ IN BOOLEAN Unicode,
+ IN PVOID StringBuffer,
+ IN ULONG NumCharsToWrite,
+ OUT PULONG NumCharsWritten OPTIONAL)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PWCHAR Buffer = NULL;
+ ULONG Written = 0;
+ ULONG Length;
+
+ if (Console == NULL || ScreenBuffer == NULL /* || StringBuffer == NULL */)
+ return STATUS_INVALID_PARAMETER;
+
+ /* Validity checks */
+ ASSERT(Console == ScreenBuffer->Header.Console);
+ ASSERT( (StringBuffer != NULL && NumCharsToWrite >= 0) ||
+ (StringBuffer == NULL && NumCharsToWrite == 0) );
+
+ // if (Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR |
PAUSED_FROM_SELECTION))
+ if (Console->PauseFlags && Console->UnpauseEvent != NULL)
+ {
+ return STATUS_PENDING;
+ }
+
+ if (Unicode)
+ {
+ Buffer = StringBuffer;
+ }
+ else
+ {
+ Length = MultiByteToWideChar(Console->OutputCodePage, 0,
+ (PCHAR)StringBuffer,
+ NumCharsToWrite,
+ NULL, 0);
+ Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
+ if (Buffer)
+ {
+ MultiByteToWideChar(Console->OutputCodePage, 0,
+ (PCHAR)StringBuffer,
+ NumCharsToWrite,
+ (PWCHAR)Buffer, Length);
+ }
+ else
+ {
+ Status = STATUS_NO_MEMORY;
+ }
+ }
+
+ if (Buffer)
+ {
+ if (NT_SUCCESS(Status))
+ {
+ Status = ConioWriteConsole(Console,
+ ScreenBuffer,
+ Buffer,
+ NumCharsToWrite,
+ TRUE);
+ if (NT_SUCCESS(Status))
+ {
+ Written = NumCharsToWrite;
+ }
+ }
+
+ if (!Unicode) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
+ }
+
+ if (NumCharsWritten) *NumCharsWritten = Written;
+
+ return Status;
}
NTSTATUS NTAPI
Modified: trunk/reactos/win32ss/user/consrv/coninput.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/consrv/coninp…
==============================================================================
--- trunk/reactos/win32ss/user/consrv/coninput.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/consrv/coninput.c [iso-8859-1] Thu Jun 27 00:20:58 2013
@@ -31,15 +31,6 @@
ConSrvReleaseObject(&(Buff)->Header, (IsConsoleLocked))
-#define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
- WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
-
-typedef struct ConsoleInput_t
-{
- LIST_ENTRY ListEntry;
- INPUT_RECORD InputEvent;
-} ConsoleInput;
-
typedef struct _GET_INPUT_INFO
{
PCSR_THREAD CallingThread; // The thread which called the input API.
@@ -49,19 +40,6 @@
/* PRIVATE FUNCTIONS **********************************************************/
-
-static VOID FASTCALL
-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
WaitBeforeReading(IN PGET_INPUT_INFO InputInfo,
@@ -95,6 +73,120 @@
}
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;
+
+ PVOID InputHandle = WaitArgument2;
+
+ DPRINT("ReadCharsThread - WaitContext = 0x%p, WaitArgument1 = 0x%p,
WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2,
WaitFlags);
+
+ /*
+ * If we are notified of the process termination via a call
+ * to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
+ * CsrDestroyThread, just return.
+ */
+ if (WaitFlags & CsrProcessTerminating)
+ {
+ Status = STATUS_THREAD_IS_TERMINATING;
+ goto Quit;
+ }
+
+ /*
+ * Somebody is closing a handle to this input buffer,
+ * by calling ConSrvCloseHandleEntry.
+ * See whether we are linked to that handle (ie. we
+ * are a waiter for this handle), and if so, return.
+ * Otherwise, ignore the call and continue waiting.
+ */
+ if (InputHandle != NULL)
+ {
+ Status = (InputHandle == InputInfo->HandleEntry ? STATUS_ALERTED
+ : STATUS_PENDING);
+ goto Quit;
+ }
+
+ /*
+ * If we go there, that means we are notified for some new input.
+ * The console is therefore already locked.
+ */
+ Status = ReadChars(InputInfo,
+ WaitApiMessage,
+ FALSE);
+
+Quit:
+ if (Status != STATUS_PENDING)
+ {
+ WaitApiMessage->Status = Status;
+ ConsoleFreeHeap(InputInfo);
+ }
+
+ return (Status == STATUS_PENDING ? FALSE : TRUE);
+}
+
+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);
+static NTSTATUS
+ReadChars(IN PGET_INPUT_INFO InputInfo,
+ IN PCSR_API_MESSAGE ApiMessage,
+ IN BOOL CreateWaitBlock OPTIONAL)
+{
+ NTSTATUS Status;
+ PCONSOLE_READCONSOLE ReadConsoleRequest =
&((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
+ PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer;
+ CONSOLE_READCONSOLE_CONTROL ReadControl;
+
+ ReadControl.nLength = sizeof(CONSOLE_READCONSOLE_CONTROL);
+ ReadControl.nInitialChars = ReadConsoleRequest->NrCharactersRead;
+ ReadControl.dwCtrlWakeupMask = ReadConsoleRequest->CtrlWakeupMask;
+ ReadControl.dwControlKeyState = ReadConsoleRequest->ControlKeyState;
+
+ Status = ConDrvReadConsole(InputBuffer->Header.Console,
+ InputBuffer,
+ ReadConsoleRequest->Unicode,
+ ReadConsoleRequest->Buffer,
+ &ReadControl,
+ ReadConsoleRequest->NrCharactersToRead,
+ &ReadConsoleRequest->NrCharactersRead);
+
+ ReadConsoleRequest->ControlKeyState = ReadControl.dwControlKeyState;
+
+ if (Status == STATUS_PENDING)
+ {
+ /* We haven't completed a read, so start a wait */
+ return WaitBeforeReading(InputInfo,
+ ApiMessage,
+ ReadCharsThread,
+ CreateWaitBlock);
+ }
+ else
+ {
+ /* We read all what we wanted, we return the error code we were given */
+ return Status;
+ // return STATUS_SUCCESS;
+ }
+}
+
+static NTSTATUS
ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
IN BOOL Wait,
IN PCSR_API_MESSAGE ApiMessage,
@@ -162,292 +254,47 @@
return (Status == STATUS_PENDING ? FALSE : TRUE);
}
+NTSTATUS NTAPI
+ConDrvGetConsoleInput(IN PCONSOLE Console,
+ IN PCONSOLE_INPUT_BUFFER InputBuffer,
+ IN BOOLEAN WaitForMoreEvents,
+ IN BOOLEAN Unicode,
+ OUT PINPUT_RECORD InputRecord,
+ IN ULONG NumEventsToRead,
+ OUT PULONG NumEventsRead);
static NTSTATUS
ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
IN BOOL Wait, // TRUE --> Read ; FALSE --> Peek
IN PCSR_API_MESSAGE ApiMessage,
IN BOOL CreateWaitBlock OPTIONAL)
{
+ NTSTATUS Status;
+ PCONSOLE_GETINPUT GetInputRequest =
&((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest;
PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer;
- if (IsListEmpty(&InputBuffer->InputEvents))
- {
- if (Wait)
- {
- return WaitBeforeReading(InputInfo,
- ApiMessage,
- ReadInputBufferThread,
- CreateWaitBlock);
- }
- else
- {
- /* No input available and we don't wait, so we return success */
- return STATUS_SUCCESS;
- }
- }
- else
- {
- PCONSOLE_GETINPUT GetInputRequest =
&((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest;
- PLIST_ENTRY CurrentInput;
- ConsoleInput* Input;
- ULONG Length = GetInputRequest->Length;
- PINPUT_RECORD InputRecord = GetInputRequest->InputRecord;
-
- /* Only get input if there is any */
- CurrentInput = InputBuffer->InputEvents.Flink;
-
- while ( CurrentInput != &InputBuffer->InputEvents &&
- GetInputRequest->InputsRead < Length )
- {
- Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry);
-
- GetInputRequest->InputsRead++;
- *InputRecord = Input->InputEvent;
-
- if (GetInputRequest->Unicode == FALSE)
- {
- ConioInputEventToAnsi(InputBuffer->Header.Console, InputRecord);
- }
-
- InputRecord++;
- CurrentInput = CurrentInput->Flink;
-
- if (Wait) // TRUE --> Read, we remove inputs from the buffer ; FALSE
--> Peek, we keep inputs.
- {
- RemoveEntryList(&Input->ListEntry);
- ConsoleFreeHeap(Input);
- }
- }
-
- if (IsListEmpty(&InputBuffer->InputEvents))
- {
- ResetEvent(InputBuffer->ActiveEvent);
- }
-
- /* 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;
-
- PVOID InputHandle = WaitArgument2;
-
- DPRINT("ReadCharsThread - WaitContext = 0x%p, WaitArgument1 = 0x%p,
WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2,
WaitFlags);
-
- /*
- * If we are notified of the process termination via a call
- * to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
- * CsrDestroyThread, just return.
- */
- if (WaitFlags & CsrProcessTerminating)
- {
- Status = STATUS_THREAD_IS_TERMINATING;
- goto Quit;
- }
-
- /*
- * Somebody is closing a handle to this input buffer,
- * by calling ConSrvCloseHandleEntry.
- * See whether we are linked to that handle (ie. we
- * are a waiter for this handle), and if so, return.
- * Otherwise, ignore the call and continue waiting.
- */
- if (InputHandle != NULL)
- {
- Status = (InputHandle == InputInfo->HandleEntry ? STATUS_ALERTED
- : STATUS_PENDING);
- goto Quit;
- }
-
- /*
- * If we go there, that means we are notified for some new input.
- * The console is therefore already locked.
- */
- Status = ReadChars(InputInfo,
- WaitApiMessage,
- FALSE);
-
-Quit:
- if (Status != STATUS_PENDING)
- {
- WaitApiMessage->Status = Status;
- ConsoleFreeHeap(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.
-
- PCONSOLE_READCONSOLE ReadConsoleRequest =
&((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
- PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer;
- PCONSOLE Console = InputBuffer->Header.Console;
- 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 (InputBuffer->Mode & ENABLE_LINE_INPUT)
- {
- if (Console->LineBuffer == NULL)
- {
- /* Starting a new line */
- Console->LineMaxSize = (WORD)max(256, nNumberOfCharsToRead);
- 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 = 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 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 (KEY_EVENT == Input->InputEvent.EventType
- && Input->InputEvent.Event.KeyEvent.bKeyDown)
- {
- LineInputKeyDown(Console, &Input->InputEvent.Event.KeyEvent);
- ReadConsoleRequest->ControlKeyState =
Input->InputEvent.Event.KeyEvent.dwControlKeyState;
- }
- ConsoleFreeHeap(Input);
- }
-
- /* Check if we have a complete line to read from */
- if (Console->LineComplete)
- {
- while ( ReadConsoleRequest->NrCharactersRead < nNumberOfCharsToRead
&&
- Console->LinePos != Console->LineSize )
- {
- WCHAR Char = Console->LineBuffer[Console->LinePos++];
-
- if (ReadConsoleRequest->Unicode)
- {
- UnicodeBuffer[ReadConsoleRequest->NrCharactersRead] = Char;
- }
- else
- {
- ConsoleInputUnicodeCharToAnsiChar(Console,
-
&Buffer[ReadConsoleRequest->NrCharactersRead],
- &Char);
- }
-
- ReadConsoleRequest->NrCharactersRead++;
- }
-
- if (Console->LinePos == Console->LineSize)
- {
- /* Entire line has been read */
- ConsoleFreeHeap(Console->LineBuffer);
- Console->LineBuffer = NULL;
- }
-
- WaitForMoreToRead = FALSE;
- }
- }
- else
- {
- /* Character input */
- while ( ReadConsoleRequest->NrCharactersRead < nNumberOfCharsToRead
&&
- !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 (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[ReadConsoleRequest->NrCharactersRead] = Char;
- }
- else
- {
- ConsoleInputUnicodeCharToAnsiChar(Console,
-
&Buffer[ReadConsoleRequest->NrCharactersRead],
- &Char);
- }
-
- ReadConsoleRequest->NrCharactersRead++;
-
- /* Did read something */
- WaitForMoreToRead = FALSE;
- }
- ConsoleFreeHeap(Input);
- }
- }
-
- /* We haven't completed a read, so start a wait */
- if (WaitForMoreToRead == TRUE)
- {
+ // GetInputRequest->InputsRead = 0;
+
+ Status = ConDrvGetConsoleInput(InputBuffer->Header.Console,
+ InputBuffer,
+ Wait,
+ GetInputRequest->Unicode,
+ GetInputRequest->InputRecord,
+ GetInputRequest->Length,
+ &GetInputRequest->InputsRead);
+
+ if (Status == STATUS_PENDING)
+ {
+ /* We haven't completed a read, so start a wait */
return WaitBeforeReading(InputInfo,
ApiMessage,
- ReadCharsThread,
+ ReadInputBufferThread,
CreateWaitBlock);
}
- else /* We read all what we wanted, we return success */
- {
- return STATUS_SUCCESS;
+ else
+ {
+ /* We read all what we wanted, we return the error code we were given */
+ return Status;
+ // return STATUS_SUCCESS;
}
}
@@ -481,7 +328,8 @@
Status = ConSrvGetInputBufferAndHandleEntry(ProcessData,
ReadConsoleRequest->InputHandle, &InputBuffer, &HandleEntry, GENERIC_READ,
TRUE);
if (!NT_SUCCESS(Status)) return Status;
- ReadConsoleRequest->NrCharactersRead = 0;
+ // This member is set by the caller (IntReadConsole in kernel32)
+ // ReadConsoleRequest->NrCharactersRead = 0;
InputInfo.CallingThread = CsrGetClientThread();
InputInfo.HandleEntry = HandleEntry;
@@ -493,8 +341,7 @@
ConSrvReleaseInputBuffer(InputBuffer, TRUE);
- if (Status == STATUS_PENDING)
- *ReplyCode = CsrReplyPending;
+ if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
return Status;
}
@@ -518,10 +365,10 @@
return STATUS_INVALID_PARAMETER;
}
- GetInputRequest->InputsRead = 0;
-
Status = ConSrvGetInputBufferAndHandleEntry(ProcessData,
GetInputRequest->InputHandle, &InputBuffer, &HandleEntry, GENERIC_READ, TRUE);
if (!NT_SUCCESS(Status)) return Status;
+
+ GetInputRequest->InputsRead = 0;
InputInfo.CallingThread = CsrGetClientThread();
InputInfo.HandleEntry = HandleEntry;
@@ -534,8 +381,7 @@
ConSrvReleaseInputBuffer(InputBuffer, TRUE);
- if (Status == STATUS_PENDING)
- *ReplyCode = CsrReplyPending;
+ if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
return Status;
}
@@ -546,13 +392,13 @@
IN BOOLEAN Unicode,
IN PINPUT_RECORD InputRecord,
IN ULONG NumEventsToWrite,
- OUT PULONG NumEventsWritten);
+ OUT PULONG NumEventsWritten OPTIONAL);
CSR_API(SrvWriteConsoleInput)
{
NTSTATUS Status;
PCONSOLE_WRITEINPUT WriteInputRequest =
&((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteInputRequest;
PCONSOLE_INPUT_BUFFER InputBuffer;
- ULONG NumEventsWritten = 0;
+ ULONG NumEventsWritten;
DPRINT("SrvWriteConsoleInput\n");
@@ -569,6 +415,7 @@
&InputBuffer, GENERIC_WRITE, TRUE);
if (!NT_SUCCESS(Status)) return Status;
+ NumEventsWritten = 0;
Status = ConDrvWriteConsoleInput(InputBuffer->Header.Console,
InputBuffer,
WriteInputRequest->Unicode,
Modified: trunk/reactos/win32ss/user/consrv/conoutput.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/consrv/conout…
==============================================================================
--- trunk/reactos/win32ss/user/consrv/conoutput.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/consrv/conoutput.c [iso-8859-1] Thu Jun 27 00:20:58 2013
@@ -314,30 +314,39 @@
return (Status == STATUS_PENDING ? FALSE : TRUE);
}
+NTSTATUS NTAPI
+ConDrvWriteConsole(IN PCONSOLE Console,
+ IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
+ IN BOOLEAN Unicode,
+ IN PVOID StringBuffer,
+ IN ULONG NumCharsToWrite,
+ OUT PULONG NumCharsWritten OPTIONAL);
static NTSTATUS
DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
IN PCSR_THREAD ClientThread,
IN BOOL CreateWaitBlock OPTIONAL)
{
- NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status;
PCONSOLE_WRITECONSOLE WriteConsoleRequest =
&((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
- PCONSOLE Console;
- PTEXTMODE_SCREEN_BUFFER Buff;
- PVOID Buffer;
- DWORD Written = 0;
- ULONG Length;
-
- Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread->Process),
WriteConsoleRequest->OutputHandle, &Buff, GENERIC_WRITE, FALSE);
- if (!NT_SUCCESS(Status)) return Status;
-
- Console = Buff->Header.Console;
-
- // if (Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR |
PAUSED_FROM_SELECTION))
- if (Console->PauseFlags && Console->UnpauseEvent != NULL)
+ PTEXTMODE_SCREEN_BUFFER ScreenBuffer;
+
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread->Process),
+ WriteConsoleRequest->OutputHandle,
+ &ScreenBuffer, GENERIC_WRITE, FALSE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Status = ConDrvWriteConsole(ScreenBuffer->Header.Console,
+ ScreenBuffer,
+ WriteConsoleRequest->Unicode,
+ WriteConsoleRequest->Buffer,
+ WriteConsoleRequest->NrCharactersToWrite,
+ &WriteConsoleRequest->NrCharactersWritten);
+
+ if (Status == STATUS_PENDING)
{
if (CreateWaitBlock)
{
- if (!CsrCreateWait(&Console->WriteWaitQueue,
+ if (!CsrCreateWait(&ScreenBuffer->Header.Console->WriteWaitQueue,
WriteConsoleThread,
ClientThread,
ApiMessage,
@@ -345,63 +354,17 @@
NULL))
{
/* Fail */
- ConSrvReleaseScreenBuffer(Buff, FALSE);
- return STATUS_NO_MEMORY;
+ Status = STATUS_NO_MEMORY;
+ goto Quit;
}
}
/* Wait until we un-pause the console */
- Status = STATUS_PENDING;
- }
- else
- {
- if (WriteConsoleRequest->Unicode)
- {
- Buffer = WriteConsoleRequest->Buffer;
- }
- else
- {
- Length = MultiByteToWideChar(Console->OutputCodePage, 0,
- (PCHAR)WriteConsoleRequest->Buffer,
- WriteConsoleRequest->NrCharactersToWrite,
- NULL, 0);
- Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
- if (Buffer)
- {
- MultiByteToWideChar(Console->OutputCodePage, 0,
- (PCHAR)WriteConsoleRequest->Buffer,
- WriteConsoleRequest->NrCharactersToWrite,
- (PWCHAR)Buffer, Length);
- }
- else
- {
- Status = STATUS_NO_MEMORY;
- }
- }
-
- if (Buffer)
- {
- if (NT_SUCCESS(Status))
- {
- Status = ConioWriteConsole(Console,
- Buff,
- Buffer,
- WriteConsoleRequest->NrCharactersToWrite,
- TRUE);
- if (NT_SUCCESS(Status))
- {
- Written = WriteConsoleRequest->NrCharactersToWrite;
- }
- }
-
- if (!WriteConsoleRequest->Unicode)
- RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
- }
-
- WriteConsoleRequest->NrCharactersWritten = Written;
- }
-
- ConSrvReleaseScreenBuffer(Buff, FALSE);
+ // Status = STATUS_PENDING;
+ }
+
+Quit:
+ ConSrvReleaseScreenBuffer(ScreenBuffer, FALSE);
return Status;
}
@@ -509,8 +472,7 @@
CsrGetClientThread(),
TRUE);
- if (Status == STATUS_PENDING)
- *ReplyCode = CsrReplyPending;
+ if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
return Status;
}