[KERNEL32], [WIN32CSR] More fixes for console winetest
[reactos.git] / reactos / subsystems / win32 / csrss / win32csr / conio.c
index 4fdee22..579e4fe 100644 (file)
@@ -8,9 +8,8 @@
 
 /* INCLUDES ******************************************************************/
 
-#include "w32csr.h"
-
 #define NDEBUG
+#include "w32csr.h"
 #include <debug.h>
 
 /* GLOBALS *******************************************************************/
 #define ConioIsRectEmpty(Rect) \
   (((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom))
 
-#define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
+#define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
   WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
 
-#define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \
-  MultiByteToWideChar((Console)->CodePage, 0, (dChar), 1, (sWChar), 1)
+#define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \
+  MultiByteToWideChar((Console)->CodePage, 0, (sChar), 1, (dWChar), 1)
+
+#define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
+  WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
+
+#define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \
+  MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
 
 
 /* FUNCTIONS *****************************************************************/
 
-static NTSTATUS FASTCALL
+NTSTATUS FASTCALL
 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData, PCSRSS_CONSOLE *Console)
 {
-  if (NULL == ProcessData->Console)
+  PCSRSS_CONSOLE ProcessConsole;
+
+  RtlEnterCriticalSection(&ProcessData->HandleTableLock);
+  ProcessConsole = ProcessData->Console;
+
+  if (!ProcessConsole)
     {
       *Console = NULL;
-      return STATUS_SUCCESS;
+      RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+      return STATUS_INVALID_HANDLE;
     }
 
-  EnterCriticalSection(&(ProcessData->Console->Header.Lock));
-  *Console = ProcessData->Console;
+  InterlockedIncrement(&ProcessConsole->ReferenceCount);
+  RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+  EnterCriticalSection(&(ProcessConsole->Lock));
+  *Console = ProcessConsole;
 
   return STATUS_SUCCESS;
 }
@@ -60,7 +73,7 @@ ConioConsoleCtrlEventTimeout(DWORD Event, PCSRSS_PROCESS_DATA ProcessData, DWORD
 
       Thread = CreateRemoteThread(ProcessData->Process, NULL, 0,
                                   (LPTHREAD_START_ROUTINE) ProcessData->CtrlDispatcher,
-                                  (PVOID) Event, 0, NULL);
+                                  UlongToPtr(Event), 0, NULL);
       if (NULL == Thread)
         {
           DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
@@ -74,26 +87,26 @@ ConioConsoleCtrlEventTimeout(DWORD Event, PCSRSS_PROCESS_DATA ProcessData, DWORD
 VOID FASTCALL
 ConioConsoleCtrlEvent(DWORD Event, PCSRSS_PROCESS_DATA ProcessData)
 {
-  ConioConsoleCtrlEventTimeout(Event, ProcessData, INFINITE);
+  ConioConsoleCtrlEventTimeout(Event, ProcessData, 0);
 }
 
-#define GET_CELL_BUFFER(b,o)\
-(b)->Buffer[(o)++]
-
-#define SET_CELL_BUFFER(b,o,c,a)\
-(b)->Buffer[(o)++]=(c),\
-(b)->Buffer[(o)++]=(a)
+PBYTE FASTCALL
+ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buff, ULONG X, ULONG Y)
+{
+  return &Buff->Buffer[2 * (((Y + Buff->VirtualY) % Buff->MaxY) * Buff->MaxX + X)];
+}
 
 static VOID FASTCALL
 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff)
 {
-  DWORD Offset = 2 * (Buff->CurrentY * Buff->MaxX);
+  PBYTE Ptr = ConioCoordToPointer(Buff, 0, Buff->CurrentY);
   UINT Pos;
 
   for (Pos = 0; Pos < Buff->MaxX; Pos++)
     {
-      /* Fill the cell: Offset is incremented by the macro */
-      SET_CELL_BUFFER(Buff, Offset, ' ', Buff->DefaultAttrib);
+      /* Fill the cell */
+      *Ptr++ = ' ';
+      *Ptr++ = Buff->DefaultAttrib;
     }
 }
 
@@ -104,15 +117,16 @@ CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console,
   DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer->MaxX, Buffer->MaxY);
 
   Buffer->Header.Type = CONIO_SCREEN_BUFFER_MAGIC;
-  Buffer->Header.ReferenceCount = 0;
+  Buffer->Header.Console = Console;
+  Buffer->Header.HandleCount = 0;
   Buffer->ShowX = 0;
   Buffer->ShowY = 0;
+  Buffer->VirtualY = 0;
   Buffer->Buffer = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY, Buffer->MaxX * Buffer->MaxY * 2);
   if (NULL == Buffer->Buffer)
     {
       return STATUS_INSUFFICIENT_RESOURCES;
     }
-  InitializeCriticalSection(&Buffer->Header.Lock);
   ConioInitScreenBuffer(Console, Buffer);
   /* initialize buffer to be empty with default attributes */
   for (Buffer->CurrentY = 0 ; Buffer->CurrentY < Buffer->MaxY; Buffer->CurrentY++)
@@ -123,11 +137,12 @@ CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console,
   Buffer->CurrentX = 0;
   Buffer->CurrentY = 0;
 
+  InsertHeadList(&Console->BufferList, &Buffer->ListEntry);
   return STATUS_SUCCESS;
 }
 
-static NTSTATUS STDCALL
-CsrInitConsole(PCSRSS_CONSOLE Console)
+static NTSTATUS WINAPI
+CsrInitConsole(PCSRSS_CONSOLE Console, BOOL Visible)
 {
   NTSTATUS Status;
   SECURITY_ATTRIBUTES SecurityAttributes;
@@ -140,13 +155,15 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
   //FIXME
   RtlCreateUnicodeString(&Console->Title, L"Command Prompt");
 
-  Console->Header.ReferenceCount = 0;
+  Console->ReferenceCount = 0;
   Console->WaitingChars = 0;
   Console->WaitingLines = 0;
   Console->EchoCount = 0;
   Console->Header.Type = CONIO_CONSOLE_MAGIC;
+  Console->Header.Console = Console;
   Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
   Console->EarlyReturn = FALSE;
+  InitializeListHead(&Console->BufferList);
   Console->ActiveBuffer = NULL;
   InitializeListHead(&Console->InputEvents);
   Console->CodePage = GetOEMCP();
@@ -163,26 +180,24 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
       return STATUS_UNSUCCESSFUL;
     }
   Console->PrivateData = NULL;
-  InitializeCriticalSection(&Console->Header.Lock);
+  InitializeCriticalSection(&Console->Lock);
 
   GuiMode = DtbgIsDesktopVisible();
 
   /* allocate console screen buffer */
   NewBuffer = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_SCREEN_BUFFER));
-  /* init screen buffer with defaults */
-  NewBuffer->CursorInfo.bVisible = TRUE;
-  NewBuffer->CursorInfo.dwSize = 5;
-  /* make console active, and insert into console list */
-  Console->ActiveBuffer = (PCSRSS_SCREEN_BUFFER) NewBuffer;
-  /* add a reference count because the buffer is tied to the console */
-  InterlockedIncrement(&Console->ActiveBuffer->Header.ReferenceCount);
   if (NULL == NewBuffer)
     {
       RtlFreeUnicodeString(&Console->Title);
-      DeleteCriticalSection(&Console->Header.Lock);
+      DeleteCriticalSection(&Console->Lock);
       CloseHandle(Console->ActiveEvent);
       return STATUS_INSUFFICIENT_RESOURCES;
     }
+  /* init screen buffer with defaults */
+  NewBuffer->CursorInfo.bVisible = TRUE;
+  NewBuffer->CursorInfo.dwSize = CSR_DEFAULT_CURSOR_SIZE;
+  /* make console active, and insert into console list */
+  Console->ActiveBuffer = (PCSRSS_SCREEN_BUFFER) NewBuffer;
 
   if (! GuiMode)
     {
@@ -195,12 +210,12 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
     }
   if (GuiMode)
     {
-      Status = GuiInitConsole(Console);
+      Status = GuiInitConsole(Console, Visible);
       if (! NT_SUCCESS(Status))
         {
           HeapFree(Win32CsrApiHeap,0, NewBuffer);
           RtlFreeUnicodeString(&Console->Title);
-          DeleteCriticalSection(&Console->Header.Lock);
+          DeleteCriticalSection(&Console->Lock);
           CloseHandle(Console->ActiveEvent);
           DPRINT1("GuiInitConsole: failed\n");
           return Status;
@@ -212,14 +227,13 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
     {
       ConioCleanupConsole(Console);
       RtlFreeUnicodeString(&Console->Title);
-      DeleteCriticalSection(&Console->Header.Lock);
+      DeleteCriticalSection(&Console->Lock);
       CloseHandle(Console->ActiveEvent);
       HeapFree(Win32CsrApiHeap, 0, NewBuffer);
       DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
       return Status;
     }
 
-
   /* copy buffer contents to screen */
   ConioDrawConsole(Console);
 
@@ -238,26 +252,19 @@ CSR_API(CsrAllocConsole)
     Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
     Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
-    if (ProcessData == NULL)
-    {
-        DPRINT1("No process data\n");
-        return Request->Status = STATUS_INVALID_PARAMETER;
-    }
-
+    RtlEnterCriticalSection(&ProcessData->HandleTableLock);
     if (ProcessData->Console)
     {
         DPRINT1("Process already has a console\n");
-        Request->Status = STATUS_INVALID_PARAMETER;
+        RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
         return STATUS_INVALID_PARAMETER;
     }
 
-    /* Assume success */
-    Request->Status = STATUS_SUCCESS;
-
     /* If we don't need a console, then get out of here */
     if (!Request->Data.AllocConsoleRequest.ConsoleNeeded)
     {
         DPRINT("No console needed\n");
+        RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
         return STATUS_SUCCESS;
     }
 
@@ -271,7 +278,7 @@ CSR_API(CsrAllocConsole)
         if (NULL == Console)
         {
             DPRINT1("Not enough memory for console\n");
-            Request->Status = STATUS_NO_MEMORY;
+            RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
             return STATUS_NO_MEMORY;
         }
         /* initialize list head */
@@ -279,12 +286,13 @@ CSR_API(CsrAllocConsole)
         /* insert process data required for GUI initialization */
         InsertHeadList(&Console->ProcessList, &ProcessData->ProcessEntry);
         /* Initialize the Console */
-        Request->Status = CsrInitConsole(Console);
-        if (!NT_SUCCESS(Request->Status))
+        Status = CsrInitConsole(Console, Request->Data.AllocConsoleRequest.Visible);
+        if (!NT_SUCCESS(Status))
         {
             DPRINT1("Console init failed\n");
             HeapFree(Win32CsrApiHeap, 0, Console);
-            return Request->Status;
+            RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+            return Status;
         }
     }
     else
@@ -300,25 +308,32 @@ CSR_API(CsrAllocConsole)
     Request->Data.AllocConsoleRequest.Console = Console;
 
     /* Add a reference count because the process is tied to the console */
-    Console->Header.ReferenceCount++;
+    _InterlockedIncrement(&Console->ReferenceCount);
 
     if (NewConsole || !ProcessData->bInheritHandles)
     {
         /* Insert the Objects */
         Status = Win32CsrInsertObject(ProcessData,
                                       &Request->Data.AllocConsoleRequest.InputHandle,
-                                      &Console->Header);
+                                      &Console->Header,
+                                      GENERIC_READ | GENERIC_WRITE,
+                                      TRUE,
+                                      FILE_SHARE_READ | FILE_SHARE_WRITE);
         if (! NT_SUCCESS(Status))
         {
             DPRINT1("Failed to insert object\n");
             ConioDeleteConsole((Object_t *) Console);
             ProcessData->Console = 0;
-            return Request->Status = Status;
+            RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+            return Status;
         }
 
         Status = Win32CsrInsertObject(ProcessData,
                                       &Request->Data.AllocConsoleRequest.OutputHandle,
-                                      &Console->ActiveBuffer->Header);
+                                      &Console->ActiveBuffer->Header,
+                                      GENERIC_READ | GENERIC_WRITE,
+                                      TRUE,
+                                      FILE_SHARE_READ | FILE_SHARE_WRITE);
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("Failed to insert object\n");
@@ -326,7 +341,8 @@ CSR_API(CsrAllocConsole)
             Win32CsrReleaseObject(ProcessData,
                                   Request->Data.AllocConsoleRequest.InputHandle);
             ProcessData->Console = 0;
-            return Request->Status = Status;
+            RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+            return Status;
         }
     }
 
@@ -349,7 +365,8 @@ CSR_API(CsrAllocConsole)
                                   Request->Data.AllocConsoleRequest.InputHandle);
         }
         ProcessData->Console = 0;
-        return Request->Status = Status;
+        RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+        return Status;
     }
 
     /* Set the Ctrl Dispatcher */
@@ -362,57 +379,38 @@ CSR_API(CsrAllocConsole)
         InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ProcessEntry);
     }
 
