[KERNEL32/CONSRV]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Mon, 19 Nov 2012 23:26:36 +0000 (23:26 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Mon, 19 Nov 2012 23:26:36 +0000 (23:26 +0000)
- Merge IntWriteConsoleOutputCharacter and WriteConsoleOutputAttribute functions into IntWriteConsoleOutputCode helper functions, which is used inside WriteConsoleOutputAttribute and WriteConsoleOutputCharacterW/A.
- In server-side, merge CsrWriteConsoleOutputChar and CsrWriteConsoleOutputAttrib into the server API SrvWriteConsoleOutputString.
- The structures CSRSS_WRITE_CONSOLE_OUTPUT_CHAR and CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB are merged into CSRSS_WRITE_CONSOLE_OUTPUT_CODE.

[CONSRV]
- Add a CsrValidateMessageBuffer usage.

svn path=/branches/ros-csrss/; revision=57740

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

index 7025a6e..5cda806 100644 (file)
@@ -436,6 +436,7 @@ IntWriteConsole(HANDLE hConsoleOutput,
     ULONG /* SizeBytes, */ CharSize;
     // DWORD Written = 0;
 
+    /* Determine the needed size */
     CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
     WriteConsoleRequest->BufferSize = nNumberOfCharsToWrite * CharSize;
 
@@ -654,75 +655,109 @@ IntWriteConsoleOutput(HANDLE hConsoleOutput,
 
 static
 BOOL
-IntWriteConsoleOutputCharacter(HANDLE hConsoleOutput,
-                               PVOID lpCharacter,
-                               DWORD nLength,
-                               COORD dwWriteCoord,
-                               LPDWORD lpNumberOfCharsWritten,
-                               BOOL bUnicode)
+IntWriteConsoleOutputCode(HANDLE hConsoleOutput,
+                          CODE_TYPE CodeType,
+                          CONST VOID *pCode,
+                          DWORD nLength,
+                          COORD dwWriteCoord,
+                          LPDWORD lpNumberOfCodesWritten)
 {
-    PCSR_API_MESSAGE Request;
-    ULONG CsrRequest;
     NTSTATUS Status;
-    ULONG CharSize, nChars;
-    //ULONG SizeBytes;
-    DWORD Written = 0;
+    CONSOLE_API_MESSAGE ApiMessage;
+    PCSRSS_WRITE_CONSOLE_OUTPUT_CODE WriteConsoleOutputCodeRequest = &ApiMessage.Data.WriteConsoleOutputCodeRequest;
+    PCSR_CAPTURE_BUFFER CaptureBuffer;
+    ULONG CodeSize; //, nChars;
+    // ULONG SizeBytes;
+    // DWORD Written = 0;
 
-    CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
+    /* Determine the needed size */
+/*
+    CodeSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
+    nChars = min(nLength, CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR / CodeSize);
+    SizeBytes = nChars * CodeSize;
+*/
+    switch (CodeType)
+    {
+        case CODE_ASCII:
+            CodeSize = sizeof(CHAR);
+            break;
 
-    nChars = min(nLength, CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR / CharSize);
-    //SizeBytes = nChars * CharSize;
+        case CODE_UNICODE:
+            CodeSize = sizeof(WCHAR);
+            break;
 
-    Request = RtlAllocateHeap(RtlGetProcessHeap(), 0,
-                              max(sizeof(CSR_API_MESSAGE),
-                              CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR)
-                                + min (nChars, CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR / CharSize) * CharSize));
-    if (Request == NULL)
+        case CODE_ATTRIBUTE:
+            CodeSize = sizeof(WORD);
+            break;
+
+        default:
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return FALSE;
+    }
+    WriteConsoleOutputCodeRequest->BufferSize = nLength * CodeSize;
+
+    /* Allocate a Capture Buffer */
+    CaptureBuffer = CsrAllocateCaptureBuffer(1, WriteConsoleOutputCodeRequest->BufferSize);
+    if (CaptureBuffer == NULL)
     {
+        DPRINT1("CsrAllocateCaptureBuffer failed!\n");
         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return FALSE;
     }
 
-    CsrRequest = CSR_CREATE_API_NUMBER(CSR_CONSOLE, WRITE_CONSOLE_OUTPUT_CHAR);
-    Request->Data.WriteConsoleOutputCharRequest.Coord = dwWriteCoord;
+/*
+    /\* Allocate space in the Buffer *\/
+    CsrAllocateMessagePointer(CaptureBuffer,
+                              SizeBytes,
+                              (PVOID*)&WriteConsoleOutputCodeRequest->pCode.pCode);
+*/
+    /* Capture the buffer to write */
+    CsrCaptureMessageBuffer(CaptureBuffer,
+                            (PVOID)pCode,
+                            WriteConsoleOutputCodeRequest->BufferSize,
+                            (PVOID*)&WriteConsoleOutputCodeRequest->pCode.pCode);
 
-    while (nLength > 0)
-    {
-        DWORD BytesWrite;
+    /* Start writing */
+    WriteConsoleOutputCodeRequest->ConsoleHandle = hConsoleOutput;
+    WriteConsoleOutputCodeRequest->CodeType = CodeType;
+    WriteConsoleOutputCodeRequest->Coord = dwWriteCoord;
 
-        Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle = hConsoleOutput;
-        Request->Data.WriteConsoleOutputCharRequest.Unicode = bUnicode;
-        Request->Data.WriteConsoleOutputCharRequest.Length = (WORD)min(nLength, nChars);
-        BytesWrite = Request->Data.WriteConsoleOutputCharRequest.Length * CharSize;
+    /**
+     ** TODO: HACK: Surely it has to go into CONSRV !!
+     **/
+    // while (nLength > 0)
+    {
+        // DWORD BytesWrite;
 
-        memcpy(Request->Data.WriteConsoleOutputCharRequest.String, lpCharacter, BytesWrite);
+        WriteConsoleOutputCodeRequest->Length = nLength; // (WORD)min(nLength, nChars);
+        // BytesWrite = WriteConsoleOutputCodeRequest->Length * CodeSize;
 
-        Status = CsrClientCallServer(Request,
-                                     NULL,
-                                     CsrRequest,
-                                     max(sizeof(CSR_API_MESSAGE),
-                                     CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR) + BytesWrite));
+        // memcpy(WriteConsoleOutputCodeRequest->pCode.pCode, pCode, BytesWrite);
 
-        if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request->Status))
+        Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+                                     CaptureBuffer,
+                                     CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleOutputString),
+                                     sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_CODE));
+        if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = ApiMessage.Status))
         {
-            RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
+            CsrFreeCaptureBuffer(CaptureBuffer);
             BaseSetLastNTError(Status);
             return FALSE;
         }
 
