[CONSRV]: Move all references to VDM screenbuffers from condrv back to consrv (only...
[reactos.git] / win32ss / user / winsrv / consrv / conoutput.c
index 223f6ca..0ab69b9 100644 (file)
 /* INCLUDES *******************************************************************/
 
 #include "consrv.h"
-#include "console.h"
-#include "include/conio.h"
-#include "include/conio2.h"
-#include "conoutput.h"
-#include "handle.h"
 
 #define NDEBUG
 #include <debug.h>
 
-
-/* PRIVATE FUNCTIONS **********************************************************/
-
-
 /* PUBLIC SERVER APIS *********************************************************/
 
+/*
+ * FIXME: This function MUST be moved fro condrv/conoutput.c because only
+ * consrv knows how to manipulate VDM screenbuffers.
+ */
+NTSTATUS NTAPI
+ConDrvWriteConsoleOutputVDM(IN PCONSOLE Console,
+                            IN PTEXTMODE_SCREEN_BUFFER Buffer,
+                            IN PCHAR_CELL CharInfo/*Buffer*/,
+                            IN COORD CharInfoSize,
+                            IN PSMALL_RECT WriteRegion);
 NTSTATUS NTAPI
 ConDrvInvalidateBitMapRect(IN PCONSOLE Console,
                            IN PCONSOLE_SCREEN_BUFFER Buffer,
@@ -42,6 +43,18 @@ CSR_API(SrvInvalidateBitMapRect)
                                    &Buffer, GENERIC_READ, TRUE);
     if (!NT_SUCCESS(Status)) return Status;
 
+    /* In text-mode only, draw the VDM buffer if present */
+    if (GetType(Buffer) == TEXTMODE_BUFFER)
+    {
+        PTEXTMODE_SCREEN_BUFFER TextBuffer = (PTEXTMODE_SCREEN_BUFFER)Buffer;
+
+        /*Status =*/ ConDrvWriteConsoleOutputVDM(Buffer->Header.Console,
+                                                 TextBuffer,
+                                                 Buffer->Header.Console->VDMBuffer,
+                                                 Buffer->Header.Console->VDMBufferSize,
+                                                 &InvalidateDIBitsRequest->Region);
+    }
+
     Status = ConDrvInvalidateBitMapRect(Buffer->Header.Console,
                                         Buffer,
                                         &InvalidateDIBitsRequest->Region);
@@ -50,6 +63,55 @@ CSR_API(SrvInvalidateBitMapRect)
     return Status;
 }
 