+    RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
     return STATUS_SUCCESS;
 }
 
 CSR_API(CsrFreeConsole)
 {
-  PCSRSS_CONSOLE Console;
-
-
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
-  if (ProcessData == NULL || ProcessData->Console == NULL)
-    {
-      return Request->Status = STATUS_INVALID_PARAMETER;
-    }
-
-  Console = ProcessData->Console;
-  ProcessData->Console = NULL;
-  if (0 == InterlockedDecrement(&Console->Header.ReferenceCount))
-    {
-      ConioDeleteConsole((Object_t *) Console);
-    }
-  return STATUS_SUCCESS;
+  return Win32CsrReleaseConsole(ProcessData);
 }
 
 static VOID FASTCALL
 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff, RECT *UpdateRect, UINT *ScrolledLines)
 {
-  /* slide the viewable screen */
-  if (((Buff->CurrentY - Buff->ShowY + Buff->MaxY) % Buff->MaxY) == (ULONG)Buff->MaxY - 1)
+  /* If we hit bottom, slide the viewable screen */
+  if (++Buff->CurrentY == Buff->MaxY)
     {
-      if (++Buff->ShowY == Buff->MaxY)
+      Buff->CurrentY--;
+      if (++Buff->VirtualY == Buff->MaxY)
         {
-          Buff->ShowY = 0;
+          Buff->VirtualY = 0;
         }
       (*ScrolledLines)++;
-    }
-  if (++Buff->CurrentY == Buff->MaxY)
-    {
-      Buff->CurrentY = 0;
-    }
-  ClearLineBuffer(Buff);
-  UpdateRect->left = 0;
-  UpdateRect->right = Buff->MaxX - 1;
-  if (UpdateRect->top == (LONG)Buff->CurrentY)
-    {
-      if (++UpdateRect->top == Buff->MaxY)
+      ClearLineBuffer(Buff);
+      if (UpdateRect->top != 0)
         {
-          UpdateRect->top = 0;
+          UpdateRect->top--;
         }
     }
+  UpdateRect->left = 0;
+  UpdateRect->right = Buff->MaxX - 1;
   UpdateRect->bottom = Buff->CurrentY;
 }
 
@@ -421,12 +419,13 @@ ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
                   CHAR *Buffer, DWORD Length, BOOL Attrib)
 {
   UINT i;
-  DWORD Offset;
+  PBYTE Ptr;
   RECT UpdateRect;
   LONG CursorStartX, CursorStartY;
   UINT ScrolledLines;
 
-  ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, &CursorStartX, &CursorStartY);
+  CursorStartX = Buff->CurrentX;
+  CursorStartY = Buff->CurrentY;
   UpdateRect.left = Buff->MaxX;
   UpdateRect.top = Buff->CurrentY;
   UpdateRect.right = -1;
@@ -448,32 +447,22 @@ ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
           else if (Buffer[i] == '\b')
             {
               /* Only handle BS if we're not on the first pos of the first line */
-              if (0 != Buff->CurrentX || Buff->ShowY != Buff->CurrentY)
+              if (0 != Buff->CurrentX || 0 != Buff->CurrentY)
                 {
                   if (0 == Buff->CurrentX)
                     {
                       /* slide virtual position up */
                       Buff->CurrentX = Buff->MaxX - 1;
-                      if (0 == Buff->CurrentY)
-                        {
-                          Buff->CurrentY = Buff->MaxY;
-                        }
-                      else
-                        {
-                          Buff->CurrentY--;
-                        }
-                      if ((0 == UpdateRect.top && UpdateRect.bottom < (LONG)Buff->CurrentY)
-                          || (0 != UpdateRect.top && (LONG)Buff->CurrentY < UpdateRect.top))
-                        {
-                          UpdateRect.top = Buff->CurrentY;
-                        }
+                      Buff->CurrentY--;
+                      UpdateRect.top = min(UpdateRect.top, (LONG)Buff->CurrentY);
                     }
                   else
                     {
-                       Buff->CurrentX--;
+                      Buff->CurrentX--;
                     }
-                  Offset = 2 * ((Buff->CurrentY * Buff->MaxX) + Buff->CurrentX);
-                  SET_CELL_BUFFER(Buff, Offset, ' ', Buff->DefaultAttrib);
+                  Ptr = ConioCoordToPointer(Buff, Buff->CurrentX, Buff->CurrentY);
+                  Ptr[0] = ' ';
+                  Ptr[1] = Buff->DefaultAttrib;
                   UpdateRect.left = min(UpdateRect.left, (LONG) Buff->CurrentX);
                   UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX);
                 }
@@ -498,11 +487,11 @@ ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
                 {
                   EndX = Buff->MaxX;
                 }
-              Offset = 2 * (((Buff->CurrentY * Buff->MaxX)) + Buff->CurrentX);
+              Ptr = ConioCoordToPointer(Buff, Buff->CurrentX, Buff->CurrentY);
               while (Buff->CurrentX < EndX)
                 {
-                  Buff->Buffer[Offset] = ' ';
-                  Offset += 2;
+                  *Ptr++ = ' ';
+                  *Ptr++ = Buff->DefaultAttrib;
                   Buff->CurrentX++;
                 }
               UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX - 1);
@@ -523,11 +512,11 @@ ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
         }
       UpdateRect.left = min(UpdateRect.left, (LONG)Buff->CurrentX);
       UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX);
-      Offset = 2 * (((Buff->CurrentY * Buff->MaxX)) + Buff->CurrentX);
-      Buff->Buffer[Offset++] = Buffer[i];
+      Ptr = ConioCoordToPointer(Buff, Buff->CurrentX, Buff->CurrentY);
+      Ptr[0] = Buffer[i];
       if (Attrib)
         {
-          Buff->Buffer[Offset] = Buff->DefaultAttrib;
+          Ptr[1] = Buff->DefaultAttrib;
         }
       Buff->CurrentX++;
       if (Buff->CurrentX == Buff->MaxX)
@@ -544,11 +533,7 @@ ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
         }
     }
 
-  ConioPhysicalToLogical(Buff, UpdateRect.left, UpdateRect.top, &(UpdateRect.left),
-                         &(UpdateRect.top));
-  ConioPhysicalToLogical(Buff, UpdateRect.right, UpdateRect.bottom, &(UpdateRect.right),
-                         &(UpdateRect.bottom));
-  if (! ConioIsRectEmpty(&UpdateRect) && NULL != Console && Buff == Console->ActiveBuffer)
+  if (! ConioIsRectEmpty(&UpdateRect) && Buff == Console->ActiveBuffer)
     {
       ConioWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY, ScrolledLines,
                        Buffer, Length);
@@ -580,10 +565,10 @@ CSR_API(CsrReadConsole)
   Buffer = Request->Data.ReadConsoleRequest.Buffer;
   UnicodeBuffer = (PWCHAR)Buffer;
   Status = ConioLockConsole(ProcessData, Request->Data.ReadConsoleRequest.ConsoleHandle,
-                               &Console);
+                               &Console, GENERIC_READ);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
   Request->Data.ReadConsoleRequest.EventHandle = ProcessData->ConsoleEvent;
   for (i = 0; i < nNumberOfCharsToRead && Console->InputEvents.Flink != &Console->InputEvents; i++)
@@ -592,7 +577,6 @@ CSR_API(CsrReadConsole)
       CurrentEntry = RemoveHeadList(&Console->InputEvents);
       if (IsListEmpty(&Console->InputEvents))
       {
-         CHECKPOINT;
          ResetEvent(Console->ActiveEvent);
       }
       Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
@@ -604,9 +588,9 @@ CSR_API(CsrReadConsole)
         {
           /*
            * backspace handling - if we are in charge of echoing it then we handle it here
-           * otherwise we treat it like a normal char. 
+           * otherwise we treat it like a normal char.
            */
-          if ('\b' == Input->InputEvent.Event.KeyEvent.uChar.AsciiChar && 0 
+          if ('\b' == Input->InputEvent.Event.KeyEvent.uChar.AsciiChar && 0
               != (Console->Mode & ENABLE_ECHO_INPUT))
             {
               /* echo if it has not already been done, and either we or the client has chars to be deleted */
@@ -626,9 +610,8 @@ CSR_API(CsrReadConsole)
                   ConioUnlockConsole(Console);
                   HeapFree(Win32CsrApiHeap, 0, Input);
                   Request->Data.ReadConsoleRequest.NrCharactersRead = 0;
-                  Request->Status = STATUS_NOTIFY_CLEANUP;
                   return STATUS_NOTIFY_CLEANUP;
-                  
+
                 }
               Request->Data.ReadConsoleRequest.nCharsCanBeDeleted--;
               Input->Echoed = TRUE;   /* mark as echoed so we don't echo it below */
@@ -637,7 +620,7 @@ CSR_API(CsrReadConsole)
           else
             {
               if(Request->Data.ReadConsoleRequest.Unicode)
-                UnicodeBuffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar; /* FIXME */
+                ConsoleInputAnsiCharToUnicodeChar(Console, &UnicodeBuffer[i], &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar);
               else
                 Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar;
             }
@@ -660,27 +643,27 @@ CSR_API(CsrReadConsole)
   Request->Data.ReadConsoleRequest.NrCharactersRead = i;
   if (0 == i)
     {
-      Request->Status = STATUS_PENDING;    /* we didn't read anything */
+      Status = STATUS_PENDING;    /* we didn't read anything */
     }
   else if (0 != (Console->Mode & ENABLE_LINE_INPUT))
     {
       if (0 == Console->WaitingLines ||
           (Request->Data.ReadConsoleRequest.Unicode ? (L'\n' != UnicodeBuffer[i - 1]) : ('\n' != Buffer[i - 1])))
         {
-          Request->Status = STATUS_PENDING; /* line buffered, didn't get a complete line */
+          Status = STATUS_PENDING; /* line buffered, didn't get a complete line */
         }
       else
         {
           Console->WaitingLines--;
-          Request->Status = STATUS_SUCCESS; /* line buffered, did get a complete line */
+          Status = STATUS_SUCCESS; /* line buffered, did get a complete line */
         }
     }
   else
     {
-      Request->Status = STATUS_SUCCESS;  /* not line buffered, did read something */
+      Status = STATUS_SUCCESS;  /* not line buffered, did read something */
     }
 
-  if (Request->Status == STATUS_PENDING)
+  if (Status == STATUS_PENDING)
     {
       Console->EchoCount = nNumberOfCharsToRead - i;
     }
@@ -697,36 +680,10 @@ CSR_API(CsrReadConsole)
       Request->Header.u1.s1.DataLength = Request->Header.u1.s1.TotalLength - sizeof(PORT_MESSAGE);
     }
 
-  return Request->Status;
-}
-
-VOID FASTCALL
-ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff,
-                       ULONG PhysicalX,
-                       ULONG PhysicalY,
-                       LONG *LogicalX,
-                       LONG *LogicalY)
-{
-   *LogicalX = PhysicalX;
-   if (PhysicalY < Buff->ShowY)
-     {
-       *LogicalY = Buff->MaxY - Buff->ShowY + PhysicalY;
-     }
-   else
-     {
-       *LogicalY = PhysicalY - Buff->ShowY;
-     }
-}
-
-BOOLEAN __inline ConioIsEqualRect(
-  RECT *Rect1,
-  RECT *Rect2)
-{
-  return ((Rect1->left == Rect2->left) && (Rect1->right == Rect2->right) &&
-    (Rect1->top == Rect2->top) && (Rect1->bottom == Rect2->bottom));
+  return Status;
 }
 