-        nLength -= Request->Data.WriteConsoleOutputCharRequest.NrCharactersWritten;
-        lpCharacter = (PVOID)((ULONG_PTR)lpCharacter + (ULONG_PTR)(Request->Data.WriteConsoleOutputCharRequest.NrCharactersWritten * CharSize));
-        Written += Request->Data.WriteConsoleOutputCharRequest.NrCharactersWritten;
+        // nLength -= WriteConsoleOutputCodeRequest->NrCharactersWritten;
+        // pCode = (PVOID)((ULONG_PTR)pCode + /*(ULONG_PTR)(*/WriteConsoleOutputCodeRequest->NrCharactersWritten * CodeSize/*)*/);
+        // Written += WriteConsoleOutputCodeRequest->NrCharactersWritten;
 
-        Request->Data.WriteConsoleOutputCharRequest.Coord = Request->Data.WriteConsoleOutputCharRequest.EndCoord;
+        WriteConsoleOutputCodeRequest->Coord = WriteConsoleOutputCodeRequest->EndCoord;
     }
 
-    if (lpNumberOfCharsWritten != NULL)
-    {
-        *lpNumberOfCharsWritten = Written;
-    }
+    if (lpNumberOfCodesWritten != NULL)
+        // *lpNumberOfCodesWritten = Written;
+        // *lpNumberOfCodesWritten = WriteConsoleOutputCodeRequest->NrCharactersWritten;
+        *lpNumberOfCodesWritten = WriteConsoleOutputCodeRequest->Length;
 
-    RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
+    CsrFreeCaptureBuffer(CaptureBuffer);
 
     return TRUE;
 }