+NTSTATUS NTAPI
+ConDrvSetConsolePalette(IN PCONSOLE Console,
+                        // IN PGRAPHICS_SCREEN_BUFFER Buffer,
+                        IN PCONSOLE_SCREEN_BUFFER Buffer,
+                        IN HPALETTE PaletteHandle,
+                        IN UINT PaletteUsage);
+CSR_API(SrvSetConsolePalette)
+{
+    NTSTATUS Status;
+    PCONSOLE_SETPALETTE SetPaletteRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetPaletteRequest;
+    // PGRAPHICS_SCREEN_BUFFER Buffer;
+    PCONSOLE_SCREEN_BUFFER Buffer;
+
+    DPRINT("SrvSetConsolePalette\n");
+
+    // NOTE: Tests show that this function is used only for graphics screen buffers
+    // and otherwise it returns FALSE + sets last error to invalid handle.
+    // I think it's ridiculous, because if you are in text mode, simulating
+    // a change of VGA palette via DAC registers (done by a call to SetConsolePalette)
+    // cannot be done... So I allow it in ReactOS !
+    /*
+    Status = ConSrvGetGraphicsBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                                     SetPaletteRequest->OutputHandle,
+                                     &Buffer, GENERIC_WRITE, TRUE);
+    */
+    Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                                   SetPaletteRequest->OutputHandle,
+                                   &Buffer, GENERIC_WRITE, TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /*
+     * Make the palette handle public, so that it can be
+     * used by other threads calling GDI functions on it.
+     * Indeed, the palette handle comes from a console app
+     * calling ourselves, running in CSRSS.
+     */
+    NtUserConsoleControl(ConsoleMakePalettePublic,
+                         &SetPaletteRequest->PaletteHandle,
+                         sizeof(SetPaletteRequest->PaletteHandle));
+
+    Status = ConDrvSetConsolePalette(Buffer->Header.Console,
+                                     Buffer,
+                                     SetPaletteRequest->PaletteHandle,
+                                     SetPaletteRequest->Usage);
+
+    ConSrvReleaseScreenBuffer(Buffer, TRUE);
+    return Status;
+}
+
 NTSTATUS NTAPI
 ConDrvGetConsoleCursorInfo(IN PCONSOLE Console,
                            IN PTEXTMODE_SCREEN_BUFFER Buffer,
@@ -129,8 +191,9 @@ CSR_API(SrvCreateConsoleScreenBuffer)
 {
     NTSTATUS Status = STATUS_INVALID_PARAMETER;
     PCONSOLE_CREATESCREENBUFFER CreateScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CreateScreenBufferRequest;
-    PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
-    PCONSOLE Console;
+    PCSR_PROCESS Process = CsrGetClientThread()->Process;
+    PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
+    PCONSRV_CONSOLE Console;
     PCONSOLE_SCREEN_BUFFER Buff;
 
     PVOID ScreenBufferInfo = NULL;
@@ -192,8 +255,8 @@ CSR_API(SrvCreateConsoleScreenBuffer)
         /* Get infos from the graphics buffer information structure */
         if (!CsrValidateMessageBuffer(ApiMessage,
                                       (PVOID*)&CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMapInfo,
-                                      1,
-                                      CreateScreenBufferRequest->GraphicsBufferInfo.dwBitMapInfoLength))
+                                      CreateScreenBufferRequest->GraphicsBufferInfo.dwBitMapInfoLength,
+                                      sizeof(BYTE)))
         {
             Status = STATUS_INVALID_PARAMETER;
             goto Quit;
@@ -202,15 +265,18 @@ CSR_API(SrvCreateConsoleScreenBuffer)
         ScreenBufferInfo = &GraphicsInfo;
 
         /* Initialize shared variables */
-        CreateScreenBufferRequest->GraphicsBufferInfo.hMutex   = GraphicsInfo.Info.hMutex   = INVALID_HANDLE_VALUE;
-        CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap = GraphicsInfo.Info.lpBitMap = NULL;
+        // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex
+        CreateScreenBufferRequest->hMutex   = GraphicsInfo.Info.hMutex   = INVALID_HANDLE_VALUE;
+        // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap
+        CreateScreenBufferRequest->lpBitMap = GraphicsInfo.Info.lpBitMap = NULL;
 
         /* A graphics screen buffer is never inheritable */
-        CreateScreenBufferRequest->Inheritable = FALSE;
+        CreateScreenBufferRequest->InheritHandle = FALSE;
     }
 
     Status = ConDrvCreateScreenBuffer(&Buff,
-                                      Console,
+                                      (PCONSOLE)Console,
+                                      Process->ProcessHandle,
                                       CreateScreenBufferRequest->ScreenBufferType,
                                       ScreenBufferInfo);
     if (!NT_SUCCESS(Status)) goto Quit;
@@ -221,8 +287,8 @@ CSR_API(SrvCreateConsoleScreenBuffer)
     Status = ConSrvInsertObject(ProcessData,
                                 &CreateScreenBufferRequest->OutputHandle,
                                 &Buff->Header,
-                                CreateScreenBufferRequest->Access,
-                                CreateScreenBufferRequest->Inheritable,
+                                CreateScreenBufferRequest->DesiredAccess,
+                                CreateScreenBufferRequest->InheritHandle,
                                 CreateScreenBufferRequest->ShareMode);
 
     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
@@ -236,8 +302,10 @@ CSR_API(SrvCreateConsoleScreenBuffer)
          * Initialize the graphics buffer information structure
          * and give it back to the client.
          */
-        CreateScreenBufferRequest->GraphicsBufferInfo.hMutex   = Buffer->ClientMutex;
-        CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap = Buffer->ClientBitMap;
+        // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex
+        CreateScreenBufferRequest->hMutex   = Buffer->ClientMutex;
+        // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap
+        CreateScreenBufferRequest->lpBitMap = Buffer->ClientBitMap;
     }
 
 Quit:
@@ -274,10 +342,11 @@ CSR_API(SrvSetConsoleActiveScreenBuffer)
 static NTSTATUS
 DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
                IN PCSR_THREAD ClientThread,