-BOOLEAN __inline ConioGetIntersection(
+__inline BOOLEAN ConioGetIntersection(
   RECT *Intersection,
   RECT *Rect1,
   RECT *Rect2)
@@ -752,7 +709,7 @@ BOOLEAN __inline ConioGetIntersection(
   return TRUE;
 }
 
-BOOLEAN __inline ConioGetUnion(
+__inline BOOLEAN ConioGetUnion(
   RECT *Union,
   RECT *Rect1,
   RECT *Rect2)
@@ -785,138 +742,65 @@ BOOLEAN __inline ConioGetUnion(
   return TRUE;
 }
 
-BOOLEAN __inline ConioSubtractRect(
-  RECT *Subtraction,
-  RECT *Rect1,
-  RECT *Rect2)
+/* 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,
+                RECT *SrcRegion,
+                RECT *DstRegion,
+                RECT *ClipRegion,
+                WORD Fill)
 {
-  RECT tmp;
-
-  if (ConioIsRectEmpty(Rect1))
-    {
-      ConioInitRect(Subtraction, 0, -1, 0, -1);
-      return FALSE;
-    }
-  *Subtraction = *Rect1;
-  if (ConioGetIntersection(&tmp, Rect1, Rect2))
-    {
-      if (ConioIsEqualRect(&tmp, Subtraction))
-        {
-          ConioInitRect(Subtraction, 0, -1, 0, -1);
-          return FALSE;
-        }
-      if ((tmp.top == Subtraction->top) && (tmp.bottom == Subtraction->bottom))
-        {
-          if (tmp.left == Subtraction->left)
-            {
-              Subtraction->left = tmp.right;
-            }
-          else if (tmp.right == Subtraction->right)
+  int Width = ConioRectWidth(SrcRegion);
+  int Height = ConioRectHeight(SrcRegion);
+  int SX, SY;
+  int DX, DY;
+  int XDelta, YDelta;
+  int i, j;
+
+  SY = SrcRegion->top;
+  DY = DstRegion->top;
+  YDelta = 1;
+  if (SY < DY)
+    {
+      /* Moving down: work from bottom up */
+      SY = SrcRegion->bottom;
+      DY = DstRegion->bottom;
+      YDelta = -1;
+    }
+  for (i = 0; i < Height; i++)
+    {
+      PWORD SRow = (PWORD)ConioCoordToPointer(ScreenBuffer, 0, SY);
+      PWORD DRow = (PWORD)ConioCoordToPointer(ScreenBuffer, 0, DY);
+
+      SX = SrcRegion->left;
+      DX = DstRegion->left;
+      XDelta = 1;
+      if (SX < DX)
+        {
+          /* Moving right: work from right to left */
+          SX = SrcRegion->right;
+          DX = DstRegion->right;
+          XDelta = -1;
+        }
+      for (j = 0; j < Width; j++)
+        {
+          WORD Cell = SRow[SX];
+          if (SX >= ClipRegion->left && SX <= ClipRegion->right
+              && SY >= ClipRegion->top && SY <= ClipRegion->bottom)
             {
-              Subtraction->right = tmp.left;
+              SRow[SX] = Fill;
             }
-        }
-      else if ((tmp.left == Subtraction->left) && (tmp.right == Subtraction->right))
-        {
-          if (tmp.top == Subtraction->top)
-            {
-              Subtraction->top = tmp.bottom;
-            }
-          else if (tmp.bottom == Subtraction->bottom)
+          if (DX >= ClipRegion->left && DX <= ClipRegion->right
+              && DY >= ClipRegion->top && DY <= ClipRegion->bottom)
             {
-              Subtraction->bottom = tmp.top;
+              DRow[DX] = Cell;
             }
+          SX += XDelta;
+          DX += XDelta;
         }
-    }
-
-  return TRUE;
-}
-
-static VOID FASTCALL
-ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer,
-                RECT *SrcRegion,
-                RECT *DstRegion)
-{
-  SHORT SrcY, DstY;
-  DWORD SrcOffset;
-  DWORD DstOffset;
-  DWORD BytesPerLine;
-  LONG i;
-
-  DstY = DstRegion->top;
-  BytesPerLine = ConioRectWidth(DstRegion) * 2;
-
-  SrcY = (SrcRegion->top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
-  DstY = (DstRegion->top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
-  SrcOffset = (SrcY * ScreenBuffer->MaxX + SrcRegion->left + ScreenBuffer->ShowX) * 2;
-  DstOffset = (DstY * ScreenBuffer->MaxX + DstRegion->left + ScreenBuffer->ShowX) * 2;
-
-  for (i = SrcRegion->top; i <= SrcRegion->bottom; i++)
-    {
-      RtlCopyMemory(
-        &ScreenBuffer->Buffer[DstOffset],
-        &ScreenBuffer->Buffer[SrcOffset],
-        BytesPerLine);
-
-      if (++DstY == ScreenBuffer->MaxY)
-        {
-          DstY = 0;
-          DstOffset = (DstRegion->left + ScreenBuffer->ShowX) * 2;
-        }
-      else
-        {
-          DstOffset += ScreenBuffer->MaxX * 2;
-        }
-
-      if (++SrcY == ScreenBuffer->MaxY)
-        {
-          SrcY = 0;
-          SrcOffset = (SrcRegion->left + ScreenBuffer->ShowX) * 2;
-        }
-      else
-        {
-          SrcOffset += ScreenBuffer->MaxX * 2;
-        }
-    }
-}
-
-static VOID FASTCALL
-ConioFillRegion(PCSRSS_CONSOLE Console,
-                PCSRSS_SCREEN_BUFFER ScreenBuffer,
-                RECT *Region,
-                CHAR_INFO *CharInfo,
-                BOOL bUnicode)
-{
-  SHORT X, Y;
-  DWORD Offset;
-  DWORD Delta;
-  LONG i;
-  CHAR Char;
-
-  if(bUnicode)
-    ConsoleUnicodeCharToAnsiChar(Console, &Char, &CharInfo->Char.UnicodeChar);
-  else
-    Char = CharInfo->Char.AsciiChar;
-
-  Y = (Region->top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
-  Offset = (Y * ScreenBuffer->MaxX + Region->left + ScreenBuffer->ShowX) * 2;
-  Delta = (ScreenBuffer->MaxX - ConioRectWidth(Region)) * 2;
-
-  for (i = Region->top; i <= Region->bottom; i++)
-    {
-      for (X = Region->left; X <= Region->right; X++)
-        {
-          SET_CELL_BUFFER(ScreenBuffer, Offset, Char, CharInfo->Attributes);
-        }
-      if (++Y == ScreenBuffer->MaxY)
-        {
-          Y = 0;
-          Offset = (Region->left + ScreenBuffer->ShowX) * 2;
-        }
-      else
-        {
-          Offset += Delta;
-        }
+      SY += YDelta;
+      DY += YDelta;
     }
 }
 
@@ -927,9 +811,9 @@ ConioInputEventToAnsi(PCSRSS_CONSOLE Console, PINPUT_RECORD InputEvent)
     {
       WCHAR UnicodeChar = InputEvent->Event.KeyEvent.uChar.UnicodeChar;
       InputEvent->Event.KeyEvent.uChar.UnicodeChar = 0;
-      ConsoleUnicodeCharToAnsiChar(Console,
-                                   &InputEvent->Event.KeyEvent.uChar.AsciiChar,
-                                   &UnicodeChar);
+      ConsoleInputUnicodeCharToAnsiChar(Console,
+                                        &InputEvent->Event.KeyEvent.uChar.AsciiChar,
+                                        &UnicodeChar);
     }
 }
 
@@ -952,28 +836,29 @@ CSR_API(CsrWriteConsole)
       DPRINT1("Invalid request size\n");
       Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
       Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
-      return Request->Status = STATUS_INVALID_PARAMETER;
+      return STATUS_INVALID_PARAMETER;
     }
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
 
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
+  Status = ConioLockScreenBuffer(ProcessData, Request->Data.WriteConsoleRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
+  Console = Buff->Header.Console;
 
   if(Request->Data.WriteConsoleRequest.Unicode)
     {
-      Length = WideCharToMultiByte(Console->CodePage, 0,
+      Length = WideCharToMultiByte(Console->OutputCodePage, 0,
                                    (PWCHAR)Request->Data.WriteConsoleRequest.Buffer,
                                    Request->Data.WriteConsoleRequest.NrCharactersToWrite,
                                    NULL, 0, NULL, NULL);
       Buffer = RtlAllocateHeap(GetProcessHeap(), 0, Length);
       if (Buffer)
         {
-          WideCharToMultiByte(Console->CodePage, 0,
+          WideCharToMultiByte(Console->OutputCodePage, 0,
                               (PWCHAR)Request->Data.WriteConsoleRequest.Buffer,
                               Request->Data.WriteConsoleRequest.NrCharactersToWrite,
                               Buffer, Length, NULL, NULL);
@@ -990,39 +875,46 @@ CSR_API(CsrWriteConsole)
 
   if (Buffer)
     {
-      Status = ConioLockScreenBuffer(ProcessData, Request->Data.WriteConsoleRequest.ConsoleHandle, &Buff);
       if (NT_SUCCESS(Status))
         {
-          Request->Status = ConioWriteConsole(Console, Buff, Buffer,
-                                              Request->Data.WriteConsoleRequest.NrCharactersToWrite, TRUE);
+          Status = ConioWriteConsole(Console, Buff, Buffer,
+                                     Request->Data.WriteConsoleRequest.NrCharactersToWrite, TRUE);
           if (NT_SUCCESS(Status))
             {
               Written = Request->Data.WriteConsoleRequest.NrCharactersToWrite;
             }
-          ConioUnlockScreenBuffer(Buff);
         }
       if (Request->Data.WriteConsoleRequest.Unicode)
         {
           RtlFreeHeap(GetProcessHeap(), 0, Buffer);
         }
     }
-  if (NULL != Console)
-    {
-      ConioUnlockConsole(Console);
-    }
+  ConioUnlockScreenBuffer(Buff);
 
   Request->Data.WriteConsoleRequest.NrCharactersWritten = Written;
 
-  return Request->Status = Status;
+  return Status;
 }
 
-VOID STDCALL
-ConioDeleteScreenBuffer(Object_t *Object)
+VOID WINAPI
+ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer)
 {
-  PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER) Object;
-  DeleteCriticalSection(&Buffer->Header.Lock);
-  HeapFree(Win32CsrApiHeap, 0, Buffer->Buffer);
-  HeapFree(Win32CsrApiHeap, 0, Buffer);
+    PCSRSS_CONSOLE Console = Buffer->Header.Console;
+
+    RemoveEntryList(&Buffer->ListEntry);
+    if (Buffer == Console->ActiveBuffer)
+    {
+        /* Deleted active buffer; switch to most recently created */
+        Console->ActiveBuffer = NULL;
+        if (!IsListEmpty(&Console->BufferList))
+        {
+            Console->ActiveBuffer = CONTAINING_RECORD(Console->BufferList.Flink, CSRSS_SCREEN_BUFFER, ListEntry);
+            ConioDrawConsole(Console);
+        }
+    }
+
+    HeapFree(Win32CsrApiHeap, 0, Buffer->Buffer);
+    HeapFree(Win32CsrApiHeap, 0, Buffer);
 }
 
 VOID FASTCALL
@@ -1036,7 +928,7 @@ ConioDrawConsole(PCSRSS_CONSOLE Console)
 }
 
 
-VOID STDCALL
+VOID WINAPI
 ConioDeleteConsole(Object_t *Object)
 {
   PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) Object;
@@ -1053,23 +945,21 @@ ConioDeleteConsole(Object_t *Object)
       HeapFree(Win32CsrApiHeap, 0, Event);
     }
 
-#if 0 // FIXME
-  if (0 == InterlockedDecrement(&Console->ActiveBuffer->Header.ReferenceCount))
+  ConioCleanupConsole(Console);
+  ConioDeleteScreenBuffer(Console->ActiveBuffer);
+  if (!IsListEmpty(&Console->BufferList))
     {
-      ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer);
+      DPRINT1("BUG: screen buffer list not empty\n");
     }
-#endif
-
-  Console->ActiveBuffer = NULL;
-  ConioCleanupConsole(Console);
 
   CloseHandle(Console->ActiveEvent);
-  DeleteCriticalSection(&Console->Header.Lock);
+  DeleteCriticalSection(&Console->Lock);
   RtlFreeUnicodeString(&Console->Title);
+  IntDeleteAllAliases(Console->Aliases);
   HeapFree(Win32CsrApiHeap, 0, Console);
 }
 
