- RtlReAllocateHeap shouldn't allocate memory if ptr == NULL.
[reactos.git] / reactos / lib / kernel32 / misc / console.c
index 98e3283..b93f0c8 100644 (file)
@@ -1,10 +1,11 @@
-/* $Id: console.c,v 1.32 2001/04/04 22:21:30 dwelch Exp $
+/* $Id: console.c,v 1.79 2004/08/28 22:14:08 navaraf Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
  * FILE:            lib/kernel32/misc/console.c
  * PURPOSE:         Win32 server console functions
- * PROGRAMMER:      ???
+ * PROGRAMMER:      James Tabor 
+ *                     <jimtabor@adsl-64-217-116-74.dsl.hstntx.swbell.net>
  * UPDATE HISTORY:
  *     199901?? ??     Created
  *     19990204 EA     SetConsoleTitleA
 
 /* INCLUDES ******************************************************************/
 
-#include <ddk/ntddk.h>
-#include <ddk/ntddblue.h>
-#include <windows.h>
-#include <assert.h>
-#include <wchar.h>
-
-#include <csrss/csrss.h>
-#include <ntdll/csr.h>
+#include <k32.h>
 
 #define NDEBUG
-#include <kernel32/kernel32.h>
-#include <kernel32/error.h>
+#include "../include/debug.h"
+
+#define _NOACHS(__X) (sizeof(__X) / sizeof((__X)[0]))
+extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event);
+extern __declspec(noreturn) VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag);
+extern CRITICAL_SECTION ConsoleLock;
+extern BOOL WINAPI IsDebuggerPresent(VOID);
+
 
 /* GLOBALS *******************************************************************/
 
 static BOOL IgnoreCtrlEvents = FALSE;
-static ULONG NrCtrlHandlers = 0;
+
 static PHANDLER_ROUTINE* CtrlHandlers = NULL;
+static ULONG NrCtrlHandlers = 0;
+
+/* Default Console Control Handler *******************************************/
+
+BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event)
+{
+       switch(Event)
+       {
+       case CTRL_C_EVENT:
+               DPRINT("Ctrl-C Event\n");
+               ExitProcess(0);
+               break;
+               
+       case CTRL_BREAK_EVENT:
+               DPRINT("Ctrl-Break Event\n");
+               ExitProcess(0);
+               break;
+
+       case CTRL_SHUTDOWN_EVENT:
+               DPRINT("Ctrl Shutdown Event\n");
+               break;
+
+       case CTRL_CLOSE_EVENT:
+               DPRINT("Ctrl Close Event\n");
+               break;
+
+       case CTRL_LOGOFF_EVENT:         
+               DPRINT("Ctrl Logoff Event\n");
+               break;
+       }
+//     ExitProcess((UINT)&ExitCode);
+       return TRUE;
+}
+
+
+__declspec(noreturn) VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag)
+{
+DWORD nExitCode = 0;
+DWORD nCode = CodeAndFlag & MAXLONG;
+UINT i;
+
+SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
+
+       switch(nCode)
+       {
+       case CTRL_C_EVENT:
+       case CTRL_BREAK_EVENT:
+       {
+               if(IsDebuggerPresent())
+               {
+                       EXCEPTION_RECORD erException;
+                       erException.ExceptionCode = 
+                       (nCode == CTRL_C_EVENT ? DBG_CONTROL_C : DBG_CONTROL_BREAK);
+                       erException.ExceptionFlags = 0;
+                       erException.ExceptionRecord = NULL;
+                       erException.ExceptionAddress = &DefaultConsoleCtrlHandler;
+                       erException.NumberParameters = 0;
+                       RtlRaiseException(&erException);
+               }               
+               RtlEnterCriticalSection(&ConsoleLock);
+
+               if(!(nCode == CTRL_C_EVENT &&
+                       NtCurrentPeb()->ProcessParameters->ProcessGroup & 1))
+               {
+                       for(i = NrCtrlHandlers; i > 0; -- i)
+                               if(CtrlHandlers[i - 1](nCode)) break;
+               }
+               RtlLeaveCriticalSection(&ConsoleLock);
+               ExitThread(0);
+       }
+       case CTRL_CLOSE_EVENT:
+       case CTRL_LOGOFF_EVENT:
+       case CTRL_SHUTDOWN_EVENT:
+               break;
+
+       default: ExitThread(0);
+       }
+
+       RtlEnterCriticalSection(&ConsoleLock);
+
+       if(!(nCode == CTRL_C_EVENT &&
+               NtCurrentPeb()->ProcessParameters->ProcessGroup & 1))
+       {
+       i = NrCtrlHandlers;
+       while(i > 0)
+               {
+               if (i == 1 && (CodeAndFlag & MINLONG) && 
+                       (nCode == CTRL_LOGOFF_EVENT || nCode == CTRL_SHUTDOWN_EVENT))
+                               break;
+
+                       if(CtrlHandlers[i - 1](nCode))
+                       {
+                               switch(nCode)
+                               {
+                                       case CTRL_CLOSE_EVENT:
+                                       case CTRL_LOGOFF_EVENT:
+                                       case CTRL_SHUTDOWN_EVENT:
+                                               nExitCode = CodeAndFlag;
+                               }
+                               break;
+                       }
+                       --i;
+               }
+       }
+       RtlLeaveCriticalSection(&ConsoleLock);
+       ExitThread(nExitCode);
+}
+
 
 /* FUNCTIONS *****************************************************************/
 
+/*
+ * @unimplemented
+ */
 BOOL STDCALL
