[CONSRV]
[reactos.git] / win32ss / user / consrv / console.c
index d522c11..7c76fcd 100644 (file)
@@ -1,21 +1,39 @@
 /*
- * reactos/win32ss/user/consrv/conio.c
- *
- * Console I/O functions
- *
- * ReactOS Operating System
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Console Server DLL
+ * FILE:            win32ss/user/consrv/console.c
+ * PURPOSE:         Console I/O functions
+ * PROGRAMMERS:
  */
 
 /* INCLUDES ******************************************************************/
 
+#include "consrv.h"
+#include "guiconsole.h"
+#include "tuiconsole.h"
+
 #define NDEBUG
-#include "w32csr.h"
 #include <debug.h>
 
 /* FUNCTIONS *****************************************************************/
 
+BOOL FASTCALL
+DtbgIsDesktopVisible(VOID)
+{
+    HWND VisibleDesktopWindow = GetDesktopWindow(); // DESKTOPWNDPROC
+
+    if (VisibleDesktopWindow != NULL &&
+            !IsWindowVisible(VisibleDesktopWindow))
+    {
+        VisibleDesktopWindow = NULL;
+    }
+
+    return VisibleDesktopWindow != NULL;
+}
+
 NTSTATUS FASTCALL
-ConioConsoleFromProcessData(PCSR_PROCESS ProcessData, PCSRSS_CONSOLE *Console)
+ConioConsoleFromProcessData(PCONSOLE_PROCESS_DATA ProcessData,
+                            PCSRSS_CONSOLE *Console)
 {
     PCSRSS_CONSOLE ProcessConsole;
 
@@ -38,30 +56,32 @@ ConioConsoleFromProcessData(PCSR_PROCESS ProcessData, PCSRSS_CONSOLE *Console)
 }
 
 VOID FASTCALL
-ConioConsoleCtrlEventTimeout(DWORD Event, PCSR_PROCESS ProcessData, DWORD Timeout)
+ConioConsoleCtrlEventTimeout(DWORD Event,
+                             PCONSOLE_PROCESS_DATA ProcessData,
+                             DWORD Timeout)
 {
     HANDLE Thread;
 
-    DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData->ClientId.UniqueProcess);
+    DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess);
 
     if (ProcessData->CtrlDispatcher)
     {
-
-        Thread = CreateRemoteThread(ProcessData->ProcessHandle, NULL, 0,
-                                    (LPTHREAD_START_ROUTINE) ProcessData->CtrlDispatcher,
+        Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
+                                    ProcessData->CtrlDispatcher,
                                     UlongToPtr(Event), 0, NULL);
         if (NULL == Thread)
         {
             DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
             return;
         }
+
         WaitForSingleObject(Thread, Timeout);
         CloseHandle(Thread);
     }
 }
 
 VOID FASTCALL
-ConioConsoleCtrlEvent(DWORD Event, PCSR_PROCESS ProcessData)
+ConioConsoleCtrlEvent(DWORD Event, PCONSOLE_PROCESS_DATA ProcessData)
 {
     ConioConsoleCtrlEventTimeout(Event, ProcessData, 0);
 }
@@ -74,19 +94,17 @@ CsrInitConsole(PCSRSS_CONSOLE Console, int ShowCmd)
     PCSRSS_SCREEN_BUFFER NewBuffer;
     BOOL GuiMode;
     WCHAR Title[255];
-    HINSTANCE hInst;
 
     Console->Title.MaximumLength = Console->Title.Length = 0;
     Console->Title.Buffer = NULL;
 
-    hInst = GetModuleHandleW(L"win32csr");
-    if (LoadStringW(hInst,IDS_COMMAND_PROMPT,Title,sizeof(Title)/sizeof(Title[0])))
+    if (LoadStringW(ConSrvDllInstance, IDS_COMMAND_PROMPT, Title, sizeof(Title) / sizeof(Title[0])))
     {
-       RtlCreateUnicodeString(&Console->Title, Title);
+        RtlCreateUnicodeString(&Console->Title, Title);
     }
     else
     {
-       RtlCreateUnicodeString(&Console->Title, L"Command Prompt");
+        RtlCreateUnicodeString(&Console->Title, L"Command Prompt");
     }
 
     Console->ReferenceCount = 0;
@@ -131,31 +149,47 @@ CsrInitConsole(PCSRSS_CONSOLE Console, int ShowCmd)
     /* make console active, and insert into console list */
     Console->ActiveBuffer = (PCSRSS_SCREEN_BUFFER) NewBuffer;
 
