[CONSRV]
[reactos.git] / win32ss / user / consrv / conoutput.c
index 9f860e4..719a534 100644 (file)
@@ -6,7 +6,7 @@
  * PROGRAMMERS:
  */
 
-/* INCLUDES ******************************************************************/
+/* INCLUDES *******************************************************************/
 
 #include "consrv.h"
 #include "conio.h"
 #define NDEBUG
 #include <debug.h>
 
-/* GLOBALS *******************************************************************/
+
+/* GLOBALS ********************************************************************/
 
 #define ConioInitRect(Rect, top, left, bottom, right) \
-    ((Rect)->Top) = top; \
-    ((Rect)->Left) = left; \
-    ((Rect)->Bottom) = bottom; \
-    ((Rect)->Right) = right
+do {    \
+    ((Rect)->Top) = top;    \
+    ((Rect)->Left) = left;  \
+    ((Rect)->Bottom) = bottom;  \
+    ((Rect)->Right) = right;    \
+} while(0)
 
 #define ConioIsRectEmpty(Rect) \
     (((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom))
@@ -31,7 +34,8 @@
 #define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \
     MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
 
-/* FUNCTIONS *****************************************************************/
+
+/* PRIVATE FUNCTIONS **********************************************************/
 
 PBYTE FASTCALL
 ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buff, ULONG X, ULONG Y)
@@ -226,7 +230,7 @@ ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
         }
     }
 
-    if (! ConioIsRectEmpty(&UpdateRect) && Buff == Console->ActiveBuffer)
+    if (!ConioIsRectEmpty(&UpdateRect) && Buff == Console->ActiveBuffer)
     {
         ConioWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY, ScrolledLines,
                          Buffer, Length);
@@ -294,8 +298,10 @@ __inline BOOLEAN ConioGetUnion(
     return TRUE;
 }
 
-/* Move from one rectangle to another. We must be careful about the order that
- * this is done, to avoid overwriting parts of the source before they are moved. */
+/*
+ * Move from one rectangle to another. We must be careful about the order that
+ * this is done, to avoid overwriting parts of the source before they are moved.
+ */
 static VOID FASTCALL
 ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer,
                 SMALL_RECT *SrcRegion,
@@ -356,91 +362,6 @@ ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer,
     }
 }
 
-CSR_API(SrvWriteConsole)
-{
-    NTSTATUS Status;
-    PCSRSS_WRITE_CONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
-    PCHAR Buffer;
-    PCSRSS_SCREEN_BUFFER Buff;
-    PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
-    PCSRSS_CONSOLE Console;
-    DWORD Written = 0;
-    ULONG Length;
-    ULONG CharSize = (WriteConsoleRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
-
-    DPRINT("SrvWriteConsole\n");
-
-    if (ApiMessage->Header.u1.s1.TotalLength
-            < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE)
-            + (WriteConsoleRequest->NrCharactersToWrite * CharSize))
-    {
-        DPRINT1("Invalid ApiMessage size\n");
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    Status = ConioLockScreenBuffer(ProcessData, WriteConsoleRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-    Console = Buff->Header.Console;
-
-    if (Console->UnpauseEvent)
-    {
-        Status = NtDuplicateObject(GetCurrentProcess(), Console->UnpauseEvent,
-                                   ProcessData->ProcessHandle, &WriteConsoleRequest->UnpauseEvent,
-                                   SYNCHRONIZE, 0, 0);
-        ConioUnlockScreenBuffer(Buff);
-        return NT_SUCCESS(Status) ? STATUS_PENDING : Status;
-    }
-
-    if(WriteConsoleRequest->Unicode)
-    {
-        Length = WideCharToMultiByte(Console->OutputCodePage, 0,
-                                     (PWCHAR)WriteConsoleRequest->Buffer,
-                                     WriteConsoleRequest->NrCharactersToWrite,
-                                     NULL, 0, NULL, NULL);
-        Buffer = RtlAllocateHeap(GetProcessHeap(), 0, Length);
-        if (Buffer)
-        {
-            WideCharToMultiByte(Console->OutputCodePage, 0,
-                                (PWCHAR)WriteConsoleRequest->Buffer,
-                                WriteConsoleRequest->NrCharactersToWrite,
-                                Buffer, Length, NULL, NULL);
-        }
-        else
-        {
-            Status = STATUS_NO_MEMORY;
-        }
-    }
-    else
-    {
-        Buffer = (PCHAR)WriteConsoleRequest->Buffer;
-    }
-
-    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(GetProcessHeap(), 0, Buffer);
-        }
-    }
-    ConioUnlockScreenBuffer(Buff);
-
-    WriteConsoleRequest->NrCharactersWritten = Written;
-
-    return Status;
-}
-
 VOID WINAPI
 ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer)
 {
@@ -472,83 +393,6 @@ ConioDrawConsole(PCSRSS_CONSOLE Console)
     ConioDrawRegion(Console, &Region);
 }
 
-CSR_API(SrvGetConsoleScreenBufferInfo) // CsrGetScreenBufferInfo
-{
-    NTSTATUS Status;
-    PCSRSS_SCREEN_BUFFER_INFO ScreenBufferInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScreenBufferInfoRequest;
-    PCSRSS_CONSOLE Console;
-    PCSRSS_SCREEN_BUFFER Buff;
-    PCONSOLE_SCREEN_BUFFER_INFO pInfo;
-
-    DPRINT("SrvGetConsoleScreenBufferInfo\n");
-
-    Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, ScreenBufferInfoRequest->ConsoleHandle, &Buff, GENERIC_READ);
-    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;
-    pInfo->dwCursorPosition.Y = Buff->CurrentY;
-    pInfo->wAttributes = Buff->DefaultAttrib;
-    pInfo->srWindow.Left = Buff->ShowX;
-    pInfo->srWindow.Right = Buff->ShowX + Console->Size.X - 1;
-    pInfo->srWindow.Top = Buff->ShowY;
-    pInfo->srWindow.Bottom = Buff->ShowY + Console->Size.Y - 1;
-    pInfo->dwMaximumWindowSize.X = Buff->MaxX;
-    pInfo->dwMaximumWindowSize.Y = Buff->MaxY;
-    ConioUnlockScreenBuffer(Buff);
-
-    return STATUS_SUCCESS;
-}
-
-CSR_API(SrvSetConsoleCursor)
-{
-    NTSTATUS Status;
-    PCSRSS_SET_CURSOR SetCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorRequest;
-    PCSRSS_CONSOLE Console;
-    PCSRSS_SCREEN_BUFFER Buff;
-    LONG OldCursorX, OldCursorY;
-    LONG NewCursorX, NewCursorY;
-
-    DPRINT("SrvSetConsoleCursor\n");
-
-    Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, SetCursorRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-    Console = Buff->Header.Console;
-
-    NewCursorX = SetCursorRequest->Position.X;
-    NewCursorY = SetCursorRequest->Position.Y;
-    if (NewCursorX < 0 || NewCursorX >= Buff->MaxX ||
-            NewCursorY < 0 || NewCursorY >= Buff->MaxY)
-    {
-        ConioUnlockScreenBuffer(Buff);
-        return STATUS_INVALID_PARAMETER;
-    }
-    OldCursorX = Buff->CurrentX;
-    OldCursorY = Buff->CurrentY;
-    Buff->CurrentX = NewCursorX;
-    Buff->CurrentY = NewCursorY;
-    if (Buff == Console->ActiveBuffer)
-    {
-        if (! ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY))
-        {
-            ConioUnlockScreenBuffer(Buff);
-            return STATUS_UNSUCCESSFUL;
-        }
-    }
-
-    ConioUnlockScreenBuffer(Buff);
-
-    return STATUS_SUCCESS;
-}
-
 static VOID FASTCALL
 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff, SMALL_RECT *UpdateRect, COORD *Start, UINT Length)
 {
@@ -576,49 +420,99 @@ ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff, SMALL_RECT *UpdateRect, COORD
     }
 }
 