-AddConsoleAliasA (DWORD a0,
-                 DWORD a1,
-                 DWORD a2)
-     /*
-      * Undocumented
-      */
+AddConsoleAliasA (LPSTR Source,
+                 LPSTR Target,
+                 LPSTR ExeName)
 {
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
 
+
+/*
+ * @unimplemented
+ */
 BOOL STDCALL
-AddConsoleAliasW (DWORD a0,
-                 DWORD a1,
-                 DWORD a2)
-     /*
-      * Undocumented
-      */
+AddConsoleAliasW (LPWSTR Source,
+                 LPWSTR Target,
+                 LPWSTR ExeName)
 {
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
 
+
+/*
+ * @unimplemented
+ */
 BOOL STDCALL
 ConsoleMenuControl (HANDLE     hConsole,
                    DWORD       Unknown1,
@@ -70,19 +183,45 @@ ConsoleMenuControl (HANDLE hConsole,
   return FALSE;
 }
 
-BOOL STDCALL
+
+/*
+ * @implemented
+ */
+HANDLE STDCALL
 DuplicateConsoleHandle (HANDLE hConsole,
-                       DWORD   Unknown1,
-                       DWORD   Unknown2,
-                       DWORD   Unknown3)
-     /*
-      * Undocumented
-      */
+                       DWORD   dwDesiredAccess,
+                       BOOL    bInheritHandle,
+                       DWORD   dwOptions)
 {
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return FALSE;
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+
+  if (IsConsoleHandle (hConsole) == FALSE)
+    {
+      SetLastError (ERROR_INVALID_PARAMETER);
+      return INVALID_HANDLE_VALUE;
+    }
+  
+  Request.Type = CSRSS_DUPLICATE_HANDLE;
+  Request.Data.DuplicateHandleRequest.Handle = hConsole;
+  Request.Data.DuplicateHandleRequest.ProcessId = GetCurrentProcessId();
+  Status = CsrClientCallServer(&Request,
+                              &Reply,
+                              sizeof(CSRSS_API_REQUEST),
+                              sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status=Reply.Status))
+    {
+      SetLastErrorByStatus(Status);
+      return INVALID_HANDLE_VALUE;
+    }
+  return Reply.Data.DuplicateHandleReply.Handle;
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 ExpungeConsoleCommandHistoryW (DWORD   Unknown0)
      /*
@@ -94,6 +233,9 @@ ExpungeConsoleCommandHistoryW (DWORD Unknown0)
 }
 
 
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 ExpungeConsoleCommandHistoryA (DWORD   Unknown0)
      /*
@@ -104,6 +246,10 @@ ExpungeConsoleCommandHistoryA (DWORD       Unknown0)
   return 0;
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleAliasW (DWORD        Unknown0,
                  DWORD Unknown1,
@@ -118,6 +264,9 @@ GetConsoleAliasW (DWORD     Unknown0,
 }
 
 
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleAliasA (DWORD        Unknown0,
                  DWORD Unknown1,
@@ -131,6 +280,10 @@ GetConsoleAliasA (DWORD    Unknown0,
        return 0;
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleAliasExesW (DWORD    Unknown0,
                      DWORD     Unknown1)
@@ -143,7 +296,9 @@ GetConsoleAliasExesW (DWORD Unknown0,
 }
 
 
-
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleAliasExesA (DWORD    Unknown0,
                      DWORD     Unknown1)
@@ -156,7 +311,9 @@ GetConsoleAliasExesA (DWORD Unknown0,
 }
 
 
-
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleAliasExesLengthA (VOID)
      /*
@@ -167,6 +324,10 @@ GetConsoleAliasExesLengthA (VOID)
   return 0;
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleAliasExesLengthW (VOID)
      /*
@@ -177,6 +338,10 @@ GetConsoleAliasExesLengthW (VOID)
   return 0;
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleAliasesW (DWORD      Unknown0,
                    DWORD       Unknown1,
@@ -189,6 +354,10 @@ GetConsoleAliasesW (DWORD  Unknown0,
   return 0;
 }
  
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleAliasesA (DWORD      Unknown0,
                    DWORD       Unknown1,
@@ -201,6 +370,10 @@ GetConsoleAliasesA (DWORD  Unknown0,
   return 0;
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleAliasesLengthW (DWORD Unknown0)
      /*
@@ -211,6 +384,10 @@ GetConsoleAliasesLengthW (DWORD Unknown0)
   return 0;
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleAliasesLengthA (DWORD Unknown0)
      /*
@@ -221,6 +398,10 @@ GetConsoleAliasesLengthA (DWORD Unknown0)
   return 0;
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleCommandHistoryW (DWORD       Unknown0,
                           DWORD        Unknown1,
@@ -233,6 +414,10 @@ GetConsoleCommandHistoryW (DWORD   Unknown0,
   return 0;
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleCommandHistoryA (DWORD       Unknown0,
                           DWORD        Unknown1,
@@ -245,6 +430,10 @@ GetConsoleCommandHistoryA (DWORD   Unknown0,
   return 0;
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleCommandHistoryLengthW (DWORD Unknown0)
      /*
@@ -255,6 +444,10 @@ GetConsoleCommandHistoryLengthW (DWORD     Unknown0)
   return 0;
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleCommandHistoryLengthA (DWORD Unknown0)
      /*
@@ -265,6 +458,9 @@ GetConsoleCommandHistoryLengthA (DWORD      Unknown0)
   return 0;
 }
 
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleDisplayMode (LPDWORD lpdwMode)
      /*
@@ -279,6 +475,10 @@ GetConsoleDisplayMode (LPDWORD lpdwMode)
   return 0;
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleFontInfo (DWORD      Unknown0,
                    DWORD       Unknown1,
@@ -292,29 +492,55 @@ GetConsoleFontInfo (DWORD Unknown0,
   return 0;
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
-GetConsoleFontSize (DWORD      Unknown0,
-                   DWORD       Unknown1)
-     /*
-      * Undocumented
-      */
+GetConsoleFontSize(HANDLE hConsoleOutput,
+                  DWORD nFont)
 {
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
 
+
+/*
+ * @implemented
+ */
 DWORD STDCALL
-GetConsoleHardwareState (DWORD Unknown0,
-                        DWORD  Unknown1,
-                        DWORD  Unknown2)
+GetConsoleHardwareState (HANDLE        hConsole,
+                        DWORD  Flags,
+                        PDWORD State)
      /*
       * Undocumented
       */
 {
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return 0;
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY   Reply;
+  NTSTATUS          Status;
+
+  Request.Type = CSRSS_SETGET_CONSOLE_HW_STATE;
+  Request.Data.ConsoleHardwareStateRequest.ConsoleHandle = hConsole;
+  Request.Data.ConsoleHardwareStateRequest.SetGet = CONSOLE_HARDWARE_STATE_GET;
+
+  Status = CsrClientCallServer(& Request,
+                              & Reply,
+                              sizeof(CSRSS_API_REQUEST),
+                              sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+  {
+    SetLastErrorByStatus(Status);
+    return FALSE;
+  }
+  *State = Reply.Data.ConsoleHardwareStateReply.State;
+  return TRUE;  
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 GetConsoleInputWaitHandle (VOID)
      /*
@@ -325,18 +551,23 @@ GetConsoleInputWaitHandle (VOID)
   return FALSE;
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
-GetCurrentConsoleFont (DWORD   Unknown0,
-                      DWORD    Unknown1,
-                      DWORD    Unknown2)
-     /*
-      * Undocumented
-      */
+GetCurrentConsoleFont(HANDLE hConsoleOutput,
+                     BOOL bMaximumWindow,
+                     PCONSOLE_FONT_INFO lpConsoleCurrentFont)
 {
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
 
+
+/*
+ * @unimplemented
+ */
 ULONG STDCALL
 GetNumberOfConsoleFonts (VOID)
      /*
@@ -347,6 +578,10 @@ GetNumberOfConsoleFonts (VOID)
   return 1; /* FIXME: call csrss.exe */
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 InvalidateConsoleDIBits (DWORD Unknown0,
                         DWORD  Unknown1)
@@ -358,20 +593,67 @@ InvalidateConsoleDIBits (DWORD    Unknown0,
   return 0;
 }
 
-DWORD STDCALL
-OpenConsoleW (DWORD    Unknown0,
-             DWORD     Unknown1,
-             DWORD     Unknown2,
-             DWORD     Unknown3)
+
+/*
+ * @unimplemented
+ */
+HANDLE STDCALL
+OpenConsoleW (LPWSTR  wsName,
+             DWORD   dwDesiredAccess,
+             BOOL    bInheritHandle,
+             DWORD   dwCreationDistribution)
      /*
       * Undocumented
       */
 {
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return 0;
-}
-
-WINBOOL STDCALL
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY   Reply;
+  PHANDLE           phConsole = NULL;
+  NTSTATUS          Status = STATUS_SUCCESS;
+  
+  
+  if(0 == _wcsicmp(wsName, L"CONIN$"))
+  {
+    Request.Type = CSRSS_GET_INPUT_HANDLE;
+    phConsole = & Reply.Data.GetInputHandleReply.InputHandle;
+  }
+  else if (0 == _wcsicmp(wsName, L"CONOUT$"))
+  {
+    Request.Type = CSRSS_GET_OUTPUT_HANDLE;
+    phConsole = & Reply.Data.GetOutputHandleReply.OutputHandle;
+  }
+  else
+  {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return(INVALID_HANDLE_VALUE);
+  }
+  if ((GENERIC_READ|GENERIC_WRITE) != dwDesiredAccess)
+  {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return(INVALID_HANDLE_VALUE);
+  }
+  if (OPEN_EXISTING != dwCreationDistribution)
+  {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return(INVALID_HANDLE_VALUE);
+  }
+  Status = CsrClientCallServer(& Request,
+                              & Reply,
+                              sizeof(CSRSS_API_REQUEST),
+                              sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+  {
+    SetLastErrorByStatus(Status);
+    return INVALID_HANDLE_VALUE;
+  }
+  return(*phConsole);
+}
+
+
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
 SetConsoleCommandHistoryMode (DWORD    dwMode)
      /*
       * Undocumented
@@ -381,7 +663,11 @@ SetConsoleCommandHistoryMode (DWORD        dwMode)
   return FALSE;
 }
 
-WINBOOL STDCALL
+
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
 SetConsoleCursor (DWORD        Unknown0,
                  DWORD Unknown1)
      /*
@@ -392,7 +678,11 @@ SetConsoleCursor (DWORD    Unknown0,
   return FALSE;
 }
 
-WINBOOL STDCALL
+
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
 SetConsoleDisplayMode (HANDLE hOut,
                       DWORD dwNewMode,
                       LPDWORD lpdwOldMode)
@@ -408,7 +698,11 @@ SetConsoleDisplayMode (HANDLE hOut,
   return FALSE;
 }
 
-WINBOOL STDCALL
+
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
 SetConsoleFont (DWORD  Unknown0,
                DWORD   Unknown1)
      /*
@@ -419,19 +713,44 @@ SetConsoleFont (DWORD     Unknown0,
   return FALSE;
 }
 
-WINBOOL STDCALL
-SetConsoleHardwareState (DWORD Unknown0,
-                        DWORD  Unknown1,
-                        DWORD  Unknown2)
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetConsoleHardwareState (HANDLE        hConsole,
+                        DWORD  Flags,
+                        DWORD  State)
      /*
       * Undocumented
       */
 {
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return FALSE;
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY   Reply;
+  NTSTATUS          Status;
+
+  Request.Type = CSRSS_SETGET_CONSOLE_HW_STATE;
+  Request.Data.ConsoleHardwareStateRequest.ConsoleHandle = hConsole;
+  Request.Data.ConsoleHardwareStateRequest.SetGet = CONSOLE_HARDWARE_STATE_SET;
+  Request.Data.ConsoleHardwareStateRequest.State = State;
+
+  Status = CsrClientCallServer(& Request,
+                              & Reply,
+                              sizeof(CSRSS_API_REQUEST),
+                              sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+  {
+    SetLastErrorByStatus(Status);
+    return FALSE;
+  }
+  return TRUE;  
 }
 
-WINBOOL STDCALL
+
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
 SetConsoleKeyShortcuts (DWORD  Unknown0,
                        DWORD   Unknown1,
                        DWORD   Unknown2,
@@ -444,7 +763,11 @@ SetConsoleKeyShortcuts (DWORD      Unknown0,
   return FALSE;
 }
 
-WINBOOL STDCALL
+
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
 SetConsoleMaximumWindowSize (DWORD     Unknown0,
                             DWORD      Unknown1)
      /*
@@ -455,7 +778,11 @@ SetConsoleMaximumWindowSize (DWORD Unknown0,
   return FALSE;
 }
 
-WINBOOL STDCALL
+
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
 SetConsoleMenuClose (DWORD     Unknown0)
      /*
       * Undocumented
@@ -465,7 +792,11 @@ SetConsoleMenuClose (DWORD Unknown0)
   return FALSE;
 }
 
-WINBOOL STDCALL
+
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
 SetConsoleNumberOfCommandsA (DWORD     Unknown0,
                             DWORD      Unknown1)
      /*
@@ -476,7 +807,11 @@ SetConsoleNumberOfCommandsA (DWORD Unknown0,
   return FALSE;
 }
 
-WINBOOL STDCALL
+
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
 SetConsoleNumberOfCommandsW (DWORD     Unknown0,
                             DWORD      Unknown1)
      /*
@@ -487,7 +822,11 @@ SetConsoleNumberOfCommandsW (DWORD Unknown0,
   return FALSE;
 }
 
-WINBOOL STDCALL
+
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
 SetConsolePalette (DWORD       Unknown0,
                   DWORD        Unknown1,
                   DWORD        Unknown2)
@@ -499,7 +838,11 @@ SetConsolePalette (DWORD   Unknown0,
   return FALSE;
 }
 
-WINBOOL STDCALL
+
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
 SetLastConsoleEventActive (VOID)
      /*
       * Undocumented
@@ -509,6 +852,10 @@ SetLastConsoleEventActive (VOID)
   return FALSE;
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 ShowConsoleCursor (DWORD       Unknown0,
                   DWORD        Unknown1)
@@ -520,16 +867,44 @@ ShowConsoleCursor (DWORD  Unknown0,
   return 0;
 }
 
-DWORD STDCALL
-VerifyConsoleIoHandle (DWORD   Unknown0)
-     /*
-      * Undocumented
-      */
+
+/*
+ * FUNCTION: Checks whether the given handle is a valid console handle.
+ * ARGUMENTS:
+ *      Handle - Handle to be checked
+ * RETURNS:
+ *      TRUE: Handle is a valid console handle
+ *      FALSE: Handle is not a valid console handle.
+ * STATUS: Officially undocumented
+ *
+ * @implemented
+ */
+BOOL STDCALL
+VerifyConsoleIoHandle(HANDLE Handle)
 {
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return 0;
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+
+  Request.Type = CSRSS_VERIFY_HANDLE;
+  Request.Data.VerifyHandleRequest.Handle = Handle;
+  Status = CsrClientCallServer(&Request,
+                              &Reply,
+                              sizeof(CSRSS_API_REQUEST),
+                              sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return FALSE;
+    }
+
+  return (BOOL)NT_SUCCESS(Reply.Status);
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 WriteConsoleInputVDMA (DWORD   Unknown0,
                       DWORD    Unknown1,
@@ -540,6 +915,10 @@ WriteConsoleInputVDMA (DWORD       Unknown0,
   return 0;
 }
 
+
+/*
+ * @unimplemented
+ */
 DWORD STDCALL
 WriteConsoleInputVDMW (DWORD   Unknown0,
                       DWORD    Unknown1,
@@ -550,22 +929,46 @@ WriteConsoleInputVDMW (DWORD      Unknown0,
   return 0;
 }
 
-WINBOOL STDCALL 
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
 CloseConsoleHandle(HANDLE Handle)
      /*
       * Undocumented
       */
 {
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+
   if (IsConsoleHandle (Handle) == FALSE)
     {
       SetLastError (ERROR_INVALID_PARAMETER);
       return FALSE;
     }
-  /* FIXME: call CSRSS */
-  return FALSE;
+
+  Request.Type = CSRSS_CLOSE_HANDLE;
+  Request.Data.CloseHandleRequest.Handle = Handle;
+  Status = CsrClientCallServer(&Request,
+                              &Reply,
+                              sizeof(CSRSS_API_REQUEST),
+                              sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status))
+    {
+       SetLastErrorByStatus(Status);
+       return FALSE;
+    }
+
+  return TRUE;
 }
 
-BOOLEAN STDCALL 
+
+/*
+ * internal function
+ */
+BOOL STDCALL
 IsConsoleHandle(HANDLE Handle)
 {
   if ((((ULONG)Handle) & 0x10000003) == 0x3)
@@ -575,7 +978,11 @@ IsConsoleHandle(HANDLE Handle)
   return(FALSE);
 }
 
-HANDLE STDCALL 
+
+/*
+ * @implemented
+ */
+HANDLE STDCALL
 GetStdHandle(DWORD nStdHandle)
      /*
       * FUNCTION: Get a handle for the standard input, standard output
@@ -587,19 +994,29 @@ GetStdHandle(DWORD nStdHandle)
       */
 {
   PRTL_USER_PROCESS_PARAMETERS Ppb;
-  
-  Ppb = NtCurrentPeb()->ProcessParameters;  
+
+  Ppb = NtCurrentPeb()->ProcessParameters;
   switch (nStdHandle)
     {
-    case STD_INPUT_HANDLE:     return Ppb->InputHandle;
-    case STD_OUTPUT_HANDLE:    return Ppb->OutputHandle;
-    case STD_ERROR_HANDLE:     return Ppb->ErrorHandle;
+      case STD_INPUT_HANDLE:
+       return Ppb->hStdInput;
+
+      case STD_OUTPUT_HANDLE:
+       return Ppb->hStdOutput;
+
+      case STD_ERROR_HANDLE:
+       return Ppb->hStdError;
     }
+
   SetLastError (ERROR_INVALID_PARAMETER);
   return INVALID_HANDLE_VALUE;
 }
 
-WINBASEAPI BOOL WINAPI 
+
+/*
+ * @implemented
+ */
+BOOL WINAPI
 SetStdHandle(DWORD nStdHandle,
             HANDLE hHandle)
      /*
@@ -612,95 +1029,107 @@ SetStdHandle(DWORD nStdHandle,
       */
 {
   PRTL_USER_PROCESS_PARAMETERS Ppb;
-   
+
+  /* no need to check if hHandle == INVALID_HANDLE_VALUE */
+
   Ppb = NtCurrentPeb()->ProcessParameters;
-  
-  /* More checking needed? */
-  if (hHandle == INVALID_HANDLE_VALUE)
-    {
-      SetLastError (ERROR_INVALID_HANDLE);
-      return FALSE;
-    }
-   
-  SetLastError(ERROR_SUCCESS); /* OK */
+
   switch (nStdHandle)
     {
-    case STD_INPUT_HANDLE:
-      Ppb->InputHandle = hHandle;
-      return TRUE;
-    case STD_OUTPUT_HANDLE:
-      Ppb->OutputHandle = hHandle;
-      return TRUE;
-    case STD_ERROR_HANDLE:
-      Ppb->ErrorHandle = hHandle;
-      return TRUE;
+      case STD_INPUT_HANDLE:
+       Ppb->hStdInput = hHandle;
+       return TRUE;
+
+      case STD_OUTPUT_HANDLE:
+       Ppb->hStdOutput = hHandle;
+       return TRUE;
+
+      case STD_ERROR_HANDLE:
+       Ppb->hStdError = hHandle;
+       return TRUE;
     }
-  SetLastError (ERROR_INVALID_PARAMETER);
+
+  /* windows for whatever reason sets the last error to ERROR_INVALID_HANDLE here */
+  SetLastError (ERROR_INVALID_HANDLE);
   return FALSE;
 }
 
 
 /*--------------------------------------------------------------
  *     WriteConsoleA
+ *
+ * @implemented
  */
-WINBOOL STDCALL WriteConsoleA(HANDLE hConsoleOutput,
-                             CONST VOID *lpBuffer,
-                             DWORD nNumberOfCharsToWrite,
-                             LPDWORD lpNumberOfCharsWritten,
-                             LPVOID lpReserved)
-{
-   PCSRSS_API_REQUEST Request;
-   CSRSS_API_REPLY Reply;
-   NTSTATUS Status;
-   WORD Size;
-   
-   Request = RtlAllocateHeap(GetProcessHeap(),
-                      HEAP_ZERO_MEMORY,
-                      sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_WRITE_CONSOLE_REQUEST);
-   if (Request == NULL)
-     {
-       return(FALSE);
-     }
-
-   Request->Type = CSRSS_WRITE_CONSOLE;
-   Request->Data.WriteConsoleRequest.ConsoleHandle = hConsoleOutput;
-   if (lpNumberOfCharsWritten != NULL)
-      *lpNumberOfCharsWritten = nNumberOfCharsToWrite;
-   while( nNumberOfCharsToWrite )
-      {
-        Size = nNumberOfCharsToWrite > CSRSS_MAX_WRITE_CONSOLE_REQUEST ? CSRSS_MAX_WRITE_CONSOLE_REQUEST : nNumberOfCharsToWrite;
-
-        Request->Data.WriteConsoleRequest.NrCharactersToWrite = Size;
+BOOL STDCALL 
+WriteConsoleA(HANDLE hConsoleOutput,
+             CONST VOID *lpBuffer,
+             DWORD nNumberOfCharsToWrite,
+             LPDWORD lpNumberOfCharsWritten,
+             LPVOID lpReserved)
+{
+  PCSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+  USHORT Size;
+  ULONG MessageSize;
+
+  Request = RtlAllocateHeap(GetProcessHeap(), 0,
+                           sizeof(CSRSS_API_REQUEST) +
+                           min(nNumberOfCharsToWrite,
+                           CSRSS_MAX_WRITE_CONSOLE_REQUEST));
+  if (Request == NULL)
+    {
+      SetLastError(ERROR_OUTOFMEMORY);
+      return(FALSE);
+    }
 
-        //   DbgPrint("nNumberOfCharsToWrite %d\n", nNumberOfCharsToWrite);
-        //   DbgPrint("Buffer %s\n", Request->Data.WriteConsoleRequest.Buffer);
-        
-        memcpy( Request->Data.WriteConsoleRequest.Buffer, lpBuffer, Size );
-   
-        Status = CsrClientCallServer(Request,
-                                     &Reply,
-                                     sizeof(CSRSS_WRITE_CONSOLE_REQUEST) + 
-                                     Size,
-                                     sizeof(CSRSS_API_REPLY));
-        
-        if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply.Status ) )
-           {
-              RtlFreeHeap( GetProcessHeap(), 0, Request );
-              SetLastErrorByStatus (Status);
-              return(FALSE);
-           }
-        nNumberOfCharsToWrite -= Size;
-        lpBuffer += Size;
-      }
-   RtlFreeHeap( GetProcessHeap(), 0, Request );
-   return TRUE;
+  Request->Type = CSRSS_WRITE_CONSOLE;
+  Request->Data.WriteConsoleRequest.ConsoleHandle = hConsoleOutput;
+  if (lpNumberOfCharsWritten != NULL)
+    *lpNumberOfCharsWritten = nNumberOfCharsToWrite;
+  while (nNumberOfCharsToWrite)
+    {
+      if (nNumberOfCharsToWrite > CSRSS_MAX_WRITE_CONSOLE_REQUEST)
+       {
+         Size = CSRSS_MAX_WRITE_CONSOLE_REQUEST;
+       }
+      else
+       {
+         Size = nNumberOfCharsToWrite;
+       }
+      Request->Data.WriteConsoleRequest.NrCharactersToWrite = Size;
+
+      memcpy(Request->Data.WriteConsoleRequest.Buffer, lpBuffer, Size);
+
+      MessageSize = CSRSS_REQUEST_HEADER_SIZE + 
+       sizeof(CSRSS_WRITE_CONSOLE_REQUEST) + Size;
+      Status = CsrClientCallServer(Request,
+                                  &Reply,
+                                  MessageSize,
+                                  sizeof(CSRSS_API_REPLY));
+
+      if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+       {
+         RtlFreeHeap(GetProcessHeap(), 0, Request);
+         SetLastErrorByStatus(Status);
+         return(FALSE);
+       }
+      nNumberOfCharsToWrite -= Size;
+      lpBuffer += Size;
+    }
+
+  RtlFreeHeap(GetProcessHeap(), 0, Request);
+
+  return TRUE;
 }
 
 
 /*--------------------------------------------------------------
  *     ReadConsoleA
+ *
+ * @implemented
  */
-WINBOOL STDCALL ReadConsoleA(HANDLE hConsoleInput,
+BOOL STDCALL ReadConsoleA(HANDLE hConsoleInput,
                             LPVOID lpBuffer,
                             DWORD nNumberOfCharsToRead,
                             LPDWORD lpNumberOfCharsRead,
@@ -711,11 +1140,11 @@ WINBOOL STDCALL ReadConsoleA(HANDLE hConsoleInput,
    NTSTATUS Status;
    ULONG CharsRead = 0;
    
-   Reply = RtlAllocateHeap(GetProcessHeap(),
-                    HEAP_ZERO_MEMORY,
-                    sizeof(CSRSS_API_REPLY) + nNumberOfCharsToRead);
+   Reply = RtlAllocateHeap(GetProcessHeap(), 0,
+                           sizeof(CSRSS_API_REPLY) + nNumberOfCharsToRead);
    if (Reply == NULL)
      {
+       SetLastError(ERROR_OUTOFMEMORY);
        return(FALSE);
      }
    
@@ -791,12 +1220,24 @@ WINBOOL STDCALL ReadConsoleA(HANDLE hConsoleInput,
 
 /*--------------------------------------------------------------
  *     AllocConsole
+ *
+ * @implemented
  */
-WINBOOL STDCALL AllocConsole(VOID)
+BOOL STDCALL AllocConsole(VOID)
 {
    CSRSS_API_REQUEST Request;
    CSRSS_API_REPLY Reply;
    NTSTATUS Status;
+   HANDLE hStdError;
+
+   if(NtCurrentPeb()->ProcessParameters->hConsole)
+   {
+       DPRINT("AllocConsole: Allocate duplicate console to the same Process\n");
+       SetLastErrorByStatus (STATUS_OBJECT_NAME_EXISTS); 
+       return FALSE;    
+   }
+
+   Request.Data.AllocConsoleRequest.CtrlDispatcher = (PCONTROLDISPATCHER) &ConsoleControlDispatcher;
 
    Request.Type = CSRSS_ALLOC_CONSOLE;
    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
@@ -805,27 +1246,50 @@ WINBOOL STDCALL AllocConsole(VOID)
         SetLastErrorByStatus ( Status );
         return FALSE;
       }
+   NtCurrentPeb()->ProcessParameters->hConsole = Reply.Data.AllocConsoleReply.Console;
    SetStdHandle( STD_INPUT_HANDLE, Reply.Data.AllocConsoleReply.InputHandle );
    SetStdHandle( STD_OUTPUT_HANDLE, Reply.Data.AllocConsoleReply.OutputHandle );
-   SetStdHandle( STD_ERROR_HANDLE, Reply.Data.AllocConsoleReply.OutputHandle );
+   hStdError = DuplicateConsoleHandle(Reply.Data.AllocConsoleReply.OutputHandle,
+                                      0,
+                                     TRUE,
+                                     DUPLICATE_SAME_ACCESS);
+   SetStdHandle( STD_ERROR_HANDLE, hStdError );
    return TRUE;
 }
 
 
 /*--------------------------------------------------------------
  *     FreeConsole
+ *
+ * @implemented
  */
-WINBOOL STDCALL FreeConsole(VOID)
+BOOL STDCALL FreeConsole(VOID)
 {
-   DbgPrint("FreeConsole() is unimplemented");
-   return FALSE;
+    // AG: I'm not sure if this is correct (what happens to std handles?)
+    // but I just tried to reverse what AllocConsole() does...
+
+   CSRSS_API_REQUEST Request;
+   CSRSS_API_REPLY Reply;
+   NTSTATUS Status;
+
+   Request.Type = CSRSS_FREE_CONSOLE;
+   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
+   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
+      {
+        SetLastErrorByStatus ( Status );
+        return FALSE;
+      }
+
+   return TRUE;
 }
 
 
 /*--------------------------------------------------------------
  *     GetConsoleScreenBufferInfo
+ *
+ * @implemented
  */
-WINBOOL
+BOOL
 STDCALL
 GetConsoleScreenBufferInfo(
     HANDLE hConsoleOutput,
@@ -851,8 +1315,10 @@ GetConsoleScreenBufferInfo(
 
 /*--------------------------------------------------------------
  *     SetConsoleCursorPosition
+ *
+ * @implemented
  */
-WINBOOL
+BOOL
 STDCALL
 SetConsoleCursorPosition(
     HANDLE hConsoleOutput,
@@ -878,9 +1344,10 @@ SetConsoleCursorPosition(
 
 /*--------------------------------------------------------------
  *     FillConsoleOutputCharacterA
+ *
+ * @implemented
  */
-WINBOOL
-STDCALL
+BOOL STDCALL
 FillConsoleOutputCharacterA(
        HANDLE          hConsoleOutput,
        CHAR            cCharacter,
@@ -889,30 +1356,33 @@ FillConsoleOutputCharacterA(
        LPDWORD         lpNumberOfCharsWritten
        )
 {
-   CSRSS_API_REQUEST Request;
-   CSRSS_API_REPLY Reply;
-   NTSTATUS Status;
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
 
-   Request.Type = CSRSS_FILL_OUTPUT;
-   Request.Data.FillOutputRequest.ConsoleHandle = hConsoleOutput;
-   Request.Data.FillOutputRequest.Char = cCharacter;
-   Request.Data.FillOutputRequest.Position = dwWriteCoord;
-   Request.Data.FillOutputRequest.Length = nLength;
-   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
-   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
-      {
-        SetLastErrorByStatus ( Status );
-        return FALSE;
-      }
-   *lpNumberOfCharsWritten = nLength;
-   return TRUE;
+  Request.Type = CSRSS_FILL_OUTPUT;
+  Request.Data.FillOutputRequest.ConsoleHandle = hConsoleOutput;
+  Request.Data.FillOutputRequest.Char = cCharacter;
+  Request.Data.FillOutputRequest.Position = dwWriteCoord;
+  Request.Data.FillOutputRequest.Length = nLength;
+  Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
+  if ( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
+    {
+      SetLastErrorByStatus(Status);
+      return(FALSE);
+    }
+  if (lpNumberOfCharsWritten != NULL)
+     *lpNumberOfCharsWritten = nLength;
+  return(TRUE);
 }
 
 
 /*--------------------------------------------------------------
  *     FillConsoleOutputCharacterW
+ *
+ * @unimplemented
  */
-WINBOOL
+BOOL
 STDCALL
 FillConsoleOutputCharacterW(
        HANDLE          hConsoleOutput,
@@ -923,14 +1393,87 @@ FillConsoleOutputCharacterW(
        )
 {
 /* TO DO */
+       DbgPrint("%s unimplemented\n", __FUNCTION__);
        return FALSE;
 }
 
 
+/*--------------------------------------------------------------
+ *     IntPeekConsoleInput
+ *
+ * INTERNAL
+ */
+BOOL
+WINAPI
+IntPeekConsoleInput(
+       HANDLE                  hConsoleInput,
+       PINPUT_RECORD           lpBuffer,
+       DWORD                   nLength,
+       LPDWORD                 lpNumberOfEventsRead,
+       BOOL                    bUnicode
+       )
+{
+  PCSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+  PVOID BufferBase;
+  PVOID BufferTargetBase;
+  DWORD Size;
+  
+  if(lpBuffer == NULL)
+  {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return FALSE;
+  }
+  
+  Size = nLength * sizeof(INPUT_RECORD);
+
+  Status = CsrCaptureParameterBuffer((PVOID)lpBuffer, Size, &BufferBase, &BufferTargetBase);
+  if(!NT_SUCCESS(Status))
+  {
+    SetLastErrorByStatus(Status);
+    return FALSE;
+  }
+  
+  Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSRSS_API_REQUEST));
+  if(Request == NULL)
+  {
+    CsrReleaseParameterBuffer(BufferBase);
+    SetLastError(ERROR_OUTOFMEMORY);
+    return FALSE;
+  }
+  
+  Request->Type = CSRSS_PEEK_CONSOLE_INPUT;
+  Request->Data.PeekConsoleInputRequest.ConsoleHandle = hConsoleInput;
+  Request->Data.PeekConsoleInputRequest.Unicode = bUnicode;
+  Request->Data.PeekConsoleInputRequest.Length = nLength;
+  Request->Data.PeekConsoleInputRequest.InputRecord = (INPUT_RECORD*)BufferTargetBase;
+  
+  Status = CsrClientCallServer(Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY));
+  
+  if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+  {
+    RtlFreeHeap(GetProcessHeap(), 0, Request);
+    CsrReleaseParameterBuffer(BufferBase);
+    return FALSE;
+  }
+
+  memcpy(lpBuffer, BufferBase, sizeof(INPUT_RECORD) * Reply.Data.PeekConsoleInputReply.Length);
+
+  if(lpNumberOfEventsRead != NULL)
+    *lpNumberOfEventsRead = Reply.Data.PeekConsoleInputReply.Length;
+
+  RtlFreeHeap(GetProcessHeap(), 0, Request);
+  CsrReleaseParameterBuffer(BufferBase);  
+  
+  return TRUE;
+}
+
 /*--------------------------------------------------------------
  *     PeekConsoleInputA
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 PeekConsoleInputA(
@@ -940,15 +1483,16 @@ PeekConsoleInputA(
        LPDWORD                 lpNumberOfEventsRead
        )
 {
-/* TO DO */
-       return FALSE;
+  return IntPeekConsoleInput(hConsoleInput, lpBuffer, nLength,
+                             lpNumberOfEventsRead, FALSE);
 }
 
 
 /*--------------------------------------------------------------
  *     PeekConsoleInputW
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 PeekConsoleInputW(
@@ -958,61 +1502,111 @@ PeekConsoleInputW(
        LPDWORD                 lpNumberOfEventsRead
        )    
 {
-/* TO DO */
-       return FALSE;
+  return IntPeekConsoleInput(hConsoleInput, lpBuffer, nLength,
+                             lpNumberOfEventsRead, TRUE);
 }
 
 
 /*--------------------------------------------------------------
- *     ReadConsoleInputA
+ *     IntReadConsoleInput
+ *
+ * INTERNAL
  */
-WINBASEAPI
-BOOL
-WINAPI
-ReadConsoleInputA(
-       HANDLE                  hConsoleInput,
-       PINPUT_RECORD           lpBuffer,
-       DWORD                   nLength,
-       LPDWORD                 lpNumberOfEventsRead
-       )
+BOOL WINAPI
+IntReadConsoleInput(HANDLE hConsoleInput,
+                    PINPUT_RECORD lpBuffer,
+                    DWORD nLength,
+                    LPDWORD lpNumberOfEventsRead,
+                    BOOL bUnicode)
 {
-   CSRSS_API_REQUEST Request;
-   CSRSS_API_REPLY Reply;
-   NTSTATUS Status;
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  DWORD NumEventsRead;
+  NTSTATUS Status;
 
-   Request.Type = CSRSS_READ_INPUT;
-   Request.Data.ReadInputRequest.ConsoleHandle = hConsoleInput;
-   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
-   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
-      {
-        SetLastErrorByStatus ( Status );
-        return FALSE;
-      }
-   while( Status == STATUS_PENDING )
-      {
-        Status = NtWaitForSingleObject( Reply.Data.ReadInputReply.Event, FALSE, 0 );
-        if( !NT_SUCCESS( Status ) )
-           {
-              SetLastErrorByStatus ( Status );
-              return FALSE;
-           }
-        Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
-        if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
-           {
-              SetLastErrorByStatus ( Status );
-              return FALSE;
-           }
-      }
-   *lpNumberOfEventsRead = 1;
-   *lpBuffer = Reply.Data.ReadInputReply.Input;
-   return TRUE;
+  Request.Type = CSRSS_READ_INPUT;
+  Request.Data.ReadInputRequest.ConsoleHandle = hConsoleInput;
+  Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST),
+                               sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+    {
+      SetLastErrorByStatus(Status);
+      return(FALSE);
+    }
+  
+  while (Status == STATUS_PENDING)
+    {
+      Status = NtWaitForSingleObject(Reply.Data.ReadInputReply.Event, FALSE, 
+                                    0);
+      if(!NT_SUCCESS(Status))
+       {
+         SetLastErrorByStatus(Status);
+         return FALSE;
+       }
+      
+      Request.Type = CSRSS_READ_INPUT;
+      Request.Data.ReadInputRequest.ConsoleHandle = hConsoleInput;
+      Request.Data.ReadInputRequest.Unicode = bUnicode;
+      Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST),
+                                  sizeof(CSRSS_API_REPLY));
+      if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+       {
+         SetLastErrorByStatus(Status);
+         return(FALSE);
+       }
+    }
+  
+  NumEventsRead = 1;
+  *lpBuffer = Reply.Data.ReadInputReply.Input;
+  lpBuffer++;
+  
+  while ((NumEventsRead < nLength) && (Reply.Data.ReadInputReply.MoreEvents))
+    {
+      Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST),
+                                  sizeof(CSRSS_API_REPLY));
+      if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+       {
+         SetLastErrorByStatus(Status);
+         return(FALSE);
+       }
+      
+      if (Status == STATUS_PENDING)
+       {
+         break;
+       }
+      
+      *lpBuffer = Reply.Data.ReadInputReply.Input;
+      lpBuffer++;
+      NumEventsRead++;
+      
+    }
+  *lpNumberOfEventsRead = NumEventsRead;
+  
+  return TRUE;
+}
+
+
+/*--------------------------------------------------------------
+ *     ReadConsoleInputA
+ *
+ * @implemented
+ */
+BOOL WINAPI
+ReadConsoleInputA(HANDLE hConsoleInput,
+                 PINPUT_RECORD lpBuffer,
+                 DWORD nLength,
+                 LPDWORD lpNumberOfEventsRead)
+{
+  return IntReadConsoleInput(hConsoleInput, lpBuffer, nLength,
+                             lpNumberOfEventsRead, FALSE);
 }
 
 
 /*--------------------------------------------------------------
  *     ReadConsoleInputW
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 ReadConsoleInputW(
@@ -1022,15 +1616,16 @@ ReadConsoleInputW(
        LPDWORD                 lpNumberOfEventsRead
        )
 {
-/* TO DO */
-       return FALSE;
+  return IntReadConsoleInput(hConsoleInput, lpBuffer, nLength,
+                             lpNumberOfEventsRead, TRUE);
 }
 
 
 /*--------------------------------------------------------------
  *     WriteConsoleInputA
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 WriteConsoleInputA(
@@ -1040,15 +1635,63 @@ WriteConsoleInputA(
        LPDWORD                  lpNumberOfEventsWritten
        )
 {
-/* TO DO */
-       return FALSE;
+  PCSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  PVOID BufferBase, BufferTargetBase;
+  NTSTATUS Status;
+  DWORD Size;
+  
+  if(lpBuffer == NULL)
+  {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return FALSE;
+  }
+  
+  Size = nLength * sizeof(INPUT_RECORD);
+
+  Status = CsrCaptureParameterBuffer((PVOID)lpBuffer, Size, &BufferBase, &BufferTargetBase);
+  if(!NT_SUCCESS(Status))
+  {
+    SetLastErrorByStatus(Status);
+    return FALSE;
+  }
+  
+  Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSRSS_API_REQUEST));
+  if(Request == NULL)
+  {
+    SetLastError(ERROR_OUTOFMEMORY);
+    CsrReleaseParameterBuffer(BufferBase);
+    return FALSE;
+  }
+
+  Request->Type = CSRSS_WRITE_CONSOLE_INPUT;
+  Request->Data.WriteConsoleInputRequest.ConsoleHandle = hConsoleInput;
+  Request->Data.WriteConsoleInputRequest.Length = nLength;
+  Request->Data.WriteConsoleInputRequest.InputRecord = (PINPUT_RECORD)BufferTargetBase;
+  
+  Status = CsrClientCallServer(Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY));
+  if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+  {
+    RtlFreeHeap(GetProcessHeap(), 0, Request);
+    CsrReleaseParameterBuffer(BufferBase);
+    return FALSE;
+  }
+  
+  if(lpNumberOfEventsWritten != NULL)
+    *lpNumberOfEventsWritten = Reply.Data.WriteConsoleInputReply.Length;
+  
+  RtlFreeHeap(GetProcessHeap(), 0, Request);
+  CsrReleaseParameterBuffer(BufferBase);
+  
+  return TRUE;
 }
 
 
 /*--------------------------------------------------------------
  *     WriteConsoleInputW
+ *
+ * @unimplemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 WriteConsoleInputW(
@@ -1059,14 +1702,91 @@ WriteConsoleInputW(
        )
 {
 /* TO DO */
+       DbgPrint("%s unimplemented\n", __FUNCTION__);
        return FALSE;
 }
 
 
+/*--------------------------------------------------------------
+ *     IntReadConsoleOutput
+ *
+ * INTERNAL
+ */
+BOOL
+WINAPI
+IntReadConsoleOutput(
+       HANDLE          hConsoleOutput,
+       PCHAR_INFO      lpBuffer,
+       COORD           dwBufferSize,
+       COORD           dwBufferCoord,
+       PSMALL_RECT     lpReadRegion,
+       BOOL            bUnicode
+       )
+{
+  PCSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  PVOID BufferBase;
+  PVOID BufferTargetBase;
+  NTSTATUS Status;
+  DWORD Size, SizeX, SizeY;
+  
+  if(lpBuffer == NULL)
+  {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return FALSE;
+  }
+  
+  Size = dwBufferSize.X * dwBufferSize.Y * sizeof(CHAR_INFO);
+
+  Status = CsrCaptureParameterBuffer((PVOID)lpBuffer, Size, &BufferBase, &BufferTargetBase);
+  if(!NT_SUCCESS(Status))
+  {
+    SetLastErrorByStatus(Status);
+    return FALSE;
+  }
+  
+  Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSRSS_API_REQUEST));
+  if(Request == NULL)
+  {
+    SetLastError(ERROR_OUTOFMEMORY);
+    CsrReleaseParameterBuffer(BufferBase);
+    return FALSE;
+  }
+   
+  Request->Type = CSRSS_READ_CONSOLE_OUTPUT;
+  Request->Data.ReadConsoleOutputRequest.ConsoleHandle = hConsoleOutput;
+  Request->Data.ReadConsoleOutputRequest.Unicode = bUnicode;
+  Request->Data.ReadConsoleOutputRequest.BufferSize = dwBufferSize;
+  Request->Data.ReadConsoleOutputRequest.BufferCoord = dwBufferCoord;
+  Request->Data.ReadConsoleOutputRequest.ReadRegion = *lpReadRegion;
+  Request->Data.ReadConsoleOutputRequest.CharInfo = (PCHAR_INFO)BufferTargetBase;
+  
+  Status = CsrClientCallServer(Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY));
+  if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+  {
+    SetLastErrorByStatus(Status);
+    RtlFreeHeap(GetProcessHeap(), 0, Request);
+    CsrReleaseParameterBuffer(BufferBase);
+    return FALSE;
+  }
+  
+  SizeX = Reply.Data.ReadConsoleOutputReply.ReadRegion.Right - Reply.Data.ReadConsoleOutputReply.ReadRegion.Left + 1;
+  SizeY = Reply.Data.ReadConsoleOutputReply.ReadRegion.Bottom - Reply.Data.ReadConsoleOutputReply.ReadRegion.Top + 1;
+  
+  memcpy(lpBuffer, BufferBase, sizeof(CHAR_INFO) * SizeX * SizeY);
+  *lpReadRegion = Reply.Data.ReadConsoleOutputReply.ReadRegion;
+  
+  RtlFreeHeap(GetProcessHeap(), 0, Request);
+  CsrReleaseParameterBuffer(BufferBase);
+  
+  return TRUE;
+}
+
 /*--------------------------------------------------------------
  *     ReadConsoleOutputA
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 ReadConsoleOutputA(
@@ -1077,15 +1797,16 @@ ReadConsoleOutputA(
        PSMALL_RECT     lpReadRegion
        )
 {
-/* TO DO */
-       return FALSE;
+  return IntReadConsoleOutput(hConsoleOutput, lpBuffer, dwBufferSize,
+                             dwBufferCoord, lpReadRegion, FALSE);
 }
 
 
 /*--------------------------------------------------------------
  *     ReadConsoleOutputW
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 ReadConsoleOutputW(
@@ -1096,33 +1817,99 @@ ReadConsoleOutputW(
        PSMALL_RECT     lpReadRegion
        )
 {
-/* TO DO */
-       return FALSE;
+  return IntReadConsoleOutput(hConsoleOutput, lpBuffer, dwBufferSize,
+                             dwBufferCoord, lpReadRegion, TRUE);
+}
+
+
+/*--------------------------------------------------------------
+ *     IntWriteConsoleOutput
+ *
+ * INTERNAL
+ */
+BOOL WINAPI
+IntWriteConsoleOutput(HANDLE           hConsoleOutput,
+                      CONST CHAR_INFO *lpBuffer,
+                      COORD            dwBufferSize,
+                      COORD            dwBufferCoord,
+                      PSMALL_RECT      lpWriteRegion,
+                      BOOL             bUnicode)
+{
+  PCSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+  ULONG Size;
+  PVOID BufferBase;
+  PVOID BufferTargetBase;
+
+  Size = dwBufferSize.Y * dwBufferSize.X * sizeof(CHAR_INFO);
+
+  Status = CsrCaptureParameterBuffer((PVOID)lpBuffer,
+                                    Size,
+                                    &BufferBase,
+                                    &BufferTargetBase);
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return(FALSE);
+    }
+  
+  Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, 
+                           sizeof(CSRSS_API_REQUEST));
+  if (Request == NULL)
+    {
+      CsrReleaseParameterBuffer(BufferBase);
+      SetLastError(ERROR_OUTOFMEMORY);
+      return FALSE;
+    }
+  Request->Type = CSRSS_WRITE_CONSOLE_OUTPUT;
+  Request->Data.WriteConsoleOutputRequest.ConsoleHandle = hConsoleOutput;
+  Request->Data.WriteConsoleOutputRequest.Unicode = bUnicode;
+  Request->Data.WriteConsoleOutputRequest.BufferSize = dwBufferSize;
+  Request->Data.WriteConsoleOutputRequest.BufferCoord = dwBufferCoord;
+  Request->Data.WriteConsoleOutputRequest.WriteRegion = *lpWriteRegion;
+  Request->Data.WriteConsoleOutputRequest.CharInfo = 
+    (CHAR_INFO*)BufferTargetBase;
+  
+  Status = CsrClientCallServer(Request, &Reply, 
+                              sizeof(CSRSS_API_REQUEST), 
+                              sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+    {
+      CsrReleaseParameterBuffer(BufferBase);
+      RtlFreeHeap(GetProcessHeap(), 0, Request);
+      SetLastErrorByStatus(Status);
+      return FALSE;
+    }
+      
+  *lpWriteRegion = Reply.Data.WriteConsoleOutputReply.WriteRegion;
+  RtlFreeHeap(GetProcessHeap(), 0, Request);
+  CsrReleaseParameterBuffer(BufferBase);
+  return(TRUE);
 }
 
 /*--------------------------------------------------------------
  *     WriteConsoleOutputA
+ *
+ * @implemented
  */