-VOID STDCALL
+VOID WINAPI
 CsrInitConsoleSupport(VOID)
 {
   DPRINT("CSR: CsrInitConsoleSupport()\n");
@@ -1082,82 +972,8 @@ ConioProcessChar(PCSRSS_CONSOLE Console,
                  ConsoleInput *KeyEventRecord)
 {
   BOOL updown;
-  BOOL bClientWake = FALSE;
   ConsoleInput *TempInput;
 
-  /* process Ctrl-C and Ctrl-Break */
-  if (Console->Mode & ENABLE_PROCESSED_INPUT &&
-      KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown &&
-      ((KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE) ||
-       (KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == 'C')) &&
-      (KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)))
-    {
-      PCSRSS_PROCESS_DATA current;
-      PLIST_ENTRY current_entry;
-      DPRINT1("Console_Api Ctrl-C\n");
-      current_entry = Console->ProcessList.Flink;
-      while (current_entry != &Console->ProcessList)
-      {
-        current = CONTAINING_RECORD(current_entry, CSRSS_PROCESS_DATA, ProcessEntry);
-        current_entry = current_entry->Flink;
-        ConioConsoleCtrlEvent((DWORD)CTRL_C_EVENT, current);
-      }
-      HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
-      return;
-    }
-
-  if (0 != (KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState
-            & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
-      && (VK_UP == KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode
-          || VK_DOWN == KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode))
-    {
-      if (KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown)
-        {
-          /* scroll up or down */
-          if (NULL == Console)
-            {
-              DPRINT1("No Active Console!\n");
-              HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
-              return;
-            }
-          if (VK_UP == KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode)
-            {
-              /* only scroll up if there is room to scroll up into */
-              if (Console->ActiveBuffer->ShowY != ((Console->ActiveBuffer->CurrentY + 1) %
-                                                     Console->ActiveBuffer->MaxY))
-                {
-                  Console->ActiveBuffer->ShowY = (Console->ActiveBuffer->ShowY +
-                                                  Console->ActiveBuffer->MaxY - 1) %
-                                                 Console->ActiveBuffer->MaxY;
-                }
-            }
-          else if (Console->ActiveBuffer->ShowY != Console->ActiveBuffer->CurrentY)
-            /* only scroll down if there is room to scroll down into */
-            {
-              if (Console->ActiveBuffer->ShowY % Console->ActiveBuffer->MaxY !=
-                  Console->ActiveBuffer->CurrentY)
-                {
-                  if (((Console->ActiveBuffer->CurrentY + 1) % Console->ActiveBuffer->MaxY) !=
-                      (Console->ActiveBuffer->ShowY + Console->ActiveBuffer->MaxY) %
-                      Console->ActiveBuffer->MaxY)
-                    {
-                      Console->ActiveBuffer->ShowY = (Console->ActiveBuffer->ShowY + 1) %
-                                                     Console->ActiveBuffer->MaxY;
-                    }
-                }
-            }
-          ConioDrawConsole(Console);
-        }
-      HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
-      return;
-    }
-  if (NULL == Console)
-    {
-      DPRINT1("No Active Console!\n");
-      HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
-      return;
-    }
-
   if (0 != (Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT)))
     {
       switch(KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar)
@@ -1199,8 +1015,6 @@ ConioProcessChar(PCSRSS_CONSOLE Console,
         {
           Console->WaitingLines++;
         }
-      bClientWake = TRUE;
-      SetEvent(Console->ActiveEvent);
     }
   KeyEventRecord->Echoed = FALSE;
   if (0 != (Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT))
@@ -1232,10 +1046,7 @@ ConioProcessChar(PCSRSS_CONSOLE Console,
           RemoveEntryList(&KeyEventRecord->ListEntry);
           HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
           Console->WaitingChars -= 2;
-        }
-      else
-        {
-          SetEvent(Console->ActiveEvent);
+          return;
         }
     }
   else
@@ -1256,10 +1067,7 @@ ConioProcessChar(PCSRSS_CONSOLE Console,
     }
 
   /* Console->WaitingChars++; */
-  if (bClientWake || 0 == (Console->Mode & ENABLE_LINE_INPUT))
-    {
-      SetEvent(Console->ActiveEvent);
-    }
+  SetEvent(Console->ActiveEvent);
 }
 
 static DWORD FASTCALL
@@ -1292,7 +1100,7 @@ ConioGetShiftState(PBYTE KeyState)
   return ssOut;
 }
 
-VOID STDCALL
+VOID WINAPI
 ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode)
 {
   static BYTE KeyState[256] = { 0 };
@@ -1376,6 +1184,7 @@ ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode)
 
   if (NULL == Console)
     {
+      DPRINT1("No Active Console!\n");
       return;
     }
 
@@ -1406,20 +1215,75 @@ ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode)
     (AsciiChar >= ' ') ? AsciiChar : '.',
     ShiftState);
 
-  if (! ConInRec->Fake || ! ConInRec->NotChar)
+  if (ConInRec->Fake && ConInRec->NotChar)
     {
-      /* FIXME - convert to ascii */
-      ConioProcessChar(Console, ConInRec);
+      HeapFree(Win32CsrApiHeap, 0, ConInRec);
+      return;
     }
-  else
+
+  /* process Ctrl-C and Ctrl-Break */
+  if (Console->Mode & ENABLE_PROCESSED_INPUT &&
+      er.Event.KeyEvent.bKeyDown &&
+      ((er.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE) ||
+       (er.Event.KeyEvent.wVirtualKeyCode == 'C')) &&
+      (er.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)))
     {
+      PCSRSS_PROCESS_DATA current;
+      PLIST_ENTRY current_entry;
+      DPRINT1("Console_Api Ctrl-C\n");
+      current_entry = Console->ProcessList.Flink;
+      while (current_entry != &Console->ProcessList)
+      {
+        current = CONTAINING_RECORD(current_entry, CSRSS_PROCESS_DATA, ProcessEntry);
+        current_entry = current_entry->Flink;
+        ConioConsoleCtrlEvent((DWORD)CTRL_C_EVENT, current);
+      }
       HeapFree(Win32CsrApiHeap, 0, ConInRec);
+      return;
     }
+
+  if (0 != (er.Event.KeyEvent.dwControlKeyState
+            & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
+      && (VK_UP == er.Event.KeyEvent.wVirtualKeyCode
+          || VK_DOWN == er.Event.KeyEvent.wVirtualKeyCode))
+    {
+      if (er.Event.KeyEvent.bKeyDown)
+        {
+          /* scroll up or down */
+          if (VK_UP == er.Event.KeyEvent.wVirtualKeyCode)
+            {
+              /* only scroll up if there is room to scroll up into */
+              if (Console->ActiveBuffer->CurrentY != Console->ActiveBuffer->MaxY - 1)
+                {
+                  Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY +
+                                                     Console->ActiveBuffer->MaxY - 1) %
+                                                    Console->ActiveBuffer->MaxY;
+                  Console->ActiveBuffer->CurrentY++;
+                }
+            }
+          else
+            {
+              /* only scroll down if there is room to scroll down into */
+              if (Console->ActiveBuffer->CurrentY != 0)
+                {
+                  Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 1) %
+                                                    Console->ActiveBuffer->MaxY;
+                  Console->ActiveBuffer->CurrentY--;
+                }
+            }
+          ConioDrawConsole(Console);
+        }
+      HeapFree(Win32CsrApiHeap, 0, ConInRec);
+      return;
+    }
+  /* FIXME - convert to ascii */
+  ConioProcessChar(Console, ConInRec);
 }
 
 CSR_API(CsrGetScreenBufferInfo)
 {
   NTSTATUS Status;
+  PCSRSS_CONSOLE Console;
   PCSRSS_SCREEN_BUFFER Buff;
   PCONSOLE_SCREEN_BUFFER_INFO pInfo;
 
@@ -1428,28 +1292,27 @@ CSR_API(CsrGetScreenBufferInfo)
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
-  Status = ConioLockScreenBuffer(ProcessData, Request->Data.ScreenBufferInfoRequest.ConsoleHandle, &Buff);
+  Status = ConioLockScreenBuffer(ProcessData, Request->Data.ScreenBufferInfoRequest.ConsoleHandle, &Buff, GENERIC_READ);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
+  Console = Buff->Header.Console;
   pInfo = &Request->Data.ScreenBufferInfoRequest.Info;
   pInfo->dwSize.X = Buff->MaxX;
   pInfo->dwSize.Y = Buff->MaxY;
-  pInfo->dwCursorPosition.X = Buff->CurrentX - Buff->ShowX;
-  pInfo->dwCursorPosition.Y = (Buff->CurrentY + Buff->MaxY - Buff->ShowY) % Buff->MaxY;
+  pInfo->dwCursorPosition.X = Buff->CurrentX;
+  pInfo->dwCursorPosition.Y = Buff->CurrentY;
   pInfo->wAttributes = Buff->DefaultAttrib;
-  pInfo->srWindow.Left = 0;
-  pInfo->srWindow.Right = Buff->MaxX - 1;
-  pInfo->srWindow.Top = 0;
-  pInfo->srWindow.Bottom = Buff->MaxY - 1;
+  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);
 
-  Request->Status = STATUS_SUCCESS;
-
-  return Request->Status;
+  return STATUS_SUCCESS;
 }
 
 CSR_API(CsrSetCursor)
@@ -1462,24 +1325,15 @@ CSR_API(CsrSetCursor)
 
   DPRINT("CsrSetCursor\n");
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
-  if (! NT_SUCCESS(Status))
-    {
-      return Request->Status = Status;
-    }
-
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
-  Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff);
+  Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      if (NULL != Console)
-        {
-          ConioUnlockConsole(Console);
-        }
-      return Request->Status = Status;
+      return Status;
     }
+  Console = Buff->Header.Console;
 
   NewCursorX = Request->Data.SetCursorRequest.Position.X;
   NewCursorY = Request->Data.SetCursorRequest.Position.Y;
@@ -1487,35 +1341,24 @@ CSR_API(CsrSetCursor)
       NewCursorY < 0 || NewCursorY >= Buff->MaxY)
     {
       ConioUnlockScreenBuffer(Buff);
-      if (NULL != Console)
-        {
-          ConioUnlockConsole(Console);
-        }
-      return Request->Status = STATUS_INVALID_PARAMETER;
+      return STATUS_INVALID_PARAMETER;
     }
-  ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, &OldCursorX, &OldCursorY);
-  Buff->CurrentX = NewCursorX + Buff->ShowX;
-  Buff->CurrentY = (NewCursorY + Buff->ShowY) % Buff->MaxY;
-  if (NULL != Console && Buff == Console->ActiveBuffer)
+  OldCursorX = Buff->CurrentX;
+  OldCursorY = Buff->CurrentY;
+  Buff->CurrentX = NewCursorX;
+  Buff->CurrentY = NewCursorY;
+  if (Buff == Console->ActiveBuffer)
     {
       if (! ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY))
         {
           ConioUnlockScreenBuffer(Buff);
-          if (NULL != Console)
-            {
-              ConioUnlockConsole(Console);
-            }
-          return Request->Status = STATUS_UNSUCCESSFUL;
+          return STATUS_UNSUCCESSFUL;
         }
     }
 
   ConioUnlockScreenBuffer(Buff);
-  if (NULL != Console)
-    {
-      ConioUnlockConsole(Console);
-    }
 
-  return Request->Status = STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }
 
 static VOID FASTCALL
@@ -1566,24 +1409,28 @@ CSR_API(CsrWriteConsoleOutputChar)
       DPRINT1("Invalid request size\n");
       Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
       Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
-      return Request->Status = STATUS_INVALID_PARAMETER;
+      return STATUS_INVALID_PARAMETER;
     }
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
+  Status = ConioLockScreenBuffer(ProcessData,
+                                 Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle,
+                                 &Buff,
+                                 GENERIC_WRITE);
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
   if (NT_SUCCESS(Status))
     {
+      Console = Buff->Header.Console;
       if(Request->Data.WriteConsoleOutputCharRequest.Unicode)
         {
-          Length = WideCharToMultiByte(Console->CodePage, 0,
+          Length = WideCharToMultiByte(Console->OutputCodePage, 0,
                                       (PWCHAR)Request->Data.WriteConsoleOutputCharRequest.String,
                                        Request->Data.WriteConsoleOutputCharRequest.Length,
                                        NULL, 0, NULL, NULL);
           tmpString = String = RtlAllocateHeap(GetProcessHeap(), 0, Length);
           if (String)
             {
-              WideCharToMultiByte(Console->CodePage, 0,
+              WideCharToMultiByte(Console->OutputCodePage, 0,
                                   (PWCHAR)Request->Data.WriteConsoleOutputCharRequest.String,
                                   Request->Data.WriteConsoleOutputCharRequest.Length,
                                   String, Length, NULL, NULL);
@@ -1600,13 +1447,10 @@ CSR_API(CsrWriteConsoleOutputChar)
 
       if (String)
         {
-          Status = ConioLockScreenBuffer(ProcessData,
-                                         Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle,
-                                         &Buff);
           if (NT_SUCCESS(Status))
             {
-              X = Request->Data.WriteConsoleOutputCharRequest.Coord.X + Buff->ShowX;
-              Y = (Request->Data.WriteConsoleOutputCharRequest.Coord.Y + Buff->ShowY) % Buff->MaxY;
+              X = Request->Data.WriteConsoleOutputCharRequest.Coord.X;
+              Y = (Request->Data.WriteConsoleOutputCharRequest.Coord.Y + Buff->VirtualY) % Buff->MaxY;
               Length = Request->Data.WriteConsoleOutputCharRequest.Length;
               Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)];
               while (Length--)
@@ -1624,30 +1468,26 @@ CSR_API(CsrWriteConsoleOutputChar)
                       X = 0;
                     }
                 }
-              if (NULL != Console && Buff == Console->ActiveBuffer)
+              if (Buff == Console->ActiveBuffer)
                 {
                   ConioComputeUpdateRect(Buff, &UpdateRect, &Request->Data.WriteConsoleOutputCharRequest.Coord,
                                          Request->Data.WriteConsoleOutputCharRequest.Length);
                   ConioDrawRegion(Console, &UpdateRect);
                 }
 
-                Request->Data.WriteConsoleOutputCharRequest.EndCoord.X = X - Buff->ShowX;
-                Request->Data.WriteConsoleOutputCharRequest.EndCoord.Y = (Y + Buff->MaxY - Buff->ShowY) % Buff->MaxY;
+                Request->Data.WriteConsoleOutputCharRequest.EndCoord.X = X;
+                Request->Data.WriteConsoleOutputCharRequest.EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY;
 
-                ConioUnlockScreenBuffer(Buff);
             }
           if (Request->Data.WriteConsoleRequest.Unicode)
             {
               RtlFreeHeap(GetProcessHeap(), 0, tmpString);
             }
         }
-      if (NULL != Console)
-        {
-          ConioUnlockConsole(Console);
-        }
+      ConioUnlockScreenBuffer(Buff);
     }
   Request->Data.WriteConsoleOutputCharRequest.NrCharactersWritten = Written;
