update for HEAD-2003021201
[reactos.git] / lib / kernel32 / misc / console.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS system libraries
5  * FILE:            lib/kernel32/misc/console.c
6  * PURPOSE:         Win32 server console functions
7  * PROGRAMMER:      ???
8  * UPDATE HISTORY:
9  *      199901?? ??     Created
10  *      19990204 EA     SetConsoleTitleA
11  *      19990306 EA     Stubs
12  */
13
14 /* INCLUDES ******************************************************************/
15
16 #include <k32.h>
17
18 #define NDEBUG
19 #include <kernel32/kernel32.h>
20
21 /* GLOBALS *******************************************************************/
22
23 static BOOL IgnoreCtrlEvents = FALSE;
24 static ULONG NrCtrlHandlers = 0;
25 static PHANDLER_ROUTINE* CtrlHandlers = NULL;
26
27 /* FUNCTIONS *****************************************************************/
28
29 BOOL STDCALL
30 AddConsoleAliasA (LPSTR Source,
31                   LPSTR Target,
32                   LPSTR ExeName)
33 {
34   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
35   return FALSE;
36 }
37
38 BOOL STDCALL
39 AddConsoleAliasW (LPWSTR Source,
40                   LPWSTR Target,
41                   LPWSTR ExeName)
42 {
43   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
44   return FALSE;
45 }
46
47 BOOL STDCALL
48 ConsoleMenuControl (HANDLE      hConsole,
49                     DWORD       Unknown1,
50                     DWORD       Unknown2)
51      /*
52       * Undocumented
53       */
54 {
55   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
56   return FALSE;
57 }
58
59 BOOL STDCALL
60 DuplicateConsoleHandle (HANDLE  hConsole,
61                         DWORD   Unknown1,
62                         DWORD   Unknown2,
63                         DWORD   Unknown3)
64      /*
65       * Undocumented
66       */
67 {
68   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
69   return FALSE;
70 }
71
72 DWORD STDCALL
73 ExpungeConsoleCommandHistoryW (DWORD    Unknown0)
74      /*
75       * Undocumented
76       */
77 {
78   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
79   return 0;
80 }
81
82
83 DWORD STDCALL
84 ExpungeConsoleCommandHistoryA (DWORD    Unknown0)
85      /*
86       * Undocumented
87       */
88 {
89   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
90   return 0;
91 }
92
93 DWORD STDCALL
94 GetConsoleAliasW (DWORD Unknown0,
95                   DWORD Unknown1,
96                   DWORD Unknown2,
97                   DWORD Unknown3)
98      /*
99       * Undocumented
100       */
101 {
102   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
103   return 0;
104 }
105
106
107 DWORD STDCALL
108 GetConsoleAliasA (DWORD Unknown0,
109                   DWORD Unknown1,
110                   DWORD Unknown2,
111                   DWORD Unknown3)
112      /*
113       * Undocumented
114       */
115 {
116         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
117         return 0;
118 }
119
120 DWORD STDCALL
121 GetConsoleAliasExesW (DWORD     Unknown0,
122                       DWORD     Unknown1)
123      /*
124       * Undocumented
125       */
126 {
127   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
128   return 0;
129 }
130
131
132
133 DWORD STDCALL
134 GetConsoleAliasExesA (DWORD     Unknown0,
135                       DWORD     Unknown1)
136      /*
137       * Undocumented
138       */
139 {
140         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
141         return 0;
142 }
143
144
145
146 DWORD STDCALL
147 GetConsoleAliasExesLengthA (VOID)
148      /*
149       * Undocumented
150       */
151 {
152   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
153   return 0;
154 }
155
156 DWORD STDCALL
157 GetConsoleAliasExesLengthW (VOID)
158      /*
159       * Undocumented
160       */
161 {
162   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
163   return 0;
164 }
165
166 DWORD STDCALL
167 GetConsoleAliasesW (DWORD       Unknown0,
168                     DWORD       Unknown1,
169                     DWORD       Unknown2)
170      /*
171       * Undocumented
172       */
173 {
174   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
175   return 0;
176 }
177  
178 DWORD STDCALL
179 GetConsoleAliasesA (DWORD       Unknown0,
180                     DWORD       Unknown1,
181                     DWORD       Unknown2)
182      /*
183       * Undocumented
184       */
185 {
186   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
187   return 0;
188 }
189
190 DWORD STDCALL
191 GetConsoleAliasesLengthW (DWORD Unknown0)
192      /*
193       * Undocumented
194       */
195 {
196   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
197   return 0;
198 }
199
200 DWORD STDCALL
201 GetConsoleAliasesLengthA (DWORD Unknown0)
202      /*
203       * Undocumented
204       */
205 {
206   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
207   return 0;
208 }
209
210 DWORD STDCALL
211 GetConsoleCommandHistoryW (DWORD        Unknown0,
212                            DWORD        Unknown1,
213                            DWORD        Unknown2)
214      /*
215       * Undocumented
216       */
217 {
218   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
219   return 0;
220 }
221
222 DWORD STDCALL
223 GetConsoleCommandHistoryA (DWORD        Unknown0,
224                            DWORD        Unknown1,
225                            DWORD        Unknown2)
226      /*
227       * Undocumented
228       */
229 {
230   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
231   return 0;
232 }
233
234 DWORD STDCALL
235 GetConsoleCommandHistoryLengthW (DWORD  Unknown0)
236      /*
237       * Undocumented
238       */
239 {
240   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
241   return 0;
242 }
243
244 DWORD STDCALL
245 GetConsoleCommandHistoryLengthA (DWORD  Unknown0)
246      /*
247       * Undocumented
248       */
249 {
250   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
251   return 0;
252 }
253
254 DWORD STDCALL
255 GetConsoleDisplayMode (LPDWORD lpdwMode)
256      /*
257       * FUNCTION: Get the console display mode
258       * ARGUMENTS:
259       *      lpdwMode - Address of variable that receives the current value
260       *                 of display mode
261       * STATUS: Undocumented
262       */
263 {
264   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
265   return 0;
266 }
267
268 DWORD STDCALL
269 GetConsoleFontInfo (DWORD       Unknown0,
270                     DWORD       Unknown1,
271                     DWORD       Unknown2,
272                     DWORD       Unknown3)
273      /*
274       * Undocumented
275       */
276 {
277   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
278   return 0;
279 }
280
281 DWORD STDCALL
282 GetConsoleFontSize(HANDLE hConsoleOutput,
283                    DWORD nFont)
284 {
285   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
286   return 0;
287 }
288
289 DWORD STDCALL
290 GetConsoleHardwareState (DWORD  Unknown0,
291                          DWORD  Unknown1,
292                          DWORD  Unknown2)
293      /*
294       * Undocumented
295       */
296 {
297   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
298   return 0;
299 }
300
301 DWORD STDCALL
302 GetConsoleInputWaitHandle (VOID)
303      /*
304       * Undocumented
305       */
306 {
307   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
308   return FALSE;
309 }
310
311 DWORD STDCALL
312 GetCurrentConsoleFont(HANDLE hConsoleOutput,
313                       BOOL bMaximumWindow,
314                       PCONSOLE_FONT_INFO lpConsoleCurrentFont)
315 {
316   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
317   return 0;
318 }
319
320 ULONG STDCALL
321 GetNumberOfConsoleFonts (VOID)
322      /*
323       * Undocumented
324       */
325 {
326   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
327   return 1; /* FIXME: call csrss.exe */
328 }
329
330 DWORD STDCALL
331 InvalidateConsoleDIBits (DWORD  Unknown0,
332                          DWORD  Unknown1)
333      /*
334       * Undocumented
335       */
336 {
337   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
338   return 0;
339 }
340
341 DWORD STDCALL
342 OpenConsoleW (DWORD     Unknown0,
343               DWORD     Unknown1,
344               DWORD     Unknown2,
345               DWORD     Unknown3)
346      /*
347       * Undocumented
348       */
349 {
350   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
351   return 0;
352 }
353
354 WINBOOL STDCALL
355 SetConsoleCommandHistoryMode (DWORD     dwMode)
356      /*
357       * Undocumented
358       */
359 {
360   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
361   return FALSE;
362 }
363
364 WINBOOL STDCALL
365 SetConsoleCursor (DWORD Unknown0,
366                   DWORD Unknown1)
367      /*
368       * Undocumented
369       */
370 {
371   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
372   return FALSE;
373 }
374
375 WINBOOL STDCALL
376 SetConsoleDisplayMode (HANDLE hOut,
377                        DWORD dwNewMode,
378                        LPDWORD lpdwOldMode)
379      /*
380       * FUNCTION: Set the console display mode.
381       * ARGUMENTS:
382       *       hOut - Standard output handle.
383       *       dwNewMode - New mode.
384       *       lpdwOldMode - Address of a variable that receives the old mode.
385       */
386 {
387   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
388   return FALSE;
389 }
390
391 WINBOOL STDCALL
392 SetConsoleFont (DWORD   Unknown0,
393                 DWORD   Unknown1)
394      /*
395       * Undocumented
396       */
397 {
398   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
399   return FALSE;
400 }
401
402 WINBOOL STDCALL
403 SetConsoleHardwareState (DWORD  Unknown0,
404                          DWORD  Unknown1,
405                          DWORD  Unknown2)
406      /*
407       * Undocumented
408       */
409 {
410   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
411   return FALSE;
412 }
413
414 WINBOOL STDCALL
415 SetConsoleKeyShortcuts (DWORD   Unknown0,
416                         DWORD   Unknown1,
417                         DWORD   Unknown2,
418                         DWORD   Unknown3)
419      /*
420       * Undocumented
421       */
422 {
423   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
424   return FALSE;
425 }
426
427 WINBOOL STDCALL
428 SetConsoleMaximumWindowSize (DWORD      Unknown0,
429                              DWORD      Unknown1)
430      /*
431       * Undocumented
432       */
433 {
434   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
435   return FALSE;
436 }
437
438 WINBOOL STDCALL
439 SetConsoleMenuClose (DWORD      Unknown0)
440      /*
441       * Undocumented
442       */
443 {
444   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
445   return FALSE;
446 }
447
448 WINBOOL STDCALL
449 SetConsoleNumberOfCommandsA (DWORD      Unknown0,
450                              DWORD      Unknown1)
451      /*
452       * Undocumented
453       */
454 {
455   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
456   return FALSE;
457 }
458
459 WINBOOL STDCALL
460 SetConsoleNumberOfCommandsW (DWORD      Unknown0,
461                              DWORD      Unknown1)
462      /*
463       * Undocumented
464       */
465 {
466   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
467   return FALSE;
468 }
469
470 WINBOOL STDCALL
471 SetConsolePalette (DWORD        Unknown0,
472                    DWORD        Unknown1,
473                    DWORD        Unknown2)
474      /*
475       * Undocumented
476       */
477 {
478   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
479   return FALSE;
480 }
481
482 WINBOOL STDCALL
483 SetLastConsoleEventActive (VOID)
484      /*
485       * Undocumented
486       */
487 {
488   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
489   return FALSE;
490 }
491
492 DWORD STDCALL
493 ShowConsoleCursor (DWORD        Unknown0,
494                    DWORD        Unknown1)
495      /*
496       * Undocumented
497       */
498 {
499   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
500   return 0;
501 }
502
503 DWORD STDCALL
504 VerifyConsoleIoHandle (DWORD    Unknown0)
505      /*
506       * Undocumented
507       */
508 {
509   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
510   return 0;
511 }
512
513 DWORD STDCALL
514 WriteConsoleInputVDMA (DWORD    Unknown0,
515                        DWORD    Unknown1,
516                        DWORD    Unknown2,
517                        DWORD    Unknown3)
518 {
519   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
520   return 0;
521 }
522
523 DWORD STDCALL
524 WriteConsoleInputVDMW (DWORD    Unknown0,
525                        DWORD    Unknown1,
526                        DWORD    Unknown2,
527                        DWORD    Unknown3)
528 {
529   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
530   return 0;
531 }
532
533 WINBOOL STDCALL 
534 CloseConsoleHandle(HANDLE Handle)
535      /*
536       * Undocumented
537       */
538 {
539   if (IsConsoleHandle (Handle) == FALSE)
540     {
541       SetLastError (ERROR_INVALID_PARAMETER);
542       return FALSE;
543     }
544   /* FIXME: call CSRSS */
545   return TRUE/*FALSE*/;
546 }
547
548 BOOLEAN STDCALL 
549 IsConsoleHandle(HANDLE Handle)
550 {
551   if ((((ULONG)Handle) & 0x10000003) == 0x3)
552     {
553       return(TRUE);
554     }
555   return(FALSE);
556 }
557
558 HANDLE STDCALL 
559 GetStdHandle(DWORD nStdHandle)
560      /*
561       * FUNCTION: Get a handle for the standard input, standard output
562       * and a standard error device.
563       * ARGUMENTS:
564       *       nStdHandle - Specifies the device for which to return the handle.
565       * RETURNS: If the function succeeds, the return value is the handle
566       * of the specified device. Otherwise the value is INVALID_HANDLE_VALUE.
567       */
568 {
569   PRTL_USER_PROCESS_PARAMETERS Ppb;
570   
571   Ppb = NtCurrentPeb()->ProcessParameters;  
572   switch (nStdHandle)
573     {
574     case STD_INPUT_HANDLE:      return Ppb->hStdInput;
575     case STD_OUTPUT_HANDLE:     return Ppb->hStdOutput;
576     case STD_ERROR_HANDLE:      return Ppb->hStdError;
577     }
578   SetLastError (ERROR_INVALID_PARAMETER);
579   return INVALID_HANDLE_VALUE;
580 }
581
582 WINBASEAPI BOOL WINAPI 
583 SetStdHandle(DWORD nStdHandle,
584              HANDLE hHandle)
585      /*
586       * FUNCTION: Set the handle for the standard input, standard output or
587       * the standard error device.
588       * ARGUMENTS:
589       *        nStdHandle - Specifies the handle to be set.
590       *        hHandle - The handle to set.
591       * RETURNS: TRUE if the function succeeds, FALSE otherwise.
592       */
593 {
594   PRTL_USER_PROCESS_PARAMETERS Ppb;
595    
596   Ppb = NtCurrentPeb()->ProcessParameters;
597   
598   /* More checking needed? */
599   if (hHandle == INVALID_HANDLE_VALUE)
600     {
601       SetLastError (ERROR_INVALID_HANDLE);
602       return FALSE;
603     }
604    
605   SetLastError(ERROR_SUCCESS); /* OK */
606   switch (nStdHandle)
607     {
608     case STD_INPUT_HANDLE:
609       Ppb->hStdInput = hHandle;
610       return TRUE;
611     case STD_OUTPUT_HANDLE:
612       Ppb->hStdOutput = hHandle;
613       return TRUE;
614     case STD_ERROR_HANDLE:
615       Ppb->hStdError = hHandle;
616       return TRUE;
617     }
618   SetLastError (ERROR_INVALID_PARAMETER);
619   return FALSE;
620 }
621
622
623 /*--------------------------------------------------------------
624  *      WriteConsoleA
625  */
626 WINBOOL STDCALL 
627 WriteConsoleA(HANDLE hConsoleOutput,
628               CONST VOID *lpBuffer,
629               DWORD nNumberOfCharsToWrite,
630               LPDWORD lpNumberOfCharsWritten,
631               LPVOID lpReserved)
632 {
633   PCSRSS_API_REQUEST Request;
634   CSRSS_API_REPLY Reply;
635   NTSTATUS Status;
636   USHORT Size;
637   ULONG MessageSize;
638   
639   Request = RtlAllocateHeap(GetProcessHeap(),
640                             HEAP_ZERO_MEMORY,
641                             sizeof(CSRSS_API_REQUEST) + 
642                             CSRSS_MAX_WRITE_CONSOLE_REQUEST);
643   if (Request == NULL)
644     {
645       SetLastError(ERROR_OUTOFMEMORY);
646       return(FALSE);
647     }
648   
649   Request->Type = CSRSS_WRITE_CONSOLE;
650   Request->Data.WriteConsoleRequest.ConsoleHandle = hConsoleOutput;
651   if (lpNumberOfCharsWritten != NULL)
652     *lpNumberOfCharsWritten = nNumberOfCharsToWrite;
653   while (nNumberOfCharsToWrite)
654     {
655       if (nNumberOfCharsToWrite > CSRSS_MAX_WRITE_CONSOLE_REQUEST)
656         {
657           Size = CSRSS_MAX_WRITE_CONSOLE_REQUEST;
658         }
659       else
660         {
661           Size = nNumberOfCharsToWrite;
662         }
663       Request->Data.WriteConsoleRequest.NrCharactersToWrite = Size;
664       
665       memcpy(Request->Data.WriteConsoleRequest.Buffer, lpBuffer, Size);
666
667       MessageSize = CSRSS_REQUEST_HEADER_SIZE + 
668         sizeof(CSRSS_WRITE_CONSOLE_REQUEST) + Size;
669       Status = CsrClientCallServer(Request,
670                                    &Reply,
671                                    MessageSize,
672                                    sizeof(CSRSS_API_REPLY));
673       
674       if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
675         {
676           RtlFreeHeap(GetProcessHeap(), 0, Request);
677           SetLastErrorByStatus(Status);
678           return(FALSE);
679         }
680       nNumberOfCharsToWrite -= Size;
681       lpBuffer += Size;
682     }
683   RtlFreeHeap(GetProcessHeap(), 0, Request);
684   return TRUE;
685 }
686
687
688 /*--------------------------------------------------------------
689  *      ReadConsoleA
690  */
691 WINBOOL STDCALL ReadConsoleA(HANDLE hConsoleInput,
692                              LPVOID lpBuffer,
693                              DWORD nNumberOfCharsToRead,
694                              LPDWORD lpNumberOfCharsRead,
695                              LPVOID lpReserved)
696 {
697    CSRSS_API_REQUEST Request;
698    PCSRSS_API_REPLY Reply;
699    NTSTATUS Status;
700    ULONG CharsRead = 0;
701    
702    Reply = RtlAllocateHeap(GetProcessHeap(),
703                      HEAP_ZERO_MEMORY,
704                      sizeof(CSRSS_API_REPLY) + nNumberOfCharsToRead);
705    if (Reply == NULL)
706      {
707         SetLastError(ERROR_OUTOFMEMORY);
708         return(FALSE);
709      }
710    
711    Request.Type = CSRSS_READ_CONSOLE;
712    Request.Data.ReadConsoleRequest.ConsoleHandle = hConsoleInput;
713    Request.Data.ReadConsoleRequest.NrCharactersToRead = nNumberOfCharsToRead > CSRSS_MAX_READ_CONSOLE_REQUEST ? CSRSS_MAX_READ_CONSOLE_REQUEST : nNumberOfCharsToRead;
714    Request.Data.ReadConsoleRequest.nCharsCanBeDeleted = 0;
715    Status = CsrClientCallServer(&Request, 
716                                 Reply,
717                                 sizeof(CSRSS_API_REQUEST),
718                                 sizeof(CSRSS_API_REPLY) + 
719                                 Request.Data.ReadConsoleRequest.NrCharactersToRead);
720    if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply->Status ))
721      {
722         DbgPrint( "CSR returned error in ReadConsole\n" );
723         SetLastErrorByStatus ( Status );
724         RtlFreeHeap( GetProcessHeap(), 0, Reply );
725         return(FALSE);
726      }
727    if( Reply->Status == STATUS_NOTIFY_CLEANUP )
728       Reply->Status = STATUS_PENDING;     // ignore backspace because we have no chars to backspace
729    /* There may not be any chars or lines to read yet, so wait */
730    while( Reply->Status == STATUS_PENDING )
731      {
732        /* some chars may have been returned, but not a whole line yet, so recompute buffer and try again */
733        nNumberOfCharsToRead -= Reply->Data.ReadConsoleReply.NrCharactersRead;
734        /* don't overflow caller's buffer, even if you still don't have a complete line */
735        if( !nNumberOfCharsToRead )
736          break;
737        Request.Data.ReadConsoleRequest.NrCharactersToRead = nNumberOfCharsToRead > CSRSS_MAX_READ_CONSOLE_REQUEST ? CSRSS_MAX_READ_CONSOLE_REQUEST : nNumberOfCharsToRead;
738        /* copy any chars already read to buffer */
739        memcpy( lpBuffer + CharsRead, Reply->Data.ReadConsoleReply.Buffer, Reply->Data.ReadConsoleReply.NrCharactersRead );
740        CharsRead += Reply->Data.ReadConsoleReply.NrCharactersRead;
741        /* wait for csrss to signal there is more data to read, but not if we got STATUS_NOTIFY_CLEANUP for backspace */
742        Status = NtWaitForSingleObject( Reply->Data.ReadConsoleReply.EventHandle, FALSE, 0 );
743        if( !NT_SUCCESS( Status ) )
744           {
745              DbgPrint( "Wait for console input failed!\n" );
746              RtlFreeHeap( GetProcessHeap(), 0, Reply );
747              return FALSE;
748           }
749        Request.Data.ReadConsoleRequest.nCharsCanBeDeleted = CharsRead;
750        Status = CsrClientCallServer( &Request, Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) + Request.Data.ReadConsoleRequest.NrCharactersToRead );
751        if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply->Status ) )
752          {
753            SetLastErrorByStatus ( Status );
754            RtlFreeHeap( GetProcessHeap(), 0, Reply );
755            return FALSE;
756          }
757        if( Reply->Status == STATUS_NOTIFY_CLEANUP )
758           {
759              // delete last char
760              if( CharsRead )
761                 {
762                    CharsRead--;
763                    nNumberOfCharsToRead++;
764                 }
765              Reply->Status = STATUS_PENDING;  // retry
766           }
767      }
768    /* copy data to buffer, count total returned, and return */
769    memcpy( lpBuffer + CharsRead, Reply->Data.ReadConsoleReply.Buffer, Reply->Data.ReadConsoleReply.NrCharactersRead );
770    CharsRead += Reply->Data.ReadConsoleReply.NrCharactersRead;
771    if (lpNumberOfCharsRead != NULL)
772      *lpNumberOfCharsRead = CharsRead;
773    RtlFreeHeap(GetProcessHeap(),
774             0,
775             Reply);
776    
777    return(TRUE);
778 }
779
780
781 /*--------------------------------------------------------------
782  *      AllocConsole
783  */
784 WINBOOL STDCALL AllocConsole(VOID)
785 {
786    CSRSS_API_REQUEST Request;
787    CSRSS_API_REPLY Reply;
788    NTSTATUS Status;
789
790    Request.Type = CSRSS_ALLOC_CONSOLE;
791    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
792    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
793       {
794          SetLastErrorByStatus ( Status );
795          return FALSE;
796       }
797    SetStdHandle( STD_INPUT_HANDLE, Reply.Data.AllocConsoleReply.InputHandle );
798    SetStdHandle( STD_OUTPUT_HANDLE, Reply.Data.AllocConsoleReply.OutputHandle );
799    SetStdHandle( STD_ERROR_HANDLE, Reply.Data.AllocConsoleReply.OutputHandle );
800    return TRUE;
801 }
802
803
804 /*--------------------------------------------------------------
805  *      FreeConsole
806  */
807 WINBOOL STDCALL FreeConsole(VOID)
808 {
809    DbgPrint("FreeConsole() is unimplemented\n");
810    return FALSE;
811 }
812
813
814 /*--------------------------------------------------------------
815  *      GetConsoleScreenBufferInfo
816  */
817 WINBOOL
818 STDCALL
819 GetConsoleScreenBufferInfo(
820     HANDLE hConsoleOutput,
821     PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo
822     )
823 {
824    CSRSS_API_REQUEST Request;
825    CSRSS_API_REPLY Reply;
826    NTSTATUS Status;
827
828    Request.Type = CSRSS_SCREEN_BUFFER_INFO;
829    Request.Data.ScreenBufferInfoRequest.ConsoleHandle = hConsoleOutput;
830    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
831    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
832       {
833          SetLastErrorByStatus ( Status );
834          return FALSE;
835       }
836    *lpConsoleScreenBufferInfo = Reply.Data.ScreenBufferInfoReply.Info;
837    return TRUE;
838 }
839
840
841 /*--------------------------------------------------------------
842  *      SetConsoleCursorPosition
843  */
844 WINBOOL
845 STDCALL
846 SetConsoleCursorPosition(
847     HANDLE hConsoleOutput,
848     COORD dwCursorPosition
849     )
850 {
851    CSRSS_API_REQUEST Request;
852    CSRSS_API_REPLY Reply;
853    NTSTATUS Status;
854
855    Request.Type = CSRSS_SET_CURSOR;
856    Request.Data.SetCursorRequest.ConsoleHandle = hConsoleOutput;
857    Request.Data.SetCursorRequest.Position = dwCursorPosition;
858    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
859    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
860       {
861          SetLastErrorByStatus ( Status );
862          return FALSE;
863       }
864    return TRUE;
865 }
866
867
868 /*--------------------------------------------------------------
869  *      FillConsoleOutputCharacterA
870  */
871 WINBOOL STDCALL
872 FillConsoleOutputCharacterA(
873         HANDLE          hConsoleOutput,
874         CHAR            cCharacter,
875         DWORD           nLength,
876         COORD           dwWriteCoord,
877         LPDWORD         lpNumberOfCharsWritten
878         )
879 {
880   CSRSS_API_REQUEST Request;
881   CSRSS_API_REPLY Reply;
882   NTSTATUS Status;
883
884   Request.Type = CSRSS_FILL_OUTPUT;
885   Request.Data.FillOutputRequest.ConsoleHandle = hConsoleOutput;
886   Request.Data.FillOutputRequest.Char = cCharacter;
887   Request.Data.FillOutputRequest.Position = dwWriteCoord;
888   Request.Data.FillOutputRequest.Length = nLength;
889   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
890   if ( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
891     {
892       SetLastErrorByStatus(Status);
893       return(FALSE);
894     }
895   if (lpNumberOfCharsWritten != NULL)
896      *lpNumberOfCharsWritten = nLength;
897   return(TRUE);
898 }
899
900
901 /*--------------------------------------------------------------
902  *      FillConsoleOutputCharacterW
903  */
904 WINBOOL
905 STDCALL
906 FillConsoleOutputCharacterW(
907         HANDLE          hConsoleOutput,
908         WCHAR           cCharacter,
909         DWORD           nLength,
910         COORD           dwWriteCoord,
911         LPDWORD         lpNumberOfCharsWritten
912         )
913 {
914 /* TO DO */
915         return FALSE;
916 }
917
918
919 /*--------------------------------------------------------------
920  *      PeekConsoleInputA
921  */
922 WINBASEAPI
923 BOOL
924 WINAPI
925 PeekConsoleInputA(
926         HANDLE                  hConsoleInput,
927         PINPUT_RECORD           lpBuffer,
928         DWORD                   nLength,
929         LPDWORD                 lpNumberOfEventsRead
930         )
931 {
932   PCSRSS_API_REQUEST Request;
933   CSRSS_API_REPLY Reply;
934   NTSTATUS Status;
935   PVOID BufferBase;
936   PVOID BufferTargetBase;
937   DWORD Size;
938   
939   if(lpBuffer == NULL)
940   {
941     SetLastError(ERROR_INVALID_PARAMETER);
942     return FALSE;
943   }
944   
945   Size = nLength * sizeof(INPUT_RECORD);
946
947   Status = CsrCaptureParameterBuffer((PVOID)lpBuffer, Size, &BufferBase, &BufferTargetBase);
948   if(!NT_SUCCESS(Status))
949   {
950     SetLastErrorByStatus(Status);
951     return FALSE;
952   }
953   
954   Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSRSS_API_REQUEST));
955   if(Request == NULL)
956   {
957     CsrReleaseParameterBuffer(BufferBase);
958     SetLastError(ERROR_OUTOFMEMORY);
959     return FALSE;
960   }
961   
962   Request->Type = CSRSS_PEEK_CONSOLE_INPUT;
963   Request->Data.PeekConsoleInputRequest.ConsoleHandle = hConsoleInput;
964   Request->Data.PeekConsoleInputRequest.Length = nLength;
965   Request->Data.PeekConsoleInputRequest.InputRecord = (INPUT_RECORD*)BufferTargetBase;
966   
967   Status = CsrClientCallServer(Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY));
968   
969   if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
970   {
971     RtlFreeHeap(GetProcessHeap(), 0, Request);
972     CsrReleaseParameterBuffer(BufferBase);
973     return FALSE;
974   }
975
976   memcpy(lpBuffer, BufferBase, sizeof(INPUT_RECORD) * Reply.Data.PeekConsoleInputReply.Length);
977
978   if(lpNumberOfEventsRead != NULL)
979     *lpNumberOfEventsRead = Reply.Data.PeekConsoleInputReply.Length;
980
981   RtlFreeHeap(GetProcessHeap(), 0, Request);
982   CsrReleaseParameterBuffer(BufferBase);  
983   
984         return TRUE;
985 }
986
987
988 /*--------------------------------------------------------------
989  *      PeekConsoleInputW
990  */
991 WINBASEAPI
992 BOOL
993 WINAPI
994 PeekConsoleInputW(
995         HANDLE                  hConsoleInput,
996         PINPUT_RECORD           lpBuffer,
997         DWORD                   nLength,
998         LPDWORD                 lpNumberOfEventsRead
999         )    
1000 {
1001 /* TO DO */
1002         return FALSE;
1003 }
1004
1005
1006 /*--------------------------------------------------------------
1007  *      ReadConsoleInputA
1008  */
1009 WINBASEAPI BOOL WINAPI
1010 ReadConsoleInputA(HANDLE hConsoleInput,
1011                   PINPUT_RECORD lpBuffer,
1012                   DWORD nLength,
1013                   LPDWORD lpNumberOfEventsRead)
1014 {
1015   CSRSS_API_REQUEST Request;
1016   CSRSS_API_REPLY Reply;
1017   DWORD NumEventsRead;
1018   NTSTATUS Status;
1019
1020   Request.Type = CSRSS_READ_INPUT;
1021   Request.Data.ReadInputRequest.ConsoleHandle = hConsoleInput;
1022   Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST),
1023                                 sizeof(CSRSS_API_REPLY));
1024   if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
1025     {
1026       SetLastErrorByStatus(Status);
1027       return(FALSE);
1028     }
1029   
1030   while (Status == STATUS_PENDING)
1031     {
1032       Status = NtWaitForSingleObject(Reply.Data.ReadInputReply.Event, FALSE, 
1033                                      0);
1034       if(!NT_SUCCESS(Status))
1035         {
1036           SetLastErrorByStatus(Status);
1037           return FALSE;
1038         }
1039       
1040       Request.Type = CSRSS_READ_INPUT;
1041       Request.Data.ReadInputRequest.ConsoleHandle = hConsoleInput;
1042       Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST),
1043                                    sizeof(CSRSS_API_REPLY));
1044       if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
1045         {
1046           SetLastErrorByStatus(Status);
1047           return(FALSE);
1048         }
1049     }
1050   
1051   NumEventsRead = 0;
1052   *lpBuffer = Reply.Data.ReadInputReply.Input;
1053   lpBuffer++;
1054   NumEventsRead++;
1055   
1056   while ((NumEventsRead < nLength) && (Reply.Data.ReadInputReply.MoreEvents))
1057     {
1058       Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST),
1059                                    sizeof(CSRSS_API_REPLY));
1060       if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
1061         {
1062           SetLastErrorByStatus(Status);
1063           return(FALSE);
1064         }
1065       
1066       if (Status == STATUS_PENDING)
1067         {
1068           break;
1069         }
1070       
1071       *lpBuffer = Reply.Data.ReadInputReply.Input;
1072       lpBuffer++;
1073       NumEventsRead++;
1074       
1075     }
1076   *lpNumberOfEventsRead = NumEventsRead;
1077   
1078   return TRUE;
1079 }
1080
1081
1082 /*--------------------------------------------------------------
1083  *      ReadConsoleInputW
1084  */
1085 WINBASEAPI
1086 BOOL
1087 WINAPI
1088 ReadConsoleInputW(
1089         HANDLE                  hConsoleInput,
1090         PINPUT_RECORD           lpBuffer,
1091         DWORD                   nLength,
1092         LPDWORD                 lpNumberOfEventsRead
1093         )
1094 {
1095 /* TO DO */
1096         return FALSE;
1097 }
1098
1099
1100 /*--------------------------------------------------------------
1101  *      WriteConsoleInputA
1102  */
1103 WINBASEAPI
1104 BOOL
1105 WINAPI
1106 WriteConsoleInputA(
1107         HANDLE                   hConsoleInput,
1108         CONST INPUT_RECORD      *lpBuffer,
1109         DWORD                    nLength,
1110         LPDWORD                  lpNumberOfEventsWritten
1111         )
1112 {
1113   PCSRSS_API_REQUEST Request;
1114   CSRSS_API_REPLY Reply;
1115   PVOID BufferBase, BufferTargetBase;
1116   NTSTATUS Status;
1117   DWORD Size;
1118   
1119   if(lpBuffer == NULL)
1120   {
1121     SetLastError(ERROR_INVALID_PARAMETER);
1122     return FALSE;
1123   }
1124   
1125   Size = nLength * sizeof(INPUT_RECORD);
1126
1127   Status = CsrCaptureParameterBuffer((PVOID)lpBuffer, Size, &BufferBase, &BufferTargetBase);
1128   if(!NT_SUCCESS(Status))
1129   {
1130     SetLastErrorByStatus(Status);
1131     return FALSE;
1132   }
1133   
1134   Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSRSS_API_REQUEST));
1135   if(Request == NULL)
1136   {
1137     SetLastError(ERROR_OUTOFMEMORY);
1138     CsrReleaseParameterBuffer(BufferBase);
1139     return FALSE;
1140   }
1141
1142   Request->Type = CSRSS_WRITE_CONSOLE_INPUT;
1143   Request->Data.WriteConsoleInputRequest.ConsoleHandle = hConsoleInput;
1144   Request->Data.WriteConsoleInputRequest.Length = nLength;
1145   Request->Data.WriteConsoleInputRequest.InputRecord = (PINPUT_RECORD)BufferTargetBase;
1146   
1147   Status = CsrClientCallServer(Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY));
1148   if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
1149   {
1150     RtlFreeHeap(GetProcessHeap(), 0, Request);
1151     CsrReleaseParameterBuffer(BufferBase);
1152     return FALSE;
1153   }
1154   
1155   if(lpNumberOfEventsWritten != NULL)
1156     *lpNumberOfEventsWritten = Reply.Data.WriteConsoleInputReply.Length;
1157   
1158   RtlFreeHeap(GetProcessHeap(), 0, Request);
1159   CsrReleaseParameterBuffer(BufferBase);
1160   
1161   return TRUE;
1162 }
1163
1164
1165 /*--------------------------------------------------------------
1166  *      WriteConsoleInputW
1167  */
1168 WINBASEAPI
1169 BOOL
1170 WINAPI
1171 WriteConsoleInputW(
1172         HANDLE                   hConsoleInput,
1173         CONST INPUT_RECORD      *lpBuffer,
1174         DWORD                    nLength,
1175         LPDWORD                  lpNumberOfEventsWritten
1176         )
1177 {
1178 /* TO DO */
1179         return FALSE;
1180 }
1181
1182
1183 /*--------------------------------------------------------------
1184  *      ReadConsoleOutputA
1185  */
1186 WINBASEAPI
1187 BOOL
1188 WINAPI
1189 ReadConsoleOutputA(
1190         HANDLE          hConsoleOutput,
1191         PCHAR_INFO      lpBuffer,
1192         COORD           dwBufferSize,
1193         COORD           dwBufferCoord,
1194         PSMALL_RECT     lpReadRegion
1195         )
1196 {
1197   PCSRSS_API_REQUEST Request;
1198   CSRSS_API_REPLY Reply;
1199   PVOID BufferBase;
1200   PVOID BufferTargetBase;
1201   NTSTATUS Status;
1202   DWORD Size, SizeX, SizeY;
1203   
1204   if(lpBuffer == NULL)
1205   {
1206     SetLastError(ERROR_INVALID_PARAMETER);
1207     return FALSE;
1208   }
1209   
1210   Size = dwBufferSize.X * dwBufferSize.Y * sizeof(CHAR_INFO);
1211
1212   Status = CsrCaptureParameterBuffer((PVOID)lpBuffer, Size, &BufferBase, &BufferTargetBase);
1213   if(!NT_SUCCESS(Status))
1214   {
1215     SetLastErrorByStatus(Status);
1216     return FALSE;
1217   }
1218   
1219   Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSRSS_API_REQUEST));
1220   if(Request == NULL)
1221   {
1222     SetLastError(ERROR_OUTOFMEMORY);
1223     CsrReleaseParameterBuffer(BufferBase);
1224     return FALSE;
1225   }
1226    
1227   Request->Type = CSRSS_READ_CONSOLE_OUTPUT;
1228   Request->Data.ReadConsoleOutputRequest.ConsoleHandle = hConsoleOutput;
1229   Request->Data.ReadConsoleOutputRequest.BufferSize = dwBufferSize;
1230   Request->Data.ReadConsoleOutputRequest.BufferCoord = dwBufferCoord;
1231   Request->Data.ReadConsoleOutputRequest.ReadRegion = *lpReadRegion;
1232   Request->Data.ReadConsoleOutputRequest.CharInfo = (PCHAR_INFO)BufferTargetBase;
1233   
1234   Status = CsrClientCallServer(Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY));
1235   if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
1236   {
1237     SetLastErrorByStatus(Status);
1238     RtlFreeHeap(GetProcessHeap(), 0, Request);
1239     CsrReleaseParameterBuffer(BufferBase);
1240     return FALSE;
1241   }
1242   
1243   SizeX = Reply.Data.ReadConsoleOutputReply.ReadRegion.Right - Reply.Data.ReadConsoleOutputReply.ReadRegion.Left + 1;
1244   SizeY = Reply.Data.ReadConsoleOutputReply.ReadRegion.Bottom - Reply.Data.ReadConsoleOutputReply.ReadRegion.Top + 1;
1245   
1246   memcpy(lpBuffer, BufferBase, sizeof(CHAR_INFO) * SizeX * SizeY);
1247   *lpReadRegion = Reply.Data.ReadConsoleOutputReply.ReadRegion;
1248   
1249   RtlFreeHeap(GetProcessHeap(), 0, Request);
1250   CsrReleaseParameterBuffer(BufferBase);
1251   
1252   return TRUE;
1253 }
1254
1255
1256 /*--------------------------------------------------------------
1257  *      ReadConsoleOutputW
1258  */
1259 WINBASEAPI
1260 BOOL
1261 WINAPI
1262 ReadConsoleOutputW(
1263         HANDLE          hConsoleOutput,
1264         PCHAR_INFO      lpBuffer,
1265         COORD           dwBufferSize,
1266         COORD           dwBufferCoord,
1267         PSMALL_RECT     lpReadRegion
1268         )
1269 {
1270 /* TO DO */
1271         return FALSE;
1272 }
1273
1274 /*--------------------------------------------------------------
1275  *      WriteConsoleOutputA
1276  */
1277 WINBASEAPI BOOL WINAPI
1278 WriteConsoleOutputA(HANDLE               hConsoleOutput,
1279                     CONST CHAR_INFO     *lpBuffer,
1280                     COORD                dwBufferSize,
1281                     COORD                dwBufferCoord,
1282                     PSMALL_RECT  lpWriteRegion)
1283 {
1284   PCSRSS_API_REQUEST Request;
1285   CSRSS_API_REPLY Reply;
1286   NTSTATUS Status;
1287   ULONG Size;
1288   BOOLEAN Result;
1289   ULONG i, j;
1290   PVOID BufferBase;
1291   PVOID BufferTargetBase;
1292
1293   Size = dwBufferSize.Y * dwBufferSize.X * sizeof(CHAR_INFO);
1294
1295   Status = CsrCaptureParameterBuffer((PVOID)lpBuffer,
1296                                      Size,
1297                                      &BufferBase,
1298                                      &BufferTargetBase);
1299   if (!NT_SUCCESS(Status))
1300     {
1301       SetLastErrorByStatus(Status);
1302       return(FALSE);
1303     }
1304   
1305   Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, 
1306                             sizeof(CSRSS_API_REQUEST));
1307   if (Request == NULL)
1308     {
1309       CsrReleaseParameterBuffer(BufferBase);
1310       SetLastError(ERROR_OUTOFMEMORY);
1311       return FALSE;
1312     }
1313   Request->Type = CSRSS_WRITE_CONSOLE_OUTPUT;
1314   Request->Data.WriteConsoleOutputRequest.ConsoleHandle = hConsoleOutput;
1315   Request->Data.WriteConsoleOutputRequest.BufferSize = dwBufferSize;
1316   Request->Data.WriteConsoleOutputRequest.BufferCoord = dwBufferCoord;
1317   Request->Data.WriteConsoleOutputRequest.WriteRegion = *lpWriteRegion;
1318   Request->Data.WriteConsoleOutputRequest.CharInfo = 
1319     (CHAR_INFO*)BufferTargetBase;
1320   
1321   Status = CsrClientCallServer(Request, &Reply, 
1322                                sizeof(CSRSS_API_REQUEST), 
1323                                sizeof(CSRSS_API_REPLY));
1324   if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
1325     {
1326       CsrReleaseParameterBuffer(BufferBase);
1327       RtlFreeHeap(GetProcessHeap(), 0, Request);
1328       SetLastErrorByStatus(Status);
1329       return FALSE;
1330     }
1331       
1332   *lpWriteRegion = Reply.Data.WriteConsoleOutputReply.WriteRegion;
1333   RtlFreeHeap(GetProcessHeap(), 0, Request);
1334   CsrReleaseParameterBuffer(BufferBase);
1335   return(TRUE);
1336 }
1337
1338
1339 /*--------------------------------------------------------------
1340  *      WriteConsoleOutputW
1341  */
1342 WINBASEAPI
1343 BOOL
1344 WINAPI
1345 WriteConsoleOutputW(
1346         HANDLE           hConsoleOutput,
1347         CONST CHAR_INFO *lpBuffer,
1348         COORD            dwBufferSize,
1349         COORD            dwBufferCoord,
1350         PSMALL_RECT      lpWriteRegion
1351         )
1352 {
1353 /* TO DO */
1354         return FALSE;
1355 }
1356
1357
1358 /*--------------------------------------------------------------
1359  *      ReadConsoleOutputCharacterA
1360  */
1361 WINBASEAPI
1362 BOOL
1363 WINAPI
1364 ReadConsoleOutputCharacterA(
1365         HANDLE          hConsoleOutput,
1366         LPSTR           lpCharacter,
1367         DWORD           nLength,
1368         COORD           dwReadCoord,
1369         LPDWORD         lpNumberOfCharsRead
1370         )
1371 {
1372   CSRSS_API_REQUEST Request;
1373   PCSRSS_API_REPLY Reply;
1374   NTSTATUS Status;
1375   DWORD Size;
1376
1377   Reply = RtlAllocateHeap(GetProcessHeap(),
1378                           HEAP_ZERO_MEMORY,
1379                           sizeof(CSRSS_API_REPLY) + CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR);
1380   if (Reply == NULL)
1381     {
1382       SetLastError(ERROR_OUTOFMEMORY);
1383       return(FALSE);
1384     }
1385
1386   if (lpNumberOfCharsRead != NULL)
1387     *lpNumberOfCharsRead = nLength;
1388
1389   Request.Type = CSRSS_READ_CONSOLE_OUTPUT_CHAR;
1390   Request.Data.ReadConsoleOutputCharRequest.ConsoleHandle = hConsoleOutput;
1391   Request.Data.ReadConsoleOutputCharRequest.ReadCoord = dwReadCoord;
1392
1393   while (nLength != 0)
1394     {
1395       if (nLength > CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR)
1396         Size = CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR;
1397       else
1398         Size = nLength;
1399
1400       Request.Data.ReadConsoleOutputCharRequest.NumCharsToRead = Size;
1401
1402       Status = CsrClientCallServer(&Request,
1403                                    Reply,
1404                                    sizeof(CSRSS_API_REQUEST),
1405                                    sizeof(CSRSS_API_REPLY) + Size);
1406       if (!NT_SUCCESS(Status) || !NT_SUCCESS(Reply->Status))
1407         {
1408           RtlFreeHeap(GetProcessHeap(), 0, Reply);
1409           SetLastErrorByStatus(Status);
1410           return(FALSE);
1411         }
1412
1413       memcpy(lpCharacter, &Reply->Data.ReadConsoleOutputCharReply.String[0], Size);
1414       lpCharacter += Size;
1415       nLength -= Size;
1416       Request.Data.ReadConsoleOutputCharRequest.ReadCoord = Reply->Data.ReadConsoleOutputCharReply.EndCoord;
1417     }
1418
1419   RtlFreeHeap(GetProcessHeap(), 0, Reply);
1420
1421   return(TRUE);
1422 }
1423
1424
1425 /*--------------------------------------------------------------
1426  *      ReadConsoleOutputCharacterW
1427  */
1428 WINBASEAPI
1429 BOOL
1430 WINAPI
1431 ReadConsoleOutputCharacterW(
1432         HANDLE          hConsoleOutput,
1433         LPWSTR          lpCharacter,
1434         DWORD           nLength,
1435         COORD           dwReadCoord,
1436         LPDWORD         lpNumberOfCharsRead
1437         )
1438 {
1439 /* TO DO */
1440         return FALSE;
1441 }
1442
1443
1444 /*--------------------------------------------------------------
1445  *      ReadConsoleOutputAttribute
1446  */
1447 WINBASEAPI
1448 BOOL
1449 WINAPI
1450 ReadConsoleOutputAttribute(
1451         HANDLE          hConsoleOutput,
1452         LPWORD          lpAttribute,
1453         DWORD           nLength,
1454         COORD           dwReadCoord,
1455         LPDWORD         lpNumberOfAttrsRead
1456         )
1457 {
1458   CSRSS_API_REQUEST Request;
1459   PCSRSS_API_REPLY Reply;
1460   NTSTATUS Status;
1461   DWORD Size, i;
1462   
1463   Reply = RtlAllocateHeap(GetProcessHeap(),
1464                           HEAP_ZERO_MEMORY,
1465                           sizeof(CSRSS_API_REPLY) + CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB);
1466   if (Reply == NULL)
1467     {
1468       SetLastError(ERROR_OUTOFMEMORY);
1469       return(FALSE);
1470     }
1471
1472   if (lpNumberOfAttrsRead != NULL)
1473     *lpNumberOfAttrsRead = nLength;
1474
1475   Request.Type = CSRSS_READ_CONSOLE_OUTPUT_ATTRIB;
1476   Request.Data.ReadConsoleOutputAttribRequest.ConsoleHandle = hConsoleOutput;
1477   Request.Data.ReadConsoleOutputAttribRequest.ReadCoord = dwReadCoord;
1478
1479   while (nLength != 0)
1480     {
1481       if (nLength > CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB)
1482         Size = CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB;
1483       else
1484         Size = nLength;
1485
1486       Request.Data.ReadConsoleOutputAttribRequest.NumAttrsToRead = Size;
1487
1488       Status = CsrClientCallServer(&Request,
1489                                    Reply,
1490                                    sizeof(CSRSS_API_REQUEST),
1491                                    sizeof(CSRSS_API_REPLY) + Size);
1492       if (!NT_SUCCESS(Status) || !NT_SUCCESS(Reply->Status))
1493         {
1494           RtlFreeHeap(GetProcessHeap(), 0, Reply);
1495           SetLastErrorByStatus(Status);
1496           return(FALSE);
1497         }
1498
1499       // Convert CHARs to WORDs
1500       for(i = 0; i < Size; ++i)
1501         *lpAttribute++ = Reply->Data.ReadConsoleOutputAttribReply.String[i];
1502       
1503       nLength -= Size;
1504       Request.Data.ReadConsoleOutputAttribRequest.ReadCoord = Reply->Data.ReadConsoleOutputAttribReply.EndCoord;
1505     }
1506
1507   RtlFreeHeap(GetProcessHeap(), 0, Reply);
1508
1509   return(TRUE);
1510 }
1511
1512
1513 /*--------------------------------------------------------------
1514  *      WriteConsoleOutputCharacterA
1515  */
1516 WINBASEAPI BOOL WINAPI
1517 WriteConsoleOutputCharacterA(HANDLE             hConsoleOutput,
1518                              LPCSTR             lpCharacter,
1519                              DWORD              nLength,
1520                              COORD              dwWriteCoord,
1521                              LPDWORD            lpNumberOfCharsWritten)
1522 {
1523   PCSRSS_API_REQUEST Request;
1524   CSRSS_API_REPLY Reply;
1525   NTSTATUS Status;
1526   WORD Size;
1527   
1528   Request = RtlAllocateHeap(GetProcessHeap(),
1529                             HEAP_ZERO_MEMORY,
1530                             sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR);
1531   if( !Request )
1532     {
1533       SetLastError( ERROR_OUTOFMEMORY );
1534       return FALSE;
1535     }
1536   Request->Type = CSRSS_WRITE_CONSOLE_OUTPUT_CHAR;
1537   Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle = hConsoleOutput;
1538   Request->Data.WriteConsoleOutputCharRequest.Coord = dwWriteCoord;
1539   if( lpNumberOfCharsWritten )
1540     *lpNumberOfCharsWritten = nLength;
1541   while( nLength )
1542     {
1543       Size = nLength > CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR ? CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR : nLength;
1544       Request->Data.WriteConsoleOutputCharRequest.Length = Size;
1545       memcpy( &Request->Data.WriteConsoleOutputCharRequest.String[0],
1546               lpCharacter,
1547               Size );
1548       Status = CsrClientCallServer( Request, &Reply, sizeof( CSRSS_API_REQUEST ) + Size, sizeof( CSRSS_API_REPLY ) );
1549       if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
1550         {
1551           RtlFreeHeap( GetProcessHeap(), 0, Request );
1552           SetLastErrorByStatus ( Status );
1553           return FALSE;
1554         }
1555       nLength -= Size;
1556       lpCharacter += Size;
1557       Request->Data.WriteConsoleOutputCharRequest.Coord = Reply.Data.WriteConsoleOutputCharReply.EndCoord;
1558     }
1559   
1560   RtlFreeHeap( GetProcessHeap(), 0, Request );  
1561   return TRUE;
1562 }
1563
1564
1565 /*--------------------------------------------------------------
1566  *      WriteConsoleOutputCharacterW
1567  */
1568 WINBASEAPI
1569 BOOL
1570 WINAPI
1571 WriteConsoleOutputCharacterW(
1572         HANDLE          hConsoleOutput,
1573         LPCWSTR         lpCharacter,
1574         DWORD           nLength,
1575         COORD           dwWriteCoord,
1576         LPDWORD         lpNumberOfCharsWritten
1577         )
1578 {
1579 /* TO DO */
1580         return FALSE;
1581 }
1582
1583
1584
1585 /*--------------------------------------------------------------
1586  *      WriteConsoleOutputAttribute
1587  */
1588 WINBASEAPI
1589 BOOL
1590 WINAPI
1591 WriteConsoleOutputAttribute(
1592         HANDLE           hConsoleOutput,
1593         CONST WORD      *lpAttribute,
1594         DWORD            nLength,
1595         COORD            dwWriteCoord,
1596         LPDWORD          lpNumberOfAttrsWritten
1597         )
1598 {
1599    PCSRSS_API_REQUEST Request;
1600    CSRSS_API_REPLY Reply;
1601    NTSTATUS Status;
1602    WORD Size;
1603    int c;
1604
1605    Request = RtlAllocateHeap(GetProcessHeap(),
1606                        HEAP_ZERO_MEMORY,
1607                        sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB);
1608    if( !Request )
1609      {
1610        SetLastError( ERROR_OUTOFMEMORY );
1611        return FALSE;
1612      }
1613    Request->Type = CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB;
1614    Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle = hConsoleOutput;
1615    Request->Data.WriteConsoleOutputAttribRequest.Coord = dwWriteCoord;
1616    if( lpNumberOfAttrsWritten )
1617       *lpNumberOfAttrsWritten = nLength;
1618    while( nLength )
1619       {
1620          Size = nLength > CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB ? CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB : nLength;
1621          Request->Data.WriteConsoleOutputAttribRequest.Length = Size;
1622          for( c = 0; c < ( Size * 2 ); c++ )
1623            Request->Data.WriteConsoleOutputAttribRequest.String[c] = (char)lpAttribute[c];
1624          Status = CsrClientCallServer( Request, &Reply, sizeof( CSRSS_API_REQUEST ) + (Size * 2), sizeof( CSRSS_API_REPLY ) );
1625          if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
1626             {
1627                RtlFreeHeap( GetProcessHeap(), 0, Request );
1628                SetLastErrorByStatus ( Status );
1629                return FALSE;
1630             }
1631          nLength -= Size;
1632          lpAttribute += Size;
1633          Request->Data.WriteConsoleOutputAttribRequest.Coord = Reply.Data.WriteConsoleOutputAttribReply.EndCoord;
1634       }
1635    
1636    RtlFreeHeap( GetProcessHeap(), 0, Request );
1637    return TRUE;
1638 }
1639
1640
1641 /*--------------------------------------------------------------
1642  *      FillConsoleOutputAttribute
1643  */
1644 WINBASEAPI
1645 BOOL
1646 WINAPI
1647 FillConsoleOutputAttribute(
1648         HANDLE          hConsoleOutput,
1649         WORD            wAttribute,
1650         DWORD           nLength,
1651         COORD           dwWriteCoord,
1652         LPDWORD         lpNumberOfAttrsWritten
1653         )
1654 {
1655    CSRSS_API_REQUEST Request;
1656    CSRSS_API_REPLY Reply;
1657    NTSTATUS Status;
1658
1659    Request.Type = CSRSS_FILL_OUTPUT_ATTRIB;
1660    Request.Data.FillOutputAttribRequest.ConsoleHandle = hConsoleOutput;
1661    Request.Data.FillOutputAttribRequest.Attribute = wAttribute;
1662    Request.Data.FillOutputAttribRequest.Coord = dwWriteCoord;
1663    Request.Data.FillOutputAttribRequest.Length = nLength;
1664    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
1665    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
1666       {
1667          SetLastErrorByStatus ( Status );
1668          return FALSE;
1669       }
1670    if( lpNumberOfAttrsWritten )
1671       *lpNumberOfAttrsWritten = nLength;
1672    return TRUE;
1673 }
1674
1675
1676 /*--------------------------------------------------------------
1677  *      GetConsoleMode
1678  */
1679 WINBASEAPI
1680 BOOL
1681 WINAPI
1682 GetConsoleMode(
1683         HANDLE          hConsoleHandle,
1684         LPDWORD         lpMode
1685         )
1686 {
1687   CSRSS_API_REQUEST Request;
1688   CSRSS_API_REPLY Reply;
1689   NTSTATUS Status;
1690   
1691   Request.Type = CSRSS_GET_MODE;
1692   Request.Data.GetConsoleModeRequest.ConsoleHandle = hConsoleHandle;
1693   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
1694   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
1695       {
1696         SetLastErrorByStatus ( Status );
1697         return FALSE;
1698       }
1699   *lpMode = Reply.Data.GetConsoleModeReply.ConsoleMode;
1700   return TRUE;
1701 }
1702
1703
1704 /*--------------------------------------------------------------
1705  *      GetNumberOfConsoleInputEvents
1706  */
1707 WINBASEAPI
1708 BOOL
1709 WINAPI
1710 GetNumberOfConsoleInputEvents(
1711         HANDLE          hConsoleInput,
1712         LPDWORD         lpNumberOfEvents
1713         )
1714 {
1715    CSRSS_API_REQUEST Request;
1716    CSRSS_API_REPLY Reply;
1717    NTSTATUS Status;
1718  
1719    if(lpNumberOfEvents == NULL)
1720    {
1721       SetLastError(ERROR_INVALID_PARAMETER);
1722       return FALSE;
1723    }
1724    
1725    Request.Type = CSRSS_GET_NUM_INPUT_EVENTS;
1726    Request.Data.GetNumInputEventsRequest.ConsoleHandle = hConsoleInput;
1727    Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY));
1728    if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
1729    {
1730       SetLastErrorByStatus(Status);
1731       return FALSE;
1732    }
1733    
1734    *lpNumberOfEvents = Reply.Data.GetNumInputEventsReply.NumInputEvents;
1735    
1736         return TRUE;
1737 }
1738
1739
1740 /*--------------------------------------------------------------
1741  *      GetLargestConsoleWindowSize
1742  */
1743 WINBASEAPI
1744 COORD
1745 WINAPI
1746 GetLargestConsoleWindowSize(
1747         HANDLE          hConsoleOutput
1748         )
1749 {
1750 #if 1   /* FIXME: */
1751         COORD Coord = {80,25};
1752
1753 /* TO DO */
1754         return Coord;
1755 #endif
1756 }
1757
1758
1759 /*--------------------------------------------------------------
1760  *      GetConsoleCursorInfo
1761  */
1762 WINBASEAPI
1763 BOOL
1764 WINAPI
1765 GetConsoleCursorInfo(
1766         HANDLE                  hConsoleOutput,
1767         PCONSOLE_CURSOR_INFO    lpConsoleCursorInfo
1768         )
1769 {
1770    CSRSS_API_REQUEST Request;
1771    CSRSS_API_REPLY Reply;
1772    NTSTATUS Status;
1773
1774    Request.Type = CSRSS_GET_CURSOR_INFO;
1775    Request.Data.GetCursorInfoRequest.ConsoleHandle = hConsoleOutput;
1776    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
1777
1778    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
1779       {
1780          SetLastErrorByStatus ( Status );
1781          return FALSE;
1782       }
1783    *lpConsoleCursorInfo = Reply.Data.GetCursorInfoReply.Info;
1784    return TRUE;
1785 }
1786
1787
1788 /*--------------------------------------------------------------
1789  *      GetNumberOfConsoleMouseButtons
1790  */
1791 WINBASEAPI
1792 BOOL
1793 WINAPI
1794 GetNumberOfConsoleMouseButtons(
1795         LPDWORD         lpNumberOfMouseButtons
1796         )
1797 {
1798 /* TO DO */
1799         return FALSE;
1800 }
1801
1802
1803 /*--------------------------------------------------------------
1804  *      SetConsoleMode
1805  */
1806 WINBASEAPI
1807 BOOL
1808 WINAPI
1809 SetConsoleMode(
1810         HANDLE          hConsoleHandle,
1811         DWORD           dwMode
1812         )
1813 {
1814   CSRSS_API_REQUEST Request;
1815   CSRSS_API_REPLY Reply;
1816   NTSTATUS Status;
1817   
1818   Request.Type = CSRSS_SET_MODE;
1819   Request.Data.SetConsoleModeRequest.ConsoleHandle = hConsoleHandle;
1820   Request.Data.SetConsoleModeRequest.Mode = dwMode;
1821   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
1822   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
1823       {
1824         SetLastErrorByStatus ( Status );
1825         return FALSE;
1826       }
1827   return TRUE;
1828 }
1829
1830
1831 /*--------------------------------------------------------------
1832  *      SetConsoleActiveScreenBuffer
1833  */
1834 WINBASEAPI
1835 BOOL
1836 WINAPI
1837 SetConsoleActiveScreenBuffer(
1838         HANDLE          hConsoleOutput
1839         )
1840 {
1841    CSRSS_API_REQUEST Request;
1842    CSRSS_API_REPLY Reply;
1843    NTSTATUS Status;
1844
1845    Request.Type = CSRSS_SET_SCREEN_BUFFER;
1846    Request.Data.SetActiveScreenBufferRequest.OutputHandle = hConsoleOutput;
1847    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
1848    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
1849       {
1850          SetLastErrorByStatus ( Status );
1851          return FALSE;
1852       }
1853    return TRUE;
1854 }
1855
1856
1857 /*--------------------------------------------------------------
1858  *      FlushConsoleInputBuffer
1859  */
1860 WINBASEAPI
1861 BOOL
1862 WINAPI
1863 FlushConsoleInputBuffer(
1864         HANDLE          hConsoleInput
1865         )
1866 {
1867    CSRSS_API_REQUEST Request;
1868    CSRSS_API_REPLY Reply;
1869    NTSTATUS Status;
1870
1871    Request.Type = CSRSS_FLUSH_INPUT_BUFFER;
1872    Request.Data.FlushInputBufferRequest.ConsoleInput = hConsoleInput;
1873    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
1874    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
1875       {
1876          SetLastErrorByStatus ( Status );
1877          return FALSE;
1878       }
1879    return TRUE;
1880 }
1881
1882
1883 /*--------------------------------------------------------------
1884  *      SetConsoleScreenBufferSize
1885  */
1886 WINBASEAPI
1887 BOOL
1888 WINAPI
1889 SetConsoleScreenBufferSize(
1890         HANDLE          hConsoleOutput,
1891         COORD           dwSize
1892         )
1893 {
1894 /* TO DO */
1895         return FALSE;
1896 }
1897
1898 /*--------------------------------------------------------------
1899  *      SetConsoleCursorInfo
1900  */
1901 WINBASEAPI
1902 BOOL
1903 WINAPI
1904 SetConsoleCursorInfo(
1905         HANDLE                           hConsoleOutput,
1906         CONST CONSOLE_CURSOR_INFO       *lpConsoleCursorInfo
1907         )
1908 {
1909    CSRSS_API_REQUEST Request;
1910    CSRSS_API_REPLY Reply;
1911    NTSTATUS Status;
1912
1913    Request.Type = CSRSS_SET_CURSOR_INFO;
1914    Request.Data.SetCursorInfoRequest.ConsoleHandle = hConsoleOutput;
1915    Request.Data.SetCursorInfoRequest.Info = *lpConsoleCursorInfo;
1916    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
1917
1918    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
1919       {
1920          SetLastErrorByStatus ( Status );
1921          return FALSE;
1922       }
1923    return TRUE;
1924 }
1925
1926
1927 /*--------------------------------------------------------------
1928  *      ScrollConsoleScreenBufferA
1929  */
1930 WINBASEAPI
1931 BOOL
1932 WINAPI
1933 ScrollConsoleScreenBufferA(
1934         HANDLE                   hConsoleOutput,
1935         CONST SMALL_RECT        *lpScrollRectangle,
1936         CONST SMALL_RECT        *lpClipRectangle,
1937         COORD                    dwDestinationOrigin,
1938         CONST CHAR_INFO         *lpFill
1939         )
1940 {
1941   CSRSS_API_REQUEST Request;
1942   CSRSS_API_REPLY Reply;
1943   NTSTATUS Status;
1944
1945   Request.Type = CSRSS_SCROLL_CONSOLE_SCREEN_BUFFER;
1946   Request.Data.ScrollConsoleScreenBufferRequest.ConsoleHandle = hConsoleOutput;
1947   Request.Data.ScrollConsoleScreenBufferRequest.ScrollRectangle = *lpScrollRectangle;
1948
1949   if (lpClipRectangle != NULL)
1950     {
1951   Request.Data.ScrollConsoleScreenBufferRequest.UseClipRectangle = TRUE;
1952   Request.Data.ScrollConsoleScreenBufferRequest.ClipRectangle = *lpClipRectangle;
1953     }
1954   else
1955     {
1956   Request.Data.ScrollConsoleScreenBufferRequest.UseClipRectangle = FALSE;
1957     }
1958
1959   Request.Data.ScrollConsoleScreenBufferRequest.DestinationOrigin = dwDestinationOrigin;
1960   Request.Data.ScrollConsoleScreenBufferRequest.Fill = *lpFill;
1961   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
1962
1963   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
1964     {
1965       SetLastErrorByStatus ( Status );
1966       return FALSE;
1967     }
1968   return TRUE;
1969 }
1970
1971
1972 /*--------------------------------------------------------------
1973  *      ScrollConsoleScreenBufferW
1974  */
1975 WINBASEAPI
1976 BOOL
1977 WINAPI
1978 ScrollConsoleScreenBufferW(
1979         HANDLE                   hConsoleOutput,
1980         CONST SMALL_RECT        *lpScrollRectangle,
1981         CONST SMALL_RECT        *lpClipRectangle,
1982         COORD                    dwDestinationOrigin,
1983         CONST CHAR_INFO         *lpFill
1984         )
1985 {
1986 /* TO DO */
1987         return FALSE;
1988 }
1989
1990
1991 /*--------------------------------------------------------------
1992  *      SetConsoleWindowInfo
1993  */
1994 WINBASEAPI
1995 BOOL
1996 WINAPI
1997 SetConsoleWindowInfo(
1998         HANDLE                   hConsoleOutput,
1999         BOOL                     bAbsolute,
2000         CONST SMALL_RECT        *lpConsoleWindow
2001         )
2002 {
2003 /* TO DO */
2004         return FALSE;
2005 }
2006
2007
2008 /*--------------------------------------------------------------
2009  *      SetConsoleTextAttribute
2010  */
2011 WINBASEAPI
2012 BOOL
2013 WINAPI
2014 SetConsoleTextAttribute(
2015         HANDLE          hConsoleOutput,
2016         WORD            wAttributes
2017         )
2018 {
2019    CSRSS_API_REQUEST Request;
2020    CSRSS_API_REPLY Reply;
2021    NTSTATUS Status;
2022
2023    Request.Type = CSRSS_SET_ATTRIB;
2024    Request.Data.SetAttribRequest.ConsoleHandle = hConsoleOutput;
2025    Request.Data.SetAttribRequest.Attrib = wAttributes;
2026    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
2027    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
2028       {
2029          SetLastErrorByStatus ( Status );
2030          return FALSE;
2031       }
2032    return TRUE;
2033 }
2034
2035 BOOL STATIC
2036 AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
2037 {
2038   if (HandlerRoutine == NULL)
2039     {
2040       IgnoreCtrlEvents = TRUE;
2041       return(TRUE);
2042     }
2043   else
2044     {
2045       NrCtrlHandlers++;
2046       CtrlHandlers = 
2047         RtlReAllocateHeap(RtlGetProcessHeap(),
2048                            HEAP_ZERO_MEMORY,
2049                            (PVOID)CtrlHandlers,
2050                            NrCtrlHandlers * sizeof(PHANDLER_ROUTINE)); 
2051       if (CtrlHandlers == NULL)
2052         {
2053           SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2054           return(FALSE);
2055         }
2056       CtrlHandlers[NrCtrlHandlers - 1] = HandlerRoutine;
2057       return(TRUE);
2058     }
2059 }
2060
2061 BOOL STATIC
2062 RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
2063 {
2064   ULONG i;
2065
2066   if (HandlerRoutine == NULL)
2067     {
2068       IgnoreCtrlEvents = FALSE;
2069       return(TRUE);
2070     }
2071   else
2072     {
2073       for (i = 0; i < NrCtrlHandlers; i++)
2074         {
2075           if (CtrlHandlers[i] == HandlerRoutine)
2076             {
2077               CtrlHandlers[i] = CtrlHandlers[NrCtrlHandlers - 1];
2078               NrCtrlHandlers--;
2079               CtrlHandlers = 
2080                 RtlReAllocateHeap(RtlGetProcessHeap(),
2081                                   HEAP_ZERO_MEMORY,
2082                                   (PVOID)CtrlHandlers,
2083                                   NrCtrlHandlers * sizeof(PHANDLER_ROUTINE));
2084               return(TRUE);
2085             }
2086         }
2087     }
2088   return(FALSE);
2089 }
2090
2091 WINBASEAPI BOOL WINAPI
2092 SetConsoleCtrlHandler(PHANDLER_ROUTINE  HandlerRoutine,
2093                       BOOL Add)
2094 {
2095   BOOLEAN Ret;
2096
2097   RtlEnterCriticalSection(&DllLock);
2098   if (Add)
2099     {
2100       Ret = AddConsoleCtrlHandler(HandlerRoutine);
2101     }
2102   else
2103     {
2104       Ret = RemoveConsoleCtrlHandler(HandlerRoutine);
2105     }
2106   RtlLeaveCriticalSection(&DllLock);
2107   return(Ret);
2108 }
2109
2110
2111 /*--------------------------------------------------------------
2112  *      GenerateConsoleCtrlEvent
2113  */
2114 WINBASEAPI BOOL WINAPI
2115 GenerateConsoleCtrlEvent(
2116         DWORD           dwCtrlEvent,
2117         DWORD           dwProcessGroupId
2118         )
2119 {
2120   /* TO DO */
2121   return FALSE;
2122 }
2123
2124
2125 /*--------------------------------------------------------------
2126  *      GetConsoleTitleW
2127  */
2128 #define MAX_CONSOLE_TITLE_LENGTH 80
2129
2130 WINBASEAPI
2131 DWORD
2132 WINAPI
2133 GetConsoleTitleW(
2134         LPWSTR          lpConsoleTitle,
2135         DWORD           nSize
2136         )
2137 {
2138         union {
2139         CSRSS_API_REQUEST       quest;
2140         CSRSS_API_REPLY         ply;
2141         } Re;
2142         NTSTATUS                Status;
2143
2144         /* Marshall data */
2145         Re.quest.Type = CSRSS_GET_TITLE;
2146         Re.quest.Data.GetTitleRequest.ConsoleHandle =
2147                 GetStdHandle (STD_INPUT_HANDLE);
2148
2149         /* Call CSRSS */
2150         Status = CsrClientCallServer (
2151                         & Re.quest,
2152                         & Re.ply,
2153                         (sizeof (CSRSS_GET_TITLE_REQUEST) +
2154                         sizeof (LPC_MESSAGE) +
2155                         sizeof (ULONG)),
2156                         sizeof (CSRSS_API_REPLY)
2157                         );
2158         if (    !NT_SUCCESS(Status)
2159                 || !NT_SUCCESS (Status = Re.ply.Status)
2160                 )
2161         {
2162                 SetLastErrorByStatus (Status);
2163                 return (0);
2164         }
2165
2166         /* Convert size in characters to size in bytes */
2167         nSize = sizeof (WCHAR) * nSize;
2168
2169         /* Unmarshall data */
2170         if (nSize < Re.ply.Data.GetTitleReply.Length)
2171         {
2172                 DbgPrint ("%s: ret=%d\n", __FUNCTION__, Re.ply.Data.GetTitleReply.Length);
2173                 nSize /= sizeof (WCHAR);
2174                 if (nSize > 1)
2175                 {
2176                         wcsncpy (
2177                                 lpConsoleTitle,
2178                                 Re.ply.Data.GetTitleReply.Title,
2179                                 (nSize - 1)
2180                                 );
2181                         /* Add null */
2182                         lpConsoleTitle [nSize --] = L'\0';
2183                 }
2184         }
2185         else
2186         {
2187                 nSize = Re.ply.Data.GetTitleReply.Length / sizeof (WCHAR);
2188                 wcscpy (lpConsoleTitle, Re.ply.Data.GetTitleReply.Title);
2189         }
2190
2191         return nSize;
2192 }
2193
2194
2195 /*--------------------------------------------------------------
2196  *      GetConsoleTitleA
2197  *
2198  *      19990306 EA
2199  */
2200 WINBASEAPI
2201 DWORD
2202 WINAPI
2203 GetConsoleTitleA(
2204         LPSTR           lpConsoleTitle,
2205         DWORD           nSize
2206         )
2207 {
2208         wchar_t WideTitle [MAX_CONSOLE_TITLE_LENGTH];
2209         DWORD   nWideTitle = sizeof WideTitle;
2210 //      DWORD   nWritten;
2211         
2212         if (!lpConsoleTitle || !nSize) return 0;
2213         nWideTitle = GetConsoleTitleW( (LPWSTR) WideTitle, nWideTitle );
2214         if (!nWideTitle) return 0;
2215 #if 0
2216         if ( (nWritten = WideCharToMultiByte(
2217                 CP_ACP,                 // ANSI code page 
2218                 0,                      // performance and mapping flags 
2219                 (LPWSTR) WideTitle,     // address of wide-character string 
2220                 nWideTitle,             // number of characters in string 
2221                 lpConsoleTitle,         // address of buffer for new string 
2222                 nSize,                  // size of buffer 
2223                 NULL,                   // FAST
2224                 NULL                    // FAST
2225                 )))
2226         {
2227                 lpConsoleTitle[nWritten] = '\0';
2228                 return nWritten;
2229         }
2230 #endif
2231         return 0;
2232 }
2233
2234
2235 /*--------------------------------------------------------------
2236  *      SetConsoleTitleW
2237  */
2238 WINBASEAPI
2239 BOOL
2240 WINAPI
2241 SetConsoleTitleW(
2242         LPCWSTR         lpConsoleTitle
2243         )
2244 {
2245   PCSRSS_API_REQUEST Request;
2246   CSRSS_API_REPLY Reply;
2247   NTSTATUS Status;
2248   unsigned int c;
2249   
2250   Request = RtlAllocateHeap(GetProcessHeap(),
2251                             HEAP_ZERO_MEMORY,
2252                             sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_SET_TITLE_REQUEST);
2253   if (Request == NULL)
2254     {
2255       SetLastError(ERROR_OUTOFMEMORY);
2256       return(FALSE);
2257     }
2258   
2259   Request->Type = CSRSS_SET_TITLE;
2260   Request->Data.SetTitleRequest.Console = GetStdHandle( STD_INPUT_HANDLE );
2261   
2262   for( c = 0; lpConsoleTitle[c] && c < CSRSS_MAX_TITLE_LENGTH; c++ )
2263     Request->Data.SetTitleRequest.Title[c] = lpConsoleTitle[c];
2264   // add null
2265   Request->Data.SetTitleRequest.Title[c] = 0;
2266   Request->Data.SetTitleRequest.Length = c;  
2267   Status = CsrClientCallServer(Request,
2268                                &Reply,
2269                                sizeof(CSRSS_SET_TITLE_REQUEST) +
2270                                c +
2271                                sizeof( LPC_MESSAGE ) +
2272                                sizeof( ULONG ),
2273                                sizeof(CSRSS_API_REPLY));
2274   
2275   if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply.Status ) )
2276     {
2277       RtlFreeHeap( GetProcessHeap(), 0, Request );
2278       SetLastErrorByStatus (Status);
2279       return(FALSE);
2280     }
2281   RtlFreeHeap( GetProcessHeap(), 0, Request );
2282   return TRUE;
2283 }
2284
2285
2286 /*--------------------------------------------------------------
2287  *      SetConsoleTitleA
2288  *      
2289  *      19990204 EA     Added
2290  */
2291 WINBASEAPI
2292 BOOL
2293 WINAPI
2294 SetConsoleTitleA(
2295         LPCSTR          lpConsoleTitle
2296         )
2297 {
2298   PCSRSS_API_REQUEST Request;
2299   CSRSS_API_REPLY Reply;
2300   NTSTATUS Status;
2301   unsigned int c;
2302   
2303   Request = RtlAllocateHeap(GetProcessHeap(),
2304                             HEAP_ZERO_MEMORY,
2305                             sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_SET_TITLE_REQUEST);
2306   if (Request == NULL)
2307     {
2308       SetLastError(ERROR_OUTOFMEMORY);
2309       return(FALSE);
2310     }
2311   
2312   Request->Type = CSRSS_SET_TITLE;
2313   Request->Data.SetTitleRequest.Console = GetStdHandle( STD_INPUT_HANDLE );
2314   
2315   for( c = 0; lpConsoleTitle[c] && c < CSRSS_MAX_TITLE_LENGTH; c++ )
2316     Request->Data.SetTitleRequest.Title[c] = lpConsoleTitle[c];
2317   // add null
2318   Request->Data.SetTitleRequest.Title[c] = 0;
2319   Request->Data.SetTitleRequest.Length = c;
2320   Status = CsrClientCallServer(Request,
2321                                &Reply,
2322                                sizeof(CSRSS_SET_TITLE_REQUEST) +
2323                                c +
2324                                sizeof( LPC_MESSAGE ) +
2325                                sizeof( ULONG ),
2326                                sizeof(CSRSS_API_REPLY));
2327   
2328   if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply.Status ) )
2329     {
2330       RtlFreeHeap( GetProcessHeap(), 0, Request );
2331       SetLastErrorByStatus (Status);
2332       return(FALSE);
2333     }
2334   RtlFreeHeap( GetProcessHeap(), 0, Request );
2335   return TRUE;
2336 }
2337
2338
2339 /*--------------------------------------------------------------
2340  *      ReadConsoleW
2341  */
2342 WINBASEAPI
2343 BOOL
2344 WINAPI
2345 ReadConsoleW(
2346         HANDLE          hConsoleInput,
2347         LPVOID          lpBuffer,
2348         DWORD           nNumberOfCharsToRead,
2349         LPDWORD         lpNumberOfCharsRead,
2350         LPVOID          lpReserved
2351         )
2352 {
2353 /* --- TO DO --- */
2354         return FALSE;
2355 }
2356
2357
2358 /*--------------------------------------------------------------
2359  *      WriteConsoleW
2360  */
2361 WINBASEAPI
2362 BOOL
2363 WINAPI
2364 WriteConsoleW(
2365         HANDLE           hConsoleOutput,
2366         CONST VOID      *lpBuffer,
2367         DWORD            nNumberOfCharsToWrite,
2368         LPDWORD          lpNumberOfCharsWritten,
2369         LPVOID           lpReserved
2370         )
2371 {
2372 #if 0
2373   PCSRSS_API_REQUEST Request;
2374   CSRSS_API_REPLY Reply;
2375   NTSTATUS Status;
2376
2377   Request = RtlAllocateHeap(GetProcessHeap(),
2378                             HEAP_ZERO_MEMORY,
2379                             sizeof(CSRSS_API_REQUEST) + nNumberOfCharsToWrite * sizeof(WCHAR));
2380   if (Request == NULL)
2381     {
2382       SetLastError(ERROR_OUTOFMEMORY);
2383       return(FALSE);
2384     }
2385
2386   Request->Type = CSRSS_WRITE_CONSOLE;
2387   Request->Data.WriteConsoleRequest.ConsoleHandle = hConsoleOutput;
2388   Request->Data.WriteConsoleRequest.NrCharactersToWrite =
2389     nNumberOfCharsToWrite;
2390 //  DbgPrint("nNumberOfCharsToWrite %d\n", nNumberOfCharsToWrite);
2391 //  DbgPrint("Buffer %s\n", Request->Data.WriteConsoleRequest.Buffer);
2392   memcpy(Request->Data.WriteConsoleRequest.Buffer,
2393          lpBuffer,
2394          nNumberOfCharsToWrite * sizeof(WCHAR));
2395
2396   Status = CsrClientCallServer(Request,
2397                                &Reply,
2398                                sizeof(CSRSS_API_REQUEST) + nNumberOfCharsToWrite,
2399                                sizeof(CSRSS_API_REPLY));
2400
2401   RtlFreeHeap(GetProcessHeap(),
2402               0,
2403               Request);
2404
2405   if (!NT_SUCCESS(Status))
2406     {
2407       return(FALSE);
2408     }
2409
2410   if (lpNumberOfCharsWritten != NULL)
2411     {
2412       *lpNumberOfCharsWritten = 
2413           Reply.Data.WriteConsoleReply.NrCharactersWritten;
2414     }
2415
2416   return(TRUE);
2417 #endif
2418   return(FALSE);
2419 }
2420
2421
2422 /*--------------------------------------------------------------
2423  *      CreateConsoleScreenBuffer
2424  */
2425 WINBASEAPI
2426 HANDLE
2427 WINAPI
2428 CreateConsoleScreenBuffer(
2429         DWORD                            dwDesiredAccess,
2430         DWORD                            dwShareMode,
2431         CONST SECURITY_ATTRIBUTES       *lpSecurityAttributes,
2432         DWORD                            dwFlags,
2433         LPVOID                           lpScreenBufferData
2434         )
2435 {
2436    // FIXME: don't ignore access, share mode, and security
2437    CSRSS_API_REQUEST Request;
2438    CSRSS_API_REPLY Reply;
2439    NTSTATUS Status;
2440
2441    Request.Type = CSRSS_CREATE_SCREEN_BUFFER;
2442    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
2443    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
2444       {
2445          SetLastErrorByStatus ( Status );
2446          return FALSE;
2447       }
2448    return Reply.Data.CreateScreenBufferReply.OutputHandle;
2449 }
2450
2451
2452 /*--------------------------------------------------------------
2453  *      GetConsoleCP
2454  */
2455 WINBASEAPI
2456 UINT
2457 WINAPI
2458 GetConsoleCP( VOID )
2459 {
2460 /* --- TO DO --- */
2461         return CP_OEMCP; /* FIXME */
2462 }
2463
2464
2465 /*--------------------------------------------------------------
2466  *      SetConsoleCP
2467  */
2468 WINBASEAPI
2469 BOOL
2470 WINAPI
2471 SetConsoleCP(
2472         UINT            wCodePageID
2473         )
2474 {
2475 /* --- TO DO --- */
2476         return FALSE;
2477 }
2478
2479
2480 /*--------------------------------------------------------------
2481  *      GetConsoleOutputCP
2482  */
2483 WINBASEAPI
2484 UINT
2485 WINAPI
2486 GetConsoleOutputCP( VOID )
2487 {
2488 /* --- TO DO --- */
2489         return 0; /* FIXME */
2490 }
2491
2492
2493 /*--------------------------------------------------------------
2494  *      SetConsoleOutputCP
2495  */
2496 WINBASEAPI
2497 BOOL
2498 WINAPI
2499 SetConsoleOutputCP(
2500         UINT            wCodePageID
2501         )
2502 {
2503 /* --- TO DO --- */
2504         return FALSE;
2505 }
2506
2507
2508 /*--------------------------------------------------------------
2509  *      GetConsoleProcessList
2510  */
2511 DWORD STDCALL
2512 GetConsoleProcessList(LPDWORD lpdwProcessList,
2513                   DWORD dwProcessCount)
2514 {
2515    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2516    return 0;
2517 }
2518
2519
2520
2521 /*--------------------------------------------------------------
2522  *      GetConsoleSelectionInfo
2523  */
2524 BOOL STDCALL
2525 GetConsoleSelectionInfo(PCONSOLE_SELECTION_INFO lpConsoleSelectionInfo)
2526 {
2527    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2528    return FALSE;
2529 }
2530
2531
2532
2533 /*--------------------------------------------------------------
2534  *      AttachConsole
2535  */
2536 BOOL STDCALL 
2537 AttachConsole(DWORD dwProcessId)
2538 {
2539    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2540    return FALSE;
2541 }
2542
2543 /* EOF */