-WINBASEAPI
-BOOL
-WINAPI
-WriteConsoleOutputA(
-       HANDLE           hConsoleOutput,
-       CONST CHAR_INFO *lpBuffer,
-       COORD            dwBufferSize,
-       COORD            dwBufferCoord,
-       PSMALL_RECT      lpWriteRegion
-       )
+BOOL WINAPI
+WriteConsoleOutputA(HANDLE              hConsoleOutput,
+                   CONST CHAR_INFO     *lpBuffer,
+                   COORD                dwBufferSize,
+                   COORD                dwBufferCoord,
+                   PSMALL_RECT  lpWriteRegion)
 {
-/* TO DO */
-       return FALSE;
+  return IntWriteConsoleOutput(hConsoleOutput, lpBuffer, dwBufferSize,
+                               dwBufferCoord, lpWriteRegion, FALSE);
 }
 
 
 /*--------------------------------------------------------------
  *     WriteConsoleOutputW
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 WriteConsoleOutputW(
@@ -1133,15 +1920,16 @@ WriteConsoleOutputW(
        PSMALL_RECT      lpWriteRegion
        )
 {
-/* TO DO */
-       return FALSE;
+  return IntWriteConsoleOutput(hConsoleOutput, lpBuffer, dwBufferSize,
+                               dwBufferCoord, lpWriteRegion, TRUE);
 }
 
 
 /*--------------------------------------------------------------
  *     ReadConsoleOutputCharacterA
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 ReadConsoleOutputCharacterA(
@@ -1152,15 +1940,64 @@ ReadConsoleOutputCharacterA(
        LPDWORD         lpNumberOfCharsRead
        )
 {
-   SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
-   return FALSE;
+  CSRSS_API_REQUEST Request;
+  PCSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+  DWORD Size;
+
+  Reply = RtlAllocateHeap(GetProcessHeap(), 0,
+                         sizeof(CSRSS_API_REPLY) +
+                         min(nLength, CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR));
+  if (Reply == NULL)
+    {
+      SetLastError(ERROR_OUTOFMEMORY);
+      return(FALSE);
+    }
+
+  if (lpNumberOfCharsRead != NULL)
+    *lpNumberOfCharsRead = nLength;
+
+  Request.Type = CSRSS_READ_CONSOLE_OUTPUT_CHAR;
+  Request.Data.ReadConsoleOutputCharRequest.ConsoleHandle = hConsoleOutput;
+  Request.Data.ReadConsoleOutputCharRequest.ReadCoord = dwReadCoord;
+
+  while (nLength != 0)
+    {
+      if (nLength > CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR)
+       Size = CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR;
+      else
+       Size = nLength;
+
+      Request.Data.ReadConsoleOutputCharRequest.NumCharsToRead = Size;
+
+      Status = CsrClientCallServer(&Request,
+                                  Reply,
+                                  sizeof(CSRSS_API_REQUEST),
+                                  sizeof(CSRSS_API_REPLY) + Size);
+      if (!NT_SUCCESS(Status) || !NT_SUCCESS(Reply->Status))
+       {
+         RtlFreeHeap(GetProcessHeap(), 0, Reply);
+         SetLastErrorByStatus(Status);
+         return(FALSE);
+       }
+
+      memcpy(lpCharacter, &Reply->Data.ReadConsoleOutputCharReply.String[0], Size);
+      lpCharacter += Size;
+      nLength -= Size;
+      Request.Data.ReadConsoleOutputCharRequest.ReadCoord = Reply->Data.ReadConsoleOutputCharReply.EndCoord;
+    }
+
+  RtlFreeHeap(GetProcessHeap(), 0, Reply);
+
+  return(TRUE);
 }
 
 
 /*--------------------------------------------------------------
  *      ReadConsoleOutputCharacterW
+ *
+ * @unimplemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 ReadConsoleOutputCharacterW(
@@ -1172,14 +2009,16 @@ ReadConsoleOutputCharacterW(
        )
 {
 /* TO DO */