-               IN BOOL CreateWaitBlock OPTIONAL);
+               IN BOOLEAN CreateWaitBlock OPTIONAL);
 
 // Wait function CSR_WAIT_FUNCTION
 static BOOLEAN
+NTAPI
 WriteConsoleThread(IN PLIST_ENTRY WaitList,
                    IN PCSR_THREAD WaitThread,
                    IN PCSR_API_MESSAGE WaitApiMessage,
@@ -301,9 +370,7 @@ WriteConsoleThread(IN PLIST_ENTRY WaitList,
         goto Quit;
     }
 
-    Status = DoWriteConsole(WaitApiMessage,
-                            WaitThread,
-                            FALSE);
+    Status = DoWriteConsole(WaitApiMessage, WaitThread, FALSE);
 
 Quit:
     if (Status != STATUS_PENDING)
@@ -324,33 +391,62 @@ ConDrvWriteConsole(IN PCONSOLE Console,
 static NTSTATUS
 DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
                IN PCSR_THREAD ClientThread,
-               IN BOOL CreateWaitBlock OPTIONAL)
+               IN BOOLEAN CreateWaitBlock OPTIONAL)
 {
     NTSTATUS Status;
     PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
     PTEXTMODE_SCREEN_BUFFER ScreenBuffer;
 
+    PVOID Buffer;
+    ULONG NrCharactersWritten = 0;
+    ULONG CharSize = (WriteConsoleRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
+
     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread->Process),
                                      WriteConsoleRequest->OutputHandle,
                                      &ScreenBuffer, GENERIC_WRITE, FALSE);
     if (!NT_SUCCESS(Status)) return Status;
 