-    if (! GuiMode)
+    /*
+     * If we are not in GUI-mode, start the text-mode console. If we fail,
+     * try to start the GUI-mode console (win32k will automatically switch
+     * to graphical mode, therefore no additional code is needed).
+     */
+    if (!GuiMode)
     {
+        DPRINT1("CONSRV: Opening text-mode console\n");
         Status = TuiInitConsole(Console);
-        if (! NT_SUCCESS(Status))
+        if (!NT_SUCCESS(Status))
         {
-            DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
+            DPRINT1("Failed to open text-mode console, switching to gui-mode, Status = 0x%08lx\n", Status);
             GuiMode = TRUE;
         }
     }
-    else /* GuiMode */
+
+    /*
+     * Try to open the GUI-mode console. Two cases are possible:
+     * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
+     *   failed and we start GUI-mode console.
+     * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
+     *   succeeded BUT we failed at starting text-mode console. Then GuiMode
+     *   was switched to TRUE in order to try to open the console in GUI-mode.
+     */
+    if (GuiMode)
     {
+        DPRINT1("CONSRV: Opening GUI-mode console\n");
         Status = GuiInitConsole(Console, ShowCmd);
-        if (! NT_SUCCESS(Status))
+        if (!NT_SUCCESS(Status))
         {
             HeapFree(ConSrvHeap,0, NewBuffer);
             RtlFreeUnicodeString(&Console->Title);
             DeleteCriticalSection(&Console->Lock);
             CloseHandle(Console->ActiveEvent);
-            DPRINT1("GuiInitConsole: failed\n");
+            DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status);
             return Status;
         }
     }
 
     Status = CsrInitConsoleScreenBuffer(Console, NewBuffer);
-    if (! NT_SUCCESS(Status))
+    if (!NT_SUCCESS(Status))
     {
         ConioCleanupConsole(Console);
         RtlFreeUnicodeString(&Console->Title);
@@ -172,16 +206,76 @@ CsrInitConsole(PCSRSS_CONSOLE Console, int ShowCmd)
     return STATUS_SUCCESS;
 }
 