-CSR_API(CsrWriteConsoleOutputChar)
+DWORD FASTCALL
+ConioEffectiveCursorSize(PCSRSS_CONSOLE Console, DWORD Scale)
+{
+    DWORD Size = (Console->ActiveBuffer->CursorInfo.dwSize * Scale + 99) / 100;
+    /* If line input in progress, perhaps adjust for insert toggle */
+    if (Console->LineBuffer && !Console->LineComplete && Console->LineInsertToggle)
+        return (Size * 2 <= Scale) ? (Size * 2) : (Size / 2);
+    return Size;
+}
+
+static NTSTATUS
+DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
+               IN PCSR_THREAD ClientThread,
+               IN BOOL CreateWaitBlock OPTIONAL);
+
+// Wait function CSR_WAIT_FUNCTION
+static BOOLEAN
+WriteConsoleThread(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;
-    PCSRSS_WRITE_CONSOLE_OUTPUT_CHAR WriteConsoleOutputCharRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleOutputCharRequest;
-    PCHAR String, tmpString = NULL;
-    PBYTE Buffer;
+
+    Status = DoWriteConsole(WaitApiMessage,
+                            WaitThread,
+                            FALSE);
+
+    if (Status != STATUS_PENDING)
+    {
+        WaitApiMessage->Status = Status;
+    }
+
+    return (Status == STATUS_PENDING ? FALSE : TRUE);
+}
+
+static NTSTATUS
+DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
+               IN PCSR_THREAD ClientThread,
+               IN BOOL CreateWaitBlock OPTIONAL)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    PCSRSS_WRITE_CONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
     PCSRSS_CONSOLE Console;
     PCSRSS_SCREEN_BUFFER Buff;
-    DWORD X, Y, Length, CharSize, Written = 0;
-    SMALL_RECT UpdateRect;
+    PCHAR Buffer;
+    DWORD Written = 0;
+    ULONG Length;
 
-    DPRINT("CsrWriteConsoleOutputChar\n");
+    Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(ClientThread->Process), WriteConsoleRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
+    if (!NT_SUCCESS(Status)) return Status;
 
-    CharSize = (WriteConsoleOutputCharRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
+    Console = Buff->Header.Console;
 
-    if (ApiMessage->Header.u1.s1.TotalLength
-            < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR)
-            + (WriteConsoleOutputCharRequest->Length * CharSize))
+    // if (Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION))
+    if (Console->PauseFlags && Console->UnpauseEvent != NULL)
     {
-        DPRINT1("Invalid ApiMessage size\n");
-        return STATUS_INVALID_PARAMETER;
-    }
+        if (CreateWaitBlock)
+        {
+            if (!CsrCreateWait(&Console->WriteWaitQueue,
+                               WriteConsoleThread,
+                               ClientThread,
+                               ApiMessage,
+                               NULL,
+                               NULL))
+            {
+                /* Fail */
+                ConioUnlockScreenBuffer(Buff);
+                return STATUS_NO_MEMORY;
+            }
+        }
 
-    Status = ConioLockScreenBuffer(CsrGetClientThread()->Process,
-                                    WriteConsoleOutputCharRequest->ConsoleHandle,
-                                    &Buff,
-                                    GENERIC_WRITE);
-    if (NT_SUCCESS(Status))
+        /* Wait until we un-pause the console */
+        Status = STATUS_PENDING;
+    }
+    else
     {
-        Console = Buff->Header.Console;
-        if(WriteConsoleOutputCharRequest->Unicode)
+        if(WriteConsoleRequest->Unicode)
         {
             Length = WideCharToMultiByte(Console->OutputCodePage, 0,
-                                         (PWCHAR)WriteConsoleOutputCharRequest->String,
-                                         WriteConsoleOutputCharRequest->Length,
+                                         (PWCHAR)WriteConsoleRequest->Buffer,
+                                         WriteConsoleRequest->NrCharactersToWrite,
                                          NULL, 0, NULL, NULL);
-            tmpString = String = RtlAllocateHeap(GetProcessHeap(), 0, Length);
-            if (String)
+            Buffer = RtlAllocateHeap(GetProcessHeap(), 0, Length);
+            if (Buffer)
             {
                 WideCharToMultiByte(Console->OutputCodePage, 0,
-                                    (PWCHAR)WriteConsoleOutputCharRequest->String,
-                                    WriteConsoleOutputCharRequest->Length,
-                                    String, Length, NULL, NULL);
+                                    (PWCHAR)WriteConsoleRequest->Buffer,
+                                    WriteConsoleRequest->NrCharactersToWrite,
+                                    Buffer, Length, NULL, NULL);
             }
             else
             {
@@ -627,212 +521,546 @@ CSR_API(CsrWriteConsoleOutputChar)
         }
         else
         {
-            String = (PCHAR)WriteConsoleOutputCharRequest->String;
+            Buffer = (PCHAR)WriteConsoleRequest->Buffer;
         }
 
-        if (String)
+        if (Buffer)
         {
             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--)
+                Status = ConioWriteConsole(Console, Buff, Buffer,
+                                           WriteConsoleRequest->NrCharactersToWrite, TRUE);
+                if (NT_SUCCESS(Status))
                 {
-                    *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);
+                    Written = WriteConsoleRequest->NrCharactersToWrite;
                 }
-
-                WriteConsoleOutputCharRequest->EndCoord.X = X;
-                WriteConsoleOutputCharRequest->EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY;
-
             }
-            if (WriteConsoleOutputCharRequest->Unicode)
+            if (WriteConsoleRequest->Unicode)
             {
-                RtlFreeHeap(GetProcessHeap(), 0, tmpString);
+                RtlFreeHeap(GetProcessHeap(), 0, Buffer);
             }
         }
-        ConioUnlockScreenBuffer(Buff);
+
+        WriteConsoleRequest->NrCharactersWritten = Written;
     }
-    WriteConsoleOutputCharRequest->NrCharactersWritten = Written;
+
+    ConioUnlockScreenBuffer(Buff);
     return Status;
 }
 