-  return Request->Status = Status;
+  return Status;
 }
 
 CSR_API(CsrFillOutputChar)
@@ -1665,24 +1505,15 @@ CSR_API(CsrFillOutputChar)
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
-  if (! NT_SUCCESS(Status))
-    {
-      return Request->Status = Status;
-    }
-
-  Status = ConioLockScreenBuffer(ProcessData, Request->Data.FillOutputRequest.ConsoleHandle, &Buff);
+  Status = ConioLockScreenBuffer(ProcessData, Request->Data.FillOutputRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      if (NULL != Console)
-        {
-          ConioUnlockConsole(Console);
-        }
-      return Request->Status = Status;
+      return Status;
     }
+  Console = Buff->Header.Console;
 
-  X = Request->Data.FillOutputRequest.Position.X + Buff->ShowX;
-  Y = (Request->Data.FillOutputRequest.Position.Y + Buff->ShowY) % Buff->MaxY;
+  X = Request->Data.FillOutputRequest.Position.X;
+  Y = (Request->Data.FillOutputRequest.Position.Y + Buff->VirtualY) % Buff->MaxY;
   Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)];
   if(Request->Data.FillOutputRequest.Unicode)
     ConsoleUnicodeCharToAnsiChar(Console, &Char, &Request->Data.FillOutputRequest.Char.UnicodeChar);
@@ -1705,7 +1536,7 @@ CSR_API(CsrFillOutputChar)
         }
     }
 
-  if (NULL != Console && Buff == Console->ActiveBuffer)
+  if (Buff == Console->ActiveBuffer)
     {
       ConioComputeUpdateRect(Buff, &UpdateRect, &Request->Data.FillOutputRequest.Position,
                              Request->Data.FillOutputRequest.Length);
@@ -1713,13 +1544,9 @@ CSR_API(CsrFillOutputChar)
     }
 
   ConioUnlockScreenBuffer(Buff);
-  if (NULL != Console)
-    {
-      ConioUnlockConsole(Console);
-    }
   Length = Request->Data.FillOutputRequest.Length;
   Request->Data.FillOutputRequest.NrCharactersWritten = Length;
-  return Request->Status;
+  return STATUS_SUCCESS;
 }
 
 CSR_API(CsrReadInputEvent)
@@ -1736,10 +1563,10 @@ CSR_API(CsrReadInputEvent)
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
   Request->Data.ReadInputRequest.Event = ProcessData->ConsoleEvent;
 
-  Status = ConioLockConsole(ProcessData, Request->Data.ReadInputRequest.ConsoleHandle, &Console);
+  Status = ConioLockConsole(ProcessData, Request->Data.ReadInputRequest.ConsoleHandle, &Console, GENERIC_READ);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
 
   /* only get input if there is any */
@@ -1798,7 +1625,7 @@ CSR_API(CsrReadInputEvent)
 
   ConioUnlockConsole(Console);
 
-  return Request->Status = Status;
+  return Status;
 }
 
 CSR_API(CsrWriteConsoleOutputAttrib)
@@ -1820,31 +1647,24 @@ CSR_API(CsrWriteConsoleOutputAttrib)
       DPRINT1("Invalid request size\n");
       Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
       Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
-      return Request->Status = STATUS_INVALID_PARAMETER;
+      return STATUS_INVALID_PARAMETER;
     }
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
-  if (! NT_SUCCESS(Status))
-    {
-      return Request->Status = Status;
-    }
 
   Status = ConioLockScreenBuffer(ProcessData,
                                  Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle,
-                                 &Buff);
+                                 &Buff,
+                                 GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      if (NULL != Console)
-        {
-          ConioUnlockConsole(Console);
-        }
-      return Request->Status = Status;
+      return Status;
     }
+  Console = Buff->Header.Console;
 
-  X = Request->Data.WriteConsoleOutputAttribRequest.Coord.X + Buff->ShowX;
-  Y = (Request->Data.WriteConsoleOutputAttribRequest.Coord.Y + Buff->ShowY) % Buff->MaxY;
+  X = Request->Data.WriteConsoleOutputAttribRequest.Coord.X;
+  Y = (Request->Data.WriteConsoleOutputAttribRequest.Coord.Y + Buff->VirtualY) % Buff->MaxY;
   Length = Request->Data.WriteConsoleOutputAttribRequest.Length;
   Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X) + 1];
   Attribute = Request->Data.WriteConsoleOutputAttribRequest.Attribute;
@@ -1863,24 +1683,19 @@ CSR_API(CsrWriteConsoleOutputAttrib)
         }
     }
 
-  if (NULL != Console && Buff == Console->ActiveBuffer)
+  if (Buff == Console->ActiveBuffer)
     {
       ConioComputeUpdateRect(Buff, &UpdateRect, &Request->Data.WriteConsoleOutputAttribRequest.Coord,
                              Request->Data.WriteConsoleOutputAttribRequest.Length);
       ConioDrawRegion(Console, &UpdateRect);
     }
 
-  if (NULL != Console)
-    {
-      ConioUnlockConsole(Console);
-    }
-
-  Request->Data.WriteConsoleOutputAttribRequest.EndCoord.X = Buff->CurrentX - Buff->ShowX;
-  Request->Data.WriteConsoleOutputAttribRequest.EndCoord.Y = (Buff->CurrentY + Buff->MaxY - Buff->ShowY) % Buff->MaxY;
+  Request->Data.WriteConsoleOutputAttribRequest.EndCoord.X = X;
+  Request->Data.WriteConsoleOutputAttribRequest.EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY;
 
   ConioUnlockScreenBuffer(Buff);
 
-  return Request->Status = STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }
 
 CSR_API(CsrFillOutputAttrib)
@@ -1895,26 +1710,17 @@ CSR_API(CsrFillOutputAttrib)
 
   DPRINT("CsrFillOutputAttrib\n");
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
-  if (! NT_SUCCESS(Status))
-    {
-      return Request->Status = Status;
-    }
-
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
-  Status = ConioLockScreenBuffer(ProcessData, Request->Data.FillOutputAttribRequest.ConsoleHandle, &Buff);
+  Status = ConioLockScreenBuffer(ProcessData, Request->Data.FillOutputAttribRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      if (NULL != Console)
-        {
-          ConioUnlockConsole(Console);
-        }
-      return Request->Status = Status;
+      return Status;
     }
+  Console = Buff->Header.Console;
 
-  X = Request->Data.FillOutputAttribRequest.Coord.X + Buff->ShowX;
-  Y = (Request->Data.FillOutputAttribRequest.Coord.Y + Buff->ShowY) % Buff->MaxY;
+  X = Request->Data.FillOutputAttribRequest.Coord.X;
+  Y = (Request->Data.FillOutputAttribRequest.Coord.Y + Buff->VirtualY) % Buff->MaxY;
   Length = Request->Data.FillOutputAttribRequest.Length;
   Attr = Request->Data.FillOutputAttribRequest.Attribute;
   Buffer = &Buff->Buffer[(Y * Buff->MaxX * 2) + (X * 2) + 1];
@@ -1933,7 +1739,7 @@ CSR_API(CsrFillOutputAttrib)
         }
     }
 
-  if (NULL != Console && Buff == Console->ActiveBuffer)
+  if (Buff == Console->ActiveBuffer)
     {
       ConioComputeUpdateRect(Buff, &UpdateRect, &Request->Data.FillOutputAttribRequest.Coord,
                              Request->Data.FillOutputAttribRequest.Length);
@@ -1941,12 +1747,8 @@ CSR_API(CsrFillOutputAttrib)
     }
 
   ConioUnlockScreenBuffer(Buff);
-  if (NULL != Console)
-    {
-      ConioUnlockConsole(Console);
-    }
 
-  return Request->Status = STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }
 
 
@@ -1960,16 +1762,16 @@ CSR_API(CsrGetCursorInfo)
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
-  Status = ConioLockScreenBuffer(ProcessData, Request->Data.GetCursorInfoRequest.ConsoleHandle, &Buff);
+  Status = ConioLockScreenBuffer(ProcessData, Request->Data.GetCursorInfoRequest.ConsoleHandle, &Buff, GENERIC_READ);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
   Request->Data.GetCursorInfoRequest.Info.bVisible = Buff->CursorInfo.bVisible;
   Request->Data.GetCursorInfoRequest.Info.dwSize = Buff->CursorInfo.dwSize;
   ConioUnlockScreenBuffer(Buff);
 
-  return Request->Status = STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }
 
 CSR_API(CsrSetCursorInfo)
@@ -1985,21 +1787,12 @@ CSR_API(CsrSetCursorInfo)
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
-  if (! NT_SUCCESS(Status))
-    {
-      return Request->Status = Status;
-    }
-
-  Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorInfoRequest.ConsoleHandle, &Buff);
+  Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorInfoRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      if (NULL != Console)
-        {
-          ConioUnlockConsole(Console);
-        }
-      return Request->Status = Status;
+      return Status;
     }
+  Console = Buff->Header.Console;
 
   Size = Request->Data.SetCursorInfoRequest.Info.dwSize;
   Visible = Request->Data.SetCursorInfoRequest.Info.bVisible;
@@ -2018,21 +1811,16 @@ CSR_API(CsrSetCursorInfo)
       Buff->CursorInfo.dwSize = Size;
       Buff->CursorInfo.bVisible = Visible;
 
-      if (NULL != Console && ! ConioSetCursorInfo(Console, Buff))
+      if (! ConioSetCursorInfo(Console, Buff))
         {
           ConioUnlockScreenBuffer(Buff);
-          ConioUnlockConsole(Console);
-          return Request->Status = STATUS_UNSUCCESSFUL;
+          return STATUS_UNSUCCESSFUL;
         }
     }
 
   ConioUnlockScreenBuffer(Buff);
-  if (NULL != Console)
-    {
-      ConioUnlockConsole(Console);
-    }
 
-  return Request->Status = STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }
 
 CSR_API(CsrSetTextAttrib)
@@ -2040,46 +1828,29 @@ CSR_API(CsrSetTextAttrib)
   NTSTATUS Status;
   PCSRSS_CONSOLE Console;
   PCSRSS_SCREEN_BUFFER Buff;
-  LONG OldCursorX, OldCursorY;
 
   DPRINT("CsrSetTextAttrib\n");
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
-  if (! NT_SUCCESS(Status))
-    {
-      return Request->Status = Status;
-    }
-
-  Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff);
+  Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      if (NULL != Console)
-        {
-          ConioUnlockConsole(Console);
-        }
-      return Request->Status = Status;
+      return Status;
     }
-
-  ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, &OldCursorX, &OldCursorY);
+  Console = Buff->Header.Console;
 
   Buff->DefaultAttrib = Request->Data.SetAttribRequest.Attrib;
-  if (NULL != Console && Buff == Console->ActiveBuffer)
+  if (Buff == Console->ActiveBuffer)
     {
-      if (! ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY))
+      if (! ConioUpdateScreenInfo(Console, Buff))
         {
           ConioUnlockScreenBuffer(Buff);
-          ConioUnlockConsole(Console);
-          return Request->Status = STATUS_UNSUCCESSFUL;
+          return STATUS_UNSUCCESSFUL;
         }
     }
 
   ConioUnlockScreenBuffer(Buff);
-  if (NULL != Console)
-    {
-      ConioUnlockConsole(Console);
-    }
 
-  return Request->Status = STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }
 
 CSR_API(CsrSetConsoleMode)
@@ -2092,12 +1863,12 @@ CSR_API(CsrSetConsoleMode)
 
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
-  Status = Win32CsrGetObject(ProcessData,
-                             Request->Data.SetConsoleModeRequest.ConsoleHandle,
-                             (Object_t **) &Console);
+  Status = Win32CsrLockObject(ProcessData,
+                              Request->Data.SetConsoleModeRequest.ConsoleHandle,
+                              (Object_t **) &Console, GENERIC_WRITE, 0);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
 
   Buff = (PCSRSS_SCREEN_BUFFER)Console;
@@ -2111,12 +1882,12 @@ CSR_API(CsrSetConsoleMode)
     }
   else
     {
-      return Request->Status = STATUS_INVALID_HANDLE;
+      Status = STATUS_INVALID_HANDLE;
     }
 
-  Request->Status = STATUS_SUCCESS;
+  Win32CsrUnlockObject((Object_t *)Console);
 
-  return Request->Status;
+  return Status;
 }
 
 CSR_API(CsrGetConsoleMode)
