[KERNEL32]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 27 Jun 2013 00:20:58 +0000 (00:20 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 27 Jun 2013 00:20:58 +0000 (00:20 +0000)
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?)

svn path=/trunk/; revision=59345

reactos/dll/win32/kernel32/client/console/readwrite.c
reactos/include/reactos/subsys/win/conmsg.h
reactos/win32ss/user/consrv/condrv/coninput.c
reactos/win32ss/user/consrv/condrv/text.c
reactos/win32ss/user/consrv/coninput.c
reactos/win32ss/user/consrv/conoutput.c

index df78b95..1b45d8d 100644 (file)
@@ -60,11 +60,17 @@ IntReadConsole(HANDLE hConsoleInput,
     /* 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,
index 0f75fcc..2d989f7 100644 (file)
@@ -167,8 +167,8 @@ typedef struct
     HANDLE InputHandle;
 
     BOOL Unicode;
-    WORD NrCharactersToRead;
-    WORD NrCharactersRead;
+    ULONG NrCharactersToRead;
+    ULONG NrCharactersRead;
 
     UNICODE_STRING ExeName;
     DWORD CtrlWakeupMask;
index fb4347e..ef64fc4 100644 (file)
@@ -43,17 +43,9 @@ typedef struct ConsoleInput_t
     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 @@ ConioInputEventToAnsi(PCONSOLE Console, PINPUT_RECORD InputEvent)
                                           &UnicodeChar);
     }
 }
-#endif
 
 NTSTATUS FASTCALL
 ConioProcessInputEvent(PCONSOLE Console,
@@ -211,13 +202,231 @@ ConDrvProcessKey(IN PCONSOLE Console,
 
 /* 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 @@ ConDrvWriteConsoleInput(IN PCONSOLE Console,
     ASSERT( (InputRecord != NULL && NumEventsToWrite >= 0) ||
             (InputRecord == NULL && NumEventsToWrite == 0) );
 
-    if (NumEventsWritten) *NumEventsWritten = 0;
+    // Do NOT do that !! Use the existing number of events already written, if any...
+    // if (NumEventsWritten) *NumEventsWritten = 0;
 
-    for (i = 0; i < NumEventsToWrite && NT_SUCCESS(Status); ++i)
+    for (i = (NumEventsWritten ? *NumEventsWritten : 0); i < NumEventsToWrite && NT_SUCCESS(Status); ++i)
     {
         if (InputRecord->EventType == KEY_EVENT && !Unicode)
         {
index 4f04c35..7c7b5d5 100644 (file)
@@ -751,9 +751,77 @@ ConDrvWriteConsoleOutput(IN PCONSOLE Console,
 }
 
 NTSTATUS NTAPI
-ConDrvWriteConsole(IN PCONSOLE Console)
+ConDrvWriteConsole(IN PCONSOLE Console,
+                   IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
+                   IN BOOLEAN Unicode,
+                   IN PVOID StringBuffer,
+                   IN ULONG NumCharsToWrite,
+                   OUT PULONG NumCharsWritten OPTIONAL)
 {
-    return STATUS_NOT_IMPLEMENTED;
+    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
index 4160132..a26b5b1 100644 (file)
     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.
@@ -50,19 +41,6 @@ typedef struct _GET_INPUT_INFO
 
 /* 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,
                   IN PCSR_API_MESSAGE ApiMessage,
@@ -95,28 +73,26 @@ WaitBeforeReading(IN PGET_INPUT_INFO InputInfo,
 }
 
 static NTSTATUS
-ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
-                IN BOOL Wait,
-                IN PCSR_API_MESSAGE ApiMessage,
-                IN BOOL CreateWaitBlock OPTIONAL);
+ReadChars(IN PGET_INPUT_INFO InputInfo,
+          IN PCSR_API_MESSAGE ApiMessage,
+          IN BOOL CreateWaitBlock OPTIONAL);
 
 // Wait function CSR_WAIT_FUNCTION
 static BOOLEAN
-ReadInputBufferThread(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)
+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;
-    PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)WaitApiMessage)->Data.GetInputRequest;
     PGET_INPUT_INFO InputInfo = (PGET_INPUT_INFO)WaitContext;
 
     PVOID InputHandle = WaitArgument2;
 
-    DPRINT("ReadInputBufferThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2, WaitFlags);
+    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
@@ -147,10 +123,9 @@ ReadInputBufferThread(IN PLIST_ENTRY WaitList,
      * If we go there, that means we are notified for some new input.
      * The console is therefore already locked.
      */
-    Status = ReadInputBuffer(InputInfo,
-                             GetInputRequest->bRead,
-                             WaitApiMessage,
-                             FALSE);
+    Status = ReadChars(InputInfo,
+                       WaitApiMessage,
+                       FALSE);
 
 Quit:
     if (Status != STATUS_PENDING)
@@ -162,94 +137,78 @@ Quit:
     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
-ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
-                IN BOOL Wait,   // TRUE --> Read ; FALSE --> Peek
-                IN PCSR_API_MESSAGE ApiMessage,
-                IN BOOL CreateWaitBlock OPTIONAL)
+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;
 
-    if (IsListEmpty(&InputBuffer->InputEvents))
+    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)
     {
-        if (Wait)
-        {
-            return WaitBeforeReading(InputInfo,
-                                     ApiMessage,
-                                     ReadInputBufferThread,
-                                     CreateWaitBlock);
-        }
-        else
-        {
-            /* No input available and we don't wait, so we return success */
-            return STATUS_SUCCESS;
-        }
+        /* We haven't completed a read, so start a wait */
+        return WaitBeforeReading(InputInfo,
+                                 ApiMessage,
+                                 ReadCharsThread,
+                                 CreateWaitBlock);
     }
     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;