-CSR_API(CsrFillOutputChar)
+
+/* PUBLIC APIS ****************************************************************/
+
+CSR_API(SrvReadConsoleOutput)
 {
-    NTSTATUS Status;
-    PCSRSS_FILL_OUTPUT FillOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FillOutputRequest;
-    PCSRSS_CONSOLE Console;
+    PCSRSS_READ_CONSOLE_OUTPUT ReadConsoleOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputRequest;
+    PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+    PCHAR_INFO CharInfo;
+    PCHAR_INFO CurCharInfo;
     PCSRSS_SCREEN_BUFFER Buff;
-    DWORD X, Y, Length, Written = 0;
-    CHAR Char;
-    PBYTE Buffer;
-    SMALL_RECT UpdateRect;
+    DWORD SizeX, SizeY;
+    NTSTATUS Status;
+    COORD BufferSize;
+    COORD BufferCoord;
+    SMALL_RECT ReadRegion;
+    SMALL_RECT ScreenRect;
+    DWORD i;
+    PBYTE Ptr;
+    LONG X, Y;
+    UINT CodePage;
+
+    DPRINT("SrvReadConsoleOutput\n");
 
-    DPRINT("CsrFillOutputChar\n");
+    CharInfo = ReadConsoleOutputRequest->CharInfo;
+    ReadRegion = ReadConsoleOutputRequest->ReadRegion;
+    BufferSize = ReadConsoleOutputRequest->BufferSize;
+    BufferCoord = ReadConsoleOutputRequest->BufferCoord;
 
-    Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, FillOutputRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
-    if (! NT_SUCCESS(Status))
+    if (!CsrValidateMessageBuffer(ApiMessage,
+                                  (PVOID*)&ReadConsoleOutputRequest->CharInfo,
+                                  BufferSize.X * BufferSize.Y,
+                                  sizeof(CHAR_INFO)))
     {
-        return Status;
+        return STATUS_INVALID_PARAMETER;
     }
-    Console = Buff->Header.Console;
 
-    X = FillOutputRequest->Position.X;
-    Y = (FillOutputRequest->Position.Y + Buff->VirtualY) % Buff->MaxY;
-    Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)];
-    if(FillOutputRequest->Unicode)
-        ConsoleUnicodeCharToAnsiChar(Console, &Char, &FillOutputRequest->Char.UnicodeChar);
-    else
-        Char = FillOutputRequest->Char.AsciiChar;
-    Length = FillOutputRequest->Length;
-    while (Length--)
+    Status = ConioLockScreenBuffer(ProcessData, ReadConsoleOutputRequest->ConsoleHandle, &Buff, GENERIC_READ);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* FIXME: Is this correct? */
+    CodePage = ProcessData->Console->OutputCodePage;
+
+    SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&ReadRegion));
+    SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&ReadRegion));
+    ReadRegion.Bottom = ReadRegion.Top + SizeY;
+    ReadRegion.Right = ReadRegion.Left + SizeX;
+
+    ConioInitRect(&ScreenRect, 0, 0, Buff->MaxY, Buff->MaxX);
+    if (!ConioGetIntersection(&ReadRegion, &ScreenRect, &ReadRegion))
     {
-        *Buffer = Char;
-        Buffer += 2;
-        Written++;
-        if (++X == Buff->MaxX)
+        ConioUnlockScreenBuffer(Buff);
+        return STATUS_SUCCESS;
+    }
+
+    for (i = 0, Y = ReadRegion.Top; Y < ReadRegion.Bottom; ++i, ++Y)
+    {
+        CurCharInfo = CharInfo + (i * BufferSize.X);
+
+        Ptr = ConioCoordToPointer(Buff, ReadRegion.Left, Y);
+        for (X = ReadRegion.Left; X < ReadRegion.Right; ++X)
         {
-            if (++Y == Buff->MaxY)
+            if (ReadConsoleOutputRequest->Unicode)
             {
-                Y = 0;
-                Buffer = Buff->Buffer;
+                // ConsoleAnsiCharToUnicodeChar(ProcessData->Console, (PCHAR)Ptr++, &CurCharInfo->Char.UnicodeChar);
+                MultiByteToWideChar(CodePage, 0,
+                                    (PCHAR)Ptr++, 1,
+                                    &CurCharInfo->Char.UnicodeChar, 1);
             }
-            X = 0;
+            else
+            {
+                CurCharInfo->Char.AsciiChar = *Ptr++;
+            }
+            CurCharInfo->Attributes = *Ptr++;
+            ++CurCharInfo;
         }
     }
 
-    if (Buff == Console->ActiveBuffer)
-    {
-        ConioComputeUpdateRect(Buff, &UpdateRect, &FillOutputRequest->Position,
-                               FillOutputRequest->Length);
-        ConioDrawRegion(Console, &UpdateRect);
-    }
-
     ConioUnlockScreenBuffer(Buff);
-    Length = FillOutputRequest->Length;
-    FillOutputRequest->NrCharactersWritten = Length;
+
+    ReadConsoleOutputRequest->ReadRegion.Right = ReadRegion.Left + SizeX - 1;
+    ReadConsoleOutputRequest->ReadRegion.Bottom = ReadRegion.Top + SizeY - 1;
+    ReadConsoleOutputRequest->ReadRegion.Left = ReadRegion.Left;
+    ReadConsoleOutputRequest->ReadRegion.Top = ReadRegion.Top;
+
     return STATUS_SUCCESS;
 }
 
-CSR_API(CsrWriteConsoleOutputAttrib)
+CSR_API(SrvWriteConsole)
 {
-    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;
+    PCSRSS_WRITE_CONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
+
+    DPRINT("SrvWriteConsole\n");
+
+    if (!CsrValidateMessageBuffer(ApiMessage,
+                                  (PVOID)&WriteConsoleRequest->Buffer,
+                                  WriteConsoleRequest->BufferSize,
+                                  sizeof(BYTE)))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    Status = DoWriteConsole(ApiMessage,
+                            CsrGetClientThread(),
+                            TRUE);
+
+    if (Status == STATUS_PENDING)
+        *ReplyCode = CsrReplyPending;
+
+    return Status;
+}
+
+CSR_API(SrvWriteConsoleOutput)
+{
+    PCSRSS_WRITE_CONSOLE_OUTPUT WriteConsoleOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleOutputRequest;
+    PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+    SHORT i, X, Y, SizeX, SizeY;
+    PCSRSS_CONSOLE Console;
+    PCSRSS_SCREEN_BUFFER Buff;
+    SMALL_RECT ScreenBuffer;
+    CHAR_INFO* CurCharInfo;
+    SMALL_RECT WriteRegion;
+    CHAR_INFO* CharInfo;
+    COORD BufferCoord;
+    COORD BufferSize;
+    NTSTATUS Status;
+    PBYTE Ptr;
 
-    DPRINT("CsrWriteConsoleOutputAttrib\n");
+    DPRINT("SrvWriteConsoleOutput\n");
+
+    BufferSize = WriteConsoleOutputRequest->BufferSize;
+    BufferCoord = WriteConsoleOutputRequest->BufferCoord;
+    CharInfo = WriteConsoleOutputRequest->CharInfo;
 
-    if (ApiMessage->Header.u1.s1.TotalLength
-            < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB)
-            + WriteConsoleOutputAttribRequest->Length * sizeof(WORD))
+    if (!CsrValidateMessageBuffer(ApiMessage,
+                                  (PVOID*)&WriteConsoleOutputRequest->CharInfo,
+                                  BufferSize.X * BufferSize.Y,
+                                  sizeof(CHAR_INFO)))
     {
-        DPRINT1("Invalid ApiMessage size\n");
         return STATUS_INVALID_PARAMETER;
     }
 
-    Status = ConioLockScreenBuffer(CsrGetClientThread()->Process,
-                                   WriteConsoleOutputAttribRequest->ConsoleHandle,
+    Status = ConioLockScreenBuffer(ProcessData,
+                                   WriteConsoleOutputRequest->ConsoleHandle,
                                    &Buff,
                                    GENERIC_WRITE);
-    if (! NT_SUCCESS(Status))
+    if (!NT_SUCCESS(Status)) return Status;
+
+    Console = Buff->Header.Console;
+
+    WriteRegion = WriteConsoleOutputRequest->WriteRegion;
+
+    SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&WriteRegion));
+    SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&WriteRegion));
+    WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
+    WriteRegion.Right = WriteRegion.Left + SizeX - 1;
+
+    /* Make sure WriteRegion is inside the screen buffer */
+    ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1);
+    if (!ConioGetIntersection(&WriteRegion, &ScreenBuffer, &WriteRegion))
     {
-        return Status;
+        ConioUnlockScreenBuffer(Buff);
+
+        /* It is okay to have a WriteRegion completely outside the screen buffer.
+           No data is written then. */
+        return STATUS_SUCCESS;
     }