+       DbgPrint("%s unimplemented\n", __FUNCTION__);
        return FALSE;
 }
 
 
 /*--------------------------------------------------------------
  *     ReadConsoleOutputAttribute
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 ReadConsoleOutputAttribute(
@@ -1190,88 +2029,183 @@ ReadConsoleOutputAttribute(
        LPDWORD         lpNumberOfAttrsRead
        )
 {
-   SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
-   return FALSE;
-}
+  CSRSS_API_REQUEST Request;
+  PCSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+  DWORD Size, i;
+  
+  Reply = RtlAllocateHeap(GetProcessHeap(), 0,
+                         sizeof(CSRSS_API_REPLY) +
+                         min(nLength, CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB));
+  if (Reply == NULL)
+    {
+      SetLastError(ERROR_OUTOFMEMORY);
+      return(FALSE);
+    }
 
+  if (lpNumberOfAttrsRead != NULL)
+    *lpNumberOfAttrsRead = nLength;
 
-/*--------------------------------------------------------------
- *     WriteConsoleOutputCharacterA
- */
-WINBASEAPI
-BOOL
-WINAPI
-WriteConsoleOutputCharacterA(
-       HANDLE          hConsoleOutput,
-       LPCSTR          lpCharacter,
-       DWORD           nLength,
-       COORD           dwWriteCoord,
-       LPDWORD         lpNumberOfCharsWritten
-       )
-{
-   PCSRSS_API_REQUEST Request;
-   CSRSS_API_REPLY Reply;
-   NTSTATUS Status;
-   WORD Size;
+  Request.Type = CSRSS_READ_CONSOLE_OUTPUT_ATTRIB;
+  Request.Data.ReadConsoleOutputAttribRequest.ConsoleHandle = hConsoleOutput;
+  Request.Data.ReadConsoleOutputAttribRequest.ReadCoord = dwReadCoord;
 
-   Request = RtlAllocateHeap(GetProcessHeap(),
-                      HEAP_ZERO_MEMORY,
-                      sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR);
-   if( !Request )
-     {
-       SetLastError( ERROR_OUTOFMEMORY );
-       return FALSE;
-     }
-   Request->Type = CSRSS_WRITE_CONSOLE_OUTPUT_CHAR;
-   Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle = hConsoleOutput;
-   Request->Data.WriteConsoleOutputCharRequest.Coord = dwWriteCoord;
-   if( lpNumberOfCharsWritten )
-      *lpNumberOfCharsWritten = nLength;
-   while( nLength )
-      {
-        Size = nLength > CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR ? CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR : nLength;
-        Request->Data.WriteConsoleOutputCharRequest.Length = Size;
-        memcpy( &Request->Data.WriteConsoleOutputCharRequest.String[0],
-                lpCharacter,
-                Size );
-        Status = CsrClientCallServer( Request, &Reply, sizeof( CSRSS_API_REQUEST ) + Size, sizeof( CSRSS_API_REPLY ) );
-        if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
-           {
-              SetLastErrorByStatus ( Status );
-              return FALSE;
-           }
-        nLength -= Size;
-        lpCharacter += Size;
-        Request->Data.WriteConsoleOutputCharRequest.Coord = Reply.Data.WriteConsoleOutputCharReply.EndCoord;
-      }
-   return TRUE;
+  while (nLength != 0)
+    {
+      if (nLength > CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB)
+       Size = CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB;
+      else
+       Size = nLength;
+
+      Request.Data.ReadConsoleOutputAttribRequest.NumAttrsToRead = Size;
+
+      Status = CsrClientCallServer(&Request,
+                                  Reply,
+                                  sizeof(CSRSS_API_REQUEST),
+                                  sizeof(CSRSS_API_REPLY) + Size);
+      if (!NT_SUCCESS(Status) || !NT_SUCCESS(Reply->Status))
+       {
+         RtlFreeHeap(GetProcessHeap(), 0, Reply);
+         SetLastErrorByStatus(Status);
+         return(FALSE);
+       }
+
+      // Convert CHARs to WORDs
+      for(i = 0; i < Size; ++i)
+        *lpAttribute++ = Reply->Data.ReadConsoleOutputAttribReply.String[i];
+      
+      nLength -= Size;
+      Request.Data.ReadConsoleOutputAttribRequest.ReadCoord = Reply->Data.ReadConsoleOutputAttribReply.EndCoord;
+    }
+
+  RtlFreeHeap(GetProcessHeap(), 0, Reply);
+
+  return(TRUE);
+}
+
+
+/*--------------------------------------------------------------
+ *     WriteConsoleOutputCharacterA
+ *
+ * @implemented
+ */
+BOOL WINAPI
+WriteConsoleOutputCharacterA(HANDLE            hConsoleOutput,
+                            LPCSTR             lpCharacter,
+                            DWORD              nLength,
+                            COORD              dwWriteCoord,
+                            LPDWORD            lpNumberOfCharsWritten)
+{
+  PCSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+  WORD Size;
+
+  Request = RtlAllocateHeap(GetProcessHeap(), 0,
+                           sizeof(CSRSS_API_REQUEST) +
+                           min(nLength, CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR));
+  if( !Request )
+    {
+      SetLastError( ERROR_OUTOFMEMORY );
+      return FALSE;
+    }
+  Request->Type = CSRSS_WRITE_CONSOLE_OUTPUT_CHAR;
+  Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle = hConsoleOutput;
+  Request->Data.WriteConsoleOutputCharRequest.Coord = dwWriteCoord;
+  if( lpNumberOfCharsWritten )
+    *lpNumberOfCharsWritten = nLength;
+  while( nLength )
+    {
+      Size = nLength > CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR ? CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR : nLength;
+      Request->Data.WriteConsoleOutputCharRequest.Length = Size;
+      memcpy( &Request->Data.WriteConsoleOutputCharRequest.String[0],
+             lpCharacter,
+             Size );
+      Status = CsrClientCallServer( Request, &Reply, sizeof( CSRSS_API_REQUEST ) + Size, sizeof( CSRSS_API_REPLY ) );
+      if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
+       {
+         RtlFreeHeap( GetProcessHeap(), 0, Request );
+         SetLastErrorByStatus ( Status );
+         return FALSE;
+       }
+      nLength -= Size;
+      lpCharacter += Size;
+      Request->Data.WriteConsoleOutputCharRequest.Coord = Reply.Data.WriteConsoleOutputCharReply.EndCoord;
+    }
+  
+  RtlFreeHeap( GetProcessHeap(), 0, Request ); 
+  return TRUE;
 }
 
 
 /*--------------------------------------------------------------
  *     WriteConsoleOutputCharacterW
+ *
+ * @implemented
  */