@@ -2129,13 +1900,13 @@ CSR_API(CsrGetConsoleMode)
 
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
-  Status = Win32CsrGetObject(ProcessData, Request->Data.GetConsoleModeRequest.ConsoleHandle,
-                             (Object_t **) &Console);
+  Status = Win32CsrLockObject(ProcessData, Request->Data.GetConsoleModeRequest.ConsoleHandle,
+                              (Object_t **) &Console, GENERIC_READ, 0);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
-  Request->Status = STATUS_SUCCESS;
+  Status = STATUS_SUCCESS;
   Buff = (PCSRSS_SCREEN_BUFFER) Console;
   if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
     {
@@ -2147,10 +1918,11 @@ CSR_API(CsrGetConsoleMode)
     }
   else
     {
-      Request->Status = STATUS_INVALID_HANDLE;
+      Status = STATUS_INVALID_HANDLE;
     }
 
-  return Request->Status;
+  Win32CsrUnlockObject((Object_t *)Console);
+  return Status;
 }
 
 CSR_API(CsrCreateScreenBuffer)
@@ -2161,19 +1933,11 @@ CSR_API(CsrCreateScreenBuffer)
 
   DPRINT("CsrCreateScreenBuffer\n");
 
-  if (ProcessData == NULL)
-    {
-      return Request->Status = STATUS_INVALID_PARAMETER;
-    }
-
+  RtlEnterCriticalSection(&ProcessData->HandleTableLock);
   Status = ConioConsoleFromProcessData(ProcessData, &Console);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
-    }
-  if (NULL == Console)
-    {
-      return Request->Status = STATUS_INVALID_HANDLE;
+      return Status;
     }
 
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
@@ -2193,7 +1957,7 @@ CSR_API(CsrCreateScreenBuffer)
       else
         {
           Buff->CursorInfo.bVisible = TRUE;
-          Buff->CursorInfo.dwSize = 5;
+          Buff->CursorInfo.dwSize = CSR_DEFAULT_CURSOR_SIZE;
         }
 
       if (Buff->MaxX == 0)
@@ -2207,22 +1971,24 @@ CSR_API(CsrCreateScreenBuffer)
         }
 
       Status = CsrInitConsoleScreenBuffer(Console, Buff);
-      if(! NT_SUCCESS(Status))
-        {
-          Request->Status = Status;
-        }
-      else
+      if(NT_SUCCESS(Status))
         {
-          Request->Status = Win32CsrInsertObject(ProcessData, &Request->Data.CreateScreenBufferRequest.OutputHandle, &Buff->Header);
+          Status = Win32CsrInsertObject(ProcessData,
+            &Request->Data.CreateScreenBufferRequest.OutputHandle,
+            &Buff->Header,
+            Request->Data.CreateScreenBufferRequest.Access,
+            Request->Data.CreateScreenBufferRequest.Inheritable,
+            Request->Data.CreateScreenBufferRequest.ShareMode);
         }
     }
   else
     {
-      Request->Status = STATUS_INSUFFICIENT_RESOURCES;
+      Status = STATUS_INSUFFICIENT_RESOURCES;
     }
 
   ConioUnlockConsole(Console);
-  return Request->Status;
+  RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+  return Status;
 }
 
 CSR_API(CsrSetScreenBuffer)
@@ -2233,50 +1999,35 @@ CSR_API(CsrSetScreenBuffer)
 
   DPRINT("CsrSetScreenBuffer\n");
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
-  if (! NT_SUCCESS(Status))
-    {
-      return Request->Status = Status;
-    }
-  if (NULL == Console)
-    {
-      DPRINT1("Trying to set screen buffer for app without console\n");
-      return Request->Status = STATUS_INVALID_HANDLE;
-    }
-
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
-  Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetScreenBufferRequest.OutputHandle, &Buff);
+  Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetScreenBufferRequest.OutputHandle, &Buff, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      ConioUnlockConsole(Console);
-      return Request->Status;
+      return Status;
     }
+  Console = Buff->Header.Console;
 
   if (Buff == Console->ActiveBuffer)
     {
       ConioUnlockScreenBuffer(Buff);
-      ConioUnlockConsole(Console);
       return STATUS_SUCCESS;
     }
 
-  /* drop reference to old buffer, maybe delete */
-  if (! InterlockedDecrement(&Console->ActiveBuffer->Header.ReferenceCount))
+  /* If old buffer has no handles, it's now unreferenced */
+  if (Console->ActiveBuffer->Header.HandleCount == 0)
     {
-      ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer);
+      ConioDeleteScreenBuffer(Console->ActiveBuffer);
     }
   /* tie console to new buffer */
   Console->ActiveBuffer = Buff;
-  /* inc ref count on new buffer */
-  InterlockedIncrement(&Buff->Header.ReferenceCount);
   /* Redraw the console */
   ConioDrawConsole(Console);
 
   ConioUnlockScreenBuffer(Buff);
-  ConioUnlockConsole(Console);
 
-  return Request->Status = STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }
 
 CSR_API(CsrSetTitle)
@@ -2294,17 +2045,13 @@ CSR_API(CsrSetTitle)
       DPRINT1("Invalid request size\n");
       Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
       Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
-      return Request->Status = STATUS_INVALID_PARAMETER;
+      return STATUS_INVALID_PARAMETER;
     }
 
-  Status = ConioLockConsole(ProcessData, Request->Data.SetTitleRequest.Console, &Console);
+  Status = ConioConsoleFromProcessData(ProcessData, &Console);
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
-  if(! NT_SUCCESS(Status))
-    {
-      Request->Status = Status;
-    }
-  else
+  if(NT_SUCCESS(Status))
     {
       Buffer =  RtlAllocateHeap(RtlGetProcessHeap(), 0, Request->Data.SetTitleRequest.Length);
       if (Buffer)
@@ -2316,21 +2063,21 @@ CSR_API(CsrSetTitle)
           memcpy(Console->Title.Buffer, Request->Data.SetTitleRequest.Title, Console->Title.Length);
           if (! ConioChangeTitle(Console))
             {
-              Request->Status = STATUS_UNSUCCESSFUL;
+              Status = STATUS_UNSUCCESSFUL;
             }
           else
             {
-              Request->Status = STATUS_SUCCESS;
+              Status = STATUS_SUCCESS;
             }
         }
       else
         {
-          Request->Status = STATUS_NO_MEMORY;
+          Status = STATUS_NO_MEMORY;
         }
+      ConioUnlockConsole(Console);
     }
-  ConioUnlockConsole(Console);
 
-  return Request->Status;
+  return Status;
 }
 
 CSR_API(CsrGetTitle)
@@ -2343,18 +2090,15 @@ CSR_API(CsrGetTitle)
 
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
-  Status = ConioLockConsole(ProcessData,
-                            Request->Data.GetTitleRequest.ConsoleHandle,
-                            &Console);
+  Status = ConioConsoleFromProcessData(ProcessData, &Console);
   if (! NT_SUCCESS(Status))
     {
       DPRINT1("Can't get console\n");
-      return Request->Status = Status;
+      return Status;
     }
 
   /* Copy title of the console to the user title buffer */
   RtlZeroMemory(&Request->Data.GetTitleRequest, sizeof(CSRSS_GET_TITLE));
-  Request->Data.GetTitleRequest.ConsoleHandle = Request->Data.GetTitleRequest.ConsoleHandle;
   Request->Data.GetTitleRequest.Length = Console->Title.Length;
   memcpy (Request->Data.GetTitleRequest.Title, Console->Title.Buffer,
           Console->Title.Length);
@@ -2367,9 +2111,7 @@ CSR_API(CsrGetTitle)
       Request->Header.u1.s1.TotalLength = Length;
       Request->Header.u1.s1.DataLength = Length - sizeof(PORT_MESSAGE);
     }
-  Request->Status = STATUS_SUCCESS;
-
-  return Request->Status;
+  return STATUS_SUCCESS;
 }
 
 CSR_API(CsrWriteConsoleOutput)
@@ -2384,30 +2126,22 @@ CSR_API(CsrWriteConsoleOutput)
   COORD BufferCoord;
   COORD BufferSize;
   NTSTATUS Status;
-  DWORD Offset;
+  PBYTE Ptr;
   DWORD PSize;
 
   DPRINT("CsrWriteConsoleOutput\n");
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
-  if (! NT_SUCCESS(Status))
-    {
-      return Request->Status = Status;
-    }
-
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
   Status = ConioLockScreenBuffer(ProcessData,
                                  Request->Data.WriteConsoleOutputRequest.ConsoleHandle,
-                                 &Buff);
+                                 &Buff,
+                                 GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      if (NULL != Console)
-        {
-          ConioUnlockConsole(Console);
-        }
-      return Request->Status = Status;
+      return Status;
     }
+  Console = Buff->Header.Console;
 
   BufferSize = Request->Data.WriteConsoleOutputRequest.BufferSize;
   PSize = BufferSize.X * BufferSize.Y * sizeof(CHAR_INFO);
@@ -2418,8 +2152,7 @@ CSR_API(CsrWriteConsoleOutput)
        ((ULONG_PTR)ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
     {
       ConioUnlockScreenBuffer(Buff);
-      ConioUnlockConsole(Console);
-      return Request->Status = STATUS_ACCESS_VIOLATION;
+      return STATUS_ACCESS_VIOLATION;
     }
   WriteRegion.left = Request->Data.WriteConsoleOutputRequest.WriteRegion.Left;
   WriteRegion.top = Request->Data.WriteConsoleOutputRequest.WriteRegion.Top;
@@ -2436,47 +2169,43 @@ CSR_API(CsrWriteConsoleOutput)
   if (! ConioGetIntersection(&WriteRegion, &ScreenBuffer, &WriteRegion))
     {
       ConioUnlockScreenBuffer(Buff);
-      ConioUnlockConsole(Console);
 
       /* It is okay to have a WriteRegion completely outside the screen buffer.
          No data is written then. */
-      return Request->Status = STATUS_SUCCESS;
+      return STATUS_SUCCESS;
     }
 
   for (i = 0, Y = WriteRegion.top; Y <= WriteRegion.bottom; i++, Y++)
     {
       CurCharInfo = CharInfo + (i + BufferCoord.Y) * BufferSize.X + BufferCoord.X;
-      Offset = (((Y + Buff->ShowY) % Buff->MaxY) * Buff->MaxX + WriteRegion.left) * 2;
+      Ptr = ConioCoordToPointer(Buff, WriteRegion.left, Y);
       for (X = WriteRegion.left; X <= WriteRegion.right; X++)
         {
+          CHAR AsciiChar;
           if (Request->Data.WriteConsoleOutputRequest.Unicode)
             {
-              CHAR AsciiChar;
               ConsoleUnicodeCharToAnsiChar(Console, &AsciiChar, &CurCharInfo->Char.UnicodeChar);
-              SET_CELL_BUFFER(Buff, Offset, AsciiChar, CurCharInfo->Attributes);
             }
           else
             {
-              SET_CELL_BUFFER(Buff, Offset, CurCharInfo->Char.AsciiChar, CurCharInfo->Attributes);
+              AsciiChar = CurCharInfo->Char.AsciiChar;
             }
+          *Ptr++ = AsciiChar;
+          *Ptr++ = CurCharInfo->Attributes;
           CurCharInfo++;
         }
     }
 
-  if (NULL != Console)
-    {
-      ConioDrawRegion(Console, &WriteRegion);
-    }
+  ConioDrawRegion(Console, &WriteRegion);
 
   ConioUnlockScreenBuffer(Buff);
-  ConioUnlockConsole(Console);
 
   Request->Data.WriteConsoleOutputRequest.WriteRegion.Right = WriteRegion.left + SizeX - 1;
   Request->Data.WriteConsoleOutputRequest.WriteRegion.Bottom = WriteRegion.top + SizeY - 1;
   Request->Data.WriteConsoleOutputRequest.WriteRegion.Left = WriteRegion.left;
   Request->Data.WriteConsoleOutputRequest.WriteRegion.Top = WriteRegion.top;
 
-  return Request->Status = STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }
 
 CSR_API(CsrFlushInputBuffer)
@@ -2492,10 +2221,11 @@ CSR_API(CsrFlushInputBuffer)
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
   Status = ConioLockConsole(ProcessData,
                             Request->Data.FlushInputBufferRequest.ConsoleInput,
-                            &Console);
+                            &Console,
+                            GENERIC_WRITE);
   if(! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
 
   /* Discard all entries in the input event queue */
@@ -2511,7 +2241,7 @@ CSR_API(CsrFlushInputBuffer)
 
   ConioUnlockConsole(Console);
 
-  return Request->Status = STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }
 
 CSR_API(CsrScrollConsoleScreenBuffer)
@@ -2521,15 +2251,15 @@ CSR_API(CsrScrollConsoleScreenBuffer)
   RECT ScreenBuffer;
   RECT SrcRegion;
   RECT DstRegion;
-  RECT FillRegion;
+  RECT UpdateRegion;
   RECT ScrollRectangle;
   RECT ClipRectangle;
   NTSTATUS Status;
-  BOOLEAN DoFill;
   HANDLE ConsoleHandle;
   BOOLEAN UseClipRectangle;
   COORD DestinationOrigin;
   CHAR_INFO Fill;