-    Console = Buff->Header.Console;
 
-    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--)
+    for (i = 0, Y = WriteRegion.Top; Y <= WriteRegion.Bottom; i++, Y++)
     {
-        *Buffer = (UCHAR)(*Attribute++);
-        Buffer += 2;
-        if (++X == Buff->MaxX)
+        CurCharInfo = CharInfo + (i + BufferCoord.Y) * BufferSize.X + BufferCoord.X;
+        Ptr = ConioCoordToPointer(Buff, WriteRegion.Left, Y);
+        for (X = WriteRegion.Left; X <= WriteRegion.Right; X++)
         {
-            if (++Y == Buff->MaxY)
+            CHAR AsciiChar;
+            if (WriteConsoleOutputRequest->Unicode)
             {
-                Y = 0;
-                Buffer = Buff->Buffer + 1;
+                ConsoleUnicodeCharToAnsiChar(Console, &AsciiChar, &CurCharInfo->Char.UnicodeChar);
             }
-            X = 0;
+            else
+            {
+                AsciiChar = CurCharInfo->Char.AsciiChar;
+            }
+            *Ptr++ = AsciiChar;
+            *Ptr++ = CurCharInfo->Attributes;
+            CurCharInfo++;
         }
     }
 
-    if (Buff == Console->ActiveBuffer)
+    ConioDrawRegion(Console, &WriteRegion);
+
+    ConioUnlockScreenBuffer(Buff);
+
+    WriteConsoleOutputRequest->WriteRegion.Right = WriteRegion.Left + SizeX - 1;
+    WriteConsoleOutputRequest->WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
+    WriteConsoleOutputRequest->WriteRegion.Left = WriteRegion.Left;
+    WriteConsoleOutputRequest->WriteRegion.Top = WriteRegion.Top;
+
+    return STATUS_SUCCESS;
+}
+
+CSR_API(SrvReadConsoleOutputString)
+{
+    NTSTATUS Status;
+    PCSRSS_READ_CONSOLE_OUTPUT_CODE ReadConsoleOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputCodeRequest;
+    PCSRSS_CONSOLE Console;
+    PCSRSS_SCREEN_BUFFER Buff;
+    USHORT CodeType;
+    DWORD Xpos, Ypos;
+    PVOID ReadBuffer;
+    DWORD i;
+    ULONG CodeSize;
+    BYTE Code;
+
+    DPRINT("SrvReadConsoleOutputString\n");
+
+    CodeType = ReadConsoleOutputCodeRequest->CodeType;
+    switch (CodeType)
     {
-        ConioComputeUpdateRect(Buff, &UpdateRect, &WriteConsoleOutputAttribRequest->Coord,
-                               WriteConsoleOutputAttribRequest->Length);
-        ConioDrawRegion(Console, &UpdateRect);
+        case CODE_ASCII:
+            CodeSize = sizeof(CHAR);
+            break;
+
+        case CODE_UNICODE:
+            CodeSize = sizeof(WCHAR);
+            break;
+
+        case CODE_ATTRIBUTE:
+            CodeSize = sizeof(WORD);
+            break;
+
+        default:
+            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;
+
+    /*
+     * MSDN (ReadConsoleOutputAttribute and ReadConsoleOutputCharacter) :
+     *
+     * If the number of attributes (resp. characters) to be read from extends
+     * beyond the end of the specified screen buffer row, attributes (resp.
+     * characters) are read from the next row. If the number of attributes
+     * (resp. characters) to be read from extends beyond the end of the console
+     * screen buffer, attributes (resp. characters) up to the end of the console
+     * screen buffer are read.
+     *
+     * TODO: Do NOT loop up to NumCodesToRead, but stop before
+     * if we are going to overflow...
+     */
+    for (i = 0; i < ReadConsoleOutputCodeRequest->NumCodesToRead; ++i)
+    {
+        Code = Buff->Buffer[2 * (Xpos + Ypos * Buff->MaxX) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)];
+
+        switch (CodeType)
+        {
+            case CODE_UNICODE:
+                ConsoleAnsiCharToUnicodeChar(Console, (PWCHAR)ReadBuffer, (PCHAR)&Code);
+                break;
+
+            case CODE_ASCII:
+                *(PCHAR)ReadBuffer = (CHAR)Code;
+                break;
+
+            case CODE_ATTRIBUTE:
+                *(PWORD)ReadBuffer = (WORD)Code;
+                break;
+        }
+        ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
+
+        Xpos++;
+
+        if (Xpos == Buff->MaxX)
+        {
+            Xpos = 0;
+            Ypos++;
+
+            if (Ypos == Buff->MaxY)
+            {
+                Ypos = 0;
+            }
+        }
+    }
+
+    switch (CodeType)
+    {
+        case CODE_UNICODE:
+            *(PWCHAR)ReadBuffer = 0;
+            break;
+
+        case CODE_ASCII:
+            *(PCHAR)ReadBuffer = 0;
+            break;
+
+        case CODE_ATTRIBUTE:
+            *(PWORD)ReadBuffer = 0;
+            break;
     }
 
-    WriteConsoleOutputAttribRequest->EndCoord.X = X;
-    WriteConsoleOutputAttribRequest->EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY;
+    ReadConsoleOutputCodeRequest->EndCoord.X = Xpos;
+    ReadConsoleOutputCodeRequest->EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY;
 
     ConioUnlockScreenBuffer(Buff);
 
+    ReadConsoleOutputCodeRequest->CodesRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)ReadConsoleOutputCodeRequest->pCode.pCode) / CodeSize;
+    // <= ReadConsoleOutputCodeRequest->NumCodesToRead
+
     return STATUS_SUCCESS;
 }
 