@@ -778,7 +813,7 @@ IntFillConsoleOutputCode(HANDLE hConsoleOutput,
 
     if (lpNumberOfCodesWritten)
         *lpNumberOfCodesWritten = FillOutputRequest->Length;
-        // *lpNumberOfCharsWritten = Request.Data.FillOutputRequest.NrCharactersWritten;
+        // *lpNumberOfCodesWritten = Request.Data.FillOutputRequest.NrCharactersWritten;
 
     return TRUE;
 }
@@ -1191,12 +1226,12 @@ WriteConsoleOutputCharacterW(HANDLE hConsoleOutput,
                              COORD dwWriteCoord,
                              LPDWORD lpNumberOfCharsWritten)
 {
-    return IntWriteConsoleOutputCharacter(hConsoleOutput,
-                                          (PVOID)lpCharacter,
-                                          nLength,
-                                          dwWriteCoord,
-                                          lpNumberOfCharsWritten,
-                                          TRUE);
+    return IntWriteConsoleOutputCode(hConsoleOutput,
+                                     CODE_UNICODE,
+                                     lpCharacter,
+                                     nLength,
+                                     dwWriteCoord,
+                                     lpNumberOfCharsWritten);
 }
 
 
@@ -1213,12 +1248,12 @@ WriteConsoleOutputCharacterA(HANDLE hConsoleOutput,
                              COORD dwWriteCoord,
                              LPDWORD lpNumberOfCharsWritten)
 {
-    return IntWriteConsoleOutputCharacter(hConsoleOutput,
-                                          (PVOID)lpCharacter,
-                                          nLength,
-                                          dwWriteCoord,
-                                          lpNumberOfCharsWritten,
-                                          FALSE);
+    return IntWriteConsoleOutputCode(hConsoleOutput,
+                                     CODE_ASCII,
+                                     lpCharacter,
+                                     nLength,
+                                     dwWriteCoord,
+                                     lpNumberOfCharsWritten);
 }
 
 
@@ -1235,54 +1270,12 @@ WriteConsoleOutputAttribute(HANDLE hConsoleOutput,
                             COORD dwWriteCoord,
                             LPDWORD lpNumberOfAttrsWritten)
 {
-    PCSR_API_MESSAGE Request;
-    ULONG CsrRequest;
-    NTSTATUS Status;
-    WORD Size;
-
-    Request = RtlAllocateHeap(RtlGetProcessHeap(),
-                              0,
-                              max(sizeof(CSR_API_MESSAGE),
-                              CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB)
-                                + min(nLength, CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB / sizeof(WORD)) * sizeof(WORD)));
-    if (Request == NULL)
-    {
-        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        return FALSE;
-    }
-
-    CsrRequest = CSR_CREATE_API_NUMBER(CSR_CONSOLE, WRITE_CONSOLE_OUTPUT_ATTRIB);
-    Request->Data.WriteConsoleOutputAttribRequest.Coord = dwWriteCoord;
-
-    if (lpNumberOfAttrsWritten)
-        *lpNumberOfAttrsWritten = nLength;
-    while (nLength)
-    {
-        Size = (WORD)min(nLength, CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB / sizeof(WORD));
-        Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle = hConsoleOutput;
-        Request->Data.WriteConsoleOutputAttribRequest.Length = Size;
-        memcpy(Request->Data.WriteConsoleOutputAttribRequest.Attribute, lpAttribute, Size * sizeof(WORD));
-
-        Status = CsrClientCallServer(Request,
-                                     NULL,
-                                     CsrRequest,
-                                     max(sizeof(CSR_API_MESSAGE),
-                                     CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB) + Size * sizeof(WORD)));
-
-        if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request->Status))
-        {
-            RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
-            BaseSetLastNTError (Status);
-            return FALSE;
-        }
-        nLength -= Size;
-        lpAttribute += Size;
-        Request->Data.WriteConsoleOutputAttribRequest.Coord = Request->Data.WriteConsoleOutputAttribRequest.EndCoord;
-    }
-
-    RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
-
-    return TRUE;
+    return IntWriteConsoleOutputCode(hConsoleOutput,
+                                     CODE_ATTRIBUTE,
+                                     lpAttribute,
+                                     nLength,
+                                     dwWriteCoord,
+                                     lpNumberOfAttrsWritten);
 }
 
 