+  CHAR FillChar;
 
   DPRINT("CsrScrollConsoleScreenBuffer\n");
 
@@ -2538,97 +2268,81 @@ CSR_API(CsrScrollConsoleScreenBuffer)
   DestinationOrigin = Request->Data.ScrollConsoleScreenBufferRequest.DestinationOrigin;
   Fill = Request->Data.ScrollConsoleScreenBufferRequest.Fill;
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
-  if (! NT_SUCCESS(Status))
-    {
-      return Request->Status = Status;
-    }
-
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
-  Status = ConioLockScreenBuffer(ProcessData, ConsoleHandle, &Buff);
+  Status = ConioLockScreenBuffer(ProcessData, ConsoleHandle, &Buff, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      if (NULL != Console)
-        {
-          ConioUnlockConsole(Console);
-        }
-      return Request->Status = Status;
+      return Status;
     }
+  Console = Buff->Header.Console;
 
   ScrollRectangle.left = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Left;
   ScrollRectangle.top = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Top;
   ScrollRectangle.right = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Right;
   ScrollRectangle.bottom = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Bottom;
-  ClipRectangle.left = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Left;
-  ClipRectangle.top = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Top;
-  ClipRectangle.right = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Right;
-  ClipRectangle.bottom = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Bottom;
 
   /* Make sure source rectangle is inside the screen buffer */
   ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1);
   if (! ConioGetIntersection(&SrcRegion, &ScreenBuffer, &ScrollRectangle))
     {
       ConioUnlockScreenBuffer(Buff);
-      return Request->Status = STATUS_INVALID_PARAMETER;
+      return STATUS_SUCCESS;
     }
 
-  if (UseClipRectangle && ! ConioGetIntersection(&SrcRegion, &SrcRegion, &ClipRectangle))
+  /* If the source was clipped on the left or top, adjust the destination accordingly */
+  if (ScrollRectangle.left < 0)
     {
-      ConioUnlockScreenBuffer(Buff);
-      return Request->Status = STATUS_SUCCESS;
+      DestinationOrigin.X -= ScrollRectangle.left;
+    }
+  if (ScrollRectangle.top < 0)
+    {
+      DestinationOrigin.Y -= ScrollRectangle.top;
     }
 
+  if (UseClipRectangle)
+    {
+      ClipRectangle.left = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Left;
+      ClipRectangle.top = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Top;
+      ClipRectangle.right = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Right;
+      ClipRectangle.bottom = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Bottom;
+      if (!ConioGetIntersection(&ClipRectangle, &ClipRectangle, &ScreenBuffer))
+        {
+          ConioUnlockScreenBuffer(Buff);
+          return STATUS_SUCCESS;
+      }
+    }
+  else
+    {
+      ClipRectangle = ScreenBuffer;
+    }
 
   ConioInitRect(&DstRegion,
                DestinationOrigin.Y,
                DestinationOrigin.X,
-               DestinationOrigin.Y + ConioRectHeight(&ScrollRectangle) - 1,
-               DestinationOrigin.X + ConioRectWidth(&ScrollRectangle) - 1);
-
-  /* Make sure destination rectangle is inside the screen buffer */
-  if (! ConioGetIntersection(&DstRegion, &DstRegion, &ScreenBuffer))
-    {
-      ConioUnlockScreenBuffer(Buff);
-      return Request->Status = STATUS_INVALID_PARAMETER;
-    }
-
-  ConioCopyRegion(Buff, &SrcRegion, &DstRegion);
+               DestinationOrigin.Y + ConioRectHeight(&SrcRegion) - 1,
+               DestinationOrigin.X + ConioRectWidth(&SrcRegion) - 1);
 
-  /* Get the region that should be filled with the specified character and attributes */
-
-  DoFill = FALSE;
-
-  ConioGetUnion(&FillRegion, &SrcRegion, &DstRegion);
-
-  if (ConioSubtractRect(&FillRegion, &FillRegion, &DstRegion))
-    {
-      /* FIXME: The subtracted rectangle is off by one line */
-      FillRegion.top += 1;
+  if (Request->Data.ScrollConsoleScreenBufferRequest.Unicode)
+    ConsoleUnicodeCharToAnsiChar(Console, &FillChar, &Fill.Char.UnicodeChar);
+  else
+    FillChar = Fill.Char.AsciiChar;
 
-      ConioFillRegion(Console, Buff, &FillRegion, &Fill, Request->Data.ScrollConsoleScreenBufferRequest.Unicode);
-      DoFill = TRUE;
-    }
+  ConioMoveRegion(Buff, &SrcRegion, &DstRegion, &ClipRectangle, Fill.Attributes << 8 | (BYTE)FillChar);
 
-  if (NULL != Console && Buff == Console->ActiveBuffer)
+  if (Buff == Console->ActiveBuffer)
     {
-      /* Draw destination region */
-      ConioDrawRegion(Console, &DstRegion);
-
-      if (DoFill)
+      ConioGetUnion(&UpdateRegion, &SrcRegion, &DstRegion);
+      if (ConioGetIntersection(&UpdateRegion, &UpdateRegion, &ClipRectangle))
         {
-          /* Draw filled region */
-          ConioDrawRegion(Console, &FillRegion);
+          /* Draw update region */
+          ConioDrawRegion(Console, &UpdateRegion);
         }
     }
 
   ConioUnlockScreenBuffer(Buff);
-  if (NULL != Console)
-    {
-      ConioUnlockConsole(Console);
-    }
 
-  return Request->Status = STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }
 
 CSR_API(CsrReadConsoleOutputChar)
@@ -2650,20 +2364,15 @@ CSR_API(CsrReadConsoleOutputChar)
 
   CharSize = (Request->Data.ReadConsoleOutputCharRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
-  if (! NT_SUCCESS(Status))
-    {
-      return Request->Status = Status;
-    }
-
-  Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputCharRequest.ConsoleHandle, &Buff);
+  Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputCharRequest.ConsoleHandle, &Buff, GENERIC_READ);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
+  Console = Buff->Header.Console;
 
-  Xpos = Request->Data.ReadConsoleOutputCharRequest.ReadCoord.X + Buff->ShowX;
-  Ypos = (Request->Data.ReadConsoleOutputCharRequest.ReadCoord.Y + Buff->ShowY) % Buff->MaxY;
+  Xpos = Request->Data.ReadConsoleOutputCharRequest.ReadCoord.X;
+  Ypos = (Request->Data.ReadConsoleOutputCharRequest.ReadCoord.Y + Buff->VirtualY) % Buff->MaxY;
 
   for (i = 0; i < Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead; ++i)
     {
@@ -2692,15 +2401,10 @@ CSR_API(CsrReadConsoleOutputChar)
     }
 
   *ReadBuffer = 0;
-  Request->Status = STATUS_SUCCESS;
-  Request->Data.ReadConsoleOutputCharRequest.EndCoord.X = Xpos - Buff->ShowX;
-  Request->Data.ReadConsoleOutputCharRequest.EndCoord.Y = (Ypos - Buff->ShowY + Buff->MaxY) % Buff->MaxY;
+  Request->Data.ReadConsoleOutputCharRequest.EndCoord.X = Xpos;
+  Request->Data.ReadConsoleOutputCharRequest.EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY;
 
   ConioUnlockScreenBuffer(Buff);
-  if (NULL != Console)
-    {
-      ConioUnlockConsole(Console);
-    }
 
   Request->Data.ReadConsoleOutputCharRequest.CharsRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)Request->Data.ReadConsoleOutputCharRequest.String) / CharSize;
   if (Request->Data.ReadConsoleOutputCharRequest.CharsRead * CharSize + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR) > sizeof(CSR_API_MESSAGE))
@@ -2709,7 +2413,7 @@ CSR_API(CsrReadConsoleOutputChar)
       Request->Header.u1.s1.DataLength = Request->Header.u1.s1.TotalLength - sizeof(PORT_MESSAGE);
     }
 
-  return Request->Status;
+  return STATUS_SUCCESS;
 }
 
 
@@ -2728,14 +2432,14 @@ CSR_API(CsrReadConsoleOutputAttrib)
   Request->Header.u1.s1.DataLength = Request->Header.u1.s1.TotalLength - sizeof(PORT_MESSAGE);
   ReadBuffer = Request->Data.ReadConsoleOutputAttribRequest.Attribute;
 
-  Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputAttribRequest.ConsoleHandle, &Buff);
+  Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputAttribRequest.ConsoleHandle, &Buff, GENERIC_READ);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
 
-  Xpos = Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.X + Buff->ShowX;
-  Ypos = (Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.Y + Buff->ShowY) % Buff->MaxY;
+  Xpos = Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.X;
+  Ypos = (Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.Y + Buff->VirtualY) % Buff->MaxY;
 
   for (i = 0; i < Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead; ++i)
     {
@@ -2758,9 +2462,8 @@ CSR_API(CsrReadConsoleOutputAttrib)
 
   *ReadBuffer = 0;
 
-  Request->Status = STATUS_SUCCESS;
-  Request->Data.ReadConsoleOutputAttribRequest.EndCoord.X = Xpos - Buff->ShowX;
-  Request->Data.ReadConsoleOutputAttribRequest.EndCoord.Y = (Ypos - Buff->ShowY + Buff->MaxY) % Buff->MaxY;
+  Request->Data.ReadConsoleOutputAttribRequest.EndCoord.X = Xpos;
+  Request->Data.ReadConsoleOutputAttribRequest.EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY;
 
   ConioUnlockScreenBuffer(Buff);
 
@@ -2772,7 +2475,7 @@ CSR_API(CsrReadConsoleOutputAttrib)
       Request->Header.u1.s1.DataLength = CurrentLength - sizeof(PORT_MESSAGE);
     }
 
-  return Request->Status;
+  return STATUS_SUCCESS;
 }
 
 
@@ -2789,10 +2492,10 @@ CSR_API(CsrGetNumberOfConsoleInputEvents)
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = Request->Header.u1.s1.TotalLength - sizeof(PORT_MESSAGE);
 
-  Status = ConioLockConsole(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, &Console);
+  Status = ConioLockConsole(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, &Console, GENERIC_READ);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
 
   CurrentItem = Console->InputEvents.Flink;
@@ -2811,10 +2514,9 @@ CSR_API(CsrGetNumberOfConsoleInputEvents)
 
   ConioUnlockConsole(Console);
 
-  Request->Status = STATUS_SUCCESS;
   Request->Data.GetNumInputEventsRequest.NumInputEvents = NumEvents;
 
-  return Request->Status;
+  return STATUS_SUCCESS;
 }
 
 
@@ -2834,10 +2536,10 @@ CSR_API(CsrPeekConsoleInput)
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
-  Status = ConioLockConsole(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, &Console);
+  Status = ConioLockConsole(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, &Console, GENERIC_READ);
   if(! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
 
   InputRecord = Request->Data.PeekConsoleInputRequest.InputRecord;
@@ -2848,8 +2550,7 @@ CSR_API(CsrPeekConsoleInput)
       || (((ULONG_PTR)InputRecord + Size) > ((ULONG_PTR)ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
     {
       ConioUnlockConsole(Console);
-      Request->Status = STATUS_ACCESS_VIOLATION;
-      return Request->Status ;
+      return STATUS_ACCESS_VIOLATION;
     }
 
   NumItems = 0;
@@ -2883,10 +2584,9 @@ CSR_API(CsrPeekConsoleInput)
 
   ConioUnlockConsole(Console);
 
-  Request->Status = STATUS_SUCCESS;
   Request->Data.PeekConsoleInputRequest.Length = NumItems;
 
-  return Request->Status;
+  return STATUS_SUCCESS;
 }
 
 
@@ -2903,7 +2603,8 @@ CSR_API(CsrReadConsoleOutput)
   COORD BufferCoord;
   RECT ReadRegion;
   RECT ScreenRect;
-  DWORD i, Offset;
+  DWORD i;
+  PBYTE Ptr;
   LONG X, Y;
   UINT CodePage;
 
@@ -2912,10 +2613,10 @@ CSR_API(CsrReadConsoleOutput)
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
-  Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputRequest.ConsoleHandle, &Buff);
+  Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputRequest.ConsoleHandle, &Buff, GENERIC_READ);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
 
   CharInfo = Request->Data.ReadConsoleOutputRequest.CharInfo;
@@ -2935,8 +2636,7 @@ CSR_API(CsrReadConsoleOutput)
       || (((ULONG_PTR)CharInfo + Size) > ((ULONG_PTR)ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
     {
       ConioUnlockScreenBuffer(Buff);
-      Request->Status = STATUS_ACCESS_VIOLATION;
-      return Request->Status ;
+      return STATUS_ACCESS_VIOLATION;
     }
 
   SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&ReadRegion));