+        /* We read all what we wanted, we return the error code we were given */
+        return Status;
+        // return STATUS_SUCCESS;
     }
 }
 
 static NTSTATUS
-ReadChars(IN PGET_INPUT_INFO InputInfo,
-          IN PCSR_API_MESSAGE ApiMessage,
-          IN BOOL CreateWaitBlock OPTIONAL);
+ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
+                IN BOOL Wait,
+                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)
+ReadInputBufferThread(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;
+    PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)WaitApiMessage)->Data.GetInputRequest;
     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);
+    DPRINT("ReadInputBufferThread - 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
@@ -280,9 +239,10 @@ ReadCharsThread(IN PLIST_ENTRY WaitList,
      * If we go there, that means we are notified for some new input.
      * The console is therefore already locked.
      */
-    Status = ReadChars(InputInfo,
-                       WaitApiMessage,
-                       FALSE);
+    Status = ReadInputBuffer(InputInfo,
+                             GetInputRequest->bRead,
+                             WaitApiMessage,
+                             FALSE);
 
 Quit:
     if (Status != STATUS_PENDING)
@@ -294,160 +254,47 @@ Quit:
     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
-ReadChars(IN PGET_INPUT_INFO InputInfo,
-          IN PCSR_API_MESSAGE ApiMessage,
-          IN BOOL CreateWaitBlock OPTIONAL)
+ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
+                IN BOOL Wait,   // TRUE --> Read ; FALSE --> Peek
+                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;
+    NTSTATUS Status;
+    PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest;
     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) */
+    // GetInputRequest->InputsRead = 0;
 
-    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;
-            }
-        }
+    Status = ConDrvGetConsoleInput(InputBuffer->Header.Console,
+                                   InputBuffer,
+                                   Wait,
+                                   GetInputRequest->Unicode,
+                                   GetInputRequest->InputRecord,
+                                   GetInputRequest->Length,
+                                   &GetInputRequest->InputsRead);
 
-        /* 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)
+    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 */
+    else
     {
-        return STATUS_SUCCESS;
+        /* We read all what we wanted, we return the error code we were given */
+        return Status;
+        // return STATUS_SUCCESS;
     }
 }
 
@@ -481,7 +328,8 @@ CSR_API(SrvReadConsole)
     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 @@ CSR_API(SrvReadConsole)
 
     ConSrvReleaseInputBuffer(InputBuffer, TRUE);
 
-    if (Status == STATUS_PENDING)
-        *ReplyCode = CsrReplyPending;
+    if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
 
     return Status;
 }
@@ -518,11 +365,11 @@ CSR_API(SrvGetConsoleInput)
         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;
     InputInfo.InputBuffer   = InputBuffer;
@@ -534,8 +381,7 @@ CSR_API(SrvGetConsoleInput)
 
     ConSrvReleaseInputBuffer(InputBuffer, TRUE);
 
-    if (Status == STATUS_PENDING)
-        *ReplyCode = CsrReplyPending;
+    if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
 
     return Status;
 }
@@ -546,13 +392,13 @@ ConDrvWriteConsoleInput(IN PCONSOLE Console,
                         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 @@ CSR_API(SrvWriteConsoleInput)
                                   &InputBuffer, GENERIC_WRITE, TRUE);
     if (!NT_SUCCESS(Status)) return Status;
 
+    NumEventsWritten = 0;
     Status = ConDrvWriteConsoleInput(InputBuffer->Header.Console,
                                      InputBuffer,
                                      WriteInputRequest->Unicode,
index 4aeaf25..7abde25 100644 (file)
@@ -314,30 +314,39 @@ Quit:
     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;
+    PTEXTMODE_SCREEN_BUFFER ScreenBuffer;
 
-    Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread->Process), WriteConsoleRequest->OutputHandle, &Buff, GENERIC_WRITE, FALSE);
+    Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread->Process),
+                                     WriteConsoleRequest->OutputHandle,
+                                     &ScreenBuffer, GENERIC_WRITE, FALSE);
     if (!NT_SUCCESS(Status)) return Status;
 
-    Console = Buff->Header.Console;
+    Status = ConDrvWriteConsole(ScreenBuffer->Header.Console,
+                                ScreenBuffer,
+                                WriteConsoleRequest->Unicode,
+                                WriteConsoleRequest->Buffer,
+                                WriteConsoleRequest->NrCharactersToWrite,
+                                &WriteConsoleRequest->NrCharactersWritten);
 
-    // if (Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION))
-    if (Console->PauseFlags && Console->UnpauseEvent != NULL)
+    if (Status == STATUS_PENDING)
     {
         if (CreateWaitBlock)
         {
-            if (!CsrCreateWait(&Console->WriteWaitQueue,
+            if (!CsrCreateWait(&ScreenBuffer->Header.Console->WriteWaitQueue,
                                WriteConsoleThread,
                                ClientThread,
                                ApiMessage,
@@ -345,63 +354,17 @@ DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
                                NULL))
             {
                 /* Fail */
-                ConSrvReleaseScreenBuffer(Buff, FALSE);
-                return STATUS_NO_MEMORY;
-            }
-        }
-
-        /* 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;
+                goto Quit;
             }
         }
 
-        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;
+        /* Wait until we un-pause the console */
+        // Status = STATUS_PENDING;
     }
 
-    ConSrvReleaseScreenBuffer(Buff, FALSE);
+Quit:
+    ConSrvReleaseScreenBuffer(ScreenBuffer, FALSE);
     return Status;
 }
 
@@ -509,8 +472,7 @@ CSR_API(SrvWriteConsole)
                             CsrGetClientThread(),
                             TRUE);
 
-    if (Status == STATUS_PENDING)
-        *ReplyCode = CsrReplyPending;
+    if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
 
     return Status;
 }