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