[KERNEL32][CONSRV]
[reactos.git] / win32ss / user / winsrv / consrv / coninput.c
index 5bcd8f6..ba76ea7 100644 (file)
@@ -133,6 +133,7 @@ Quit:
 NTSTATUS NTAPI
 ConDrvReadConsole(IN PCONSOLE Console,
                   IN PCONSOLE_INPUT_BUFFER InputBuffer,
+                  /**/IN PUNICODE_STRING ExeName /**/OPTIONAL/**/,/**/
                   IN BOOLEAN Unicode,
                   OUT PVOID Buffer,
                   IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl,
@@ -148,20 +149,64 @@ ReadChars(IN PGET_INPUT_INFO InputInfo,
     PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer;
     CONSOLE_READCONSOLE_CONTROL ReadControl;
 
+    UNICODE_STRING ExeName;
+
+    PVOID Buffer;
+    ULONG NrCharactersRead = 0;
+    ULONG CharSize = (ReadConsoleRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
+
+    /* Compute the executable name, if needed */
+    if (ReadConsoleRequest->InitialNumBytes == 0 &&
+        ReadConsoleRequest->ExeLength <= sizeof(ReadConsoleRequest->StaticBuffer))
+    {
+        ExeName.Length = ExeName.MaximumLength = ReadConsoleRequest->ExeLength;
+        ExeName.Buffer = (PWCHAR)ReadConsoleRequest->StaticBuffer;
+    }
+    else
+    {
+        ExeName.Length = ExeName.MaximumLength = 0;
+        ExeName.Buffer = NULL;
+    }
+
+    /* Build the ReadControl structure */
     ReadControl.nLength           = sizeof(CONSOLE_READCONSOLE_CONTROL);
-    ReadControl.nInitialChars     = ReadConsoleRequest->NrCharactersRead;
+    ReadControl.nInitialChars     = ReadConsoleRequest->InitialNumBytes / CharSize;
     ReadControl.dwCtrlWakeupMask  = ReadConsoleRequest->CtrlWakeupMask;
     ReadControl.dwControlKeyState = ReadConsoleRequest->ControlKeyState;
 
+    /*
+     * For optimization purposes, Windows (and hence ReactOS, too, for
+     * compatibility reasons) uses a static buffer if no more than eighty
+     * bytes are read. Otherwise a new buffer is used.
+     * The client-side expects that we know this behaviour.
+     */
+    if (ReadConsoleRequest->CaptureBufferSize <= sizeof(ReadConsoleRequest->StaticBuffer))
+    {
+        /*
+         * Adjust the internal pointer, because its old value points to
+         * the static buffer in the original ApiMessage structure.
+         */
+        // ReadConsoleRequest->Buffer = ReadConsoleRequest->StaticBuffer;
+        Buffer = ReadConsoleRequest->StaticBuffer;
+    }
+    else
+    {
+        Buffer = ReadConsoleRequest->Buffer;
+    }
+
+    DPRINT1("Calling ConDrvReadConsole(%wZ)\n", &ExeName);
     Status = ConDrvReadConsole(InputBuffer->Header.Console,
                                InputBuffer,
+                               &ExeName,
                                ReadConsoleRequest->Unicode,
-                               ReadConsoleRequest->Buffer,
+                               Buffer,
                                &ReadControl,
-                               ReadConsoleRequest->NrCharactersToRead,
-                               &ReadConsoleRequest->NrCharactersRead);
+                               ReadConsoleRequest->NumBytes / CharSize, // NrCharactersToRead
+                               &NrCharactersRead);
+    DPRINT1("ConDrvReadConsole returned (%d ; Status = 0x%08x)\n",
+           NrCharactersRead, Status);
 
-    ReadConsoleRequest->ControlKeyState = ReadControl.dwControlKeyState;
+    // ReadConsoleRequest->ControlKeyState = ReadControl.dwControlKeyState;
 
     if (Status == STATUS_PENDING)
     {
@@ -173,7 +218,13 @@ ReadChars(IN PGET_INPUT_INFO InputInfo,
     }
     else
     {
-        /* We read all what we wanted, we return the error code we were given */
+        /*
+         * We read all what we wanted. Set the number of bytes read and
+         * return the error code we were given.
+         */
+        ReadConsoleRequest->NumBytes = NrCharactersRead * CharSize;
+        ReadConsoleRequest->ControlKeyState = ReadControl.dwControlKeyState;
+
         return Status;
         // return STATUS_SUCCESS;
     }
@@ -304,8 +355,12 @@ ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
     }
     else
     {
-        /* We read all what we wanted, we return the error code we were given */
+        /*
+         * We read all what we wanted. Set the number of events read and
+         * return the error code we were given.
+         */
         GetInputRequest->NumRecords = NumEventsRead;
+
         return Status;
         // return STATUS_SUCCESS;
     }
@@ -325,15 +380,32 @@ CSR_API(SrvReadConsole)
 
     DPRINT("SrvReadConsole\n");
 
-    if (!CsrValidateMessageBuffer(ApiMessage,
-                                  (PVOID*)&ReadConsoleRequest->Buffer,
-                                  ReadConsoleRequest->BufferSize,
-                                  sizeof(BYTE)))
+    /*
+     * For optimization purposes, Windows (and hence ReactOS, too, for
+     * compatibility reasons) uses a static buffer if no more than eighty
+     * bytes are read. Otherwise a new buffer is used.
+     * The client-side expects that we know this behaviour.
+     */
+    if (ReadConsoleRequest->CaptureBufferSize <= sizeof(ReadConsoleRequest->StaticBuffer))
     {
-        return STATUS_INVALID_PARAMETER;
+        /*
+         * Adjust the internal pointer, because its old value points to
+         * the static buffer in the original ApiMessage structure.
+         */
+        // ReadConsoleRequest->Buffer = ReadConsoleRequest->StaticBuffer;
+    }
+    else
+    {
+        if (!CsrValidateMessageBuffer(ApiMessage,
+                                      (PVOID*)&ReadConsoleRequest->Buffer,
+                                      ReadConsoleRequest->CaptureBufferSize,
+                                      sizeof(BYTE)))
+        {
+            return STATUS_INVALID_PARAMETER;
+        }
     }
 
-    if (ReadConsoleRequest->NrCharactersRead > ReadConsoleRequest->NrCharactersToRead)
+    if (ReadConsoleRequest->InitialNumBytes > ReadConsoleRequest->NumBytes)
     {
         return STATUS_INVALID_PARAMETER;
     }
@@ -341,9 +413,6 @@ CSR_API(SrvReadConsole)
     Status = ConSrvGetInputBufferAndHandleEntry(ProcessData, ReadConsoleRequest->InputHandle, &InputBuffer, &HandleEntry, GENERIC_READ, TRUE);
     if (!NT_SUCCESS(Status)) return Status;
 
-    // This member is set by the caller (IntReadConsole in kernel32)
-    // ReadConsoleRequest->NrCharactersRead = 0;
-
     InputInfo.CallingThread = CsrGetClientThread();
     InputInfo.HandleEntry   = HandleEntry;
     InputInfo.InputBuffer   = InputBuffer;
@@ -462,7 +531,11 @@ CSR_API(SrvWriteConsoleInput)
     Status = ConSrvGetInputBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
                                   WriteInputRequest->InputHandle,
                                   &InputBuffer, GENERIC_WRITE, TRUE);
-    if (!NT_SUCCESS(Status)) return Status;
+    if (!NT_SUCCESS(Status))
+    {
+        WriteInputRequest->NumRecords = 0;
+        return Status;
+    }
 
     NumEventsWritten = 0;
     Status = ConDrvWriteConsoleInput(InputBuffer->Header.Console,