-WINBASEAPI
-BOOL
-WINAPI
-WriteConsoleOutputCharacterW(
-       HANDLE          hConsoleOutput,
-       LPCWSTR         lpCharacter,
-       DWORD           nLength,
-       COORD           dwWriteCoord,
-       LPDWORD         lpNumberOfCharsWritten
-       )
-{
-/* TO DO */
-       return FALSE;
-}
+BOOL WINAPI
+WriteConsoleOutputCharacterW(HANDLE            hConsoleOutput,
+                            LPCWSTR            lpCharacter,
+                            DWORD              nLength,
+                            COORD              dwWriteCoord,
+                            LPDWORD            lpNumberOfCharsWritten)
+{
+  PCSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+  WORD Size;
+  
+  Request = RtlAllocateHeap(GetProcessHeap(), 0,
+                           sizeof(CSRSS_API_REQUEST) +
+                           min(nLength, CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR));
+  if( !Request )
+    {
+      SetLastError( ERROR_OUTOFMEMORY );
+      return FALSE;
+    }
+  Request->Type = CSRSS_WRITE_CONSOLE_OUTPUT_CHAR;
+  Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle = hConsoleOutput;
+  Request->Data.WriteConsoleOutputCharRequest.Coord = dwWriteCoord;
+  if( lpNumberOfCharsWritten )
+    *lpNumberOfCharsWritten = nLength;
+  while( nLength )
+    {
+      Size = nLength > CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR ? CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR : nLength;
+      Request->Data.WriteConsoleOutputCharRequest.Length = Size;
+      Status = RtlUnicodeToOemN (&Request->Data.WriteConsoleOutputCharRequest.String[0],
+                                Size,
+                                NULL,
+                                (PWCHAR)lpCharacter,
+                                Size * sizeof(WCHAR));
+      if (!NT_SUCCESS(Status))
+       {
+         RtlFreeHeap (GetProcessHeap(), 0, Request);
+         SetLastErrorByStatus (Status);
+         return FALSE;
+       }
 
+      Status = CsrClientCallServer( Request, &Reply, sizeof( CSRSS_API_REQUEST ) + Size, sizeof( CSRSS_API_REPLY ) );
+      if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
+       {
+         RtlFreeHeap( GetProcessHeap(), 0, Request );
+         SetLastErrorByStatus ( Status );
+         return FALSE;
+       }
+      nLength -= Size;
+      lpCharacter += Size;
+      Request->Data.WriteConsoleOutputCharRequest.Coord = Reply.Data.WriteConsoleOutputCharReply.EndCoord;
+    }
+  
+  RtlFreeHeap( GetProcessHeap(), 0, Request );
+  return TRUE;
+}
 
 
 /*--------------------------------------------------------------
  *     WriteConsoleOutputAttribute
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 WriteConsoleOutputAttribute(
@@ -1288,9 +2222,9 @@ WriteConsoleOutputAttribute(
    WORD Size;
    int c;
 
-   Request = RtlAllocateHeap(GetProcessHeap(),
-                      HEAP_ZERO_MEMORY,
-                      sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB);
+   Request = RtlAllocateHeap(GetProcessHeap(), 0,
+                            sizeof(CSRSS_API_REQUEST) +
+                            min(nLength, CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB));
    if( !Request )
      {
        SetLastError( ERROR_OUTOFMEMORY );
@@ -1310,6 +2244,7 @@ WriteConsoleOutputAttribute(
         Status = CsrClientCallServer( Request, &Reply, sizeof( CSRSS_API_REQUEST ) + (Size * 2), sizeof( CSRSS_API_REPLY ) );
         if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
            {
+              RtlFreeHeap( GetProcessHeap(), 0, Request );
               SetLastErrorByStatus ( Status );
               return FALSE;
            }
@@ -1317,14 +2252,17 @@ WriteConsoleOutputAttribute(
         lpAttribute += Size;
         Request->Data.WriteConsoleOutputAttribRequest.Coord = Reply.Data.WriteConsoleOutputAttribReply.EndCoord;
       }
+   
+   RtlFreeHeap( GetProcessHeap(), 0, Request );
    return TRUE;
 }
 
 
 /*--------------------------------------------------------------
  *     FillConsoleOutputAttribute
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 FillConsoleOutputAttribute(
@@ -1358,8 +2296,9 @@ FillConsoleOutputAttribute(
 
 /*--------------------------------------------------------------
  *     GetConsoleMode
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 GetConsoleMode(
@@ -1371,7 +2310,7 @@ GetConsoleMode(
   CSRSS_API_REPLY Reply;
   NTSTATUS Status;
   
-  Request.Type = CSRSS_GET_MODE;
+  Request.Type = CSRSS_GET_CONSOLE_MODE;
   Request.Data.GetConsoleModeRequest.ConsoleHandle = hConsoleHandle;
   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
@@ -1386,8 +2325,9 @@ GetConsoleMode(
 
 /*--------------------------------------------------------------
  *     GetNumberOfConsoleInputEvents
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 GetNumberOfConsoleInputEvents(
@@ -1395,15 +2335,36 @@ GetNumberOfConsoleInputEvents(
        LPDWORD         lpNumberOfEvents
        )
 {
-/* TO DO */
-       return FALSE;
+   CSRSS_API_REQUEST Request;
+   CSRSS_API_REPLY Reply;
+   NTSTATUS Status;
+   if(lpNumberOfEvents == NULL)
+   {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return FALSE;
+   }
+   
+   Request.Type = CSRSS_GET_NUM_INPUT_EVENTS;
+   Request.Data.GetNumInputEventsRequest.ConsoleHandle = hConsoleInput;
+   Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY));
+   if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+   {
+      SetLastErrorByStatus(Status);
+      return FALSE;
+   }
+   
+   *lpNumberOfEvents = Reply.Data.GetNumInputEventsReply.NumInputEvents;
+   
+       return TRUE;
 }
 
 
 /*--------------------------------------------------------------
  *     GetLargestConsoleWindowSize
+ *
+ * @unimplemented
  */
