Commit in reactos on MAIN
include/csrss/csrss.h+21-71.46 -> 1.47
lib/kernel32/kernel32.def+1-11.45 -> 1.46
lib/kernel32/misc/console.c+687-5861.81 -> 1.82
lib/kernel32/thread/thread.c+10-11.54 -> 1.55
subsys/csrss/win32csr/conio.c+111-341.15 -> 1.16
+830-629
5 modified files
1. Implemented WriteConsoleW(), ReadConsoleW(), FillConsoleOutputCharacterW(), WriteConsoleInputW(), ReadConsoleOutputCharacterW(), ScrollConsoleScreenBufferW()
2. added stub for SetThreadUILanguage()
This get's XP's cmd.exe to start (unfortunately it exits for some reason after one hits the enter key).

reactos/include/csrss
csrss.h 1.46 -> 1.47
diff -u -r1.46 -r1.47
--- csrss.h	19 Sep 2004 14:36:46 -0000	1.46
+++ csrss.h	2 Nov 2004 20:42:04 -0000	1.47
@@ -42,6 +42,7 @@
 typedef struct
 {
    HANDLE ConsoleHandle;
+   BOOL Unicode;
    ULONG NrCharactersToWrite;
    BYTE Buffer[1];
 } CSRSS_WRITE_CONSOLE_REQUEST, *PCSRSS_WRITE_CONSOLE_REQUEST;
@@ -54,6 +55,7 @@
 typedef struct
 {
    HANDLE ConsoleHandle;
+   BOOL Unicode;
    WORD NrCharactersToRead;
    WORD nCharsCanBeDeleted;     /* number of chars already in buffer that can be backspaced */
 } CSRSS_READ_CONSOLE_REQUEST, *PCSRSS_READ_CONSOLE_REQUEST;
@@ -108,13 +110,19 @@
 typedef struct
 {
    HANDLE ConsoleHandle;
-   CHAR Char;
+   BOOL Unicode;
+   union
+   {
+     CHAR AsciiChar;
+     WCHAR UnicodeChar;
+   } Char;
    COORD Position;
    WORD Length;
 } CSRSS_FILL_OUTPUT_REQUEST, *PCSRSS_FILL_OUTPUT_REQUEST;
 
 typedef struct
 {
+   ULONG NrCharactersWritten;
 } CSRSS_FILL_OUTPUT_REPLY, *PCSRSS_FILL_OUTPUT_REPLY;
 
 typedef struct