+CSR_API(SrvOpenConsole)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    PCSRSS_OPEN_CONSOLE OpenConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.OpenConsoleRequest;
+    PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+
+    DPRINT("SrvOpenConsole\n");
+
+    OpenConsoleRequest->Handle = INVALID_HANDLE_VALUE;
+
+    RtlEnterCriticalSection(&ProcessData->HandleTableLock);
+
+    DPRINT1("SrvOpenConsole - Checkpoint 1\n");
+    DPRINT1("ProcessData = 0x%p ; ProcessData->Console = 0x%p\n", ProcessData, ProcessData->Console);
+
+    if (ProcessData->Console)
+    {
+        DWORD DesiredAccess = OpenConsoleRequest->Access;
+        DWORD ShareMode = OpenConsoleRequest->ShareMode;
+
+        PCSRSS_CONSOLE Console = ProcessData->Console;
+        Object_t *Object;
+
+        DPRINT1("SrvOpenConsole - Checkpoint 2\n");
+        EnterCriticalSection(&Console->Lock);
+        DPRINT1("SrvOpenConsole - Checkpoint 3\n");
+
+        if (OpenConsoleRequest->HandleType == HANDLE_OUTPUT)
+            Object = &Console->ActiveBuffer->Header;
+        else // HANDLE_INPUT
+            Object = &Console->Header;
+
+        if (((DesiredAccess & GENERIC_READ)  && Object->ExclusiveRead  != 0) ||
+            ((DesiredAccess & GENERIC_WRITE) && Object->ExclusiveWrite != 0) ||
+            (!(ShareMode & FILE_SHARE_READ)  && Object->AccessRead     != 0) ||
+            (!(ShareMode & FILE_SHARE_WRITE) && Object->AccessWrite    != 0))
+        {
+            DPRINT1("Sharing violation\n");
+            Status = STATUS_SHARING_VIOLATION;
+        }
+        else
+        {
+            Status = Win32CsrInsertObject(ProcessData,
+                                          &OpenConsoleRequest->Handle,
+                                          Object,
+                                          DesiredAccess,
+                                          OpenConsoleRequest->Inheritable,
+                                          ShareMode);
+        }
+
+        LeaveCriticalSection(&Console->Lock);
+    }
+
+    RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+
+    return Status;
+}
+
 CSR_API(SrvAllocConsole)
 {
-    PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
-    PCSRSS_CONSOLE Console;
     NTSTATUS Status = STATUS_SUCCESS;
+    PCSRSS_ALLOC_CONSOLE AllocConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AllocConsoleRequest;
+    PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+    PCSRSS_CONSOLE Console;
     BOOLEAN NewConsole = FALSE;
 
     DPRINT("SrvAllocConsole\n");
 
     RtlEnterCriticalSection(&ProcessData->HandleTableLock);
+
     if (ProcessData->Console)
     {
         DPRINT1("Process already has a console\n");
@@ -189,8 +283,10 @@ CSR_API(SrvAllocConsole)
         return STATUS_INVALID_PARAMETER;
     }
 
+    DPRINT1("SrvAllocConsole - Checkpoint 1\n");
+
     /* If we don't need a console, then get out of here */
-    if (!ApiMessage->Data.AllocConsoleRequest.ConsoleNeeded)
+    if (!AllocConsoleRequest->ConsoleNeeded)
     {
         DPRINT("No console needed\n");
         RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
@@ -198,8 +294,8 @@ CSR_API(SrvAllocConsole)
     }
 
     /* If we already have one, then don't create a new one... */
-    if (!ApiMessage->Data.AllocConsoleRequest.Console ||
-            ApiMessage->Data.AllocConsoleRequest.Console != ProcessData->ParentConsole)
+    if (!AllocConsoleRequest->Console ||
+         AllocConsoleRequest->Console != ProcessData->ParentConsole)
     {
         /* Allocate a console structure */
         NewConsole = TRUE;
@@ -210,12 +306,15 @@ CSR_API(SrvAllocConsole)
             RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
             return STATUS_NO_MEMORY;
         }
-        /* initialize list head */
+
+        /* Initialize list head */
         InitializeListHead(&Console->ProcessList);
-        /* insert process data required for GUI initialization */
+
+        /* Insert process data required for GUI initialization */
         InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
+
         /* Initialize the Console */
-        Status = CsrInitConsole(Console, ApiMessage->Data.AllocConsoleRequest.ShowCmd);
+        Status = CsrInitConsole(Console, AllocConsoleRequest->ShowCmd);
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("Console init failed\n");
@@ -227,14 +326,14 @@ CSR_API(SrvAllocConsole)
     else
     {
         /* Reuse our current console */
-        Console = ApiMessage->Data.AllocConsoleRequest.Console;
+        Console = AllocConsoleRequest->Console;
     }
 
     /* Set the Process Console */
     ProcessData->Console = Console;
 
     /* Return it to the caller */
-    ApiMessage->Data.AllocConsoleRequest.Console = Console;
+    AllocConsoleRequest->Console = Console;
 
     /* Add a reference count because the process is tied to the console */
     _InterlockedIncrement(&Console->ReferenceCount);
@@ -243,7 +342,7 @@ CSR_API(SrvAllocConsole)
     {
         /* Insert the Objects */
         Status = Win32CsrInsertObject(ProcessData,
-                                      &ApiMessage->Data.AllocConsoleRequest.InputHandle,
+                                      &AllocConsoleRequest->InputHandle,
                                       &Console->Header,
                                       GENERIC_READ | GENERIC_WRITE,
                                       TRUE,
@@ -252,13 +351,13 @@ CSR_API(SrvAllocConsole)
         {
             DPRINT1("Failed to insert object\n");
             ConioDeleteConsole((Object_t *) Console);
-            ProcessData->Console = 0;
+            ProcessData->Console = NULL;
             RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
             return Status;
         }
 
         Status = Win32CsrInsertObject(ProcessData,
-                                      &ApiMessage->Data.AllocConsoleRequest.OutputHandle,
+                                      &AllocConsoleRequest->OutputHandle,
                                       &Console->ActiveBuffer->Header,
                                       GENERIC_READ | GENERIC_WRITE,
                                       TRUE,
@@ -268,38 +367,37 @@ CSR_API(SrvAllocConsole)
             DPRINT1("Failed to insert object\n");
             ConioDeleteConsole((Object_t *) Console);
             Win32CsrReleaseObject(ProcessData,
-                                  ApiMessage->Data.AllocConsoleRequest.InputHandle);
-            ProcessData->Console = 0;
+                                  AllocConsoleRequest->InputHandle);
+            ProcessData->Console = NULL;
             RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
             return Status;
         }
     }
 
     /* Duplicate the Event */
-    if (!DuplicateHandle(GetCurrentProcess(),
-                         ProcessData->Console->ActiveEvent,
-                         ProcessData->ProcessHandle,
-                         &ProcessData->ConsoleEvent,
-                         EVENT_ALL_ACCESS,
-                         FALSE,
-                         0))
-    {
-        DPRINT1("DuplicateHandle() failed: %lu\n", GetLastError());
+    Status = NtDuplicateObject(NtCurrentProcess(),
+                               ProcessData->Console->ActiveEvent,
+                               ProcessData->Process->ProcessHandle,
+                               &ProcessData->ConsoleEvent,
+                               EVENT_ALL_ACCESS, 0, 0);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
         ConioDeleteConsole((Object_t *) Console);
         if (NewConsole || !ProcessData->bInheritHandles)
         {
             Win32CsrReleaseObject(ProcessData,
-                                  ApiMessage->Data.AllocConsoleRequest.OutputHandle);
+                                  AllocConsoleRequest->OutputHandle);
             Win32CsrReleaseObject(ProcessData,
-                                  ApiMessage->Data.AllocConsoleRequest.InputHandle);
+                                  AllocConsoleRequest->InputHandle);
         }