-CSR_API(CsrFillOutputAttrib)
+CSR_API(SrvWriteConsoleOutputString)
 {
-    PCSRSS_FILL_OUTPUT_ATTRIB FillOutputAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FillOutputAttribRequest;
-    PCSRSS_SCREEN_BUFFER Buff;
-    PUCHAR Buffer;
     NTSTATUS Status;
-    int X, Y, Length;
-    UCHAR Attr;
-    SMALL_RECT UpdateRect;
+    PCSRSS_WRITE_CONSOLE_OUTPUT_CODE WriteConsoleOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleOutputCodeRequest;
     PCSRSS_CONSOLE Console;
+    PCSRSS_SCREEN_BUFFER Buff;
+    USHORT CodeType;
+    PBYTE Buffer; // PUCHAR
+    PCHAR String, tmpString = NULL;
+    DWORD X, Y, Length; // , Written = 0;
+    ULONG CodeSize;
+    SMALL_RECT UpdateRect;
 
-    DPRINT("CsrFillOutputAttrib\n");
+    DPRINT("SrvWriteConsoleOutputString\n");
 
-    Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, FillOutputAttribRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
-    if (! NT_SUCCESS(Status))
+    CodeType = WriteConsoleOutputCodeRequest->CodeType;
+    switch (CodeType)
     {
-        return Status;
+        case CODE_ASCII:
+            CodeSize = sizeof(CHAR);
+            break;
+
+        case CODE_UNICODE:
+            CodeSize = sizeof(WCHAR);
+            break;
+
+        case CODE_ATTRIBUTE:
+            CodeSize = sizeof(WORD);
+            break;
+
+        default:
+            return STATUS_INVALID_PARAMETER;
+    }
+
+    if (!CsrValidateMessageBuffer(ApiMessage,
+                                  (PVOID*)&WriteConsoleOutputCodeRequest->pCode.pCode,
+                                  WriteConsoleOutputCodeRequest->Length,
+                                  CodeSize))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                                    WriteConsoleOutputCodeRequest->ConsoleHandle,
+                                    &Buff,
+                                    GENERIC_WRITE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    Console = Buff->Header.Console;
+
+    switch (CodeType)
+    {
+        case CODE_UNICODE:
+        {
+            Length = WideCharToMultiByte(Console->OutputCodePage, 0,
+                                         (PWCHAR)WriteConsoleOutputCodeRequest->pCode.UnicodeChar,
+                                         WriteConsoleOutputCodeRequest->Length,
+                                         NULL, 0, NULL, NULL);
+            tmpString = String = RtlAllocateHeap(GetProcessHeap(), 0, Length);
+            if (String)
+            {
+                WideCharToMultiByte(Console->OutputCodePage, 0,
+                                    (PWCHAR)WriteConsoleOutputCodeRequest->pCode.UnicodeChar,
+                                    WriteConsoleOutputCodeRequest->Length,
+                                    String, Length, NULL, NULL);
+            }
+            else
+            {
+                Status = STATUS_NO_MEMORY;
+            }
+
+            break;
+        }
+
+        case CODE_ASCII:
+            String = (PCHAR)WriteConsoleOutputCodeRequest->pCode.AsciiChar;
+            break;
+
+        case CODE_ATTRIBUTE:
+        default:
+            // *(ReadBuffer++) = Code;
+            String = (PCHAR)WriteConsoleOutputCodeRequest->pCode.Attribute;
+            break;
+    }
+
+    if (String && NT_SUCCESS(Status))
+    {
+        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)];
+
+        while (Length--)
+        {
+            *Buffer = *String++;
+            // ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
+            String = (PCHAR)((ULONG_PTR)String + CodeSize);
+            // Written++;
+            Buffer += 2;
+            if (++X == Buff->MaxX)
+            {
+                if (++Y == Buff->MaxY)
+                {
+                    Y = 0;
+                    Buffer = Buff->Buffer + (CodeType == CODE_ATTRIBUTE ? 1 : 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 (tmpString)
+    {
+        RtlFreeHeap(GetProcessHeap(), 0, tmpString);
     }
+
+    ConioUnlockScreenBuffer(Buff);
+
+    // WriteConsoleOutputCodeRequest->NrCharactersWritten = Written;
+    return Status;
+}
+
+CSR_API(SrvFillConsoleOutput)
+{
+    NTSTATUS Status;
+    PCSRSS_FILL_OUTPUT FillOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FillOutputRequest;
+    PCSRSS_CONSOLE Console;
+    PCSRSS_SCREEN_BUFFER Buff;
+    DWORD X, Y, Length; // , Written = 0;
+    USHORT CodeType;
+    BYTE Code;
+    PBYTE Buffer;
+    SMALL_RECT UpdateRect;
+
+    DPRINT("SrvFillConsoleOutput\n");
+
+    Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), FillOutputRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
+    if (!NT_SUCCESS(Status)) return Status;
+
     Console = Buff->Header.Console;
 
-    X = FillOutputAttribRequest->Coord.X;
-    Y = (FillOutputAttribRequest->Coord.Y + Buff->VirtualY) % Buff->MaxY;
-    Length = FillOutputAttribRequest->Length;
-    Attr = FillOutputAttribRequest->Attribute;
-    Buffer = &Buff->Buffer[(Y * Buff->MaxX * 2) + (X * 2) + 1];
+    CodeType = FillOutputRequest->CodeType;
+
+    X = FillOutputRequest->Coord.X;
+    Y = (FillOutputRequest->Coord.Y + Buff->VirtualY) % Buff->MaxY;
+    Length = FillOutputRequest->Length;
+    Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)];
+
+    switch (CodeType)
+    {
+        case CODE_ASCII:
+            Code = (BYTE)FillOutputRequest->Code.AsciiChar;
+            break;
+
+        case CODE_UNICODE:
+            ConsoleUnicodeCharToAnsiChar(Console, (PCHAR)&Code, &FillOutputRequest->Code.UnicodeChar);
+            break;
+
+        case CODE_ATTRIBUTE:
+            Code = (BYTE)FillOutputRequest->Code.Attribute;
+            break;
+
+        default:
+            ConioUnlockScreenBuffer(Buff);
+            return STATUS_INVALID_PARAMETER;
+    }
+
     while (Length--)
     {
-        *Buffer = Attr;
+        *Buffer = Code;
         Buffer += 2;
+        // Written++;
         if (++X == Buff->MaxX)
         {
             if (++Y == Buff->MaxY)
             {
                 Y = 0;
-                Buffer = Buff->Buffer + 1;
+                Buffer = Buff->Buffer + (CodeType == CODE_ATTRIBUTE ? 1 : 0);
             }
             X = 0;
         }
@@ -840,41 +1068,32 @@ CSR_API(CsrFillOutputAttrib)
 
     if (Buff == Console->ActiveBuffer)
     {
-        ConioComputeUpdateRect(Buff, &UpdateRect, &FillOutputAttribRequest->Coord,
-                               FillOutputAttribRequest->Length);
+        ConioComputeUpdateRect(Buff, &UpdateRect, &FillOutputRequest->Coord,
+                               FillOutputRequest->Length);
         ConioDrawRegion(Console, &UpdateRect);
     }
 
     ConioUnlockScreenBuffer(Buff);
-
+/*
+    Length = FillOutputRequest->Length;
+    FillOutputRequest->NrCharactersWritten = Length;
+*/
     return STATUS_SUCCESS;
 }
 
-DWORD FASTCALL
-ConioEffectiveCursorSize(PCSRSS_CONSOLE Console, DWORD Scale)
-{
-    DWORD Size = (Console->ActiveBuffer->CursorInfo.dwSize * Scale + 99) / 100;
-    /* If line input in progress, perhaps adjust for insert toggle */
-    if (Console->LineBuffer && !Console->LineComplete && Console->LineInsertToggle)
-        return (Size * 2 <= Scale) ? (Size * 2) : (Size / 2);
-    return Size;
-}
-
 CSR_API(SrvGetConsoleCursorInfo)
 {
     NTSTATUS Status;
-    PCSRSS_GET_CURSOR_INFO GetCursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCursorInfoRequest;
+    PCSRSS_CURSOR_INFO CursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CursorInfoRequest;
     PCSRSS_SCREEN_BUFFER Buff;
 
     DPRINT("SrvGetConsoleCursorInfo\n");
 
-    Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, GetCursorInfoRequest->ConsoleHandle, &Buff, GENERIC_READ);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-    GetCursorInfoRequest->Info.bVisible = Buff->CursorInfo.bVisible;
-    GetCursorInfoRequest->Info.dwSize = Buff->CursorInfo.dwSize;
+    Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), CursorInfoRequest->ConsoleHandle, &Buff, GENERIC_READ);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    CursorInfoRequest->Info.bVisible = Buff->CursorInfo.bVisible;
+    CursorInfoRequest->Info.dwSize = Buff->CursorInfo.dwSize;
     ConioUnlockScreenBuffer(Buff);
 
     return STATUS_SUCCESS;