@@ -145,6 +153,7 @@
 typedef struct
 {
    HANDLE ConsoleHandle;
+   BOOL Unicode;
    WORD Length;
    COORD Coord;
    CHAR String[1];
@@ -153,6 +162,7 @@
 typedef struct
 {
    COORD EndCoord;
+   ULONG NrCharactersWritten;
 } CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REPLY, *PCSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REPLY;
 
 typedef struct
@@ -296,12 +306,13 @@
 
 typedef struct
 {
-  HANDLE     ConsoleHandle;
+  HANDLE ConsoleHandle;
+  BOOL Unicode;
   SMALL_RECT ScrollRectangle;
-  BOOLEAN    UseClipRectangle;
+  BOOLEAN UseClipRectangle;
   SMALL_RECT ClipRectangle;
-  COORD      DestinationOrigin;
-  CHAR_INFO  Fill;
+  COORD DestinationOrigin;
+  CHAR_INFO Fill;
 } CSRSS_SCROLL_CONSOLE_SCREEN_BUFFER_REQUEST, *PCSRSS_SCROLL_CONSOLE_SCREEN_BUFFER_REQUEST;
 
 typedef struct
@@ -311,6 +322,7 @@
 typedef struct
 {
   HANDLE ConsoleHandle;
+  BOOL Unicode;
   DWORD NumCharsToRead;
   COORD ReadCoord;
 }CSRSS_READ_CONSOLE_OUTPUT_CHAR_REQUEST, *PCSRSS_READ_CONSOLE_OUTPUT_CHAR_REQUEST;
@@ -318,6 +330,7 @@
 typedef struct
 {
   COORD EndCoord;
+  DWORD CharsRead;
   CHAR String[1];
 }CSRSS_READ_CONSOLE_OUTPUT_CHAR_REPLY, *PCSRSS_READ_CONSOLE_OUTPUT_CHAR_REPLY;
 
@@ -414,6 +427,7 @@
 typedef struct
 {
   HANDLE ConsoleHandle;
+  BOOL Unicode;
   DWORD Length;
   INPUT_RECORD* InputRecord;
 } CSRSS_WRITE_CONSOLE_INPUT_REQUEST, *PCSRSS_WRITE_CONSOLE_INPUT_REQUEST;
@@ -701,8 +715,7 @@
         CSRSS_GET_TITLE_REQUEST GetTitleRequest;
         CSRSS_WRITE_CONSOLE_OUTPUT_REQUEST WriteConsoleOutputRequest;
         CSRSS_FLUSH_INPUT_BUFFER_REQUEST FlushInputBufferRequest;
-        CSRSS_SCROLL_CONSOLE_SCREEN_BUFFER_REQUEST 
-        ScrollConsoleScreenBufferRequest;
+        CSRSS_SCROLL_CONSOLE_SCREEN_BUFFER_REQUEST ScrollConsoleScreenBufferRequest;
         CSRSS_READ_CONSOLE_OUTPUT_CHAR_REQUEST ReadConsoleOutputCharRequest;
         CSRSS_READ_CONSOLE_OUTPUT_ATTRIB_REQUEST ReadConsoleOutputAttribRequest;
         CSRSS_GET_NUM_INPUT_EVENTS_REQUEST GetNumInputEventsRequest;
@@ -746,6 +759,7 @@
       {
         CSRSS_CREATE_PROCESS_REPLY CreateProcessReply;
         CSRSS_CONNECT_PROCESS_REPLY ConnectReply;
+        CSRSS_FILL_OUTPUT_REPLY FillOutputReply;
         CSRSS_WRITE_CONSOLE_REPLY WriteConsoleReply;
         CSRSS_READ_CONSOLE_REPLY ReadConsoleReply;
         CSRSS_ALLOC_CONSOLE_REPLY AllocConsoleReply;

reactos/lib/kernel32
kernel32.def 1.45 -> 1.46
diff -u -r1.45 -r1.46
--- kernel32.def	23 Sep 2004 21:01:23 -0000	1.45
+++ kernel32.def	2 Nov 2004 20:42:05 -0000	1.46
@@ -841,7 +841,7 @@
 SetThreadLocale@4
 SetThreadPriority@8
 SetThreadPriorityBoost@8
-;SetThreadUILanguage
+SetThreadUILanguage@4
 SetTimerQueueTimer@24
 SetTimeZoneInformation@4
 SetUnhandledExceptionFilter@4

reactos/lib/kernel32/misc
console.c 1.81 -> 1.82
diff -u -r1.81 -r1.82
--- console.c	14 Sep 2004 22:30:56 -0000	1.81
+++ console.c	2 Nov 2004 20:42:05 -0000	1.82
@@ -1,4 +1,4 @@
-/* $Id: console.c,v 1.81 2004/09/14 22:30:56 hbirr Exp $
+/* $Id: console.c,v 1.82 2004/11/02 20:42:05 weiden Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
@@ -19,7 +19,6 @@
 #define NDEBUG
 #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;
@@ -148,6 +147,7 @@
 		  LPSTR Target,
 		  LPSTR ExeName)
 {
+  DPRINT1("AddConsoleAliasA(0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Source, Target, ExeName);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
@@ -161,6 +161,7 @@
 		  LPWSTR Target,
 		  LPWSTR ExeName)
 {
+  DPRINT1("AddConsoleAliasW(0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Source, Target, ExeName);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
@@ -177,6 +178,7 @@
       * Undocumented
       */
 {
+  DPRINT1("ConsoleMenuControl(0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", hConsole, Unknown1, Unknown2);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
@@ -226,6 +228,7 @@
       * Undocumented
       */
 {
+  DPRINT1("ExpungeConsoleCommandHistoryW(0x%x) UNIMPLEMENTED!\n", Unknown0);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -240,6 +243,8 @@
       * Undocumented
       */
 {
+
+  DPRINT1("ExpungeConsoleCommandHistoryW(0x%x) UNIMPLEMENTED!\n", Unknown0);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -257,6 +262,7 @@
       * Undocumented
       */
 {
+  DPRINT1("GetConsoleAliasW(0x%x, 0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2, Unknown3);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -274,8 +280,9 @@
       * Undocumented
       */
 {
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 0;
+  DPRINT1("GetConsoleAliasA(0x%x, 0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2, Unknown3);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return 0;
 }
 
 
@@ -289,6 +296,7 @@
       * Undocumented
       */
 {
+  DPRINT1("GetConsoleAliasExesW(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -304,8 +312,9 @@
       * Undocumented
       */
 {
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 0;
+  DPRINT1("GetConsoleAliasExesA(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return 0;
 }
 
 
@@ -318,6 +327,7 @@
       * Undocumented
       */
 {
+  DPRINT1("GetConsoleAliasExesLengthA() UNIMPLEMENTED!\n");
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -332,6 +342,7 @@
       * Undocumented
       */
 {
+  DPRINT1("GetConsoleAliasExesLengthW() UNIMPLEMENTED!\n");
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -348,6 +359,7 @@
       * Undocumented
       */
 {
+  DPRINT1("GetConsoleAliasesW(0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -364,6 +376,7 @@
       * Undocumented
       */
 {
+  DPRINT1("GetConsoleAliasesA(0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -378,6 +391,7 @@
       * Undocumented
       */
 {
+  DPRINT1("GetConsoleAliasesLengthW(0x%x) UNIMPLEMENTED!\n", Unknown0);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -392,6 +406,7 @@
       * Undocumented
       */
 {
+  DPRINT1("GetConsoleAliasesLengthA(0x%x) UNIMPLEMENTED!\n", Unknown0);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -408,6 +423,7 @@
       * Undocumented
       */
 {
+  DPRINT1("GetConsoleCommandHistoryW(0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -424,6 +440,7 @@
       * Undocumented
       */
 {
+  DPRINT1("GetConsoleCommandHistoryA(0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -438,6 +455,7 @@
       * Undocumented
       */
 {
+  DPRINT1("GetConsoleCommandHistoryLengthW(0x%x) UNIMPLEMENTED!\n", Unknown0);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -452,6 +470,7 @@
       * Undocumented
       */
 {
+  DPRINT1("GetConsoleCommandHistoryLengthA(0x%x) UNIMPLEMENTED!\n", Unknown0);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -469,6 +488,7 @@
       * STATUS: Undocumented
       */
 {
+  DPRINT1("GetConsoleDisplayMode(0x%x) UNIMPLEMENTED!\n", lpdwMode);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -486,6 +506,7 @@
       * Undocumented
       */
 {
+  DPRINT1("GetConsoleFontInfo(0x%x, 0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2, Unknown3);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -498,6 +519,7 @@
 GetConsoleFontSize(HANDLE hConsoleOutput,
 		   DWORD nFont)
 {
+  DPRINT1("GetConsoleFontSize(0x%x, 0x%x) UNIMPLEMENTED!\n", hConsoleOutput, nFont);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -545,6 +567,7 @@
       * Undocumented
       */
 {
+  DPRINT1("GetConsoleInputWaitHandle() UNIMPLEMENTED!\n");
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
@@ -558,6 +581,7 @@
 		      BOOL bMaximumWindow,
 		      PCONSOLE_FONT_INFO lpConsoleCurrentFont)
 {
+  DPRINT1("GetCurrentConsoleFont(0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", hConsoleOutput, bMaximumWindow, lpConsoleCurrentFont);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -572,6 +596,7 @@
       * Undocumented
       */
 {
+  DPRINT1("GetNumberOfConsoleFonts() UNIMPLEMENTED!\n");
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 1; /* FIXME: call csrss.exe */
 }
@@ -587,6 +612,7 @@
       * Undocumented
       */
 {
+  DPRINT1("InvalidateConsoleDIBits(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -609,7 +635,6 @@
   PHANDLE           phConsole = NULL;
   NTSTATUS          Status = STATUS_SUCCESS;
   
-  
   if(0 == _wcsicmp(wsName, L"CONIN$"))
   {
     Request.Type = CSRSS_GET_INPUT_HANDLE;
@@ -657,6 +682,7 @@
       * Undocumented
       */
 {
+  DPRINT1("SetConsoleCommandHistoryMode(0x%x) UNIMPLEMENTED!\n", dwMode);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
@@ -672,6 +698,7 @@
       * Undocumented
       */
 {
+  DPRINT1("SetConsoleCursor(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
@@ -692,6 +719,7 @@
       *       lpdwOldMode - Address of a variable that receives the old mode.
       */
 {
+  DPRINT1("SetConsoleDisplayMode(0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", hOut, dwNewMode, lpdwOldMode);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
@@ -707,6 +735,7 @@
       * Undocumented
       */
 {
+  DPRINT1("SetConsoleFont(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
@@ -757,6 +786,7 @@
       * Undocumented
       */
 {
+  DPRINT1("SetConsoleKeyShortcuts(0x%x, 0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2, Unknown3);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
@@ -772,6 +802,7 @@
       * Undocumented
       */
 {
+  DPRINT1("SetConsoleMaximumWindowSize(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
@@ -786,6 +817,7 @@
       * Undocumented
       */
 {
+  DPRINT1("SetConsoleMenuClose(0x%x) UNIMPLEMENTED!\n", Unknown0);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
@@ -801,6 +833,7 @@
       * Undocumented
       */
 {
+  DPRINT1("SetConsoleNumberOfCommandsA(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
@@ -816,6 +849,7 @@
       * Undocumented
       */
 {
+  DPRINT1("SetConsoleNumberOfCommandsW(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
@@ -832,6 +866,7 @@
       * Undocumented
       */
 {
+  DPRINT1("SetConsolePalette(0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
@@ -846,6 +881,7 @@
       * Undocumented
       */
 {
+  DPRINT1("SetLastConsoleEventActive() UNIMPLEMENTED!\n");
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
@@ -861,6 +897,7 @@
       * Undocumented
       */
 {
+  DPRINT1("ShowConsoleCursor(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -909,6 +946,7 @@
 		       DWORD	Unknown2,
 		       DWORD	Unknown3)
 {
+  DPRINT1("WriteConsoleInputVDMA(0x%x, 0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2, Unknown3);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -923,6 +961,7 @@
 		       DWORD	Unknown2,
 		       DWORD	Unknown3)
 {
+  DPRINT1("WriteConsoleInputVDMW(0x%x, 0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2, Unknown3);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -1053,6 +1092,73 @@
 }
 
 
+static BOOL
+IntWriteConsole(HANDLE hConsoleOutput,
+                PVOID lpBuffer,
+                DWORD nNumberOfCharsToWrite,
+                LPDWORD lpNumberOfCharsWritten,
+                LPVOID lpReserved,
+                BOOL bUnicode)
+{
+  PCSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+  USHORT nChars;
+  ULONG MessageSize, BufferSize, SizeBytes, CharSize;
+  DWORD Written = 0;
+  
+  CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
+
+  BufferSize = sizeof(CSRSS_API_REQUEST) + min(nNumberOfCharsToWrite * CharSize, CSRSS_MAX_WRITE_CONSOLE_REQUEST);
+  Request = RtlAllocateHeap(GetProcessHeap(), 0, BufferSize);
+  if(Request == NULL)
+  {
+    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    return FALSE;
+  }
+
+  Request->Type = CSRSS_WRITE_CONSOLE;
+  Request->Data.WriteConsoleRequest.ConsoleHandle = hConsoleOutput;
+  Request->Data.WriteConsoleRequest.Unicode = bUnicode;
+
+  while(nNumberOfCharsToWrite > 0)
+  {
+    nChars = min(nNumberOfCharsToWrite, CSRSS_MAX_WRITE_CONSOLE_REQUEST / CharSize);
+    Request->Data.WriteConsoleRequest.NrCharactersToWrite = nChars;
+
+    SizeBytes = nChars * CharSize;
+
+    memcpy(Request->Data.WriteConsoleRequest.Buffer, lpBuffer, SizeBytes);
+
+    MessageSize = CSRSS_REQUEST_HEADER_SIZE + sizeof(CSRSS_WRITE_CONSOLE_REQUEST) + SizeBytes;
+    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 -= nChars;
+    lpBuffer = (PVOID)((ULONG_PTR)lpBuffer + (ULONG_PTR)SizeBytes);
+    Written += Reply.Data.WriteConsoleReply.NrCharactersWritten;
+  }
+
+  RtlFreeHeap(GetProcessHeap(), 0, Request);
+  
+  if(lpNumberOfCharsWritten != NULL)
+  {
+    *lpNumberOfCharsWritten = Written;
+  }
+
+  return TRUE;
+}
+
+
 /*--------------------------------------------------------------
  *	WriteConsoleA
  *
@@ -1065,154 +1171,158 @@
 	      LPDWORD lpNumberOfCharsWritten,
 	      LPVOID lpReserved)
 {
-  PCSRSS_API_REQUEST Request;
-  CSRSS_API_REPLY Reply;
+  return IntWriteConsole(hConsoleOutput,
+                         (PVOID)lpBuffer,
+                         nNumberOfCharsToWrite,
+                         lpNumberOfCharsWritten,
+                         lpReserved,
+                         FALSE);
+}
+
+
+/*--------------------------------------------------------------
+ *	WriteConsoleW
+ *
+ * @implemented
+ */
+BOOL STDCALL
+WriteConsoleW(
+	HANDLE		 hConsoleOutput,
+	CONST VOID	*lpBuffer,
+	DWORD		 nNumberOfCharsToWrite,
+	LPDWORD		 lpNumberOfCharsWritten,
+	LPVOID		 lpReserved
+	)
+{
+  return IntWriteConsole(hConsoleOutput,
+                         (PVOID)lpBuffer,
+                         nNumberOfCharsToWrite,
+                         lpNumberOfCharsWritten,
+                         lpReserved,
+                         TRUE);
+}
+
+
+static BOOL
+IntReadConsole(HANDLE hConsoleInput,
+               PVOID lpBuffer,
+               DWORD nNumberOfCharsToRead,
+               LPDWORD lpNumberOfCharsRead,
+               LPVOID lpReserved,
+               BOOL bUnicode)
+{
+  CSRSS_API_REQUEST Request;
+  PCSRSS_API_REPLY Reply;
   NTSTATUS Status;
-  USHORT Size;
-  ULONG MessageSize;
+  ULONG BufferSize, CharSize, CharsRead = 0;
+  
+  CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
+  
+  BufferSize = sizeof(CSRSS_API_REQUEST) + min(nNumberOfCharsToRead * CharSize, CSRSS_MAX_READ_CONSOLE_REQUEST);
+  Reply = RtlAllocateHeap(GetProcessHeap(), 0, BufferSize);
+  if(Reply == NULL)
+  {
+    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    return FALSE;
+  }
+  
+  Reply->Status = STATUS_SUCCESS;
 
-  Request = RtlAllocateHeap(GetProcessHeap(), 0,
-			    sizeof(CSRSS_API_REQUEST) +
-			    min(nNumberOfCharsToWrite,
-			    CSRSS_MAX_WRITE_CONSOLE_REQUEST));
-  if (Request == NULL)
+  do
+  {
+    if(Reply->Status == STATUS_PENDING)
     {
-      SetLastError(ERROR_OUTOFMEMORY);
-      return(FALSE);
+      Status = NtWaitForSingleObject(Reply->Data.ReadConsoleReply.EventHandle, FALSE, 0);
+      if(!NT_SUCCESS(Status))
+      {
+        DPRINT1("Wait for console input failed!\n");
+        break;
+      }
     }
+    
+    Request.Type = CSRSS_READ_CONSOLE;
+    Request.Data.ReadConsoleRequest.ConsoleHandle = hConsoleInput;
+    Request.Data.ReadConsoleRequest.Unicode = bUnicode;
+    Request.Data.ReadConsoleRequest.NrCharactersToRead = min(nNumberOfCharsToRead, CSRSS_MAX_READ_CONSOLE_REQUEST / CharSize);
+    Request.Data.ReadConsoleRequest.nCharsCanBeDeleted = CharsRead;
+    Status = CsrClientCallServer(&Request,
+                                 Reply,
+                                 sizeof(CSRSS_API_REQUEST),
+                                 sizeof(CSRSS_API_REPLY) + (Request.Data.ReadConsoleRequest.NrCharactersToRead * CharSize));
 
-  Request->Type = CSRSS_WRITE_CONSOLE;
-  Request->Data.WriteConsoleRequest.ConsoleHandle = hConsoleOutput;
-  if (lpNumberOfCharsWritten != NULL)
-    *lpNumberOfCharsWritten = nNumberOfCharsToWrite;
-  while (nNumberOfCharsToWrite)
+    if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply->Status))
     {
-      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;
+      DPRINT1("CSR returned error in ReadConsole\n");
+      SetLastErrorByStatus(Status);
+      RtlFreeHeap(GetProcessHeap(), 0, Reply);
+      return FALSE;
+    }
+    
+    nNumberOfCharsToRead -= Reply->Data.ReadConsoleReply.NrCharactersRead;
+    memcpy((PVOID)((ULONG_PTR)lpBuffer + (ULONG_PTR)(CharsRead * CharSize)),
+           Reply->Data.ReadConsoleReply.Buffer,
+           Reply->Data.ReadConsoleReply.NrCharactersRead);
+    CharsRead += Reply->Data.ReadConsoleReply.NrCharactersRead;
+    
+    if(Reply->Status == STATUS_NOTIFY_CLEANUP)
+    {
+      if(CharsRead > 0)
+      {
+        CharsRead--;
+        nNumberOfCharsToRead++;
+      }
+      Reply->Status = STATUS_PENDING;
     }
+  } while(Reply->Status == STATUS_PENDING && nNumberOfCharsToRead > 0);
+  
+  if(lpNumberOfCharsRead != NULL)
+  {
+    *lpNumberOfCharsRead = CharsRead;
+  }
+  
+  return (nNumberOfCharsToRead == 0);
+}
 
-  RtlFreeHeap(GetProcessHeap(), 0, Request);
 
-  return TRUE;
+/*--------------------------------------------------------------
+ *	ReadConsoleA
+ *
+ * @implemented
+ */
+BOOL STDCALL
+ReadConsoleA(HANDLE hConsoleInput,
+             LPVOID lpBuffer,
+             DWORD nNumberOfCharsToRead,
+             LPDWORD lpNumberOfCharsRead,
+             LPVOID lpReserved)
+{
+  return IntReadConsole(hConsoleInput,
+                        lpBuffer,
+                        nNumberOfCharsToRead,
+                        lpNumberOfCharsRead,
+                        lpReserved,
+                        FALSE);
 }
 
 
 /*--------------------------------------------------------------
- *	ReadConsoleA
+ *	ReadConsoleW
  *
  * @implemented
  */
-BOOL STDCALL ReadConsoleA(HANDLE hConsoleInput,
-			     LPVOID lpBuffer,
-			     DWORD nNumberOfCharsToRead,
-			     LPDWORD lpNumberOfCharsRead,
-			     LPVOID lpReserved)
-{
-   CSRSS_API_REQUEST Request;
-   PCSRSS_API_REPLY Reply;
-   NTSTATUS Status;
-   ULONG CharsRead = 0;
-   
-   Reply = RtlAllocateHeap(GetProcessHeap(), 0,
-                           sizeof(CSRSS_API_REPLY) + nNumberOfCharsToRead);
-   if (Reply == NULL)
-     {
-	SetLastError(ERROR_OUTOFMEMORY);
-	return(FALSE);
-     }
-   
-   Request.Type = CSRSS_READ_CONSOLE;
-   Request.Data.ReadConsoleRequest.ConsoleHandle = hConsoleInput;
-   Request.Data.ReadConsoleRequest.NrCharactersToRead = nNumberOfCharsToRead > CSRSS_MAX_READ_CONSOLE_REQUEST ? CSRSS_MAX_READ_CONSOLE_REQUEST : nNumberOfCharsToRead;
-   Request.Data.ReadConsoleRequest.nCharsCanBeDeleted = 0;
-   Status = CsrClientCallServer(&Request, 
-				Reply,
-				sizeof(CSRSS_API_REQUEST),
-				sizeof(CSRSS_API_REPLY) + 
-				Request.Data.ReadConsoleRequest.NrCharactersToRead);
-   if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply->Status ))
-     {
-	DbgPrint( "CSR returned error in ReadConsole\n" );
-	SetLastErrorByStatus ( Status );
-	RtlFreeHeap( GetProcessHeap(), 0, Reply );
-	return(FALSE);
-     }
-   if( Reply->Status == STATUS_NOTIFY_CLEANUP )
-      Reply->Status = STATUS_PENDING;     // ignore backspace because we have no chars to backspace
-   /* There may not be any chars or lines to read yet, so wait */
-   while( Reply->Status == STATUS_PENDING )
-     {
-       /* some chars may have been returned, but not a whole line yet, so recompute buffer and try again */
-       nNumberOfCharsToRead -= Reply->Data.ReadConsoleReply.NrCharactersRead;
-       /* don't overflow caller's buffer, even if you still don't have a complete line */
-       if( !nNumberOfCharsToRead )
-	 break;
-       Request.Data.ReadConsoleRequest.NrCharactersToRead = nNumberOfCharsToRead > CSRSS_MAX_READ_CONSOLE_REQUEST ? CSRSS_MAX_READ_CONSOLE_REQUEST : nNumberOfCharsToRead;
-       /* copy any chars already read to buffer */
-       memcpy( lpBuffer + CharsRead, Reply->Data.ReadConsoleReply.Buffer, Reply->Data.ReadConsoleReply.NrCharactersRead );
-       CharsRead += Reply->Data.ReadConsoleReply.NrCharactersRead;
-       /* wait for csrss to signal there is more data to read, but not if we got STATUS_NOTIFY_CLEANUP for backspace */
-       Status = NtWaitForSingleObject( Reply->Data.ReadConsoleReply.EventHandle, FALSE, 0 );
-       if( !NT_SUCCESS( Status ) )
-	  {
-	     DbgPrint( "Wait for console input failed!\n" );
-	     RtlFreeHeap( GetProcessHeap(), 0, Reply );
-	     return FALSE;
-	  }
-       Request.Data.ReadConsoleRequest.nCharsCanBeDeleted = CharsRead;
-       Status = CsrClientCallServer( &Request, Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) + Request.Data.ReadConsoleRequest.NrCharactersToRead );
-       if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply->Status ) )
-	 {
-	   SetLastErrorByStatus ( Status );
-	   RtlFreeHeap( GetProcessHeap(), 0, Reply );
-	   return FALSE;
-	 }
-       if( Reply->Status == STATUS_NOTIFY_CLEANUP )
-	  {
-	     // delete last char
-	     if( CharsRead )
-		{
-		   CharsRead--;
-		   nNumberOfCharsToRead++;
-		}
-	     Reply->Status = STATUS_PENDING;  // retry
-	  }
-     }
-   /* copy data to buffer, count total returned, and return */
-   memcpy( lpBuffer + CharsRead, Reply->Data.ReadConsoleReply.Buffer, Reply->Data.ReadConsoleReply.NrCharactersRead );
-   CharsRead += Reply->Data.ReadConsoleReply.NrCharactersRead;
-   if (lpNumberOfCharsRead != NULL)
-     *lpNumberOfCharsRead = CharsRead;
-   RtlFreeHeap(GetProcessHeap(),
-	    0,
-	    Reply);
-   
-   return(TRUE);
+BOOL STDCALL
+ReadConsoleW(HANDLE hConsoleInput,
+             LPVOID lpBuffer,
+             DWORD nNumberOfCharsToRead,
+             LPDWORD lpNumberOfCharsRead,
+             LPVOID lpReserved)
+{
+  return IntReadConsole(hConsoleInput,
+                        lpBuffer,
+                        nNumberOfCharsToRead,
+                        lpNumberOfCharsRead,
+                        lpReserved,
+                        TRUE);
 }
 
 
@@ -1340,6 +1450,45 @@
 }
 
 
+static BOOL
+IntFillConsoleOutputCharacter(HANDLE hConsoleOutput,
+                              PVOID cCharacter,
+                              DWORD nLength,
+                              COORD dwWriteCoord,
+                              LPDWORD lpNumberOfCharsWritten,
+                              BOOL bUnicode)
+{
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+
+  Request.Type = CSRSS_FILL_OUTPUT;
+  Request.Data.FillOutputRequest.ConsoleHandle = hConsoleOutput;
+  Request.Data.FillOutputRequest.Unicode = bUnicode;
+  if(bUnicode)
+    Request.Data.FillOutputRequest.Char.UnicodeChar = *((WCHAR*)cCharacter);
+  else
+    Request.Data.FillOutputRequest.Char.AsciiChar = *((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 = Reply.Data.FillOutputReply.NrCharactersWritten;
+  }
+  
+  return TRUE;
+}
+
 /*--------------------------------------------------------------
  *	FillConsoleOutputCharacterA
  *
@@ -1354,31 +1503,19 @@
 	LPDWORD		lpNumberOfCharsWritten
 	)
 {
-  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);
-    }
-  if (lpNumberOfCharsWritten != NULL)
-     *lpNumberOfCharsWritten = nLength;
-  return(TRUE);
+  return IntFillConsoleOutputCharacter(hConsoleOutput,
+                                       &cCharacter,
+                                       nLength,
+                                       dwWriteCoord,
+                                       lpNumberOfCharsWritten,
+                                       FALSE);
 }
 
 
 /*--------------------------------------------------------------
  *	FillConsoleOutputCharacterW
  *
- * @unimplemented
+ * @implemented
  */
 BOOL
 STDCALL
@@ -1390,33 +1527,28 @@
 	LPDWORD		lpNumberOfCharsWritten
 	)
 {
-/* TO DO */
-	DbgPrint("%s unimplemented\n", __FUNCTION__);
-	return FALSE;
+  return IntFillConsoleOutputCharacter(hConsoleOutput,
+                                       &cCharacter,
+                                       nLength,
+                                       dwWriteCoord,
+                                       lpNumberOfCharsWritten,
+                                       TRUE);
 }
 
 
-/*--------------------------------------------------------------
- * 	IntPeekConsoleInput
- *
- * INTERNAL
- */
-BOOL
-WINAPI
-IntPeekConsoleInput(
-	HANDLE			hConsoleInput,
-	PINPUT_RECORD		lpBuffer,
-	DWORD			nLength,
-	LPDWORD			lpNumberOfEventsRead,
-	BOOL			bUnicode
-	)
+static BOOL
+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;
+  ULONG Size;
   
   if(lpBuffer == NULL)
   {
@@ -1437,7 +1569,7 @@
   if(Request == NULL)
   {
     CsrReleaseParameterBuffer(BufferBase);
-    SetLastError(ERROR_OUTOFMEMORY);
+    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
     return FALSE;
   }
   
@@ -1447,7 +1579,9 @@
   Request->Data.PeekConsoleInputRequest.Length = nLength;
   Request->Data.PeekConsoleInputRequest.InputRecord = (INPUT_RECORD*)BufferTargetBase;
   
-  Status = CsrClientCallServer(Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY));
+  Status = CsrClientCallServer(Request, &Reply,
+                               sizeof(CSRSS_API_REQUEST),
+                               sizeof(CSRSS_API_REPLY));
   
   if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
   {
@@ -1458,11 +1592,13 @@
 
   memcpy(lpBuffer, BufferBase, sizeof(INPUT_RECORD) * Reply.Data.PeekConsoleInputReply.Length);
 
+  RtlFreeHeap(GetProcessHeap(), 0, Request);
+  CsrReleaseParameterBuffer(BufferBase);
+  
   if(lpNumberOfEventsRead != NULL)
+  {
     *lpNumberOfEventsRead = Reply.Data.PeekConsoleInputReply.Length;
-
-  RtlFreeHeap(GetProcessHeap(), 0, Request);
-  CsrReleaseParameterBuffer(BufferBase);  
+  }
   
   return TRUE;
 }
@@ -1505,12 +1641,7 @@
 }
 
 
-/*--------------------------------------------------------------
- * 	IntReadConsoleInput
- *
- * INTERNAL
- */
-BOOL WINAPI
+static BOOL
 IntReadConsoleInput(HANDLE hConsoleInput,
                     PINPUT_RECORD lpBuffer,
                     DWORD nLength,
@@ -1519,68 +1650,69 @@
 {
   CSRSS_API_REQUEST Request;
   CSRSS_API_REPLY Reply;
-  DWORD NumEventsRead;
+  ULONG Read;
   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))
+  Request.Data.ReadInputRequest.Unicode = bUnicode;
+
+  Read = 0;
+  while(nLength > 0)
+  {
+    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(Read == 0)
+      {
+        /* we couldn't read a single record, fail */
+        SetLastErrorByStatus(Status);
+        return FALSE;
+      }
+      else
+      {
+        /* FIXME - fail gracefully in case we already read at least one record? */
+        break;
+      }
     }
-  
-  while (Status == STATUS_PENDING)
+    else if(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);
-	}
+      if(Read == 0)
+      {
+        Status = NtWaitForSingleObject(Reply.Data.ReadInputReply.Event, FALSE, 0);
+        if(!NT_SUCCESS(Status))
+        {
+          SetLastErrorByStatus(Status);
+          break;
+        }
+      }
+      else
+      {
+        /* nothing more to read (waiting for more input??), let's just bail */
+        break;
+      }
     }
-  
-  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++;
[truncated at 1000 lines; 973 more skipped]

reactos/lib/kernel32/thread
thread.c 1.54 -> 1.55
diff -u -r1.54 -r1.55
--- thread.c	24 Oct 2004 12:16:54 -0000	1.54
+++ thread.c	2 Nov 2004 20:42:06 -0000	1.55
@@ -1,4 +1,4 @@
-/* $Id: thread.c,v 1.54 2004/10/24 12:16:54 weiden Exp $
+/* $Id: thread.c,v 1.55 2004/11/02 20:42:06 weiden Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
@@ -714,4 +714,13 @@
   return dwIdealProcessor;
 }
 
+/*
+ * @unimplemented
+ */
+VOID STDCALL
+SetThreadUILanguage(DWORD Unknown1)
+{
+  DPRINT1("SetThreadUILanguage(0x%x) unimplemented!\n", Unknown1);
+}
+
 /* EOF */

reactos/subsys/csrss/win32csr
conio.c 1.15 -> 1.16
diff -u -r1.15 -r1.16
--- conio.c	10 Sep 2004 22:14:52 -0000	1.15
+++ conio.c	2 Nov 2004 20:42:06 -0000	1.16
@@ -1,4 +1,4 @@
-/* $Id: conio.c,v 1.15 2004/09/10 22:14:52 gvg Exp $
+/* $Id: conio.c,v 1.16 2004/11/02 20:42:06 weiden Exp $
  *
  * reactos/subsys/csrss/win32csr/conio.c
  *
@@ -46,6 +46,15 @@
 #define ConioIsRectEmpty(Rect) \
   (((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom))
 
+#define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
+  WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
+
+#define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \
+  MultiByteToWideChar((Console)->CodePage, 0, (dChar), 1, (sWChar), 1)
+
+#define ConsoleUnicodeToAnsiN(Console, dChar, sWChar, nChars) \
+  WideCharToMultiByte((Console)->CodePage, 0, (sWChar), (nChars), (dChar), (nChars) * sizeof(WCHAR), NULL, NULL)
+
 /* FUNCTIONS *****************************************************************/
 
 STATIC NTSTATUS FASTCALL
@@ -522,19 +531,23 @@
   PLIST_ENTRY CurrentEntry;
   ConsoleInput *Input;
   PCHAR Buffer;
+  PWCHAR UnicodeBuffer;
   int i;
-  ULONG nNumberOfCharsToRead;
+  ULONG nNumberOfCharsToRead, CharSize;
   PCSRSS_CONSOLE Console;
   NTSTATUS Status;
    
   DPRINT("CsrReadConsole\n");
+  
+  CharSize = (Request->Data.ReadConsoleRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
 
   /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
-  nNumberOfCharsToRead = Request->Data.ReadConsoleRequest.NrCharactersToRead > CSRSS_MAX_READ_CONSOLE_REQUEST ? CSRSS_MAX_READ_CONSOLE_REQUEST : Request->Data.ReadConsoleRequest.NrCharactersToRead;
+  nNumberOfCharsToRead = min(Request->Data.ReadConsoleRequest.NrCharactersToRead, CSRSS_MAX_READ_CONSOLE_REQUEST / CharSize);
   Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
   Reply->Header.DataSize = Reply->Header.MessageSize - LPC_MESSAGE_BASE_SIZE;
 
   Buffer = Reply->Data.ReadConsoleReply.Buffer;
+  UnicodeBuffer = (PWCHAR)Buffer;
   Status = ConioLockConsole(ProcessData, Request->Data.ReadConsoleRequest.ConsoleHandle,
                                &Console);
   if (! NT_SUCCESS(Status))
@@ -551,7 +564,7 @@
       /* only pay attention to valid ascii chars, on key down */
       if (KEY_EVENT == Input->InputEvent.EventType
           && Input->InputEvent.Event.KeyEvent.bKeyDown
-          && Input->InputEvent.Event.KeyEvent.uChar.AsciiChar)
+          && Input->InputEvent.Event.KeyEvent.uChar.AsciiChar != '\0')
         {
           /* backspace handling */
           if ('\b' == Input->InputEvent.Event.KeyEvent.uChar.AsciiChar)
@@ -561,7 +574,7 @@
                   && (0 !=  i || Request->Data.ReadConsoleRequest.nCharsCanBeDeleted))
                 {
                   ConioWriteConsole(Console, Console->ActiveBuffer,
-                                   &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE);
+                                    &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE);
                 }
               if (0 != i)
                 {
@@ -569,11 +582,11 @@
                 }
               else
                 {            /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
-                  Reply->Data.ReadConsoleReply.NrCharactersRead = 0;
-                  Reply->Status = STATUS_NOTIFY_CLEANUP;
                   Console->WaitingChars--;
-                  HeapFree(Win32CsrApiHeap, 0, Input);
                   ConioUnlockConsole(Console);
+                  HeapFree(Win32CsrApiHeap, 0, Input);
+                  Reply->Data.ReadConsoleReply.NrCharactersRead = 0;
+                  Reply->Status = STATUS_NOTIFY_CLEANUP;
                   return STATUS_NOTIFY_CLEANUP;
                 }
               Request->Data.ReadConsoleRequest.nCharsCanBeDeleted--;
@@ -582,7 +595,10 @@
           /* do not copy backspace to buffer */
           else
             {
-              Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar;
+              if(Request->Data.ReadConsoleRequest.Unicode)
+                UnicodeBuffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar; /* FIXME */
+              else
+                Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar;
             }
           /* echo to screen if enabled and we did not already echo the char */
           if (0 != (Console->Mode & ENABLE_ECHO_INPUT)
@@ -607,7 +623,8 @@
     }
   else if (0 != (Console->Mode & ENABLE_LINE_INPUT))
     {
-      if (0 == Console->WaitingLines || '\n' != Buffer[i - 1])
+      if (0 == Console->WaitingLines ||
+          (Request->Data.ReadConsoleRequest.Unicode ? (L'\n' != UnicodeBuffer[i - 1]) : ('\n' != Buffer[i - 1])))
         {
           Reply->Status = STATUS_PENDING; /* line buffered, didn't get a complete line */
         }
@@ -630,7 +647,7 @@
     {
       Console->EchoCount = 0;             /* if the client is no longer waiting on input, do not echo */
     }
-  Reply->Header.MessageSize += i;
+  Reply->Header.MessageSize += i * CharSize;
 
   ConioUnlockConsole(Console);
   return Reply->Status;
@@ -817,14 +834,22 @@
 }
 
 STATIC VOID FASTCALL
-ConioFillRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer,
+ConioFillRegion(PCSRSS_CONSOLE Console,
+                PCSRSS_SCREEN_BUFFER ScreenBuffer,
                 RECT *Region,
-                CHAR_INFO CharInfo)
+                CHAR_INFO *CharInfo,
+                BOOL bUnicode)
 {
   SHORT X, Y;
   DWORD Offset;
   DWORD Delta;
   ULONG i;
+  CHAR Char;
+  
+  if(bUnicode)
+    ConsoleUnicodeCharToAnsiChar(Console, &Char, &CharInfo->Char.UnicodeChar);
+  else
+    Char = CharInfo->Char.AsciiChar;
 
   Y = (Region->top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
   Offset = (Y * ScreenBuffer->MaxX + Region->left + ScreenBuffer->ShowX) * 2;
@@ -834,7 +859,7 @@
     {
       for (X = Region->left; X <= Region->right; X++)
         {
-          SET_CELL_BUFFER(ScreenBuffer, Offset, CharInfo.Char.AsciiChar, CharInfo.Attributes);
+          SET_CELL_BUFFER(ScreenBuffer, Offset, Char, CharInfo->Attributes);
         }
       if (++Y == ScreenBuffer->MaxY)
         {
@@ -853,10 +878,9 @@
 {
   if (InputEvent->EventType == KEY_EVENT)
     {
-      WideCharToMultiByte(Console->CodePage, 0,
-                          &InputEvent->Event.KeyEvent.uChar.UnicodeChar, 1,
-                          &InputEvent->Event.KeyEvent.uChar.AsciiChar, 1,
-                          NULL, NULL);
+      ConsoleUnicodeCharToAnsiChar(Console,
+                                   &InputEvent->Event.KeyEvent.uChar.AsciiChar,
+                                   &InputEvent->Event.KeyEvent.uChar.UnicodeChar);
     }
 }
 
@@ -866,6 +890,7 @@
   BYTE *Buffer = Request->Data.WriteConsoleRequest.Buffer;
   PCSRSS_SCREEN_BUFFER Buff;
   PCSRSS_CONSOLE Console;
+  ULONG CharSize = (Request->Data.WriteConsoleRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
 
   DPRINT("CsrWriteConsole\n");
    
@@ -874,7 +899,7 @@
 
   if (Request->Header.DataSize
       < sizeof(CSRSS_WRITE_CONSOLE_REQUEST) - 1
-        + Request->Data.WriteConsoleRequest.NrCharactersToWrite)
+        + (Request->Data.WriteConsoleRequest.NrCharactersToWrite * CharSize))
     {
       DPRINT1("Invalid request size\n");
       return Reply->Status = STATUS_INVALID_PARAMETER;
@@ -885,6 +910,11 @@
       return Reply->Status = Status;
     }
 
+  if(Request->Data.WriteConsoleRequest.Unicode)
+  {
+    ConsoleUnicodeToAnsiN(Console, Buffer, (PWCHAR)Buffer, Request->Data.WriteConsoleRequest.NrCharactersToWrite);
+  }
+
   Status = ConioLockScreenBuffer(ProcessData, Request->Data.WriteConsoleRequest.ConsoleHandle, &Buff);
   if (! NT_SUCCESS(Status))
     {
@@ -895,14 +925,23 @@
       return Reply->Status = Status;
     }
 
-  ConioWriteConsole(Console, Buff, Buffer,
-                    Request->Data.WriteConsoleRequest.NrCharactersToWrite, TRUE);
+  Reply->Status = ConioWriteConsole(Console, Buff, Buffer,
+                                    Request->Data.WriteConsoleRequest.NrCharactersToWrite, TRUE);
   ConioUnlockScreenBuffer(Buff);
   if (NULL != Console)
     {
       ConioUnlockConsole(Console);
     }
 
+  if(NT_SUCCESS(Reply->Status))
+  {
+    Reply->Data.WriteConsoleReply.NrCharactersWritten = Request->Data.WriteConsoleRequest.NrCharactersToWrite;
+  }
+  else
+  {
+    Reply->Data.WriteConsoleReply.NrCharactersWritten = 0; /* FIXME - return the actual number of characters written! */
+  }
+
   return Reply->Status = STATUS_SUCCESS;
 }
 
@@ -967,7 +1006,7 @@
 
 STATIC VOID FASTCALL
 ConioProcessChar(PCSRSS_CONSOLE Console,
-                            ConsoleInput *KeyEventRecord)
+                 ConsoleInput *KeyEventRecord)
 {
   BOOL updown;
   BOOL bClientWake = FALSE;
@@ -1114,7 +1153,7 @@
             {
               ConioWriteConsole(Console, Console->ActiveBuffer,
                                &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar,
-                               1, TRUE);	
+                               1, TRUE);
             }
           HeapFree(Win32CsrApiHeap, 0, TempInput);
 	  RemoveEntryList(&KeyEventRecord->ListEntry);
@@ -1296,6 +1335,7 @@
     
   if (! ConInRec->Fake || ! ConInRec->NotChar)
     {
+      /* FIXME - convert to ascii */
       ConioProcessChar(Console, ConInRec);
     }
   else
@@ -1461,17 +1501,19 @@
   PBYTE Buffer;
   PCSRSS_CONSOLE Console;
   PCSRSS_SCREEN_BUFFER Buff;
-  DWORD X, Y, Length;
+  DWORD X, Y, Length, CharSize, Written = 0;
   RECT UpdateRect;
 
   DPRINT("CsrWriteConsoleOutputChar\n");
 
   Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
   Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - LPC_MESSAGE_BASE_SIZE;
+  
+  CharSize = (Request->Data.WriteConsoleOutputCharRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
 
   if (Request->Header.DataSize
       < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REQUEST) - 1
-        + Request->Data.WriteConsoleOutputCharRequest.Length)
+        + (Request->Data.WriteConsoleOutputCharRequest.Length * CharSize))
     {
       DPRINT1("Invalid request size\n");
       return Reply->Status = STATUS_INVALID_PARAMETER;
@@ -1483,6 +1525,11 @@
       return Reply->Status = Status;
     }
 
+  if(Request->Data.WriteConsoleOutputCharRequest.Unicode)
+  {
+    ConsoleUnicodeToAnsiN(Console, String, (PWCHAR)String, Request->Data.WriteConsoleOutputCharRequest.Length);
+  }
+
   Status = ConioLockScreenBuffer(ProcessData,
                                  Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle,
                                  &Buff);
@@ -1502,6 +1549,7 @@
   while (Length--)
     {
       *Buffer = *String++;
+      Written++;
       Buffer += 2;
       if (++X == Buff->MaxX)
         {
@@ -1530,6 +1578,7 @@
       ConioUnlockConsole(Console);
     }
 
+  Reply->Data.WriteConsoleOutputCharReply.NrCharactersWritten = Written;
   return Reply->Status = STATUS_SUCCESS;
 }
 
@@ -1538,7 +1587,7 @@
   NTSTATUS Status;
   PCSRSS_CONSOLE Console;
   PCSRSS_SCREEN_BUFFER Buff;
-  DWORD X, Y, Length;
+  DWORD X, Y, Length, Written = 0;
   BYTE Char;
   PBYTE Buffer;
   RECT UpdateRect;
@@ -1567,12 +1616,16 @@
   X = Request->Data.FillOutputRequest.Position.X + Buff->ShowX;
   Y = (Request->Data.FillOutputRequest.Position.Y + Buff->ShowY) % Buff->MaxY;
   Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)];
-  Char = Request->Data.FillOutputRequest.Char;
+  if(Request->Data.FillOutputRequest.Unicode)
+    ConsoleUnicodeCharToAnsiChar(Console, &Char, &Request->Data.FillOutputRequest.Char.UnicodeChar);
+  else
+    Char = Request->Data.FillOutputRequest.Char.AsciiChar;
   Length = Request->Data.FillOutputRequest.Length;
   while (Length--)
     {
       *Buffer = Char;
       Buffer += 2;
+      Written++;
       if (++X == Buff->MaxX)
         {
           if (++Y == Buff->MaxY)
@@ -1597,6 +1650,7 @@
       ConioUnlockConsole(Console);
     }
 
+  Reply->Data.FillOutputReply.NrCharactersWritten = Written;
   return Reply->Status;
 }
 
@@ -1630,7 +1684,7 @@
 
       if (Request->Data.ReadInputRequest.Unicode == FALSE)
         {
-          ConioInputEventToAnsi(Console, &Reply->Data.ReadInputReply.Input);
+          ConioInputEventToAnsi(Console, &Reply->Data.ReadInputReply.Input); /* FIXME */
         }
 
       if (Input->InputEvent.EventType == KEY_EVENT)
@@ -2265,9 +2319,7 @@
           if (Request->Data.WriteConsoleOutputRequest.Unicode)
             {
               CHAR AsciiChar;
-              WideCharToMultiByte(Console->OutputCodePage, 0,
-                                  &CurCharInfo->Char.UnicodeChar, 1,
-                                  &AsciiChar, 1, NULL, NULL);
+              ConsoleUnicodeCharToAnsiChar(Console, &AsciiChar, &CurCharInfo->Char.UnicodeChar);
               SET_CELL_BUFFER(Buff, Offset, AsciiChar, CurCharInfo->Attributes);
             }
           else
@@ -2416,7 +2468,7 @@
       /* FIXME: The subtracted rectangle is off by one line */
       FillRegion.top += 1;
 
-      ConioFillRegion(Buff, &FillRegion, Fill);
+      ConioFillRegion(Console, Buff, &FillRegion, &Fill, Request->Data.ScrollConsoleScreenBufferRequest.Unicode);
       DoFill = TRUE;
     }
 
@@ -2444,16 +2496,27 @@
 CSR_API(CsrReadConsoleOutputChar)
 {
   NTSTATUS Status;
+  PCSRSS_CONSOLE Console;
   PCSRSS_SCREEN_BUFFER Buff;
   DWORD Xpos, Ypos;
   BYTE* ReadBuffer;
   DWORD i;
+  ULONG CharSize;
+  CHAR Char;
 
   DPRINT("CsrReadConsoleOutputChar\n");
 
   Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
   Reply->Header.DataSize = Reply->Header.MessageSize - LPC_MESSAGE_BASE_SIZE;
   ReadBuffer = Reply->Data.ReadConsoleOutputCharReply.String;
+  
+  CharSize = (Request->Data.ReadConsoleOutputCharRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
+  
+  Status = ConioConsoleFromProcessData(ProcessData, &Console);
+  if (! NT_SUCCESS(Status))
+    {
+      return Reply->Status = Status;
+    }
 
   Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputCharRequest.ConsoleHandle, &Buff);
   if (! NT_SUCCESS(Status))
@@ -2466,9 +2529,16 @@
 
   for (i = 0; i < Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead; ++i)
     {
-      *ReadBuffer = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX)];
+      Char = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX)];
+      
+      if(Request->Data.ReadConsoleOutputCharRequest.Unicode)
+      {
+        ConsoleAnsiCharToUnicodeChar(Console, (WCHAR*)ReadBuffer, &Char);
+        ReadBuffer += sizeof(WCHAR);
+      }
+      else
+        *(ReadBuffer++) = Char;
 
-      ReadBuffer++;
       Xpos++;
 
       if (Xpos == Buff->MaxX)
@@ -2491,6 +2561,12 @@
   Reply->Header.DataSize += Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead;
 
   ConioUnlockScreenBuffer(Buff);
+  if (NULL != Console)
+    {
+      ConioUnlockConsole(Console);
+    }
+  
+  Reply->Data.ReadConsoleOutputCharReply.CharsRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)Reply->Data.ReadConsoleOutputCharReply.String) / CharSize;
 
   return Reply->Status;
 }
@@ -2809,6 +2885,7 @@
       Record->InputEvent = *InputRecord++;
       if (KEY_EVENT == Record->InputEvent.EventType)
         {
+          /* FIXME - convert from unicode to ascii!! */
           ConioProcessChar(Console, Record);
         }
     }
CVSspam 0.2.8