-WINBASEAPI
 COORD
 WINAPI
 GetLargestConsoleWindowSize(
@@ -1421,8 +2382,9 @@ GetLargestConsoleWindowSize(
 
 /*--------------------------------------------------------------
  *     GetConsoleCursorInfo
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 GetConsoleCursorInfo(
@@ -1437,6 +2399,7 @@ GetConsoleCursorInfo(
    Request.Type = CSRSS_GET_CURSOR_INFO;
    Request.Data.GetCursorInfoRequest.ConsoleHandle = hConsoleOutput;
    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
+
    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
       {
         SetLastErrorByStatus ( Status );
@@ -1449,8 +2412,9 @@ GetConsoleCursorInfo(
 
 /*--------------------------------------------------------------
  *     GetNumberOfConsoleMouseButtons
+ *
+ * @unimplemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 GetNumberOfConsoleMouseButtons(
@@ -1464,8 +2428,9 @@ GetNumberOfConsoleMouseButtons(
 
 /*--------------------------------------------------------------
  *     SetConsoleMode
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 SetConsoleMode(
@@ -1477,7 +2442,7 @@ SetConsoleMode(
   CSRSS_API_REPLY Reply;
   NTSTATUS Status;
   
-  Request.Type = CSRSS_SET_MODE;
+  Request.Type = CSRSS_SET_CONSOLE_MODE;
   Request.Data.SetConsoleModeRequest.ConsoleHandle = hConsoleHandle;
   Request.Data.SetConsoleModeRequest.Mode = dwMode;
   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
@@ -1492,8 +2457,9 @@ SetConsoleMode(
 
 /*--------------------------------------------------------------
  *     SetConsoleActiveScreenBuffer
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 SetConsoleActiveScreenBuffer(
@@ -1505,7 +2471,7 @@ SetConsoleActiveScreenBuffer(
    NTSTATUS Status;
 
    Request.Type = CSRSS_SET_SCREEN_BUFFER;
-   Request.Data.SetActiveScreenBufferRequest.OutputHandle = hConsoleOutput;
+   Request.Data.SetScreenBufferRequest.OutputHandle = hConsoleOutput;
    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
       {
@@ -1518,23 +2484,36 @@ SetConsoleActiveScreenBuffer(
 
 /*--------------------------------------------------------------
  *     FlushConsoleInputBuffer
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 FlushConsoleInputBuffer(
        HANDLE          hConsoleInput
        )
 {
-/* TO DO */
-       return FALSE;
+   CSRSS_API_REQUEST Request;
+   CSRSS_API_REPLY Reply;
+   NTSTATUS Status;
+
+   Request.Type = CSRSS_FLUSH_INPUT_BUFFER;
+   Request.Data.FlushInputBufferRequest.ConsoleInput = hConsoleInput;
+   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
+   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
+      {
+        SetLastErrorByStatus ( Status );
+        return FALSE;
+      }
+   return TRUE;
 }
 
 
 /*--------------------------------------------------------------
  *     SetConsoleScreenBufferSize
+ *
+ * @unimplemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 SetConsoleScreenBufferSize(
@@ -1543,13 +2522,15 @@ SetConsoleScreenBufferSize(
        )
 {
 /* TO DO */
+       DbgPrint("%s unimplemented\n", __FUNCTION__);
        return FALSE;
 }
 
 /*--------------------------------------------------------------
  *     SetConsoleCursorInfo
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 SetConsoleCursorInfo(
@@ -1565,6 +2546,7 @@ SetConsoleCursorInfo(
    Request.Data.SetCursorInfoRequest.ConsoleHandle = hConsoleOutput;
    Request.Data.SetCursorInfoRequest.Info = *lpConsoleCursorInfo;
    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
+
    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
       {
         SetLastErrorByStatus ( Status );
@@ -1576,8 +2558,9 @@ SetConsoleCursorInfo(
 
 /*--------------------------------------------------------------
  *     ScrollConsoleScreenBufferA
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 ScrollConsoleScreenBufferA(
@@ -1588,15 +2571,42 @@ ScrollConsoleScreenBufferA(
        CONST CHAR_INFO         *lpFill
        )
 {
-/* TO DO */
-       return FALSE;
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+
+  Request.Type = CSRSS_SCROLL_CONSOLE_SCREEN_BUFFER;
+  Request.Data.ScrollConsoleScreenBufferRequest.ConsoleHandle = hConsoleOutput;
+  Request.Data.ScrollConsoleScreenBufferRequest.ScrollRectangle = *lpScrollRectangle;
+
+  if (lpClipRectangle != NULL)
+    {
+  Request.Data.ScrollConsoleScreenBufferRequest.UseClipRectangle = TRUE;
+  Request.Data.ScrollConsoleScreenBufferRequest.ClipRectangle = *lpClipRectangle;
+    }
+  else
+    {
+  Request.Data.ScrollConsoleScreenBufferRequest.UseClipRectangle = FALSE;
+    }
+
+  Request.Data.ScrollConsoleScreenBufferRequest.DestinationOrigin = dwDestinationOrigin;
+  Request.Data.ScrollConsoleScreenBufferRequest.Fill = *lpFill;
+  Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
+
+  if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
+    {
+      SetLastErrorByStatus ( Status );
+      return FALSE;
+    }
+  return TRUE;
 }
 
 
 /*--------------------------------------------------------------
  *     ScrollConsoleScreenBufferW
+ *
+ * @unimplemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 ScrollConsoleScreenBufferW(
@@ -1608,14 +2618,16 @@ ScrollConsoleScreenBufferW(
        )
 {
 /* TO DO */