@@ -882,24 +1101,22 @@ CSR_API(SrvGetConsoleCursorInfo)
 
 CSR_API(SrvSetConsoleCursorInfo)
 {
-    PCSRSS_SET_CURSOR_INFO SetCursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorInfoRequest;
+    NTSTATUS Status;
+    PCSRSS_CURSOR_INFO CursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CursorInfoRequest;
     PCSRSS_CONSOLE Console;
     PCSRSS_SCREEN_BUFFER Buff;
     DWORD Size;
     BOOL Visible;
-    NTSTATUS Status;
 
     DPRINT("SrvSetConsoleCursorInfo\n");
 
-    Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, SetCursorInfoRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
+    Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), CursorInfoRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
+    if (!NT_SUCCESS(Status)) return Status;
+
     Console = Buff->Header.Console;
 
-    Size = SetCursorInfoRequest->Info.dwSize;
-    Visible = SetCursorInfoRequest->Info.bVisible;
+    Size = CursorInfoRequest->Info.dwSize;
+    Visible = CursorInfoRequest->Info.bVisible;
     if (Size < 1)
     {
         Size = 1;
@@ -909,13 +1126,14 @@ CSR_API(SrvSetConsoleCursorInfo)
         Size = 100;
     }
 
-    if (Size != Buff->CursorInfo.dwSize
-            || (Visible && ! Buff->CursorInfo.bVisible) || (! Visible && Buff->CursorInfo.bVisible))
+    if ( (Size != Buff->CursorInfo.dwSize)          ||
+         (Visible && ! Buff->CursorInfo.bVisible)   ||
+         (! Visible && Buff->CursorInfo.bVisible) )
     {
         Buff->CursorInfo.dwSize = Size;
         Buff->CursorInfo.bVisible = Visible;
 
-        if (! ConioSetCursorInfo(Console, Buff))
+        if (!ConioSetCursorInfo(Console, Buff))
         {
             ConioUnlockScreenBuffer(Buff);
             return STATUS_UNSUCCESSFUL;
@@ -927,26 +1145,37 @@ CSR_API(SrvSetConsoleCursorInfo)
     return STATUS_SUCCESS;
 }
 
-CSR_API(CsrSetTextAttrib)
+CSR_API(SrvSetConsoleCursorPosition)
 {
     NTSTATUS Status;
-    PCSRSS_SET_ATTRIB SetAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetAttribRequest;
+    PCSRSS_SET_CURSOR_POSITION SetCursorPositionRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorPositionRequest;
     PCSRSS_CONSOLE Console;
     PCSRSS_SCREEN_BUFFER Buff;
+    LONG OldCursorX, OldCursorY;
+    LONG NewCursorX, NewCursorY;
 
-    DPRINT("CsrSetTextAttrib\n");
+    DPRINT("SrvSetConsoleCursorPosition\n");
+
+    Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetCursorPositionRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
+    if (!NT_SUCCESS(Status)) return Status;
 
-    Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, SetAttribRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
     Console = Buff->Header.Console;
 
-    Buff->DefaultAttrib = SetAttribRequest->Attrib;
+    NewCursorX = SetCursorPositionRequest->Position.X;
+    NewCursorY = SetCursorPositionRequest->Position.Y;
+    if ( NewCursorX < 0 || NewCursorX >= Buff->MaxX ||
+         NewCursorY < 0 || NewCursorY >= Buff->MaxY )
+    {
+        ConioUnlockScreenBuffer(Buff);
+        return STATUS_INVALID_PARAMETER;
+    }
+    OldCursorX = Buff->CurrentX;
+    OldCursorY = Buff->CurrentY;
+    Buff->CurrentX = NewCursorX;
+    Buff->CurrentY = NewCursorY;
     if (Buff == Console->ActiveBuffer)
     {
-        if (! ConioUpdateScreenInfo(Console, Buff))
+        if (! ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY))
         {
             ConioUnlockScreenBuffer(Buff);
             return STATUS_UNSUCCESSFUL;
@@ -958,25 +1187,55 @@ CSR_API(CsrSetTextAttrib)
     return STATUS_SUCCESS;
 }
 
-CSR_API(SrvCreateConsoleScreenBuffer)
+CSR_API(SrvSetConsoleTextAttribute)
 {
-    PCSRSS_CREATE_SCREEN_BUFFER CreateScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CreateScreenBufferRequest;
-    PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
+    NTSTATUS Status;
+    PCSRSS_SET_ATTRIB SetAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetAttribRequest;
     PCSRSS_CONSOLE Console;
     PCSRSS_SCREEN_BUFFER Buff;
+
+    DPRINT("SrvSetConsoleTextAttribute\n");
+
+    Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetAttribRequest->ConsoleHandle, &Buff, GENERIC_WRITE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    Console = Buff->Header.Console;
+
+    Buff->DefaultAttrib = SetAttribRequest->Attrib;
+    if (Buff == Console->ActiveBuffer)
+    {
+        if (!ConioUpdateScreenInfo(Console, Buff))
+        {
+            ConioUnlockScreenBuffer(Buff);
+            return STATUS_UNSUCCESSFUL;
+        }
+    }
+
+    ConioUnlockScreenBuffer(Buff);
+
+    return STATUS_SUCCESS;
+}
+
+CSR_API(SrvCreateConsoleScreenBuffer)
+{
     NTSTATUS Status;
+    PCSRSS_CREATE_SCREEN_BUFFER CreateScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CreateScreenBufferRequest;
+    PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+    PCSRSS_CONSOLE Console;
+    PCSRSS_SCREEN_BUFFER Buff;
 
     DPRINT("SrvCreateConsoleScreenBuffer\n");
 
     RtlEnterCriticalSection(&ProcessData->HandleTableLock);
+
     Status = ConioConsoleFromProcessData(ProcessData, &Console);
-    if (! NT_SUCCESS(Status))
+    if (!NT_SUCCESS(Status))
     {
+        RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
         return Status;
     }
 
     Buff = HeapAlloc(ConSrvHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_SCREEN_BUFFER));
-
     if (Buff != NULL)
     {
         if (Console->ActiveBuffer)
@@ -1019,131 +1278,77 @@ CSR_API(SrvCreateConsoleScreenBuffer)
     }
 
     ConioUnlockConsole(Console);
+
     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+
     return Status;
 }
 
-CSR_API(SrvSetConsoleActiveScreenBuffer)
+CSR_API(SrvGetConsoleScreenBufferInfo)
 {
     NTSTATUS Status;
-    PCSRSS_SET_SCREEN_BUFFER SetScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetScreenBufferRequest;
+    PCSRSS_SCREEN_BUFFER_INFO ScreenBufferInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScreenBufferInfoRequest;
     PCSRSS_CONSOLE Console;
     PCSRSS_SCREEN_BUFFER Buff;
+    PCONSOLE_SCREEN_BUFFER_INFO pInfo = &ScreenBufferInfoRequest->Info;
 
-    DPRINT("SrvSetConsoleActiveScreenBuffer\n");
+    DPRINT("SrvGetConsoleScreenBufferInfo\n");
 
-    Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, SetScreenBufferRequest->OutputHandle, &Buff, GENERIC_WRITE);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-    Console = Buff->Header.Console;
+    Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ScreenBufferInfoRequest->ConsoleHandle, &Buff, GENERIC_READ);
+    if (!NT_SUCCESS(Status)) return Status;
 
-    if (Buff == Console->ActiveBuffer)
-    {
-        ConioUnlockScreenBuffer(Buff);
-        return STATUS_SUCCESS;
-    }
+    Console = Buff->Header.Console;
 