index 604154a..32b1fae 100644 (file)
@@ -26,7 +26,7 @@ typedef enum _CONSRV_API_NUMBER
     ConsolepReadConsoleOutput,
     ConsolepWriteConsoleOutput,
     ConsolepReadConsoleOutputString,
-    // ConsolepWriteConsoleOutputString,
+    ConsolepWriteConsoleOutputString,
     ConsolepFillConsoleOutput,
     ConsolepGetMode,
     // ConsolepGetNumberOfFonts,
@@ -112,13 +112,6 @@ typedef enum _CONSRV_API_NUMBER
 } CONSRV_API_NUMBER, *PCONSRV_API_NUMBER;
 
 
-#define CSR_API_MESSAGE_HEADER_SIZE(Type)       (FIELD_OFFSET(CSR_API_MESSAGE, Data) + sizeof(Type))
-#define CSRSS_MAX_WRITE_CONSOLE                 (LPC_MAX_DATA_LENGTH - CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE))
-#define CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR     (LPC_MAX_DATA_LENGTH - CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR))
-#define CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB   (LPC_MAX_DATA_LENGTH - CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB))
-#define CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR      (LPC_MAX_DATA_LENGTH - CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR))
-#define CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB    (LPC_MAX_DATA_LENGTH - CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB))
-
 #define CONSOLE_INPUT_MODE_VALID  (0x0f)
 #define CONSOLE_OUTPUT_MODE_VALID (0x03)
 
@@ -150,12 +143,12 @@ typedef struct
     WORD NrCharactersRead;
     HANDLE EventHandle;
 
-    PVOID Buffer;
-    ULONG BufferSize;
-
     UNICODE_STRING ExeName;
     DWORD CtrlWakeupMask;
     DWORD ControlKeyState;
+
+    ULONG BufferSize;
+    PVOID Buffer;
 } CSRSS_READ_CONSOLE, *PCSRSS_READ_CONSOLE;
 
 typedef struct
@@ -185,26 +178,6 @@ typedef struct
     COORD Position;
 } CSRSS_SET_CURSOR_POSITION, *PCSRSS_SET_CURSOR_POSITION;
 
-typedef struct
-{
-    HANDLE ConsoleHandle;
-    BOOL Unicode;
-    WORD Length;
-    COORD Coord;
-    COORD EndCoord;
-    ULONG NrCharactersWritten;
-    CHAR String[0];
-} CSRSS_WRITE_CONSOLE_OUTPUT_CHAR, *PCSRSS_WRITE_CONSOLE_OUTPUT_CHAR;
-
-typedef struct
-{
-    HANDLE ConsoleHandle;
-    WORD Length;
-    COORD Coord;
-    COORD EndCoord;
-    WORD Attribute[0];
-} CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB, *PCSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB;
-
 typedef struct
 {
     HANDLE ConsoleHandle;
@@ -301,6 +274,28 @@ typedef struct
     } pCode;    // Either a pointer to a character or to an attribute.
 } CSRSS_READ_CONSOLE_OUTPUT_CODE, *PCSRSS_READ_CONSOLE_OUTPUT_CODE;
 