+    /*
+     * For optimization purposes, Windows (and hence ReactOS, too, for
+     * compatibility reasons) uses a static buffer if no more than eighty
+     * bytes are written. Otherwise a new buffer is used.
+     * The client-side expects that we know this behaviour.
+     */
+    if (WriteConsoleRequest->UsingStaticBuffer &&
+        WriteConsoleRequest->NumBytes <= sizeof(WriteConsoleRequest->StaticBuffer))
+    {
+        /*
+         * Adjust the internal pointer, because its old value points to
+         * the static buffer in the original ApiMessage structure.
+         */
+        // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
+        Buffer = WriteConsoleRequest->StaticBuffer;
+    }
+    else
+    {
+        Buffer = WriteConsoleRequest->Buffer;
+    }
+
+    DPRINT("Calling ConDrvWriteConsole\n");
     Status = ConDrvWriteConsole(ScreenBuffer->Header.Console,
                                 ScreenBuffer,
                                 WriteConsoleRequest->Unicode,
-                                WriteConsoleRequest->Buffer,
-                                WriteConsoleRequest->NrCharactersToWrite,
-                                &WriteConsoleRequest->NrCharactersWritten);
+                                Buffer,
+                                WriteConsoleRequest->NumBytes / CharSize, // NrCharactersToWrite
+                                &NrCharactersWritten);
+    DPRINT("ConDrvWriteConsole returned (%d ; Status = 0x%08x)\n",
+           NrCharactersWritten, Status);
 
     if (Status == STATUS_PENDING)
     {
         if (CreateWaitBlock)
         {
-            if (!CsrCreateWait(&ScreenBuffer->Header.Console->WriteWaitQueue,
+            PCONSRV_CONSOLE Console = (PCONSRV_CONSOLE)ScreenBuffer->Header.Console;
+
+            if (!CsrCreateWait(&Console->WriteWaitQueue,
                                WriteConsoleThread,
                                ClientThread,
                                ApiMessage,
-                               NULL,
                                NULL))
             {
                 /* Fail */
@@ -362,6 +458,11 @@ DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
         /* Wait until we un-pause the console */
         // Status = STATUS_PENDING;
     }
+    else
+    {
+        /* We read all what we wanted. Set the number of bytes written. */
+        WriteConsoleRequest->NumBytes = NrCharactersWritten * CharSize;
+    }
 
 Quit:
     ConSrvReleaseScreenBuffer(ScreenBuffer, FALSE);
@@ -376,8 +477,6 @@ ConDrvReadConsoleOutput(IN PCONSOLE Console,
                         IN PTEXTMODE_SCREEN_BUFFER Buffer,
                         IN BOOLEAN Unicode,
                         OUT PCHAR_INFO CharInfo/*Buffer*/,
-                        IN PCOORD BufferSize,
-                        IN PCOORD BufferCoord,
                         IN OUT PSMALL_RECT ReadRegion);
 CSR_API(SrvReadConsoleOutput)
 {
@@ -385,14 +484,40 @@ CSR_API(SrvReadConsoleOutput)
     PCONSOLE_READOUTPUT ReadOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadOutputRequest;
     PTEXTMODE_SCREEN_BUFFER Buffer;
 
+    ULONG NumCells;
+    PCHAR_INFO CharInfo;
+
     DPRINT("SrvReadConsoleOutput\n");
 
-    if (!CsrValidateMessageBuffer(ApiMessage,
-                                  (PVOID*)&ReadOutputRequest->CharInfo,
-                                  ReadOutputRequest->BufferSize.X * ReadOutputRequest->BufferSize.Y,
-                                  sizeof(CHAR_INFO)))
+    NumCells = (ReadOutputRequest->ReadRegion.Right - ReadOutputRequest->ReadRegion.Left + 1) *
+               (ReadOutputRequest->ReadRegion.Bottom - ReadOutputRequest->ReadRegion.Top + 1);
+
+    /*
+     * For optimization purposes, Windows (and hence ReactOS, too, for
+     * compatibility reasons) uses a static buffer if no more than one
+     * cell is read. Otherwise a new buffer is used.
+     * The client-side expects that we know this behaviour.
+     */
+    if (NumCells <= 1)
     {
-        return STATUS_INVALID_PARAMETER;
+        /*
+         * Adjust the internal pointer, because its old value points to
+         * the static buffer in the original ApiMessage structure.
+         */
+        // ReadOutputRequest->CharInfo = &ReadOutputRequest->StaticBuffer;
+        CharInfo = &ReadOutputRequest->StaticBuffer;
+    }
+    else
+    {
+        if (!CsrValidateMessageBuffer(ApiMessage,
+                                      (PVOID*)&ReadOutputRequest->CharInfo,
+                                      NumCells,
+                                      sizeof(CHAR_INFO)))
+        {
+            return STATUS_INVALID_PARAMETER;
+        }
+
+        CharInfo = ReadOutputRequest->CharInfo;
     }
 
     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
@@ -403,9 +528,7 @@ CSR_API(SrvReadConsoleOutput)
     Status = ConDrvReadConsoleOutput(Buffer->Header.Console,
                                      Buffer,
                                      ReadOutputRequest->Unicode,
-                                     ReadOutputRequest->CharInfo,
-                                     &ReadOutputRequest->BufferSize,
-                                     &ReadOutputRequest->BufferCoord,
+                                     CharInfo,
                                      &ReadOutputRequest->ReadRegion);
 
     ConSrvReleaseScreenBuffer(Buffer, TRUE);
@@ -417,38 +540,101 @@ ConDrvWriteConsoleOutput(IN PCONSOLE Console,
                          IN PTEXTMODE_SCREEN_BUFFER Buffer,
                          IN BOOLEAN Unicode,
                          IN PCHAR_INFO CharInfo/*Buffer*/,
-                         IN PCOORD BufferSize,
-                         IN PCOORD BufferCoord,
                          IN OUT PSMALL_RECT WriteRegion);
 CSR_API(SrvWriteConsoleOutput)
 {
     NTSTATUS Status;
     PCONSOLE_WRITEOUTPUT WriteOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteOutputRequest;
     PTEXTMODE_SCREEN_BUFFER Buffer;
+    PCSR_PROCESS Process = CsrGetClientThread()->Process;
+
+    ULONG NumCells;
+    PCHAR_INFO CharInfo;
 
     DPRINT("SrvWriteConsoleOutput\n");
 
-    if (!CsrValidateMessageBuffer(ApiMessage,
-                                  (PVOID*)&WriteOutputRequest->CharInfo,
-                                  WriteOutputRequest->BufferSize.X * WriteOutputRequest->BufferSize.Y,
-                                  sizeof(CHAR_INFO)))
-    {
-        return STATUS_INVALID_PARAMETER;
-    }
+    NumCells = (WriteOutputRequest->WriteRegion.Right - WriteOutputRequest->WriteRegion.Left + 1) *
+               (WriteOutputRequest->WriteRegion.Bottom - WriteOutputRequest->WriteRegion.Top + 1);
 
-    Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+    Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(Process),
                                      WriteOutputRequest->OutputHandle,
                                      &Buffer, GENERIC_WRITE, TRUE);
     if (!NT_SUCCESS(Status)) return Status;
 
+    /*
+     * Validate the message buffer if we do not use a process' heap buffer
+     * (CsrAllocateCaptureBuffer succeeded because we haven't allocated
+     * a too large (>= 64 kB, size of the CSR heap) data buffer).
+     */
+    if (!WriteOutputRequest->UseVirtualMemory)
+    {
+        /*
+         * For optimization purposes, Windows (and hence ReactOS, too, for
+         * compatibility reasons) uses a static buffer if no more than one
+         * cell is written. Otherwise a new buffer is used.
+         * The client-side expects that we know this behaviour.
+         */
+        if (NumCells <= 1)
+        {
+            /*
+             * Adjust the internal pointer, because its old value points to
+             * the static buffer in the original ApiMessage structure.
+             */
+            // WriteOutputRequest->CharInfo = &WriteOutputRequest->StaticBuffer;
+            CharInfo = &WriteOutputRequest->StaticBuffer;
+        }
+        else
+        {
+            if (!CsrValidateMessageBuffer(ApiMessage,
+                                          (PVOID*)&WriteOutputRequest->CharInfo,
+                                          NumCells,
+                                          sizeof(CHAR_INFO)))
+            {
+                Status = STATUS_INVALID_PARAMETER;
+                goto Quit;
+            }
+
+            CharInfo = WriteOutputRequest->CharInfo;
+        }
+    }
+    else
+    {
+        /*
+         * This was not the case: we use a heap buffer. Retrieve its contents.
+         */
+        ULONG Size = NumCells * sizeof(CHAR_INFO);
+
+        CharInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Size);
+        if (CharInfo == NULL)
+        {
+            Status = STATUS_NO_MEMORY;
+            goto Quit;
+        }
+
+        Status = NtReadVirtualMemory(Process->ProcessHandle,
+                                     WriteOutputRequest->CharInfo,
+                                     CharInfo,
+                                     Size,
+                                     NULL);
+        if (!NT_SUCCESS(Status))
+        {
+            ConsoleFreeHeap(CharInfo);
+            // Status = STATUS_NO_MEMORY;
+            goto Quit;
+        }
+    }
+
     Status = ConDrvWriteConsoleOutput(Buffer->Header.Console,
                                       Buffer,
                                       WriteOutputRequest->Unicode,
-                                      WriteOutputRequest->CharInfo,
-                                      &WriteOutputRequest->BufferSize,
-                                      &WriteOutputRequest->BufferCoord,
+                                      CharInfo,
                                       &WriteOutputRequest->WriteRegion);
 
+    /* Free the temporary buffer if we used the process' heap buffer */
+    if (WriteOutputRequest->UseVirtualMemory && CharInfo)
+        ConsoleFreeHeap(CharInfo);
+
+Quit:
     ConSrvReleaseScreenBuffer(Buffer, TRUE);
     return Status;
 }
@@ -460,17 +646,33 @@ CSR_API(SrvWriteConsole)
 
     DPRINT("SrvWriteConsole\n");
 
-    if (!CsrValidateMessageBuffer(ApiMessage,
-                                  (PVOID)&WriteConsoleRequest->Buffer,
-                                  WriteConsoleRequest->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 written. Otherwise a new buffer is used.
+     * The client-side expects that we know this behaviour.
+     */
+    if (WriteConsoleRequest->UsingStaticBuffer &&
+        WriteConsoleRequest->NumBytes <= sizeof(WriteConsoleRequest->StaticBuffer))
     {
-        return STATUS_INVALID_PARAMETER;
+        /*
+         * Adjust the internal pointer, because its old value points to
+         * the static buffer in the original ApiMessage structure.
+         */
+        // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
+    }
+    else
+    {
+        if (!CsrValidateMessageBuffer(ApiMessage,
+                                      (PVOID)&WriteConsoleRequest->Buffer,
+                                      WriteConsoleRequest->NumBytes,
+                                      sizeof(BYTE)))
+        {
+            return STATUS_INVALID_PARAMETER;
+        }
     }
 
-    Status = DoWriteConsole(ApiMessage,
-                            CsrGetClientThread(),
-                            TRUE);
+    Status = DoWriteConsole(ApiMessage, CsrGetClientThread(), TRUE);
 
     if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
 
@@ -484,8 +686,8 @@ ConDrvReadConsoleOutputString(IN PCONSOLE Console,
                               OUT PVOID StringBuffer,
                               IN ULONG NumCodesToRead,
                               IN PCOORD ReadCoord,
-                              OUT PCOORD EndCoord,
-                              OUT PULONG CodesRead);
+                              // OUT PCOORD EndCoord,
+                              OUT PULONG NumCodesRead OPTIONAL);
 CSR_API(SrvReadConsoleOutputString)
 {
     NTSTATUS Status;
@@ -493,47 +695,73 @@ CSR_API(SrvReadConsoleOutputString)
     PTEXTMODE_SCREEN_BUFFER Buffer;
     ULONG CodeSize;
 
+    PVOID pCode;
+
     DPRINT("SrvReadConsoleOutputString\n");
 
     switch (ReadOutputCodeRequest->CodeType)
     {
         case CODE_ASCII:
-            CodeSize = sizeof(CHAR);
+            CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
             break;
 
         case CODE_UNICODE:
-            CodeSize = sizeof(WCHAR);
+            CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
             break;
 
         case CODE_ATTRIBUTE:
-            CodeSize = sizeof(WORD);
+            CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
             break;
 
         default:
             return STATUS_INVALID_PARAMETER;
     }
 
-    if (!CsrValidateMessageBuffer(ApiMessage,
-                                  (PVOID*)&ReadOutputCodeRequest->pCode.pCode,
-                                  ReadOutputCodeRequest->NumCodesToRead,
-                                  CodeSize))
+    /*
+     * 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 (ReadOutputCodeRequest->NumCodes * CodeSize <= sizeof(ReadOutputCodeRequest->CodeStaticBuffer))
     {
-        return STATUS_INVALID_PARAMETER;
+        /*
+         * Adjust the internal pointer, because its old value points to
+         * the static buffer in the original ApiMessage structure.
+         */
+        // ReadOutputCodeRequest->pCode = ReadOutputCodeRequest->CodeStaticBuffer;
+        pCode = ReadOutputCodeRequest->CodeStaticBuffer;
+    }
+    else
+    {
+        if (!CsrValidateMessageBuffer(ApiMessage,
+                                      (PVOID*)&ReadOutputCodeRequest->pCode,
+                                      ReadOutputCodeRequest->NumCodes,
+                                      CodeSize))
+        {
+            return STATUS_INVALID_PARAMETER;
+        }
+
+        pCode = ReadOutputCodeRequest->pCode;
     }
 
     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
                                      ReadOutputCodeRequest->OutputHandle,
                                      &Buffer, GENERIC_READ, TRUE);
-    if (!NT_SUCCESS(Status)) return Status;
+    if (!NT_SUCCESS(Status))
+    {
+        ReadOutputCodeRequest->NumCodes = 0;
+        return Status;
+    }
 
     Status = ConDrvReadConsoleOutputString(Buffer->Header.Console,
                                            Buffer,
                                            ReadOutputCodeRequest->CodeType,
-                                           ReadOutputCodeRequest->pCode.pCode,
-                                           ReadOutputCodeRequest->NumCodesToRead,
-                                           &ReadOutputCodeRequest->ReadCoord,
-                                           &ReadOutputCodeRequest->EndCoord,
-                                           &ReadOutputCodeRequest->CodesRead);
+                                           pCode,
+                                           ReadOutputCodeRequest->NumCodes,
+                                           &ReadOutputCodeRequest->Coord,
+                                           // &ReadOutputCodeRequest->EndCoord,
+                                           &ReadOutputCodeRequest->NumCodes);
 
     ConSrvReleaseScreenBuffer(Buffer, TRUE);
     return Status;
@@ -545,9 +773,9 @@ ConDrvWriteConsoleOutputString(IN PCONSOLE Console,
                                IN CODE_TYPE CodeType,
                                IN PVOID StringBuffer,
                                IN ULONG NumCodesToWrite,
-                               IN PCOORD WriteCoord /*,
-                               OUT PCOORD EndCoord,
-                               OUT PULONG CodesWritten */);
+                               IN PCOORD WriteCoord,
+                               // OUT PCOORD EndCoord,
+                               OUT PULONG NumCodesWritten OPTIONAL);
 CSR_API(SrvWriteConsoleOutputString)
 {
     NTSTATUS Status;
@@ -555,49 +783,73 @@ CSR_API(SrvWriteConsoleOutputString)
     PTEXTMODE_SCREEN_BUFFER Buffer;
     ULONG CodeSize;
 
+    PVOID pCode;
+
     DPRINT("SrvWriteConsoleOutputString\n");
 
     switch (WriteOutputCodeRequest->CodeType)
     {
         case CODE_ASCII:
-            CodeSize = sizeof(CHAR);
+            CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
             break;
 
         case CODE_UNICODE:
-            CodeSize = sizeof(WCHAR);
+            CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
             break;
 
         case CODE_ATTRIBUTE:
-            CodeSize = sizeof(WORD);
+            CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
             break;
 
         default:
             return STATUS_INVALID_PARAMETER;
     }
 
-    if (!CsrValidateMessageBuffer(ApiMessage,
-                                  (PVOID*)&WriteOutputCodeRequest->pCode.pCode,
-                                  WriteOutputCodeRequest->Length,
-                                  CodeSize))
+    /*
+     * For optimization purposes, Windows (and hence ReactOS, too, for
+     * compatibility reasons) uses a static buffer if no more than eighty
+     * bytes are written. Otherwise a new buffer is used.
+     * The client-side expects that we know this behaviour.
+     */
+    if (WriteOutputCodeRequest->NumCodes * CodeSize <= sizeof(WriteOutputCodeRequest->CodeStaticBuffer))
     {
-        return STATUS_INVALID_PARAMETER;
+        /*
+         * Adjust the internal pointer, because its old value points to
+         * the static buffer in the original ApiMessage structure.
+         */
+        // WriteOutputCodeRequest->pCode = WriteOutputCodeRequest->CodeStaticBuffer;
+        pCode = WriteOutputCodeRequest->CodeStaticBuffer;
+    }
+    else
+    {
+        if (!CsrValidateMessageBuffer(ApiMessage,
+                                      (PVOID*)&WriteOutputCodeRequest->pCode,
+                                      WriteOutputCodeRequest->NumCodes,
+                                      CodeSize))
+        {
+            return STATUS_INVALID_PARAMETER;
+        }
+
+        pCode = WriteOutputCodeRequest->pCode;
     }
 
     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
                                      WriteOutputCodeRequest->OutputHandle,
                                      &Buffer, GENERIC_WRITE, TRUE);
-    if (!NT_SUCCESS(Status)) return Status;
+    if (!NT_SUCCESS(Status))
+    {
+        WriteOutputCodeRequest->NumCodes = 0;
+        return Status;
+    }
 
     Status = ConDrvWriteConsoleOutputString(Buffer->Header.Console,
                                             Buffer,
                                             WriteOutputCodeRequest->CodeType,
-                                            WriteOutputCodeRequest->pCode.pCode,
-                                            WriteOutputCodeRequest->Length, // NumCodesToWrite,
-                                            &WriteOutputCodeRequest->Coord /*, // WriteCoord,
-                                            &WriteOutputCodeRequest->EndCoord,
-                                            &WriteOutputCodeRequest->NrCharactersWritten */);
-
-    // WriteOutputCodeRequest->NrCharactersWritten = Written;
+                                            pCode,
+                                            WriteOutputCodeRequest->NumCodes,
+                                            &WriteOutputCodeRequest->Coord,
+                                            // &WriteOutputCodeRequest->EndCoord,
+                                            &WriteOutputCodeRequest->NumCodes);
 
     ConSrvReleaseScreenBuffer(Buffer, TRUE);
     return Status;