-    /* If old buffer has no handles, it's now unreferenced */
-    if (Console->ActiveBuffer->Header.HandleCount == 0)
-    {
-        ConioDeleteScreenBuffer(Console->ActiveBuffer);
-    }
-    /* tie console to new buffer */
-    Console->ActiveBuffer = Buff;
-    /* Redraw the console */
-    ConioDrawConsole(Console);
+    pInfo->dwSize.X = Buff->MaxX;
+    pInfo->dwSize.Y = Buff->MaxY;
+    pInfo->dwCursorPosition.X = Buff->CurrentX;
+    pInfo->dwCursorPosition.Y = Buff->CurrentY;
+    pInfo->wAttributes = Buff->DefaultAttrib;
+    pInfo->srWindow.Left = Buff->ShowX;
+    pInfo->srWindow.Right = Buff->ShowX + Console->Size.X - 1;
+    pInfo->srWindow.Top = Buff->ShowY;
+    pInfo->srWindow.Bottom = Buff->ShowY + Console->Size.Y - 1;
+    pInfo->dwMaximumWindowSize.X = Buff->MaxX;
+    pInfo->dwMaximumWindowSize.Y = Buff->MaxY;
 
     ConioUnlockScreenBuffer(Buff);
 
     return STATUS_SUCCESS;
 }
 
-CSR_API(SrvWriteConsoleOutput)
+CSR_API(SrvSetConsoleActiveScreenBuffer)
 {
-    PCSRSS_WRITE_CONSOLE_OUTPUT WriteConsoleOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleOutputRequest;
-    SHORT i, X, Y, SizeX, SizeY;
-    PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
+    NTSTATUS Status;
+    PCSRSS_SET_SCREEN_BUFFER SetScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetScreenBufferRequest;
     PCSRSS_CONSOLE Console;
     PCSRSS_SCREEN_BUFFER Buff;
-    SMALL_RECT ScreenBuffer;
-    CHAR_INFO* CurCharInfo;
-    SMALL_RECT WriteRegion;
-    CHAR_INFO* CharInfo;
-    COORD BufferCoord;
-    COORD BufferSize;
-    NTSTATUS Status;
-    PBYTE Ptr;
-
-    DPRINT("SrvWriteConsoleOutput\n");
 
-    Status = ConioLockScreenBuffer(ProcessData,
-                                   WriteConsoleOutputRequest->ConsoleHandle,
-                                   &Buff,
-                                   GENERIC_WRITE);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-    Console = Buff->Header.Console;
+    DPRINT("SrvSetConsoleActiveScreenBuffer\n");
 
-    BufferSize = WriteConsoleOutputRequest->BufferSize;
-    BufferCoord = WriteConsoleOutputRequest->BufferCoord;
-    CharInfo = WriteConsoleOutputRequest->CharInfo;
-    if (!Win32CsrValidateBuffer(ProcessData, CharInfo,
-                                BufferSize.X * BufferSize.Y, sizeof(CHAR_INFO)))
-    {
-        ConioUnlockScreenBuffer(Buff);
-        return STATUS_ACCESS_VIOLATION;
-    }
-    WriteRegion = WriteConsoleOutputRequest->WriteRegion;
+    Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetScreenBufferRequest->OutputHandle, &Buff, GENERIC_WRITE);
+    if (!NT_SUCCESS(Status)) return Status;
 
-    SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&WriteRegion));
-    SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&WriteRegion));
-    WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
-    WriteRegion.Right = WriteRegion.Left + SizeX - 1;
+    Console = Buff->Header.Console;
 
-    /* Make sure WriteRegion is inside the screen buffer */
-    ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1);
-    if (! ConioGetIntersection(&WriteRegion, &ScreenBuffer, &WriteRegion))
+    if (Buff == Console->ActiveBuffer)
     {
         ConioUnlockScreenBuffer(Buff);
-
-        /* It is okay to have a WriteRegion completely outside the screen buffer.
-           No data is written then. */
         return STATUS_SUCCESS;
     }
 
-    for (i = 0, Y = WriteRegion.Top; Y <= WriteRegion.Bottom; i++, Y++)
+    /* If old buffer has no handles, it's now unreferenced */
+    if (Console->ActiveBuffer->Header.HandleCount == 0)
     {
-        CurCharInfo = CharInfo + (i + BufferCoord.Y) * BufferSize.X + BufferCoord.X;
-        Ptr = ConioCoordToPointer(Buff, WriteRegion.Left, Y);
-        for (X = WriteRegion.Left; X <= WriteRegion.Right; X++)
-        {
-            CHAR AsciiChar;
-            if (WriteConsoleOutputRequest->Unicode)
-            {
-                ConsoleUnicodeCharToAnsiChar(Console, &AsciiChar, &CurCharInfo->Char.UnicodeChar);
-            }
-            else
-            {
-                AsciiChar = CurCharInfo->Char.AsciiChar;
-            }
-            *Ptr++ = AsciiChar;
-            *Ptr++ = CurCharInfo->Attributes;
-            CurCharInfo++;
-        }
+        ConioDeleteScreenBuffer(Console->ActiveBuffer);
     }
 
-    ConioDrawRegion(Console, &WriteRegion);
+    /* Tie console to new buffer */
+    Console->ActiveBuffer = Buff;
 
-    ConioUnlockScreenBuffer(Buff);
+    /* Redraw the console */
+    ConioDrawConsole(Console);
 
-    WriteConsoleOutputRequest->WriteRegion.Right = WriteRegion.Left + SizeX - 1;
-    WriteConsoleOutputRequest->WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
-    WriteConsoleOutputRequest->WriteRegion.Left = WriteRegion.Left;
-    WriteConsoleOutputRequest->WriteRegion.Top = WriteRegion.Top;
+    ConioUnlockScreenBuffer(Buff);
 
     return STATUS_SUCCESS;
 }
@@ -1173,11 +1378,9 @@ CSR_API(SrvScrollConsoleScreenBuffer)
     DestinationOrigin = ScrollConsoleScreenBufferRequest->DestinationOrigin;
     Fill = ScrollConsoleScreenBufferRequest->Fill;
 
-    Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, ConsoleHandle, &Buff, GENERIC_WRITE);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
+    Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ConsoleHandle, &Buff, GENERIC_WRITE);
+    if (!NT_SUCCESS(Status)) return Status;
+
     Console = Buff->Header.Console;
 
     ScrollRectangle = ScrollConsoleScreenBufferRequest->ScrollRectangle;
@@ -1242,236 +1445,16 @@ CSR_API(SrvScrollConsoleScreenBuffer)
     return STATUS_SUCCESS;
 }
 