@@ -2948,41 +2648,39 @@ CSR_API(CsrReadConsoleOutput)
   if (! ConioGetIntersection(&ReadRegion, &ScreenRect, &ReadRegion))
     {
       ConioUnlockScreenBuffer(Buff);
-      Request->Status = STATUS_SUCCESS;
-      return Request->Status;
+      return STATUS_SUCCESS;
     }
 
   for (i = 0, Y = ReadRegion.top; Y < ReadRegion.bottom; ++i, ++Y)
     {
       CurCharInfo = CharInfo + (i * BufferSize.X);
 
-      Offset = (((Y + Buff->ShowY) % Buff->MaxY) * Buff->MaxX + ReadRegion.left) * 2;
+      Ptr = ConioCoordToPointer(Buff, ReadRegion.left, Y);
       for (X = ReadRegion.left; X < ReadRegion.right; ++X)
         {
           if (Request->Data.ReadConsoleOutputRequest.Unicode)
             {
               MultiByteToWideChar(CodePage, 0,
-                                  (PCHAR)&GET_CELL_BUFFER(Buff, Offset), 1,
+                                  (PCHAR)Ptr++, 1,
                                   &CurCharInfo->Char.UnicodeChar, 1);
             }
           else
             {
-              CurCharInfo->Char.AsciiChar = GET_CELL_BUFFER(Buff, Offset);
+              CurCharInfo->Char.AsciiChar = *Ptr++;
             }
-          CurCharInfo->Attributes = GET_CELL_BUFFER(Buff, Offset);
+          CurCharInfo->Attributes = *Ptr++;
           ++CurCharInfo;
         }
     }
 
   ConioUnlockScreenBuffer(Buff);
 
-  Request->Status = STATUS_SUCCESS;
   Request->Data.ReadConsoleOutputRequest.ReadRegion.Right = ReadRegion.left + SizeX - 1;
   Request->Data.ReadConsoleOutputRequest.ReadRegion.Bottom = ReadRegion.top + SizeY - 1;
   Request->Data.ReadConsoleOutputRequest.ReadRegion.Left = ReadRegion.left;
   Request->Data.ReadConsoleOutputRequest.ReadRegion.Top = ReadRegion.top;
 
-  return Request->Status;
+  return STATUS_SUCCESS;
 }
 
 
@@ -3001,10 +2699,10 @@ CSR_API(CsrWriteConsoleInput)
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
-  Status = ConioLockConsole(ProcessData, Request->Data.WriteConsoleInputRequest.ConsoleHandle, &Console);
+  Status = ConioLockConsole(ProcessData, Request->Data.WriteConsoleInputRequest.ConsoleHandle, &Console, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
 
   InputRecord = Request->Data.WriteConsoleInputRequest.InputRecord;
@@ -3015,8 +2713,7 @@ CSR_API(CsrWriteConsoleInput)
       || (((ULONG_PTR)InputRecord + Size) > ((ULONG_PTR)ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
     {
       ConioUnlockConsole(Console);
-      Request->Status = STATUS_ACCESS_VIOLATION;
-      return Request->Status ;
+      return STATUS_ACCESS_VIOLATION;
     }
 
   for (i = 0; i < Length; i++)
@@ -3025,8 +2722,7 @@ CSR_API(CsrWriteConsoleInput)
       if (NULL == Record)
         {
           ConioUnlockConsole(Console);
-          Request->Status = STATUS_INSUFFICIENT_RESOURCES;
-          return Request->Status;
+          return STATUS_INSUFFICIENT_RESOURCES;
         }
 
       Record->Echoed = FALSE;
@@ -3042,10 +2738,9 @@ CSR_API(CsrWriteConsoleInput)
 
   ConioUnlockConsole(Console);
 
-  Request->Status = STATUS_SUCCESS;
   Request->Data.WriteConsoleInputRequest.Length = i;
 
-  return Request->Status;
+  return STATUS_SUCCESS;
 }
 
 /**********************************************************************
@@ -3095,11 +2790,12 @@ CSR_API(CsrHardwareStateProperty)
 
   Status = ConioLockConsole(ProcessData,
                             Request->Data.ConsoleHardwareStateRequest.ConsoleHandle,
-                            &Console);
+                            &Console,
+                            GENERIC_READ);
   if (! NT_SUCCESS(Status))
     {
       DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
-      return Request->Status = Status;
+      return Status;
     }
 
   switch (Request->Data.ConsoleHardwareStateRequest.SetGet)
@@ -3110,17 +2806,17 @@ CSR_API(CsrHardwareStateProperty)
 
       case CONSOLE_HARDWARE_STATE_SET:
         DPRINT("Setting console hardware state.\n");
-        Request->Status = SetConsoleHardwareState(Console, Request->Data.ConsoleHardwareStateRequest.State);
+        Status = SetConsoleHardwareState(Console, Request->Data.ConsoleHardwareStateRequest.State);
         break;
 
       default:
-        Request->Status = STATUS_INVALID_PARAMETER_2; /* Client: (handle, [set_get], mode) */
+        Status = STATUS_INVALID_PARAMETER_2; /* Client: (handle, [set_get], mode) */
         break;
     }
 
   ConioUnlockConsole(Console);
 
-  return Request->Status;
+  return Status;
 }
 
 CSR_API(CsrGetConsoleWindow)
@@ -3136,13 +2832,13 @@ CSR_API(CsrGetConsoleWindow)
   Status = ConioConsoleFromProcessData(ProcessData, &Console);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
 
   Request->Data.GetConsoleWindowRequest.WindowHandle = Console->hWindow;
   ConioUnlockConsole(Console);
 
-  return Request->Status = STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }
 
 CSR_API(CsrSetConsoleIcon)
@@ -3158,14 +2854,14 @@ CSR_API(CsrSetConsoleIcon)
   Status = ConioConsoleFromProcessData(ProcessData, &Console);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
 
-  Console->hWindowIcon = Request->Data.SetConsoleIconRequest.WindowIcon;
-  Request->Status = (ConioChangeIcon(Console) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
+  Status = (ConioChangeIcon(Console, Request->Data.SetConsoleIconRequest.WindowIcon)
+            ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
   ConioUnlockConsole(Console);
 
-  return Request->Status;
+  return Status;
 }
 
 CSR_API(CsrGetConsoleCodePage)
@@ -3178,14 +2874,14 @@ CSR_API(CsrGetConsoleCodePage)
   Status = ConioConsoleFromProcessData(ProcessData, &Console);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
 
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
   Request->Data.GetConsoleCodePage.CodePage = Console->CodePage;
   ConioUnlockConsole(Console);
-  return Request->Status = STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }
 
 CSR_API(CsrSetConsoleCodePage)
@@ -3198,19 +2894,21 @@ CSR_API(CsrSetConsoleCodePage)
   Status = ConioConsoleFromProcessData(ProcessData, &Console);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
 
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
+
   if (IsValidCodePage(Request->Data.SetConsoleCodePage.CodePage))
     {
       Console->CodePage = Request->Data.SetConsoleCodePage.CodePage;
       ConioUnlockConsole(Console);
-      return Request->Status = STATUS_SUCCESS;
+      return STATUS_SUCCESS;
     }
+
   ConioUnlockConsole(Console);
-  return Request->Status = STATUS_UNSUCCESSFUL;
+  return STATUS_INVALID_PARAMETER;
 }
 
 CSR_API(CsrGetConsoleOutputCodePage)
@@ -3223,14 +2921,14 @@ CSR_API(CsrGetConsoleOutputCodePage)
   Status = ConioConsoleFromProcessData(ProcessData, &Console);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
 
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
   Request->Data.GetConsoleOutputCodePage.CodePage = Console->OutputCodePage;
   ConioUnlockConsole(Console);
-  return Request->Status = STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }
 
 CSR_API(CsrSetConsoleOutputCodePage)
@@ -3243,72 +2941,126 @@ CSR_API(CsrSetConsoleOutputCodePage)
   Status = ConioConsoleFromProcessData(ProcessData, &Console);
   if (! NT_SUCCESS(Status))
     {
-      return Request->Status = Status;
+      return Status;
     }
 
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
+
   if (IsValidCodePage(Request->Data.SetConsoleOutputCodePage.CodePage))
     {
       Console->OutputCodePage = Request->Data.SetConsoleOutputCodePage.CodePage;
       ConioUnlockConsole(Console);
-      return Request->Status = STATUS_SUCCESS;
+      return STATUS_SUCCESS;
     }
+
   ConioUnlockConsole(Console);
-  return Request->Status = STATUS_UNSUCCESSFUL;
+  return STATUS_INVALID_PARAMETER;
 }
 
 CSR_API(CsrGetProcessList)
 {
-  PHANDLE Buffer;
+  PDWORD Buffer;
   PCSRSS_CONSOLE Console;
   PCSRSS_PROCESS_DATA current;
   PLIST_ENTRY current_entry;
-  ULONG nItems, nCopied, Length;
+  ULONG nItems = 0;
   NTSTATUS Status;
+  ULONG_PTR Offset;
 
   DPRINT("CsrGetProcessList\n");
 
-  Buffer = Request->Data.GetProcessListRequest.ProcessId;
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
-  nItems = nCopied = 0;
-  Request->Data.GetProcessListRequest.nProcessIdsCopied = 0;
-  Request->Data.GetProcessListRequest.nProcessIdsTotal = 0;
+  Buffer = Request->Data.GetProcessListRequest.ProcessId;
+  Offset = (PBYTE)Buffer - (PBYTE)ProcessData->CsrSectionViewBase;
+  if (Offset >= ProcessData->CsrSectionViewSize
+      || (Request->Data.GetProcessListRequest.nMaxIds * sizeof(DWORD)) > (ProcessData->CsrSectionViewSize - Offset)
+      || Offset & (sizeof(DWORD) - 1))
+  {
+    return STATUS_ACCESS_VIOLATION;
+  }
 
   Status = ConioConsoleFromProcessData(ProcessData, &Console);
   if (! NT_SUCCESS(Status))
   {
-    return Request->Status = Status;
+    return Status;
   }
 
-  DPRINT1("Console_Api Ctrl-C\n");
-
   for(current_entry = Console->ProcessList.Flink;
       current_entry != &Console->ProcessList;
       current_entry = current_entry->Flink)
   {
     current = CONTAINING_RECORD(current_entry, CSRSS_PROCESS_DATA, ProcessEntry);
-    if(++nItems < Request->Data.GetProcessListRequest.nMaxIds)
+    if(++nItems <= Request->Data.GetProcessListRequest.nMaxIds)
     {
-      *(Buffer++) = current->ProcessId;
-      nCopied++;
+      *Buffer++ = (DWORD)current->ProcessId;
     }
   }
 
   ConioUnlockConsole(Console);
 
-  Request->Data.GetProcessListRequest.nProcessIdsCopied = nCopied;
   Request->Data.GetProcessListRequest.nProcessIdsTotal = nItems;
+  return STATUS_SUCCESS;
+}
 
-  Length = CSR_API_MESSAGE_HEADER_SIZE(CSRSS_GET_PROCESS_LIST) + nCopied * sizeof(HANDLE);
-  if (Length > sizeof(CSR_API_MESSAGE))
+CSR_API(CsrGenerateCtrlEvent)
+{
+  PCSRSS_CONSOLE Console;
+  PCSRSS_PROCESS_DATA current;
+  PLIST_ENTRY current_entry;
+  DWORD Group;
+  NTSTATUS Status;
+
+  Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
+  Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
+
+  Status = ConioConsoleFromProcessData(ProcessData, &Console);
+  if (! NT_SUCCESS(Status))
+  {
+    return Status;
+  }
+
+  Group = Request->Data.GenerateCtrlEvent.ProcessGroup;
+  Status = STATUS_INVALID_PARAMETER;
+  for (current_entry = Console->ProcessList.Flink;
+       current_entry != &Console->ProcessList;
+       current_entry = current_entry->Flink)
   {
-     Request->Header.u1.s1.TotalLength = Length;
-     Request->Header.u1.s1.DataLength = Length - sizeof(PORT_MESSAGE);
+    current = CONTAINING_RECORD(current_entry, CSRSS_PROCESS_DATA, ProcessEntry);
+    if (Group == 0 || current->ProcessGroup == Group)
+    {
+      ConioConsoleCtrlEvent(Request->Data.GenerateCtrlEvent.Event, current);
+      Status = STATUS_SUCCESS;
+    }
   }
-  return Request->Status = STATUS_SUCCESS;
+
+  ConioUnlockConsole(Console);
+
+  return Status;
+}
+
+CSR_API(CsrSetScreenBufferSize)
+{
+    NTSTATUS Status;
+    PCSRSS_CONSOLE Console;
+    PCSRSS_SCREEN_BUFFER Buff;
+
+    Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
+    Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
+
+    Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetScreenBufferSize.OutputHandle, &Buff, GENERIC_WRITE);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+    Console = Buff->Header.Console;
+
+    Status = ConioResizeBuffer(Console, Buff, Request->Data.SetScreenBufferSize.Size);
+    ConioUnlockScreenBuffer(Buff);
+
+    return Status;
 }
 
 /* EOF */