@@ -607,16 +859,16 @@ NTSTATUS NTAPI
 ConDrvFillConsoleOutput(IN PCONSOLE Console,
                         IN PTEXTMODE_SCREEN_BUFFER Buffer,
                         IN CODE_TYPE CodeType,
-                        IN PVOID Code,
+                        IN CODE_ELEMENT Code,
                         IN ULONG NumCodesToWrite,
-                        IN PCOORD WriteCoord /*,
-                        OUT PULONG CodesWritten */);
+                        IN PCOORD WriteCoord,
+                        OUT PULONG NumCodesWritten OPTIONAL);
 CSR_API(SrvFillConsoleOutput)
 {
     NTSTATUS Status;
     PCONSOLE_FILLOUTPUTCODE FillOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FillOutputRequest;
     PTEXTMODE_SCREEN_BUFFER Buffer;
-    USHORT CodeType = FillOutputRequest->CodeType;
+    CODE_TYPE CodeType = FillOutputRequest->CodeType;
 
     DPRINT("SrvFillConsoleOutput\n");
 
@@ -630,26 +882,33 @@ CSR_API(SrvFillConsoleOutput)
     Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
                                      FillOutputRequest->OutputHandle,
                                      &Buffer, GENERIC_WRITE, TRUE);
-    if (!NT_SUCCESS(Status)) return Status;
+    if (!NT_SUCCESS(Status))
+    {
+        FillOutputRequest->NumCodes = 0;
+        return Status;
+    }
 
     Status = ConDrvFillConsoleOutput(Buffer->Header.Console,
                                      Buffer,
                                      CodeType,
-                                     &FillOutputRequest->Code,
-                                     FillOutputRequest->Length, // NumCodesToWrite,
-                                     &FillOutputRequest->Coord /*, // WriteCoord,
-                                     &FillOutputRequest->NrCharactersWritten */);
-
-    // FillOutputRequest->NrCharactersWritten = Written;
+                                     FillOutputRequest->Code,
+                                     FillOutputRequest->NumCodes,
+                                     &FillOutputRequest->WriteCoord,
+                                     &FillOutputRequest->NumCodes);
 
     ConSrvReleaseScreenBuffer(Buffer, TRUE);
     return Status;
 }
 
 NTSTATUS NTAPI