-        ProcessData->Console = 0;
+        ProcessData->Console = NULL;
         RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
         return Status;
     }
 
     /* Set the Ctrl Dispatcher */
-    ProcessData->CtrlDispatcher = ApiMessage->Data.AllocConsoleRequest.CtrlDispatcher;
+    ProcessData->CtrlDispatcher = AllocConsoleRequest->CtrlDispatcher;
     DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher);
 
     if (!NewConsole)
@@ -386,27 +484,26 @@ ConioUnpause(PCSRSS_CONSOLE Console, UINT Flags)
 CSR_API(SrvSetConsoleMode)
 {
     NTSTATUS Status;
+    PCSRSS_CONSOLE_MODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
     PCSRSS_CONSOLE Console;
     PCSRSS_SCREEN_BUFFER Buff;
 
     DPRINT("SrvSetConsoleMode\n");
 
-    Status = Win32CsrLockObject(CsrGetClientThread()->Process,
-                                ApiMessage->Data.SetConsoleModeRequest.ConsoleHandle,
+    Status = Win32CsrLockObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                                ConsoleModeRequest->ConsoleHandle,
                                 (Object_t **) &Console, GENERIC_WRITE, 0);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
+    if (!NT_SUCCESS(Status)) return Status;
 
     Buff = (PCSRSS_SCREEN_BUFFER)Console;
+
     if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
     {
-        Console->Mode = ApiMessage->Data.SetConsoleModeRequest.Mode & CONSOLE_INPUT_MODE_VALID;
+        Console->Mode = ConsoleModeRequest->ConsoleMode & CONSOLE_INPUT_MODE_VALID;
     }
     else if (CONIO_SCREEN_BUFFER_MAGIC == Console->Header.Type)
     {
-        Buff->Mode = ApiMessage->Data.SetConsoleModeRequest.Mode & CONSOLE_OUTPUT_MODE_VALID;
+        Buff->Mode = ConsoleModeRequest->ConsoleMode & CONSOLE_OUTPUT_MODE_VALID;
     }
     else
     {
@@ -421,26 +518,27 @@ CSR_API(SrvSetConsoleMode)
 CSR_API(SrvGetConsoleMode)
 {
     NTSTATUS Status;
+    PCSRSS_CONSOLE_MODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
     PCSRSS_CONSOLE Console;
-    PCSRSS_SCREEN_BUFFER Buff;   /* gee, I really wish I could use an anonymous union here */
+    PCSRSS_SCREEN_BUFFER Buff;
 
     DPRINT("SrvGetConsoleMode\n");
 
-    Status = Win32CsrLockObject(CsrGetClientThread()->Process, ApiMessage->Data.GetConsoleModeRequest.ConsoleHandle,
+    Status = Win32CsrLockObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                                ConsoleModeRequest->ConsoleHandle,
                                 (Object_t **) &Console, GENERIC_READ, 0);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
+    if (!NT_SUCCESS(Status)) return Status;
+
     Status = STATUS_SUCCESS;
     Buff = (PCSRSS_SCREEN_BUFFER) Console;
+
     if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
     {
-        ApiMessage->Data.GetConsoleModeRequest.ConsoleMode = Console->Mode;
+        ConsoleModeRequest->ConsoleMode = Console->Mode;
     }
     else if (CONIO_SCREEN_BUFFER_MAGIC == Buff->Header.Type)
     {
-        ApiMessage->Data.GetConsoleModeRequest.ConsoleMode = Buff->Mode;
+        ConsoleModeRequest->ConsoleMode = Buff->Mode;
     }
     else
     {
@@ -454,30 +552,41 @@ CSR_API(SrvGetConsoleMode)
 CSR_API(SrvSetConsoleTitle)
 {
     NTSTATUS Status;
-    PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
+    PCSRSS_CONSOLE_TITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
+    // PCSR_PROCESS Process = CsrGetClientThread()->Process;
     PCSRSS_CONSOLE Console;
     PWCHAR Buffer;
 
     DPRINT("SrvSetConsoleTitle\n");
 
-    if (!Win32CsrValidateBuffer(ProcessData, ApiMessage->Data.SetTitleRequest.Title,
-                                ApiMessage->Data.SetTitleRequest.Length, 1))
+    if (!CsrValidateMessageBuffer(ApiMessage,
+                                  (PVOID)&TitleRequest->Title,
+                                  TitleRequest->Length,
+                                  sizeof(BYTE)))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+/*
+    if (!Win32CsrValidateBuffer(Process, TitleRequest->Title,
+                                TitleRequest->Length, 1))
     {
         return STATUS_ACCESS_VIOLATION;
     }
+*/
 
-    Status = ConioConsoleFromProcessData(ProcessData, &Console);
+    Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
     if(NT_SUCCESS(Status))
     {
-        Buffer =  RtlAllocateHeap(RtlGetProcessHeap(), 0, ApiMessage->Data.SetTitleRequest.Length);
+        Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, TitleRequest->Length);
         if (Buffer)
         {
-            /* copy title to console */
+            /* Copy title to console */
             RtlFreeUnicodeString(&Console->Title);
             Console->Title.Buffer = Buffer;
-            Console->Title.Length = Console->Title.MaximumLength = ApiMessage->Data.SetTitleRequest.Length;
-            memcpy(Console->Title.Buffer, ApiMessage->Data.SetTitleRequest.Title, Console->Title.Length);
-            if (! ConioChangeTitle(Console))
+            Console->Title.Length = Console->Title.MaximumLength = TitleRequest->Length;
+            memcpy(Console->Title.Buffer, TitleRequest->Title, Console->Title.Length);
+
+            if (!ConioChangeTitle(Console))
             {
                 Status = STATUS_UNSUCCESSFUL;
             }
@@ -490,6 +599,7 @@ CSR_API(SrvSetConsoleTitle)
         {
             Status = STATUS_NO_MEMORY;
         }
+
         ConioUnlockConsole(Console);
     }
 
@@ -499,53 +609,62 @@ CSR_API(SrvSetConsoleTitle)
 CSR_API(SrvGetConsoleTitle)
 {
     NTSTATUS Status;
-    PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
+    PCSRSS_CONSOLE_TITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
+    // PCSR_PROCESS Process = CsrGetClientThread()->Process;
     PCSRSS_CONSOLE Console;
     DWORD Length;
 
     DPRINT("SrvGetConsoleTitle\n");
 
-
-    if (!Win32CsrValidateBuffer(ProcessData, ApiMessage->Data.GetTitleRequest.Title,
-                                ApiMessage->Data.GetTitleRequest.Length, 1))
+    if (!CsrValidateMessageBuffer(ApiMessage,
+                                  (PVOID)&TitleRequest->Title,
+                                  TitleRequest->Length,
+                                  sizeof(BYTE)))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+/*
+    if (!Win32CsrValidateBuffer(Process, TitleRequest->Title,
+                                TitleRequest->Length, 1))
     {
         return STATUS_ACCESS_VIOLATION;
     }
+*/
 
-    Status = ConioConsoleFromProcessData(ProcessData, &Console);
-    if (! NT_SUCCESS(Status))
+    Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
+    if (!NT_SUCCESS(Status))
     {
         DPRINT1("Can't get console\n");
         return Status;
     }
 
     /* Copy title of the console to the user title buffer */
-    if (ApiMessage->Data.GetTitleRequest.Length >= sizeof(WCHAR))
+    if (TitleRequest->Length >= sizeof(WCHAR))
     {
-        Length = min(ApiMessage->Data.GetTitleRequest.Length - sizeof(WCHAR), Console->Title.Length);
-        memcpy(ApiMessage->Data.GetTitleRequest.Title, Console->Title.Buffer, Length);
-        ApiMessage->Data.GetTitleRequest.Title[Length / sizeof(WCHAR)] = L'\0';
+        Length = min(TitleRequest->Length - sizeof(WCHAR), Console->Title.Length);
+        memcpy(TitleRequest->Title, Console->Title.Buffer, Length);
+        TitleRequest->Title[Length / sizeof(WCHAR)] = L'\0';
     }
 
-    ApiMessage->Data.GetTitleRequest.Length = Console->Title.Length;
+    TitleRequest->Length = Console->Title.Length;
 
     ConioUnlockConsole(Console);
     return STATUS_SUCCESS;
 }
 
 /**********************************************************************
- *     HardwareStateProperty
+ *  HardwareStateProperty
  *
- *     DESCRIPTION
- *             Set/Get the value of the HardwareState and switch
- *             between direct video buffer ouput and GDI windowed
- *             output.
- *     ARGUMENTS
- *             Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
- *             object. We use the same object to Request.
- *     NOTE
- *             ConsoleHwState has the correct size to be compatible
- *             with NT's, but values are not.
+ *  DESCRIPTION
+ *      Set/Get the value of the HardwareState and switch
+ *      between direct video buffer ouput and GDI windowed
+ *      output.
+ *  ARGUMENTS
+ *      Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
+ *      object. We use the same object to Request.
+ *  NOTE
+ *      ConsoleHwState has the correct size to be compatible
+ *      with NT's, but values are not.
  */
 static NTSTATUS FASTCALL
 SetConsoleHardwareState(PCSRSS_CONSOLE Console, DWORD ConsoleHwState)
@@ -570,36 +689,23 @@ SetConsoleHardwareState(PCSRSS_CONSOLE Console, DWORD ConsoleHwState)
 
 CSR_API(SrvGetConsoleHardwareState)
 {
-    PCSRSS_CONSOLE Console;
     NTSTATUS Status;
+    PCSRSS_CONSOLE_HW_STATE ConsoleHardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleHardwareStateRequest;
+    PCSRSS_CONSOLE Console;
 
     DPRINT("SrvGetConsoleHardwareState\n");
 
-    Status = ConioLockConsole(CsrGetClientThread()->Process,
-                              ApiMessage->Data.ConsoleHardwareStateRequest.ConsoleHandle,
+    Status = ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                              ConsoleHardwareStateRequest->ConsoleHandle,
                               &Console,
                               GENERIC_READ);
-    if (! NT_SUCCESS(Status))
+    if (!NT_SUCCESS(Status))
     {
-        DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
+        DPRINT1("Failed to get console handle in SrvGetConsoleHardwareState\n");
         return Status;
     }
 
-    switch (ApiMessage->Data.ConsoleHardwareStateRequest.SetGet)
-    {
-    case CONSOLE_HARDWARE_STATE_GET:
-        ApiMessage->Data.ConsoleHardwareStateRequest.State = Console->HardwareState;
-        break;
-
-    case CONSOLE_HARDWARE_STATE_SET:
-        DPRINT("Setting console hardware state.\n");
-        Status = SetConsoleHardwareState(Console, ApiMessage->Data.ConsoleHardwareStateRequest.State);
-        break;
-
-    default:
-        Status = STATUS_INVALID_PARAMETER_2; /* Client: (handle, [set_get], mode) */
-        break;
-    }
+    ConsoleHardwareStateRequest->State = Console->HardwareState;
 
     ConioUnlockConsole(Console);
 
@@ -608,36 +714,24 @@ CSR_API(SrvGetConsoleHardwareState)
 
 CSR_API(SrvSetConsoleHardwareState)
 {
-    PCSRSS_CONSOLE Console;
     NTSTATUS Status;
+    PCSRSS_CONSOLE_HW_STATE ConsoleHardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleHardwareStateRequest;
+    PCSRSS_CONSOLE Console;
 
     DPRINT("SrvSetConsoleHardwareState\n");
 
-    Status = ConioLockConsole(CsrGetClientThread()->Process,
-                              ApiMessage->Data.ConsoleHardwareStateRequest.ConsoleHandle,
+    Status = ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+                              ConsoleHardwareStateRequest->ConsoleHandle,
                               &Console,
                               GENERIC_READ);
-    if (! NT_SUCCESS(Status))
+    if (!NT_SUCCESS(Status))
     {
-        DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
+        DPRINT1("Failed to get console handle in SrvSetConsoleHardwareState\n");
         return Status;
     }
 
-    switch (ApiMessage->Data.ConsoleHardwareStateRequest.SetGet)
-    {
-    case CONSOLE_HARDWARE_STATE_GET:
-        ApiMessage->Data.ConsoleHardwareStateRequest.State = Console->HardwareState;
-        break;
-
-    case CONSOLE_HARDWARE_STATE_SET:
-        DPRINT("Setting console hardware state.\n");
-        Status = SetConsoleHardwareState(Console, ApiMessage->Data.ConsoleHardwareStateRequest.State);
-        break;
-
-    default:
-        Status = STATUS_INVALID_PARAMETER_2; /* Client: (handle, [set_get], mode) */
-        break;
-    }
+    DPRINT("Setting console hardware state.\n");
+    Status = SetConsoleHardwareState(Console, ConsoleHardwareStateRequest->State);
 
     ConioUnlockConsole(Console);
 
@@ -646,18 +740,16 @@ CSR_API(SrvSetConsoleHardwareState)
 
 CSR_API(SrvGetConsoleWindow)
 {
-    PCSRSS_CONSOLE Console;
     NTSTATUS Status;
+    PCSRSS_GET_CONSOLE_WINDOW GetConsoleWindowRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleWindowRequest;
+    PCSRSS_CONSOLE Console;
 
     DPRINT("SrvGetConsoleWindow\n");
 
-    Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
+    Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
+    if (!NT_SUCCESS(Status)) return Status;
 
-    ApiMessage->Data.GetConsoleWindowRequest.WindowHandle = Console->hWindow;
+    GetConsoleWindowRequest->WindowHandle = Console->hWindow;
     ConioUnlockConsole(Console);
 
     return STATUS_SUCCESS;
@@ -665,19 +757,19 @@ CSR_API(SrvGetConsoleWindow)
 
 CSR_API(SrvSetConsoleIcon)
 {
-    PCSRSS_CONSOLE Console;
     NTSTATUS Status;
+    PCSRSS_SET_CONSOLE_ICON SetConsoleIconRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetConsoleIconRequest;
+    PCSRSS_CONSOLE Console;
 
     DPRINT("SrvSetConsoleIcon\n");
 
-    Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
+    Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    Status = (ConioChangeIcon(Console, SetConsoleIconRequest->WindowIcon)
+                ? STATUS_SUCCESS
+                : STATUS_UNSUCCESSFUL);
 
-    Status = (ConioChangeIcon(Console, ApiMessage->Data.SetConsoleIconRequest.WindowIcon)
-              ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
     ConioUnlockConsole(Console);
 
     return Status;
@@ -685,80 +777,41 @@ CSR_API(SrvSetConsoleIcon)
 
 CSR_API(SrvGetConsoleCP)
 {
-    PCSRSS_CONSOLE Console;
     NTSTATUS Status;
-
-    DPRINT("SrvGetConsoleCP\n");
-
-    Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-
-    ApiMessage->Data.GetConsoleCodePage.CodePage = Console->CodePage;
-    ConioUnlockConsole(Console);
-    return STATUS_SUCCESS;
-}
-
-CSR_API(CsrGetConsoleOutputCodePage) // TODO: Merge this function with the other one.
-{
+    PCSRSS_CONSOLE_CP ConsoleCPRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleCPRequest;
     PCSRSS_CONSOLE Console;
-    NTSTATUS Status;
 
-    DPRINT("CsrGetConsoleOutputCodePage\n");
+    DPRINT("SrvGetConsoleCP, getting %s Code Page\n",
+            ConsoleCPRequest->InputCP ? "Input" : "Output");
 
-    Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
+    Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
+    if (!NT_SUCCESS(Status)) return Status;
 
-    ApiMessage->Data.GetConsoleOutputCodePage.CodePage = Console->OutputCodePage;
+    ConsoleCPRequest->CodePage = (ConsoleCPRequest->InputCP ? Console->CodePage
+                                                            : Console->OutputCodePage);
     ConioUnlockConsole(Console);
     return STATUS_SUCCESS;
 }
 
 CSR_API(SrvSetConsoleCP)
 {
-    PCSRSS_CONSOLE Console;
     NTSTATUS Status;
-
-    DPRINT("SrvSetConsoleCP\n");
-
-    Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-
-    if (IsValidCodePage(ApiMessage->Data.SetConsoleCodePage.CodePage))
-    {
-        Console->CodePage = ApiMessage->Data.SetConsoleCodePage.CodePage;
-        ConioUnlockConsole(Console);
-        return STATUS_SUCCESS;
-    }
-
-    ConioUnlockConsole(Console);
-    return STATUS_INVALID_PARAMETER;
-}
-
-CSR_API(CsrSetConsoleOutputCodePage) // TODO: Merge this function with the other one.
-{
+    PCSRSS_CONSOLE_CP ConsoleCPRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleCPRequest;
     PCSRSS_CONSOLE Console;
-    NTSTATUS Status;
 
-    DPRINT("CsrSetConsoleOutputCodePage\n");
+    DPRINT("SrvSetConsoleCP, setting %s Code Page\n",
+            ConsoleCPRequest->InputCP ? "Input" : "Output");
 
-    Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
+    Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
+    if (!NT_SUCCESS(Status)) return Status;
 
-    if (IsValidCodePage(ApiMessage->Data.SetConsoleOutputCodePage.CodePage))
+    if (IsValidCodePage(ConsoleCPRequest->CodePage))
     {
-        Console->OutputCodePage = ApiMessage->Data.SetConsoleOutputCodePage.CodePage;
+        if (ConsoleCPRequest->InputCP)
+            Console->CodePage = ConsoleCPRequest->CodePage;
+        else
+            Console->OutputCodePage = ConsoleCPRequest->CodePage;
+
         ConioUnlockConsole(Console);
         return STATUS_SUCCESS;
     }
@@ -769,67 +822,74 @@ CSR_API(CsrSetConsoleOutputCodePage) // TODO: Merge this function with the other
 
 CSR_API(SrvGetConsoleProcessList)
 {
+    NTSTATUS Status;
+    PCSRSS_GET_PROCESS_LIST GetProcessListRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetProcessListRequest;
     PDWORD Buffer;
-    PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
+    // PCSR_PROCESS Process = CsrGetClientThread()->Process;
     PCSRSS_CONSOLE Console;
-    PCSR_PROCESS current;
+    PCONSOLE_PROCESS_DATA current;
     PLIST_ENTRY current_entry;
     ULONG nItems = 0;
-    NTSTATUS Status;
 
     DPRINT("SrvGetConsoleProcessList\n");
 
-    Buffer = ApiMessage->Data.GetProcessListRequest.ProcessId;
-    if (!Win32CsrValidateBuffer(ProcessData, Buffer, ApiMessage->Data.GetProcessListRequest.nMaxIds, sizeof(DWORD)))
-        return STATUS_ACCESS_VIOLATION;
-
-    Status = ConioConsoleFromProcessData(ProcessData, &Console);
-    if (! NT_SUCCESS(Status))
+    if (!CsrValidateMessageBuffer(ApiMessage,
+                                  (PVOID)&GetProcessListRequest->pProcessIds,
+                                  GetProcessListRequest->nMaxIds,
+                                  sizeof(DWORD)))
     {
-        return Status;
+        return STATUS_INVALID_PARAMETER;
     }
 
+    Buffer = GetProcessListRequest->pProcessIds;
+
+/*
+    if (!Win32CsrValidateBuffer(ProcessData, Buffer, GetProcessListRequest->nMaxIds, sizeof(DWORD)))
+        return STATUS_ACCESS_VIOLATION;
+*/
+
+    Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
+    if (!NT_SUCCESS(Status)) return Status;
+
     for (current_entry = Console->ProcessList.Flink;
          current_entry != &Console->ProcessList;
          current_entry = current_entry->Flink)
     {
-        current = CONTAINING_RECORD(current_entry, CSR_PROCESS, ConsoleLink);
-        if (++nItems <= ApiMessage->Data.GetProcessListRequest.nMaxIds)
+        current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
+        if (++nItems <= GetProcessListRequest->nMaxIds)
         {
-            *Buffer++ = HandleToUlong(current->ClientId.UniqueProcess);
+            *Buffer++ = HandleToUlong(current->Process->ClientId.UniqueProcess);
         }
     }
 
     ConioUnlockConsole(Console);
 
-    ApiMessage->Data.GetProcessListRequest.nProcessIdsTotal = nItems;
+    GetProcessListRequest->nProcessIdsTotal = nItems;
     return STATUS_SUCCESS;
 }
 
 CSR_API(SrvGenerateConsoleCtrlEvent)
 {
+    NTSTATUS Status;
+    PCSRSS_GENERATE_CTRL_EVENT GenerateCtrlEvent = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GenerateCtrlEvent;
     PCSRSS_CONSOLE Console;
-    PCSR_PROCESS current;
+    PCONSOLE_PROCESS_DATA current;
     PLIST_ENTRY current_entry;
     DWORD Group;
-    NTSTATUS Status;
 
-    Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
+    Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
+    if (!NT_SUCCESS(Status)) return Status;
 
-    Group = ApiMessage->Data.GenerateCtrlEvent.ProcessGroup;
+    Group = GenerateCtrlEvent->ProcessGroup;
     Status = STATUS_INVALID_PARAMETER;
-    for (current_entry = Console->ProcessList.Flink;
-            current_entry != &Console->ProcessList;
-            current_entry = current_entry->Flink)
+    for (current_entry  = Console->ProcessList.Flink;
+         current_entry != &Console->ProcessList;
+         current_entry  = current_entry->Flink)
     {
-        current = CONTAINING_RECORD(current_entry, CSR_PROCESS, ConsoleLink);
-        if (Group == 0 || current->ProcessGroupId == Group)
+        current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
+        if (Group == 0 || current->Process->ProcessGroupId == Group)
         {
-            ConioConsoleCtrlEvent(ApiMessage->Data.GenerateCtrlEvent.Event, current);
+            ConioConsoleCtrlEvent(GenerateCtrlEvent->Event, current);
             Status = STATUS_SUCCESS;
         }
     }
@@ -842,16 +902,18 @@ CSR_API(SrvGenerateConsoleCtrlEvent)
 CSR_API(SrvGetConsoleSelectionInfo)
 {
     NTSTATUS Status;
+    PCSRSS_GET_CONSOLE_SELECTION_INFO GetConsoleSelectionInfo = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleSelectionInfo;
     PCSRSS_CONSOLE Console;
 
-    Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
+    Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
     if (NT_SUCCESS(Status))
     {
-        memset(&ApiMessage->Data.GetConsoleSelectionInfo.Info, 0, sizeof(CONSOLE_SELECTION_INFO));
+        memset(&GetConsoleSelectionInfo->Info, 0, sizeof(CONSOLE_SELECTION_INFO));
         if (Console->Selection.dwFlags != 0)
-            ApiMessage->Data.GetConsoleSelectionInfo.Info = Console->Selection;
+            GetConsoleSelectionInfo->Info = Console->Selection;
         ConioUnlockConsole(Console);
     }
+
     return Status;
 }