-CSR_API(CsrReadConsoleOutputChar)
-{
-    NTSTATUS Status;
-    PCSRSS_READ_CONSOLE_OUTPUT_CHAR ReadConsoleOutputCharRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputCharRequest;
-    PCSRSS_CONSOLE Console;
-    PCSRSS_SCREEN_BUFFER Buff;
-    DWORD Xpos, Ypos;
-    PCHAR ReadBuffer;
-    DWORD i;
-    ULONG CharSize;
-    CHAR Char;
-
-    DPRINT("CsrReadConsoleOutputChar\n");
-
-    ReadBuffer = ReadConsoleOutputCharRequest->String;
-
-    CharSize = (ReadConsoleOutputCharRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
-
-    Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, ReadConsoleOutputCharRequest->ConsoleHandle, &Buff, GENERIC_READ);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-    Console = Buff->Header.Console;
-
-    Xpos = ReadConsoleOutputCharRequest->ReadCoord.X;
-    Ypos = (ReadConsoleOutputCharRequest->ReadCoord.Y + Buff->VirtualY) % Buff->MaxY;
-
-    for (i = 0; i < ReadConsoleOutputCharRequest->NumCharsToRead; ++i)
-    {
-        Char = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX)];
-
-        if(ReadConsoleOutputCharRequest->Unicode)
-        {
-            ConsoleAnsiCharToUnicodeChar(Console, (WCHAR*)ReadBuffer, &Char);
-            ReadBuffer += sizeof(WCHAR);
-        }
-        else
-            *(ReadBuffer++) = Char;
-
-        Xpos++;
-
-        if (Xpos == Buff->MaxX)
-        {
-            Xpos = 0;
-            Ypos++;
-
-            if (Ypos == Buff->MaxY)
-            {
-                Ypos = 0;
-            }
-        }
-    }
-
-    *ReadBuffer = 0;
-    ReadConsoleOutputCharRequest->EndCoord.X = Xpos;
-    ReadConsoleOutputCharRequest->EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY;
-
-    ConioUnlockScreenBuffer(Buff);
-
-    ReadConsoleOutputCharRequest->CharsRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)ReadConsoleOutputCharRequest->String) / CharSize;
-    if (ReadConsoleOutputCharRequest->CharsRead * CharSize + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR) > sizeof(CSR_API_MESSAGE))
-    {
-        DPRINT1("Length won't fit in message\n");
-        return STATUS_BUFFER_TOO_SMALL;
-    }
-
-    return STATUS_SUCCESS;
-}
-
-CSR_API(CsrReadConsoleOutputAttrib)
-{
-    NTSTATUS Status;
-    PCSRSS_READ_CONSOLE_OUTPUT_ATTRIB ReadConsoleOutputAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputAttribRequest;
-    PCSRSS_SCREEN_BUFFER Buff;
-    DWORD Xpos, Ypos;
-    PWORD ReadBuffer;
-    DWORD i;
-    DWORD CurrentLength;
-
-    DPRINT("CsrReadConsoleOutputAttrib\n");
-
-    ReadBuffer = ReadConsoleOutputAttribRequest->Attribute;
-
-    Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, ReadConsoleOutputAttribRequest->ConsoleHandle, &Buff, GENERIC_READ);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-
-    Xpos = ReadConsoleOutputAttribRequest->ReadCoord.X;
-    Ypos = (ReadConsoleOutputAttribRequest->ReadCoord.Y + Buff->VirtualY) % Buff->MaxY;
-
-    for (i = 0; i < ReadConsoleOutputAttribRequest->NumAttrsToRead; ++i)
-    {
-        *ReadBuffer = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX) + 1];
-
-        ReadBuffer++;
-        Xpos++;
-
-        if (Xpos == Buff->MaxX)
-        {
-            Xpos = 0;
-            Ypos++;
-
-            if (Ypos == Buff->MaxY)
-            {
-                Ypos = 0;
-            }
-        }
-    }
-
-    *ReadBuffer = 0;
-
-    ReadConsoleOutputAttribRequest->EndCoord.X = Xpos;
-    ReadConsoleOutputAttribRequest->EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY;
-
-    ConioUnlockScreenBuffer(Buff);
-
-    CurrentLength = CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB)
-                    + ReadConsoleOutputAttribRequest->NumAttrsToRead * sizeof(WORD);
-    if (CurrentLength > sizeof(CSR_API_MESSAGE))
-    {
-        DPRINT1("Length won't fit in message\n");
-        return STATUS_BUFFER_TOO_SMALL;
-    }
-
-    return STATUS_SUCCESS;
-}
-
-CSR_API(SrvReadConsoleOutput)
-{
-    PCSRSS_READ_CONSOLE_OUTPUT ReadConsoleOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputRequest;
-    PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
-    PCHAR_INFO CharInfo;
-    PCHAR_INFO CurCharInfo;
-    PCSRSS_SCREEN_BUFFER Buff;
-    DWORD SizeX, SizeY;
-    NTSTATUS Status;
-    COORD BufferSize;
-    COORD BufferCoord;
-    SMALL_RECT ReadRegion;
-    SMALL_RECT ScreenRect;
-    DWORD i;
-    PBYTE Ptr;
-    LONG X, Y;
-    UINT CodePage;
-
-    DPRINT("SrvReadConsoleOutput\n");
-
-    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;
-
-    /* FIXME: Is this correct? */
-    CodePage = ProcessData->Console->OutputCodePage;
-
-    if (!Win32CsrValidateBuffer(ProcessData, CharInfo,
-                                BufferSize.X * BufferSize.Y, sizeof(CHAR_INFO)))
-    {
-        ConioUnlockScreenBuffer(Buff);
-        return STATUS_ACCESS_VIOLATION;
-    }
-
-    SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&ReadRegion));
-    SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&ReadRegion));
-    ReadRegion.Bottom = ReadRegion.Top + SizeY;
-    ReadRegion.Right = ReadRegion.Left + SizeX;
-
-    ConioInitRect(&ScreenRect, 0, 0, Buff->MaxY, Buff->MaxX);
-    if (! ConioGetIntersection(&ReadRegion, &ScreenRect, &ReadRegion))
-    {
-        ConioUnlockScreenBuffer(Buff);
-        return STATUS_SUCCESS;
-    }
-
-    for (i = 0, Y = ReadRegion.Top; Y < ReadRegion.Bottom; ++i, ++Y)
-    {
-        CurCharInfo = CharInfo + (i * BufferSize.X);
-
-        Ptr = ConioCoordToPointer(Buff, ReadRegion.Left, Y);
-        for (X = ReadRegion.Left; X < ReadRegion.Right; ++X)
-        {
-            if (ReadConsoleOutputRequest->Unicode)
-            {
-                MultiByteToWideChar(CodePage, 0,
-                                    (PCHAR)Ptr++, 1,
-                                    &CurCharInfo->Char.UnicodeChar, 1);
-            }
-            else
-            {
-                CurCharInfo->Char.AsciiChar = *Ptr++;
-            }
-            CurCharInfo->Attributes = *Ptr++;
-            ++CurCharInfo;
-        }
-    }
-
-    ConioUnlockScreenBuffer(Buff);
-
-    ReadConsoleOutputRequest->ReadRegion.Right = ReadRegion.Left + SizeX - 1;
-    ReadConsoleOutputRequest->ReadRegion.Bottom = ReadRegion.Top + SizeY - 1;
-    ReadConsoleOutputRequest->ReadRegion.Left = ReadRegion.Left;
-    ReadConsoleOutputRequest->ReadRegion.Top = ReadRegion.Top;
-
-    return STATUS_SUCCESS;
-}
-
 CSR_API(SrvSetConsoleScreenBufferSize)
 {
     NTSTATUS Status;
     PCSRSS_SET_SCREEN_BUFFER_SIZE SetScreenBufferSize = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetScreenBufferSize;
-    PCSRSS_CONSOLE Console;
     PCSRSS_SCREEN_BUFFER Buff;
 
-    Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, SetScreenBufferSize->OutputHandle, &Buff, GENERIC_WRITE);
-    if (!NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-    Console = Buff->Header.Console;
+    Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetScreenBufferSize->OutputHandle, &Buff, GENERIC_WRITE);
+    if (!NT_SUCCESS(Status)) return Status;
 
-    Status = ConioResizeBuffer(Console, Buff, SetScreenBufferSize->Size);
+    Status = ConioResizeBuffer(Buff->Header.Console, Buff, SetScreenBufferSize->Size);
     ConioUnlockScreenBuffer(Buff);
 
     return Status;