-ConDrvGetConsoleScreenBufferInfo(IN PCONSOLE Console,
-                                 IN PTEXTMODE_SCREEN_BUFFER Buffer,
-                                 OUT PCONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo);
+ConDrvGetConsoleScreenBufferInfo(IN  PCONSOLE Console,
+                                 IN  PTEXTMODE_SCREEN_BUFFER Buffer,
+                                 OUT PCOORD ScreenBufferSize,
+                                 OUT PCOORD CursorPosition,
+                                 OUT PCOORD ViewOrigin,
+                                 OUT PCOORD ViewSize,
+                                 OUT PCOORD MaximumViewSize,
+                                 OUT PWORD  Attributes);
 CSR_API(SrvGetConsoleScreenBufferInfo)
 {
     NTSTATUS Status;
@@ -665,7 +924,12 @@ CSR_API(SrvGetConsoleScreenBufferInfo)
 
     Status = ConDrvGetConsoleScreenBufferInfo(Buffer->Header.Console,
                                               Buffer,
-                                              &ScreenBufferInfoRequest->Info);
+                                              &ScreenBufferInfoRequest->ScreenBufferSize,
+                                              &ScreenBufferInfoRequest->CursorPosition,
+                                              &ScreenBufferInfoRequest->ViewOrigin,
+                                              &ScreenBufferInfoRequest->ViewSize,
+                                              &ScreenBufferInfoRequest->MaximumViewSize,
+                                              &ScreenBufferInfoRequest->Attributes);
 
     ConSrvReleaseScreenBuffer(Buffer, TRUE);
     return Status;
@@ -674,7 +938,7 @@ CSR_API(SrvGetConsoleScreenBufferInfo)
 NTSTATUS NTAPI
 ConDrvSetConsoleTextAttribute(IN PCONSOLE Console,
                               IN PTEXTMODE_SCREEN_BUFFER Buffer,
-                              IN WORD Attribute);
+                              IN WORD Attributes);
 CSR_API(SrvSetConsoleTextAttribute)
 {
     NTSTATUS Status;
@@ -690,7 +954,7 @@ CSR_API(SrvSetConsoleTextAttribute)
 
     Status = ConDrvSetConsoleTextAttribute(Buffer->Header.Console,
                                            Buffer,
-                                           SetTextAttribRequest->Attrib);
+                                           SetTextAttribRequest->Attributes);
 
     ConSrvReleaseScreenBuffer(Buffer, TRUE);
     return Status;