+typedef struct
+{
+    HANDLE ConsoleHandle;
+    USHORT CodeType;
+
+    ULONG BufferSize;
+    WORD Length;
+    COORD Coord;
+    COORD EndCoord;
+
+    ULONG NrCharactersWritten;
+
+    union
+    {
+        // PVOID String;
+        PVOID pCode;
+        PCHAR AsciiChar;
+        PWCHAR UnicodeChar;
+        PWORD Attribute;
+    } pCode;    // Either a pointer to a character or to an attribute.
+} CSRSS_WRITE_CONSOLE_OUTPUT_CODE, *PCSRSS_WRITE_CONSOLE_OUTPUT_CODE;
+
 typedef struct
 {
     HANDLE ConsoleHandle;
@@ -588,8 +583,7 @@ typedef struct _CONSOLE_API_MESSAGE
         CSRSS_WRITE_CONSOLE WriteConsoleRequest;            // SrvWriteConsole / WriteConsole
         CSRSS_WRITE_CONSOLE_INPUT WriteConsoleInputRequest;
         CSRSS_WRITE_CONSOLE_OUTPUT WriteConsoleOutputRequest;
-        CSRSS_WRITE_CONSOLE_OUTPUT_CHAR WriteConsoleOutputCharRequest;
-        CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB WriteConsoleOutputAttribRequest;
+        CSRSS_WRITE_CONSOLE_OUTPUT_CODE WriteConsoleOutputCodeRequest;
 
         CSRSS_FILL_OUTPUT FillOutputRequest;
         CSRSS_SET_ATTRIB SetAttribRequest;
index e49b31a..623a5f6 100644 (file)
@@ -469,6 +469,11 @@ CSR_API(SrvReadConsoleOutput)
 
     DPRINT("SrvReadConsoleOutput\n");
 
+    CharInfo = ReadConsoleOutputRequest->CharInfo;
+    ReadRegion = ReadConsoleOutputRequest->ReadRegion;
+    BufferSize = ReadConsoleOutputRequest->BufferSize;
+    BufferCoord = ReadConsoleOutputRequest->BufferCoord;
+
     if (!CsrValidateMessageBuffer(ApiMessage,
                                   (PVOID*)&ReadConsoleOutputRequest->CharInfo,
                                   BufferSize.X * BufferSize.Y,
@@ -480,11 +485,6 @@ CSR_API(SrvReadConsoleOutput)
     Status = ConioLockScreenBuffer(ProcessData, ReadConsoleOutputRequest->ConsoleHandle, &Buff, GENERIC_READ);
     if (!NT_SUCCESS(Status)) return Status;
 
-    CharInfo = ReadConsoleOutputRequest->CharInfo;
-    ReadRegion = ReadConsoleOutputRequest->ReadRegion;
-    BufferSize = ReadConsoleOutputRequest->BufferSize;
-    BufferCoord = ReadConsoleOutputRequest->BufferCoord;
-
 /*
     if (!Win32CsrValidateBuffer(ProcessData->Process, CharInfo,
                                 BufferSize.X * BufferSize.Y, sizeof(CHAR_INFO)))
@@ -648,6 +648,10 @@ CSR_API(SrvWriteConsoleOutput)
 
     DPRINT("SrvWriteConsoleOutput\n");
 
+    BufferSize = WriteConsoleOutputRequest->BufferSize;
+    BufferCoord = WriteConsoleOutputRequest->BufferCoord;
+    CharInfo = WriteConsoleOutputRequest->CharInfo;
+
     if (!CsrValidateMessageBuffer(ApiMessage,
                                   (PVOID*)&WriteConsoleOutputRequest->CharInfo,
                                   BufferSize.X * BufferSize.Y,
@@ -664,10 +668,6 @@ CSR_API(SrvWriteConsoleOutput)
 
     Console = Buff->Header.Console;
 
-    BufferSize = WriteConsoleOutputRequest->BufferSize;
-    BufferCoord = WriteConsoleOutputRequest->BufferCoord;
-    CharInfo = WriteConsoleOutputRequest->CharInfo;
-
 /*
     if (!Win32CsrValidateBuffer(ProcessData->Process, CharInfo,
                                 BufferSize.X * BufferSize.Y, sizeof(CHAR_INFO)))
@@ -743,8 +743,6 @@ CSR_API(SrvReadConsoleOutputString)
 
     DPRINT("SrvReadConsoleOutputString\n");
 
-    ReadBuffer = ReadConsoleOutputCodeRequest->pCode.pCode;
-
     CodeType = ReadConsoleOutputCodeRequest->CodeType;
     switch (CodeType)
     {
@@ -764,11 +762,20 @@ CSR_API(SrvReadConsoleOutputString)
             return STATUS_INVALID_PARAMETER;
     }
 
+    if (!CsrValidateMessageBuffer(ApiMessage,
+                                  (PVOID*)&ReadConsoleOutputCodeRequest->pCode.pCode,
+                                  ReadConsoleOutputCodeRequest->NumCodesToRead,
+                                  CodeSize))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
     Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ReadConsoleOutputCodeRequest->ConsoleHandle, &Buff, GENERIC_READ);
     if (!NT_SUCCESS(Status)) return Status;
 
     Console = Buff->Header.Console;
 
+    ReadBuffer = ReadConsoleOutputCodeRequest->pCode.pCode;
     Xpos = ReadConsoleOutputCodeRequest->ReadCoord.X;
     Ypos = (ReadConsoleOutputCodeRequest->ReadCoord.Y + Buff->VirtualY) % Buff->MaxY;
 
@@ -845,169 +852,136 @@ CSR_API(SrvReadConsoleOutputString)
     return STATUS_SUCCESS;
 }
 
-CSR_API(CsrWriteConsoleOutputChar)
+CSR_API(SrvWriteConsoleOutputString)
 {
     NTSTATUS Status;
-    PCSRSS_WRITE_CONSOLE_OUTPUT_CHAR WriteConsoleOutputCharRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleOutputCharRequest;
-    PCHAR String, tmpString = NULL;
-    PBYTE Buffer;
+    PCSRSS_WRITE_CONSOLE_OUTPUT_CODE WriteConsoleOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleOutputCodeRequest;
     PCSRSS_CONSOLE Console;
     PCSRSS_SCREEN_BUFFER Buff;
-    DWORD X, Y, Length, CharSize, Written = 0;
+    USHORT CodeType;
+    PBYTE Buffer; // PUCHAR
+    PCHAR String, tmpString = NULL;
+    DWORD X, Y, Length; // , Written = 0;
+    ULONG CodeSize;
     SMALL_RECT UpdateRect;
 
-    DPRINT("CsrWriteConsoleOutputChar\n");
+    DPRINT("SrvWriteConsoleOutputString\n");
+
+    CodeType = WriteConsoleOutputCodeRequest->CodeType;
+    switch (CodeType)
+    {
+        case CODE_ASCII:
+            CodeSize = sizeof(CHAR);
+            break;
 
-    CharSize = (WriteConsoleOutputCharRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
+        case CODE_UNICODE:
+            CodeSize = sizeof(WCHAR);
+            break;
+
+        case CODE_ATTRIBUTE:
+            CodeSize = sizeof(WORD);
+            break;
 
-    if (ApiMessage->Header.u1.s1.TotalLength
-            < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR)
-            + (WriteConsoleOutputCharRequest->Length * CharSize))
+        default:
+            return STATUS_INVALID_PARAMETER;
+    }
+
+    if (!CsrValidateMessageBuffer(ApiMessage,
+                                  (PVOID*)&WriteConsoleOutputCodeRequest->pCode.pCode,
+                                  WriteConsoleOutputCodeRequest->Length,
+                                  CodeSize))
     {
-        DPRINT1("Invalid ApiMessage size\n");
         return STATUS_INVALID_PARAMETER;
     }
 
-    Status = ConioLockScreenBuffer(CsrGetClientThread()->Process,
-                                    WriteConsoleOutputCharRequest->ConsoleHandle,
+    Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                                    WriteConsoleOutputCodeRequest->ConsoleHandle,
                                     &Buff,
                                     GENERIC_WRITE);
-    if (NT_SUCCESS(Status))
+    if (!NT_SUCCESS(Status)) return Status;
+
+    Console = Buff->Header.Console;
+
+    switch (CodeType)
     {
-        Console = Buff->Header.Console;
-        if(WriteConsoleOutputCharRequest->Unicode)
+        case CODE_UNICODE:
         {
             Length = WideCharToMultiByte(Console->OutputCodePage, 0,
-                                         (PWCHAR)WriteConsoleOutputCharRequest->String,
-                                         WriteConsoleOutputCharRequest->Length,
+                                         (PWCHAR)WriteConsoleOutputCodeRequest->pCode.UnicodeChar,
+                                         WriteConsoleOutputCodeRequest->Length,
                                          NULL, 0, NULL, NULL);
             tmpString = String = RtlAllocateHeap(GetProcessHeap(), 0, Length);
             if (String)
             {
                 WideCharToMultiByte(Console->OutputCodePage, 0,
-                                    (PWCHAR)WriteConsoleOutputCharRequest->String,
-                                    WriteConsoleOutputCharRequest->Length,
+                                    (PWCHAR)WriteConsoleOutputCodeRequest->pCode.UnicodeChar,
+                                    WriteConsoleOutputCodeRequest->Length,
                                     String, Length, NULL, NULL);
             }
             else
             {
                 Status = STATUS_NO_MEMORY;
             }
-        }
-        else
-        {
-            String = (PCHAR)WriteConsoleOutputCharRequest->String;
-        }
 
-        if (String)
-        {
-            if (NT_SUCCESS(Status))
-            {
-                X = WriteConsoleOutputCharRequest->Coord.X;
-                Y = (WriteConsoleOutputCharRequest->Coord.Y + Buff->VirtualY) % Buff->MaxY;
-                Length = WriteConsoleOutputCharRequest->Length;
-                Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)];
-                while (Length--)
-                {
-                    *Buffer = *String++;
-                    Written++;
-                    Buffer += 2;
-                    if (++X == Buff->MaxX)
-                    {
-                        if (++Y == Buff->MaxY)
-                        {
-                            Y = 0;
-                            Buffer = Buff->Buffer;
-                        }
-                        X = 0;
-                    }
-                }
-                if (Buff == Console->ActiveBuffer)
-                {
-                    ConioComputeUpdateRect(Buff, &UpdateRect, &WriteConsoleOutputCharRequest->Coord,
-                                           WriteConsoleOutputCharRequest->Length);
-                    ConioDrawRegion(Console, &UpdateRect);
-                }
-
-                WriteConsoleOutputCharRequest->EndCoord.X = X;
-                WriteConsoleOutputCharRequest->EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY;
-
-            }
-            if (WriteConsoleOutputCharRequest->Unicode)
-            {
-                RtlFreeHeap(GetProcessHeap(), 0, tmpString);
-            }
+            break;
         }
-        ConioUnlockScreenBuffer(Buff);
-    }
-    WriteConsoleOutputCharRequest->NrCharactersWritten = Written;
-    return Status;
-}
-
-CSR_API(CsrWriteConsoleOutputAttrib)
-{
-    PCSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB WriteConsoleOutputAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleOutputAttribRequest;
-    PCSRSS_CONSOLE Console;
-    PCSRSS_SCREEN_BUFFER Buff;
-    PUCHAR Buffer;
-    PWORD Attribute;
-    int X, Y, Length;
-    NTSTATUS Status;
-    SMALL_RECT UpdateRect;
 
-    DPRINT("CsrWriteConsoleOutputAttrib\n");
+        case CODE_ASCII:
+            String = (PCHAR)WriteConsoleOutputCodeRequest->pCode.AsciiChar;
+            break;
 
-    if (ApiMessage->Header.u1.s1.TotalLength
-            < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB)
-            + WriteConsoleOutputAttribRequest->Length * sizeof(WORD))
-    {
-        DPRINT1("Invalid ApiMessage size\n");
-        return STATUS_INVALID_PARAMETER;
+        case CODE_ATTRIBUTE:
+        default:
+            // *(ReadBuffer++) = Code;
+            String = (PCHAR)WriteConsoleOutputCodeRequest->pCode.Attribute;
+            break;
     }
 
-    Status = ConioLockScreenBuffer(CsrGetClientThread()->Process,
-                                   WriteConsoleOutputAttribRequest->ConsoleHandle,
-                                   &Buff,
-                                   GENERIC_WRITE);
-    if (! NT_SUCCESS(Status))
+    if (String && NT_SUCCESS(Status))
     {
-        return Status;
-    }
-    Console = Buff->Header.Console;
+        X = WriteConsoleOutputCodeRequest->Coord.X;
+        Y = (WriteConsoleOutputCodeRequest->Coord.Y + Buff->VirtualY) % Buff->MaxY;
+        Length = WriteConsoleOutputCodeRequest->Length;
+        Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)];
 
-    X = WriteConsoleOutputAttribRequest->Coord.X;
-    Y = (WriteConsoleOutputAttribRequest->Coord.Y + Buff->VirtualY) % Buff->MaxY;
-    Length = WriteConsoleOutputAttribRequest->Length;
-    Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X) + 1];
-    Attribute = WriteConsoleOutputAttribRequest->Attribute;
-    while (Length--)
-    {
-        *Buffer = (UCHAR)(*Attribute++);
-        Buffer += 2;
-        if (++X == Buff->MaxX)
+        while (Length--)
         {
-            if (++Y == Buff->MaxY)
+            *Buffer = *String++;
+            // ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
+            String = (PCHAR)((ULONG_PTR)String + CodeSize);
+            // Written++;
+            Buffer += 2;
+            if (++X == Buff->MaxX)
             {
-                Y = 0;
-                Buffer = Buff->Buffer + 1;
+                if (++Y == Buff->MaxY)
+                {
+                    Y = 0;
+                    Buffer = Buff->Buffer + (CodeType == CODE_ATTRIBUTE ? 1 : 0);
+                }
+                X = 0;
             }
-            X = 0;
         }
+
+        if (Buff == Console->ActiveBuffer)
+        {
+            ConioComputeUpdateRect(Buff, &UpdateRect, &WriteConsoleOutputCodeRequest->Coord,
+                                   WriteConsoleOutputCodeRequest->Length);
+            ConioDrawRegion(Console, &UpdateRect);
+        }
+
+        WriteConsoleOutputCodeRequest->EndCoord.X = X;
+        WriteConsoleOutputCodeRequest->EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY;
     }
 
-    if (Buff == Console->ActiveBuffer)
+    if (tmpString)
     {
-        ConioComputeUpdateRect(Buff, &UpdateRect, &WriteConsoleOutputAttribRequest->Coord,
-                               WriteConsoleOutputAttribRequest->Length);
-        ConioDrawRegion(Console, &UpdateRect);
+        RtlFreeHeap(GetProcessHeap(), 0, tmpString);
     }
 
-    WriteConsoleOutputAttribRequest->EndCoord.X = X;
-    WriteConsoleOutputAttribRequest->EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY;
-
     ConioUnlockScreenBuffer(Buff);
 
-    return STATUS_SUCCESS;
+    // WriteConsoleOutputCodeRequest->NrCharactersWritten = Written;
+    return Status;
 }
 
 CSR_API(SrvFillConsoleOutput)
@@ -1016,7 +990,7 @@ CSR_API(SrvFillConsoleOutput)
     PCSRSS_FILL_OUTPUT FillOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FillOutputRequest;
     PCSRSS_CONSOLE Console;
     PCSRSS_SCREEN_BUFFER Buff;
-    DWORD X, Y, Length, Start; // , Written = 0;
+    DWORD X, Y, Length; // , Written = 0;
     USHORT CodeType;
     BYTE Code;
     PBYTE Buffer;
@@ -1034,8 +1008,7 @@ CSR_API(SrvFillConsoleOutput)
     X = FillOutputRequest->Coord.X;
     Y = (FillOutputRequest->Coord.Y + Buff->VirtualY) % Buff->MaxY;
     Length = FillOutputRequest->Length;
-    Start = 2 * (Y * Buff->MaxX + X) + (CodeType == CODE_ATTRIBUTE ? 1 : 0);
-    Buffer = &Buff->Buffer[Start];
+    Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)];
 
     switch (CodeType)
     {
@@ -1296,7 +1269,7 @@ CSR_API(SrvGetConsoleScreenBufferInfo)
     PCSRSS_SCREEN_BUFFER_INFO ScreenBufferInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScreenBufferInfoRequest;
     PCSRSS_CONSOLE Console;
     PCSRSS_SCREEN_BUFFER Buff;
-    PCONSOLE_SCREEN_BUFFER_INFO pInfo;
+    PCONSOLE_SCREEN_BUFFER_INFO pInfo = &ScreenBufferInfoRequest->Info;
 
     DPRINT("SrvGetConsoleScreenBufferInfo\n");
 
@@ -1304,7 +1277,7 @@ CSR_API(SrvGetConsoleScreenBufferInfo)
     if (!NT_SUCCESS(Status)) return Status;
 
     Console = Buff->Header.Console;
-    pInfo = &ScreenBufferInfoRequest->Info;
+
     pInfo->dwSize.X = Buff->MaxX;
     pInfo->dwSize.Y = Buff->MaxY;
     pInfo->dwCursorPosition.X = Buff->CurrentX;
@@ -1316,6 +1289,7 @@ CSR_API(SrvGetConsoleScreenBufferInfo)
     pInfo->srWindow.Bottom = Buff->ShowY + Console->Size.Y - 1;
     pInfo->dwMaximumWindowSize.X = Buff->MaxX;
     pInfo->dwMaximumWindowSize.Y = Buff->MaxY;
+
     ConioUnlockScreenBuffer(Buff);
 
     return STATUS_SUCCESS;