+       DbgPrint("%s unimplemented\n", __FUNCTION__);
        return FALSE;
 }
 
 
 /*--------------------------------------------------------------
  *     SetConsoleWindowInfo
+ *
+ * @unimplemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 SetConsoleWindowInfo(
@@ -1625,18 +2637,20 @@ SetConsoleWindowInfo(
        )
 {
 /* TO DO */
+       DbgPrint("%s unimplemented\n", __FUNCTION__);
        return FALSE;
 }
 
 
 /*--------------------------------------------------------------
  *      SetConsoleTextAttribute
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 SetConsoleTextAttribute(
-       HANDLE          hConsoleOutput,
+        HANDLE         hConsoleOutput,
         WORD            wAttributes
         )
 {
@@ -1656,6 +2670,7 @@ SetConsoleTextAttribute(
    return TRUE;
 }
 
+
 BOOL STATIC
 AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
 {
@@ -1667,13 +2682,20 @@ AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
   else
     {
       NrCtrlHandlers++;
-      CtrlHandlers = 
-       RtlReAllocateHeap(RtlGetProcessHeap(),
-                          HEAP_ZERO_MEMORY,
-                          (PVOID)CtrlHandlers,
-                          NrCtrlHandlers * sizeof(PHANDLER_ROUTINE)); 
+      if (CtrlHandlers == NULL)
+        {
+          CtrlHandlers = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
+                                         NrCtrlHandlers * sizeof(PHANDLER_ROUTINE)); 
+        }
+      else
+        {
+          CtrlHandlers = RtlReAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
+                                           (PVOID)CtrlHandlers,
+                                           NrCtrlHandlers * sizeof(PHANDLER_ROUTINE)); 
+        }
       if (CtrlHandlers == NULL)
        {
+         NrCtrlHandlers = 0;
          SetLastError(ERROR_NOT_ENOUGH_MEMORY);
          return(FALSE);
        }
@@ -1682,6 +2704,7 @@ AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
     }
 }
 
+
 BOOL STATIC
 RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
 {
@@ -1696,10 +2719,11 @@ RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
     {
       for (i = 0; i < NrCtrlHandlers; i++)
        {
-         if (CtrlHandlers[i] == HandlerRoutine)
+         if ( ((void*)(CtrlHandlers[i])) == (void*)HandlerRoutine)
            {
-             CtrlHandlers[i] = CtrlHandlers[NrCtrlHandlers - 1];
              NrCtrlHandlers--;
+             memmove(CtrlHandlers + i, CtrlHandlers + i + 1, 
+                     (NrCtrlHandlers - i) * sizeof(PHANDLER_ROUTINE));
              CtrlHandlers = 
                RtlReAllocateHeap(RtlGetProcessHeap(),
                                  HEAP_ZERO_MEMORY,
@@ -1712,8 +2736,12 @@ RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
   return(FALSE);
 }
 
-WINBASEAPI BOOL WINAPI
-SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine,
+
+/*
+ * @implemented
+ */
+BOOL WINAPI
+SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine,
                      BOOL Add)
 {
   BOOLEAN Ret;
@@ -1734,8 +2762,10 @@ SetConsoleCtrlHandler(PHANDLER_ROUTINE   HandlerRoutine,
 
 /*--------------------------------------------------------------
  *     GenerateConsoleCtrlEvent
+ *
+ * @unimplemented
  */
-WINBASEAPI BOOL WINAPI
+BOOL WINAPI
 GenerateConsoleCtrlEvent(
        DWORD           dwCtrlEvent,
        DWORD           dwProcessGroupId
@@ -1748,10 +2778,9 @@ GenerateConsoleCtrlEvent(
 
 /*--------------------------------------------------------------
  *     GetConsoleTitleW
+ *
+ * @implemented
  */
-#define MAX_CONSOLE_TITLE_LENGTH 80
-
-WINBASEAPI
 DWORD
 WINAPI
 GetConsoleTitleW(
@@ -1759,8 +2788,51 @@ GetConsoleTitleW(
        DWORD           nSize
        )
 {
-/* TO DO */
-       return 0;
+   CSRSS_API_REQUEST Request;
+   PCSRSS_API_REPLY Reply;
+   NTSTATUS Status;
+   HANDLE hConsole;
+
+   hConsole = CreateFileW(L"CONIN$", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+   if (hConsole == INVALID_HANDLE_VALUE)
+   {
+      return 0;
+   }
+
+   Reply = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSRSS_API_REPLY) + CSRSS_MAX_TITLE_LENGTH * sizeof(WCHAR));
+   if(Reply == NULL)
+   {
+      CloseHandle(hConsole);   
+      SetLastError(ERROR_OUTOFMEMORY);
+      return 0;
+   }
+
+   Request.Type = CSRSS_GET_TITLE;
+   Request.Data.GetTitleRequest.ConsoleHandle = hConsole;
+   
+   Status = CsrClientCallServer(&Request, Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY) + CSRSS_MAX_TITLE_LENGTH * sizeof(WCHAR));
+   CloseHandle(hConsole);
+   if(!NT_SUCCESS(Status) || !(NT_SUCCESS(Status = Reply->Status)))
+   {
+      SetLastErrorByStatus(Status);
+      RtlFreeHeap(GetProcessHeap(), 0, Reply);
+      return 0;
+   }
+   
+   if(nSize * sizeof(WCHAR) < Reply->Data.GetTitleReply.Length)
+   {
+      wcsncpy(lpConsoleTitle, Reply->Data.GetTitleReply.Title, nSize - 1);
+      lpConsoleTitle[nSize--] = L'\0';
+   }
+   else
+   {  
+      nSize = Reply->Data.GetTitleReply.Length / sizeof (WCHAR);
+      wcscpy(lpConsoleTitle, Reply->Data.GetTitleReply.Title);
+      lpConsoleTitle[nSize] = L'\0';
+   }
+   
+   RtlFreeHeap(GetProcessHeap(), 0, Reply);
+   return nSize;
 }
 
 
@@ -1768,8 +2840,9 @@ GetConsoleTitleW(
  *     GetConsoleTitleA
  *
  *     19990306 EA
+ *
+ * @implemented
  */
-WINBASEAPI
 DWORD
 WINAPI
 GetConsoleTitleA(
@@ -1777,14 +2850,14 @@ GetConsoleTitleA(
        DWORD           nSize
        )
 {
-       wchar_t WideTitle [MAX_CONSOLE_TITLE_LENGTH];
+       wchar_t WideTitle [CSRSS_MAX_TITLE_LENGTH];
        DWORD   nWideTitle = sizeof WideTitle;
-//     DWORD   nWritten;
+       DWORD   nWritten;
        
        if (!lpConsoleTitle || !nSize) return 0;
        nWideTitle = GetConsoleTitleW( (LPWSTR) WideTitle, nWideTitle );
        if (!nWideTitle) return 0;
-#if 0
+
        if ( (nWritten = WideCharToMultiByte(
                CP_ACP,                 // ANSI code page 
                0,                      // performance and mapping flags 
@@ -1799,23 +2872,66 @@ GetConsoleTitleA(
                lpConsoleTitle[nWritten] = '\0';
                return nWritten;
        }
-#endif
+
        return 0;
 }
 
 
 /*--------------------------------------------------------------
  *     SetConsoleTitleW
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 SetConsoleTitleW(
        LPCWSTR         lpConsoleTitle
        )
 {
-/* --- TO DO --- */
-       return FALSE;
+  PCSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+  unsigned int c;
+  HANDLE hConsole;
+
+  hConsole = CreateFileW(L"CONIN$", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+  if (hConsole == INVALID_HANDLE_VALUE)
+  {
+     return FALSE;
+  }
+  
+  Request = RtlAllocateHeap(GetProcessHeap(),
+                           HEAP_ZERO_MEMORY,
+                           sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_SET_TITLE_REQUEST);
+  if (Request == NULL)
+    {
+      CloseHandle(hConsole);
+      SetLastError(ERROR_OUTOFMEMORY);
+      return(FALSE);
+    }
+  
+  Request->Type = CSRSS_SET_TITLE;
+  Request->Data.SetTitleRequest.Console = hConsole;
+  
+  for( c = 0; lpConsoleTitle[c] && c < CSRSS_MAX_TITLE_LENGTH; c++ )
+    Request->Data.SetTitleRequest.Title[c] = lpConsoleTitle[c];
+  // add null
+  Request->Data.SetTitleRequest.Title[c] = 0;
+  Request->Data.SetTitleRequest.Length = c;  
+  Status = CsrClientCallServer(Request,
+                              &Reply,
+                              sizeof(CSRSS_API_REQUEST) + 
+                              c * sizeof(WCHAR),
+                              sizeof(CSRSS_API_REPLY));
+  CloseHandle(hConsole);
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply.Status ) )
+    {
+      RtlFreeHeap( GetProcessHeap(), 0, Request );
+      SetLastErrorByStatus (Status);
+      return(FALSE);
+    }
+  RtlFreeHeap( GetProcessHeap(), 0, Request );
+  return TRUE;
 }
 
 
@@ -1823,51 +2939,67 @@ SetConsoleTitleW(
  *     SetConsoleTitleA
  *     
  *     19990204 EA     Added
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 SetConsoleTitleA(
        LPCSTR          lpConsoleTitle
        )
 {
-       wchar_t WideTitle [MAX_CONSOLE_TITLE_LENGTH];
-       char    AnsiTitle [MAX_CONSOLE_TITLE_LENGTH];
-       INT     nWideTitle;
-       
-       if (!lpConsoleTitle) return FALSE;
-       ZeroMemory( WideTitle, sizeof WideTitle );
-       nWideTitle = lstrlenA(lpConsoleTitle);
-       if (!lstrcpynA(
-               AnsiTitle,
-               lpConsoleTitle,
-               nWideTitle
-               )) 
-       {
-               return FALSE;
-       }
-       AnsiTitle[nWideTitle] = '\0';
-#if 0
-       if ( MultiByteToWideChar(
-               CP_ACP,                 // ANSI code page 
-               MB_PRECOMPOSED,         // character-type options 
-               AnsiTitle,              // address of string to map 
-               nWideTitle,             // number of characters in string 
-               (LPWSTR) WideTitle,     // address of wide-character buffer 
-               (-1)                    // size of buffer: -1=...\0
-               ))
-       {
-               return SetConsoleTitleW( (LPWSTR) WideTitle ); 
-       }
-#endif
-       return FALSE;
+  PCSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+  unsigned int c;
+  HANDLE hConsole;
+
+  hConsole = CreateFileW(L"CONIN$", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+  if (hConsole == INVALID_HANDLE_VALUE)
+  {
+     return FALSE;
+  }
+  
+  Request = RtlAllocateHeap(GetProcessHeap(),
+                           HEAP_ZERO_MEMORY,
+                           sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_SET_TITLE_REQUEST);
+  if (Request == NULL)
+    {
+      CloseHandle(hConsole);
+      SetLastError(ERROR_OUTOFMEMORY);
+      return(FALSE);
+    }
+  
+  Request->Type = CSRSS_SET_TITLE;
+  Request->Data.SetTitleRequest.Console = hConsole;
+  
+  for( c = 0; lpConsoleTitle[c] && c < CSRSS_MAX_TITLE_LENGTH; c++ )
+    Request->Data.SetTitleRequest.Title[c] = lpConsoleTitle[c];
+  // add null
+  Request->Data.SetTitleRequest.Title[c] = 0;
+  Request->Data.SetTitleRequest.Length = c;
+  Status = CsrClientCallServer(Request,
+                              &Reply,
+                              sizeof(CSRSS_API_REQUEST) + 
+                              c * sizeof(WCHAR),
+                              sizeof(CSRSS_API_REPLY));
+  CloseHandle(hConsole);
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply.Status ) )
+    {
+      RtlFreeHeap( GetProcessHeap(), 0, Request );
+      SetLastErrorByStatus (Status);
+      return(FALSE);
+    }
+  RtlFreeHeap( GetProcessHeap(), 0, Request );
+  return TRUE;
 }
 
 
 /*--------------------------------------------------------------
  *     ReadConsoleW
+ *
+ * @unimplemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 ReadConsoleW(
@@ -1879,14 +3011,16 @@ ReadConsoleW(
        )
 {
 /* --- TO DO --- */
+       DbgPrint("%s unimplemented\n", __FUNCTION__);
        return FALSE;
 }
 
 
 /*--------------------------------------------------------------
  *     WriteConsoleW
+ *
+ * @unimplemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 WriteConsoleW(
@@ -1897,60 +3031,62 @@ WriteConsoleW(
        LPVOID           lpReserved
        )
 {
+       DbgPrint("%s unimplemented\n", __FUNCTION__);
 #if 0
-   PCSRSS_API_REQUEST Request;
-   CSRSS_API_REPLY Reply;
-   NTSTATUS Status;
-   
-   Request = RtlAllocateHeap(GetProcessHeap(),
-                      HEAP_ZERO_MEMORY,
-                      sizeof(CSRSS_API_REQUEST) + nNumberOfCharsToWrite * sizeof(WCHAR));
-   if (Request == NULL)
-     {
-       return(FALSE);
-     }
-
-   Request->Type = CSRSS_WRITE_CONSOLE;
-   Request->Data.WriteConsoleRequest.ConsoleHandle = hConsoleOutput;
-   Request->Data.WriteConsoleRequest.NrCharactersToWrite =
-     nNumberOfCharsToWrite;
-//   DbgPrint("nNumberOfCharsToWrite %d\n", nNumberOfCharsToWrite);
-//   DbgPrint("Buffer %s\n", Request->Data.WriteConsoleRequest.Buffer);
-   memcpy(Request->Data.WriteConsoleRequest.Buffer,
-         lpBuffer,
-         nNumberOfCharsToWrite * sizeof(WCHAR));
-
-   Status = CsrClientCallServer(Request,
-                               &Reply,
-                               sizeof(CSRSS_API_REQUEST) +
-                               nNumberOfCharsToWrite,
-                               sizeof(CSRSS_API_REPLY));
+  PCSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
 
-   RtlFreeHeap(GetProcessHeap(),
-           0,
-           Request);
+  Request = RtlAllocateHeap(GetProcessHeap(),
+                           HEAP_ZERO_MEMORY,
+                           sizeof(CSRSS_API_REQUEST) + nNumberOfCharsToWrite * sizeof(WCHAR));
+  if (Request == NULL)
+    {
+      SetLastError(ERROR_OUTOFMEMORY);
+      return(FALSE);
+    }
 
-   if (!NT_SUCCESS(Status))
-     {
-       return(FALSE);
-     }
+  Request->Type = CSRSS_WRITE_CONSOLE;
+  Request->Data.WriteConsoleRequest.ConsoleHandle = hConsoleOutput;
+  Request->Data.WriteConsoleRequest.NrCharactersToWrite =
+    nNumberOfCharsToWrite;
+//  DbgPrint("nNumberOfCharsToWrite %d\n", nNumberOfCharsToWrite);
+//  DbgPrint("Buffer %s\n", Request->Data.WriteConsoleRequest.Buffer);
+  memcpy(Request->Data.WriteConsoleRequest.Buffer,
+        lpBuffer,
+        nNumberOfCharsToWrite * sizeof(WCHAR));
+
+  Status = CsrClientCallServer(Request,
+                              &Reply,
+                              sizeof(CSRSS_API_REQUEST) + nNumberOfCharsToWrite,
+                              sizeof(CSRSS_API_REPLY));
+
+  RtlFreeHeap(GetProcessHeap(),
+             0,
+             Request);
+
+  if (!NT_SUCCESS(Status))
+    {
+      return(FALSE);
+    }
 
-   if (lpNumberOfCharsWritten != NULL)
-     {
-       *lpNumberOfCharsWritten = 
+  if (lpNumberOfCharsWritten != NULL)
+    {
+      *lpNumberOfCharsWritten = 
          Reply.Data.WriteConsoleReply.NrCharactersWritten;
-     }
+    }
 
-   return(TRUE);
+  return(TRUE);
 #endif
-   return FALSE;
+  return(FALSE);
 }
 
 
 /*--------------------------------------------------------------
  *     CreateConsoleScreenBuffer
+ *
+ * @implemented
  */
-WINBASEAPI
 HANDLE
 WINAPI
 CreateConsoleScreenBuffer(
@@ -1979,58 +3115,192 @@ CreateConsoleScreenBuffer(
 
 /*--------------------------------------------------------------
  *     GetConsoleCP
+ *
+ * @implemented
  */
-WINBASEAPI
 UINT
 WINAPI
 GetConsoleCP( VOID )
 {
-/* --- TO DO --- */
-       return CP_OEMCP; /* FIXME */
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY   Reply;
+  NTSTATUS          Status;
+   
+  Request.Type = CSRSS_GET_CONSOLE_CP;
+  Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST),
+                               sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+  {
+    SetLastErrorByStatus (Status);
+    return 0;
+  }
+  return Reply.Data.GetConsoleCodePage.CodePage;
 }
 
 
 /*--------------------------------------------------------------
  *     SetConsoleCP
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 SetConsoleCP(
        UINT            wCodePageID
        )
 {
-/* --- TO DO --- */
-       return FALSE;
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY   Reply;
+  NTSTATUS          Status;
+   
+  Request.Type = CSRSS_SET_CONSOLE_CP;
+  Request.Data.SetConsoleCodePage.CodePage = wCodePageID;
+  Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST),
+                               sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+  {
+    SetLastErrorByStatus (Status);
+  }
+  return NT_SUCCESS(Status);
 }
 
 
 /*--------------------------------------------------------------
  *     GetConsoleOutputCP
+ *
+ * @implemented
  */
-WINBASEAPI
 UINT
 WINAPI
 GetConsoleOutputCP( VOID )
 {
-/* --- TO DO --- */
-       return 0; /* FIXME */
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY   Reply;
+  NTSTATUS          Status;
+   
+  Request.Type = CSRSS_GET_CONSOLE_OUTPUT_CP;
+  Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST),
+                               sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+  {
+    SetLastErrorByStatus (Status);
+    return 0;
+  }
+  return Reply.Data.GetConsoleOutputCodePage.CodePage;
 }
 
 
 /*--------------------------------------------------------------
  *     SetConsoleOutputCP
+ *
+ * @implemented
  */
-WINBASEAPI
 BOOL
 WINAPI
 SetConsoleOutputCP(
        UINT            wCodePageID
        )
 {
-/* --- TO DO --- */
-       return FALSE;
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY   Reply;
+  NTSTATUS          Status;
+   
+  Request.Type = CSRSS_SET_CONSOLE_OUTPUT_CP;
+  Request.Data.SetConsoleOutputCodePage.CodePage = wCodePageID;
+  Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST),
+                               sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+  {
+    SetLastErrorByStatus (Status);
+  }
+  return NT_SUCCESS(Status);
+}
+
+
+/*--------------------------------------------------------------
+ *     GetConsoleProcessList
+ *
+ * @unimplemented
+ */
+DWORD STDCALL
+GetConsoleProcessList(LPDWORD lpdwProcessList,
+                  DWORD dwProcessCount)
+{
+   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+   return 0;
+}
+
+
+
+/*--------------------------------------------------------------
+ *     GetConsoleSelectionInfo
+ *
+ * @unimplemented
+ */
+BOOL STDCALL
+GetConsoleSelectionInfo(PCONSOLE_SELECTION_INFO lpConsoleSelectionInfo)
+{
+   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+   return FALSE;
+}
+
+
+
+/*--------------------------------------------------------------
+ *     AttachConsole
+ *
+ * @unimplemented
+ */
+BOOL STDCALL 
+AttachConsole(DWORD dwProcessId)
+{
+   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+   return FALSE;
+}
+
+/*--------------------------------------------------------------
+ *     GetConsoleWindow
+ *
+ * @implemented
+ */
+HWND STDCALL
+GetConsoleWindow (VOID)
+{
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY   Reply;
+  NTSTATUS          Status;
+   
+  Request.Type = CSRSS_GET_CONSOLE_WINDOW;
+  Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
+  if (!NT_SUCCESS(Status ) || !NT_SUCCESS(Status = Reply.Status))
+  {
+    SetLastErrorByStatus (Status);
+    return (HWND) NULL;
+  }
+  return Reply.Data.GetConsoleWindowReply.WindowHandle;
 }
 
 
+/*--------------------------------------------------------------
+ *     SetConsoleIcon
+ *
+ * @implemented
+ */
+BOOL STDCALL SetConsoleIcon(HICON hicon)
+{
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY   Reply;
+  NTSTATUS          Status;
+  
+  Request.Type = CSRSS_SET_CONSOLE_ICON;
+  Request.Data.SetConsoleIconRequest.WindowIcon = hicon;
+  Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
+  {
+    SetLastErrorByStatus (Status);
+    return FALSE;
+  }
+  return NT_SUCCESS(Status);
+}
+
 /* EOF */