update for HEAD-2003091401
[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:      James Tabor 
8  *                      <jimtabor@adsl-64-217-116-74.dsl.hstntx.swbell.net>
9  * UPDATE HISTORY:
10  *      199901?? ??     Created
11  *      19990204 EA     SetConsoleTitleA
12  *      19990306 EA     Stubs
13  */
14
15 /* INCLUDES ******************************************************************/
16
17 #include <k32.h>
18
19 #define NDEBUG
20 #include <kernel32/kernel32.h>
21
22 #define _NOACHS(__X) (sizeof(__X) / sizeof((__X)[0]))
23 extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event);
24 extern __declspec(noreturn) VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag);
25 extern CRITICAL_SECTION ConsoleLock;
26 extern BOOL WINAPI IsDebuggerPresent(VOID);
27
28
29 /* GLOBALS *******************************************************************/
30
31 static BOOL IgnoreCtrlEvents = FALSE;
32
33 static PHANDLER_ROUTINE* CtrlHandlers = NULL;
34 static ULONG NrCtrlHandlers = 0;
35
36 /* Default Console Control Handler *******************************************/
37
38 BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event)
39 {
40         switch(Event)
41         {
42         case CTRL_C_EVENT:
43                 DPRINT("Ctrl-C Event\n");
44                 ExitProcess(0);
45                 break;
46                 
47         case CTRL_BREAK_EVENT:
48                 DPRINT("Ctrl-Break Event\n");
49                 ExitProcess(0);
50                 break;
51
52         case CTRL_SHUTDOWN_EVENT:
53                 DPRINT("Ctrl Shutdown Event\n");
54                 break;
55
56         case CTRL_CLOSE_EVENT:
57                 DPRINT("Ctrl Close Event\n");
58                 break;
59
60         case CTRL_LOGOFF_EVENT:         
61                 DPRINT("Ctrl Logoff Event\n");
62                 break;
63         }
64 //      ExitProcess((UINT)&ExitCode);
65         return TRUE;
66 }
67
68
69 __declspec(noreturn) VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag)
70 {
71 DWORD nExitCode = 0;
72 DWORD nCode = CodeAndFlag & MAXLONG;
73 UINT i;
74
75 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
76
77         switch(nCode)
78         {
79         case CTRL_C_EVENT:
80         case CTRL_BREAK_EVENT:
81         {
82                 if(IsDebuggerPresent())
83                 {
84                         EXCEPTION_RECORD erException;
85                         erException.ExceptionCode = 
86                         (nCode == CTRL_C_EVENT ? DBG_CONTROL_C : DBG_CONTROL_BREAK);
87                         erException.ExceptionFlags = 0;
88                         erException.ExceptionRecord = NULL;
89                         erException.ExceptionAddress = &DefaultConsoleCtrlHandler;
90                         erException.NumberParameters = 0;
91                         RtlRaiseException(&erException);
92                 }               
93                 RtlEnterCriticalSection(&ConsoleLock);
94
95                 if(!(nCode == CTRL_C_EVENT &&
96                         NtCurrentPeb()->ProcessParameters->ProcessGroup & 1))
97                 {
98                         for(i = NrCtrlHandlers; i > 0; -- i)
99                                 if(CtrlHandlers[i - 1](nCode)) break;
100                 }
101                 RtlLeaveCriticalSection(&ConsoleLock);
102                 ExitThread(0);
103         }
104         case CTRL_CLOSE_EVENT:
105         case CTRL_LOGOFF_EVENT:
106         case CTRL_SHUTDOWN_EVENT:
107                 break;
108
109         default: ExitThread(0);
110         }
111
112         RtlEnterCriticalSection(&ConsoleLock);
113
114         if(!(nCode == CTRL_C_EVENT &&
115                 NtCurrentPeb()->ProcessParameters->ProcessGroup & 1))
116         {
117         i = NrCtrlHandlers;
118         while(i > 0)
119                 {
120                 if (i == 1 && (CodeAndFlag & MINLONG) && 
121                         (nCode == CTRL_LOGOFF_EVENT || nCode == CTRL_SHUTDOWN_EVENT))
122                                 break;
123
124                         if(CtrlHandlers[i - 1](nCode))
125                         {
126                                 switch(nCode)
127                                 {
128                                         case CTRL_CLOSE_EVENT:
129                                         case CTRL_LOGOFF_EVENT:
130                                         case CTRL_SHUTDOWN_EVENT:
131                                                 nExitCode = CodeAndFlag;
132                                 }
133                                 break;
134                         }
135                         --i;
136                 }
137         }
138         RtlLeaveCriticalSection(&ConsoleLock);
139         ExitThread(nExitCode);
140 }
141
142
143 /* FUNCTIONS *****************************************************************/
144
145 /*
146  * @unimplemented
147  */
148 BOOL STDCALL
149 AddConsoleAliasA (LPSTR Source,
150                   LPSTR Target,
151                   LPSTR ExeName)
152 {
153   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
154   return FALSE;
155 }
156
157
158 /*
159  * @unimplemented
160  */
161 BOOL STDCALL
162 AddConsoleAliasW (LPWSTR Source,
163                   LPWSTR Target,
164                   LPWSTR ExeName)
165 {
166   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
167   return FALSE;
168 }
169
170
171 /*
172  * @unimplemented
173  */
174 BOOL STDCALL
175 ConsoleMenuControl (HANDLE      hConsole,
176                     DWORD       Unknown1,
177                     DWORD       Unknown2)
178      /*
179       * Undocumented
180       */
181 {
182   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
183   return FALSE;
184 }
185
186
187 /*
188  * @implemented
189  */
190 HANDLE STDCALL
191 DuplicateConsoleHandle (HANDLE  hConsole,
192                         DWORD   dwDesiredAccess,
193                         BOOL    bInheritHandle,
194                         DWORD   dwOptions)
195 {
196   CSRSS_API_REQUEST Request;
197   CSRSS_API_REPLY Reply;
198   NTSTATUS Status;
199
200   if (IsConsoleHandle (hConsole) == FALSE)
201     {
202       SetLastError (ERROR_INVALID_PARAMETER);
203       return INVALID_HANDLE_VALUE;
204     }
205   
206   Request.Type = CSRSS_DUPLICATE_HANDLE;
207   Request.Data.DuplicateHandleRequest.Handle = hConsole;
208   Request.Data.DuplicateHandleRequest.ProcessId = GetCurrentProcessId();
209   Status = CsrClientCallServer(&Request,
210                                &Reply,
211                                sizeof(CSRSS_API_REQUEST),
212                                sizeof(CSRSS_API_REPLY));
213   if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status=Reply.Status))
214     {
215       SetLastErrorByStatus(Status);
216       return INVALID_HANDLE_VALUE;
217     }
218   return Reply.Data.DuplicateHandleReply.Handle;
219 }
220
221
222 /*
223  * @unimplemented
224  */
225 DWORD STDCALL
226 ExpungeConsoleCommandHistoryW (DWORD    Unknown0)
227      /*
228       * Undocumented
229       */
230 {
231   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
232   return 0;
233 }
234
235
236 /*
237  * @unimplemented
238  */
239 DWORD STDCALL
240 ExpungeConsoleCommandHistoryA (DWORD    Unknown0)
241      /*
242       * Undocumented
243       */
244 {
245   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
246   return 0;
247 }
248
249
250 /*
251  * @unimplemented
252  */
253 DWORD STDCALL
254 GetConsoleAliasW (DWORD Unknown0,
255                   DWORD Unknown1,
256                   DWORD Unknown2,
257                   DWORD Unknown3)
258      /*
259       * Undocumented
260       */
261 {
262   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
263   return 0;
264 }
265
266
267 /*
268  * @unimplemented
269  */
270 DWORD STDCALL
271 GetConsoleAliasA (DWORD Unknown0,
272                   DWORD Unknown1,
273                   DWORD Unknown2,
274                   DWORD Unknown3)
275      /*
276       * Undocumented
277       */
278 {
279         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
280         return 0;
281 }
282
283
284 /*
285  * @unimplemented
286  */
287 DWORD STDCALL
288 GetConsoleAliasExesW (DWORD     Unknown0,
289                       DWORD     Unknown1)
290      /*
291       * Undocumented
292       */
293 {
294   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
295   return 0;
296 }
297
298
299 /*
300  * @unimplemented
301  */
302 DWORD STDCALL
303 GetConsoleAliasExesA (DWORD     Unknown0,
304                       DWORD     Unknown1)
305      /*
306       * Undocumented
307       */
308 {
309         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
310         return 0;
311 }
312
313
314 /*
315  * @unimplemented
316  */
317 DWORD STDCALL
318 GetConsoleAliasExesLengthA (VOID)
319      /*
320       * Undocumented
321       */
322 {
323   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
324   return 0;
325 }
326
327
328 /*
329  * @unimplemented
330  */
331 DWORD STDCALL
332 GetConsoleAliasExesLengthW (VOID)
333      /*
334       * Undocumented
335       */
336 {
337   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
338   return 0;
339 }
340
341
342 /*
343  * @unimplemented
344  */
345 DWORD STDCALL
346 GetConsoleAliasesW (DWORD       Unknown0,
347                     DWORD       Unknown1,
348                     DWORD       Unknown2)
349      /*
350       * Undocumented
351       */
352 {
353   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
354   return 0;
355 }
356  
357
358 /*
359  * @unimplemented
360  */
361 DWORD STDCALL
362 GetConsoleAliasesA (DWORD       Unknown0,
363                     DWORD       Unknown1,
364                     DWORD       Unknown2)
365      /*
366       * Undocumented
367       */
368 {
369   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
370   return 0;
371 }
372
373
374 /*
375  * @unimplemented
376  */
377 DWORD STDCALL
378 GetConsoleAliasesLengthW (DWORD Unknown0)
379      /*
380       * Undocumented
381       */
382 {
383   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
384   return 0;
385 }
386
387
388 /*
389  * @unimplemented
390  */
391 DWORD STDCALL
392 GetConsoleAliasesLengthA (DWORD Unknown0)
393      /*
394       * Undocumented
395       */
396 {
397   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
398   return 0;
399 }
400
401
402 /*
403  * @unimplemented
404  */
405 DWORD STDCALL
406 GetConsoleCommandHistoryW (DWORD        Unknown0,
407                            DWORD        Unknown1,
408                            DWORD        Unknown2)
409      /*
410       * Undocumented
411       */
412 {
413   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
414   return 0;
415 }
416
417
418 /*
419  * @unimplemented
420  */
421 DWORD STDCALL
422 GetConsoleCommandHistoryA (DWORD        Unknown0,
423                            DWORD        Unknown1,
424                            DWORD        Unknown2)
425      /*
426       * Undocumented
427       */
428 {
429   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
430   return 0;
431 }
432
433
434 /*
435  * @unimplemented
436  */
437 DWORD STDCALL
438 GetConsoleCommandHistoryLengthW (DWORD  Unknown0)
439      /*
440       * Undocumented
441       */
442 {
443   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
444   return 0;
445 }
446
447
448 /*
449  * @unimplemented
450  */
451 DWORD STDCALL
452 GetConsoleCommandHistoryLengthA (DWORD  Unknown0)
453      /*
454       * Undocumented
455       */
456 {
457   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
458   return 0;
459 }
460
461 /*
462  * @unimplemented
463  */
464 DWORD STDCALL
465 GetConsoleDisplayMode (LPDWORD lpdwMode)
466      /*
467       * FUNCTION: Get the console display mode
468       * ARGUMENTS:
469       *      lpdwMode - Address of variable that receives the current value
470       *                 of display mode
471       * STATUS: Undocumented
472       */
473 {
474   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
475   return 0;
476 }
477
478
479 /*
480  * @unimplemented
481  */
482 DWORD STDCALL
483 GetConsoleFontInfo (DWORD       Unknown0,
484                     DWORD       Unknown1,
485                     DWORD       Unknown2,
486                     DWORD       Unknown3)
487      /*
488       * Undocumented
489       */
490 {
491   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
492   return 0;
493 }
494
495
496 /*
497  * @unimplemented
498  */
499 DWORD STDCALL
500 GetConsoleFontSize(HANDLE hConsoleOutput,
501                    DWORD nFont)
502 {
503   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
504   return 0;
505 }
506
507
508 /*
509  * @implemented
510  */
511 DWORD STDCALL
512 GetConsoleHardwareState (HANDLE hConsole,
513                          DWORD  Flags,
514                          PDWORD State)
515      /*
516       * Undocumented
517       */
518 {
519   CSRSS_API_REQUEST Request;
520   CSRSS_API_REPLY   Reply;
521   NTSTATUS          Status;
522
523   Request.Type = CSRSS_SETGET_CONSOLE_HW_STATE;
524   Request.Data.ConsoleHardwareStateRequest.ConsoleHandle = hConsole;
525   Request.Data.ConsoleHardwareStateRequest.SetGet = CONSOLE_HARDWARE_STATE_GET;
526
527   Status = CsrClientCallServer(& Request,
528                                & Reply,
529                                sizeof(CSRSS_API_REQUEST),
530                                sizeof(CSRSS_API_REPLY));
531   if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
532   {
533     SetLastErrorByStatus(Status);
534     return FALSE;
535   }
536   *State = Reply.Data.ConsoleHardwareStateReply.State;
537   return TRUE;  
538 }
539
540
541 /*
542  * @unimplemented
543  */
544 DWORD STDCALL
545 GetConsoleInputWaitHandle (VOID)
546      /*
547       * Undocumented
548       */
549 {
550   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
551   return FALSE;
552 }
553
554
555 /*
556  * @unimplemented
557  */
558 DWORD STDCALL
559 GetCurrentConsoleFont(HANDLE hConsoleOutput,
560                       BOOL bMaximumWindow,
561                       PCONSOLE_FONT_INFO lpConsoleCurrentFont)
562 {
563   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
564   return 0;
565 }
566
567
568 /*
569  * @unimplemented
570  */
571 ULONG STDCALL
572 GetNumberOfConsoleFonts (VOID)
573      /*
574       * Undocumented
575       */
576 {
577   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
578   return 1; /* FIXME: call csrss.exe */
579 }
580
581
582 /*
583  * @unimplemented
584  */
585 DWORD STDCALL
586 InvalidateConsoleDIBits (DWORD  Unknown0,
587                          DWORD  Unknown1)
588      /*
589       * Undocumented
590       */
591 {
592   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
593   return 0;
594 }
595
596
597 /*
598  * @unimplemented
599  */
600 HANDLE STDCALL
601 OpenConsoleW (LPWSTR  wsName,
602               DWORD   dwDesiredAccess,
603               BOOL    bInheritHandle,
604               DWORD   dwCreationDistribution)
605      /*
606       * Undocumented
607       */
608 {
609   CSRSS_API_REQUEST Request;
610   CSRSS_API_REPLY   Reply;
611   PHANDLE           phConsole = NULL;
612   NTSTATUS          Status = STATUS_SUCCESS;
613   
614   
615   if(0 == _wcsicmp(wsName, L"CONIN$"))
616   {
617     Request.Type = CSRSS_GET_INPUT_HANDLE;
618     phConsole = & Reply.Data.GetInputHandleReply.InputHandle;
619   }
620   else if (0 == _wcsicmp(wsName, L"CONOUT$"))
621   {
622     Request.Type = CSRSS_GET_OUTPUT_HANDLE;
623     phConsole = & Reply.Data.GetOutputHandleReply.OutputHandle;
624   }
625   else
626   {
627     SetLastError(ERROR_INVALID_PARAMETER);
628     return(INVALID_HANDLE_VALUE);
629   }
630   if ((GENERIC_READ|GENERIC_WRITE) != dwDesiredAccess)
631   {
632     SetLastError(ERROR_INVALID_PARAMETER);
633     return(INVALID_HANDLE_VALUE);
634   }
635   if (OPEN_EXISTING != dwCreationDistribution)
636   {
637     SetLastError(ERROR_INVALID_PARAMETER);
638     return(INVALID_HANDLE_VALUE);
639   }
640   Status = CsrClientCallServer(& Request,
641                                & Reply,
642                                sizeof(CSRSS_API_REQUEST),
643                                sizeof(CSRSS_API_REPLY));
644   if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
645   {
646     SetLastErrorByStatus(Status);
647     return INVALID_HANDLE_VALUE;
648   }
649   return(*phConsole);
650 }
651
652
653 /*
654  * @unimplemented
655  */
656 WINBOOL STDCALL
657 SetConsoleCommandHistoryMode (DWORD     dwMode)
658      /*
659       * Undocumented
660       */
661 {
662   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
663   return FALSE;
664 }
665
666
667 /*
668  * @unimplemented
669  */
670 WINBOOL STDCALL
671 SetConsoleCursor (DWORD Unknown0,
672                   DWORD Unknown1)
673      /*
674       * Undocumented
675       */
676 {
677   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
678   return FALSE;
679 }
680
681
682 /*
683  * @unimplemented
684  */
685 WINBOOL STDCALL
686 SetConsoleDisplayMode (HANDLE hOut,
687                        DWORD dwNewMode,
688                        LPDWORD lpdwOldMode)
689      /*
690       * FUNCTION: Set the console display mode.
691       * ARGUMENTS:
692       *       hOut - Standard output handle.
693       *       dwNewMode - New mode.
694       *       lpdwOldMode - Address of a variable that receives the old mode.
695       */
696 {
697   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
698   return FALSE;
699 }
700
701
702 /*
703  * @unimplemented
704  */
705 WINBOOL STDCALL
706 SetConsoleFont (DWORD   Unknown0,
707                 DWORD   Unknown1)
708      /*
709       * Undocumented
710       */
711 {
712   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
713   return FALSE;
714 }
715
716
717 /*
718  * @implemented
719  */
720 WINBOOL STDCALL
721 SetConsoleHardwareState (HANDLE hConsole,
722                          DWORD  Flags,
723                          DWORD  State)
724      /*
725       * Undocumented
726       */
727 {
728   CSRSS_API_REQUEST Request;
729   CSRSS_API_REPLY   Reply;
730   NTSTATUS          Status;
731
732   Request.Type = CSRSS_SETGET_CONSOLE_HW_STATE;
733   Request.Data.ConsoleHardwareStateRequest.ConsoleHandle = hConsole;
734   Request.Data.ConsoleHardwareStateRequest.SetGet = CONSOLE_HARDWARE_STATE_SET;
735   Request.Data.ConsoleHardwareStateRequest.State = State;
736
737   Status = CsrClientCallServer(& Request,
738                                & Reply,
739                                sizeof(CSRSS_API_REQUEST),
740                                sizeof(CSRSS_API_REPLY));
741   if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
742   {
743     SetLastErrorByStatus(Status);
744     return FALSE;
745   }
746   return TRUE;  
747 }
748
749
750 /*
751  * @unimplemented
752  */
753 WINBOOL STDCALL
754 SetConsoleKeyShortcuts (DWORD   Unknown0,
755                         DWORD   Unknown1,
756                         DWORD   Unknown2,
757                         DWORD   Unknown3)
758      /*
759       * Undocumented
760       */
761 {
762   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
763   return FALSE;
764 }
765
766
767 /*
768  * @unimplemented
769  */
770 WINBOOL STDCALL
771 SetConsoleMaximumWindowSize (DWORD      Unknown0,
772                              DWORD      Unknown1)
773      /*
774       * Undocumented
775       */
776 {
777   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
778   return FALSE;
779 }
780
781
782 /*
783  * @unimplemented
784  */
785 WINBOOL STDCALL
786 SetConsoleMenuClose (DWORD      Unknown0)
787      /*
788       * Undocumented
789       */
790 {
791   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
792   return FALSE;
793 }
794
795
796 /*
797  * @unimplemented
798  */
799 WINBOOL STDCALL
800 SetConsoleNumberOfCommandsA (DWORD      Unknown0,
801                              DWORD      Unknown1)
802      /*
803       * Undocumented
804       */
805 {
806   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
807   return FALSE;
808 }
809
810
811 /*
812  * @unimplemented
813  */
814 WINBOOL STDCALL
815 SetConsoleNumberOfCommandsW (DWORD      Unknown0,
816                              DWORD      Unknown1)
817      /*
818       * Undocumented
819       */
820 {
821   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
822   return FALSE;
823 }
824
825
826 /*
827  * @unimplemented
828  */
829 WINBOOL STDCALL
830 SetConsolePalette (DWORD        Unknown0,
831                    DWORD        Unknown1,
832                    DWORD        Unknown2)
833      /*
834       * Undocumented
835       */
836 {
837   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
838   return FALSE;
839 }
840
841
842 /*
843  * @unimplemented
844  */
845 WINBOOL STDCALL
846 SetLastConsoleEventActive (VOID)
847      /*
848       * Undocumented
849       */
850 {
851   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
852   return FALSE;
853 }
854
855
856 /*
857  * @unimplemented
858  */
859 DWORD STDCALL
860 ShowConsoleCursor (DWORD        Unknown0,
861                    DWORD        Unknown1)
862      /*
863       * Undocumented
864       */
865 {
866   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
867   return 0;
868 }
869
870
871 /*
872  * FUNCTION: Checks whether the given handle is a valid console handle.
873  * ARGUMENTS:
874  *      Handle - Handle to be checked
875  * RETURNS:
876  *      TRUE: Handle is a valid console handle
877  *      FALSE: Handle is not a valid console handle.
878  * STATUS: Officially undocumented
879  *
880  * @implemented
881  */
882 BOOL STDCALL
883 VerifyConsoleIoHandle(HANDLE Handle)
884 {
885   CSRSS_API_REQUEST Request;
886   CSRSS_API_REPLY Reply;
887   NTSTATUS Status;
888
889   Request.Type = CSRSS_VERIFY_HANDLE;
890   Request.Data.VerifyHandleRequest.Handle = Handle;
891   Status = CsrClientCallServer(&Request,
892                                &Reply,
893                                sizeof(CSRSS_API_REQUEST),
894                                sizeof(CSRSS_API_REPLY));
895   if (!NT_SUCCESS(Status))
896     {
897       SetLastErrorByStatus(Status);
898       return FALSE;
899     }
900
901   return (BOOL)NT_SUCCESS(Reply.Status);
902 }
903
904
905 /*
906  * @unimplemented
907  */
908 DWORD STDCALL
909 WriteConsoleInputVDMA (DWORD    Unknown0,
910                        DWORD    Unknown1,
911                        DWORD    Unknown2,
912                        DWORD    Unknown3)
913 {
914   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
915   return 0;
916 }
917
918
919 /*
920  * @unimplemented
921  */
922 DWORD STDCALL
923 WriteConsoleInputVDMW (DWORD    Unknown0,
924                        DWORD    Unknown1,
925                        DWORD    Unknown2,
926                        DWORD    Unknown3)
927 {
928   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
929   return 0;
930 }
931
932
933 /*
934  * @implemented
935  */
936 WINBOOL STDCALL
937 CloseConsoleHandle(HANDLE Handle)
938      /*
939       * Undocumented
940       */
941 {
942   CSRSS_API_REQUEST Request;
943   CSRSS_API_REPLY Reply;
944   NTSTATUS Status;
945
946   if (IsConsoleHandle (Handle) == FALSE)
947     {
948       SetLastError (ERROR_INVALID_PARAMETER);
949       return FALSE;
950     }
951
952   Request.Type = CSRSS_CLOSE_HANDLE;
953   Request.Data.CloseHandleRequest.Handle = Handle;
954   Status = CsrClientCallServer(&Request,
955                                &Reply,
956                                sizeof(CSRSS_API_REQUEST),
957                                sizeof(CSRSS_API_REPLY));
958   if (!NT_SUCCESS(Status))
959     {
960        SetLastErrorByStatus(Status);
961        return FALSE;
962     }
963
964   return TRUE;
965 }
966
967
968 /*
969  * @implemented
970  */
971 BOOLEAN STDCALL 
972 IsConsoleHandle(HANDLE Handle)
973 {
974   if ((((ULONG)Handle) & 0x10000003) == 0x3)
975     {
976       return(TRUE);
977     }
978   return(FALSE);
979 }
980
981
982 /*
983  * @implemented
984  */
985 HANDLE STDCALL 
986 GetStdHandle(DWORD nStdHandle)
987      /*
988       * FUNCTION: Get a handle for the standard input, standard output
989       * and a standard error device.
990       * ARGUMENTS:
991       *       nStdHandle - Specifies the device for which to return the handle.
992       * RETURNS: If the function succeeds, the return value is the handle
993       * of the specified device. Otherwise the value is INVALID_HANDLE_VALUE.
994       */
995 {
996   PRTL_USER_PROCESS_PARAMETERS Ppb;
997
998   Ppb = NtCurrentPeb()->ProcessParameters;
999   switch (nStdHandle)
1000     {
1001       case STD_INPUT_HANDLE:
1002         return Ppb->hStdInput;
1003
1004       case STD_OUTPUT_HANDLE:
1005         return Ppb->hStdOutput;
1006
1007       case STD_ERROR_HANDLE:
1008         return Ppb->hStdError;
1009     }
1010
1011   SetLastError (ERROR_INVALID_PARAMETER);
1012   return INVALID_HANDLE_VALUE;
1013 }
1014
1015
1016 /*
1017  * @implemented
1018  */
1019 WINBASEAPI BOOL WINAPI 
1020 SetStdHandle(DWORD nStdHandle,
1021              HANDLE hHandle)
1022      /*
1023       * FUNCTION: Set the handle for the standard input, standard output or
1024       * the standard error device.
1025       * ARGUMENTS:
1026       *        nStdHandle - Specifies the handle to be set.
1027       *        hHandle - The handle to set.
1028       * RETURNS: TRUE if the function succeeds, FALSE otherwise.
1029       */
1030 {
1031   PRTL_USER_PROCESS_PARAMETERS Ppb;
1032
1033   Ppb = NtCurrentPeb()->ProcessParameters;
1034
1035   /* More checking needed? */
1036   if (hHandle == INVALID_HANDLE_VALUE)
1037     {
1038       SetLastError (ERROR_INVALID_HANDLE);
1039       return FALSE;
1040     }
1041
1042   SetLastError(ERROR_SUCCESS); /* OK */
1043
1044   switch (nStdHandle)
1045     {
1046       case STD_INPUT_HANDLE:
1047         Ppb->hStdInput = hHandle;
1048         return TRUE;
1049
1050       case STD_OUTPUT_HANDLE:
1051         Ppb->hStdOutput = hHandle;
1052         return TRUE;
1053
1054       case STD_ERROR_HANDLE:
1055         Ppb->hStdError = hHandle;
1056         return TRUE;
1057     }
1058
1059   SetLastError (ERROR_INVALID_PARAMETER);
1060   return FALSE;
1061 }
1062
1063
1064 /*--------------------------------------------------------------
1065  *      WriteConsoleA
1066  *
1067  * @implemented
1068  */
1069 WINBOOL STDCALL 
1070 WriteConsoleA(HANDLE hConsoleOutput,
1071               CONST VOID *lpBuffer,
1072               DWORD nNumberOfCharsToWrite,
1073               LPDWORD lpNumberOfCharsWritten,
1074               LPVOID lpReserved)
1075 {
1076   PCSRSS_API_REQUEST Request;
1077   CSRSS_API_REPLY Reply;
1078   NTSTATUS Status;
1079   USHORT Size;
1080   ULONG MessageSize;
1081
1082   Request = RtlAllocateHeap(GetProcessHeap(),
1083                             HEAP_ZERO_MEMORY,
1084                             sizeof(CSRSS_API_REQUEST) + 
1085                             CSRSS_MAX_WRITE_CONSOLE_REQUEST);
1086   if (Request == NULL)
1087     {
1088       SetLastError(ERROR_OUTOFMEMORY);
1089       return(FALSE);
1090     }
1091
1092   Request->Type = CSRSS_WRITE_CONSOLE;
1093   Request->Data.WriteConsoleRequest.ConsoleHandle = hConsoleOutput;
1094   if (lpNumberOfCharsWritten != NULL)
1095     *lpNumberOfCharsWritten = nNumberOfCharsToWrite;
1096   while (nNumberOfCharsToWrite)
1097     {
1098       if (nNumberOfCharsToWrite > CSRSS_MAX_WRITE_CONSOLE_REQUEST)
1099         {
1100           Size = CSRSS_MAX_WRITE_CONSOLE_REQUEST;
1101         }
1102       else
1103         {
1104           Size = nNumberOfCharsToWrite;
1105         }
1106       Request->Data.WriteConsoleRequest.NrCharactersToWrite = Size;
1107
1108       memcpy(Request->Data.WriteConsoleRequest.Buffer, lpBuffer, Size);
1109
1110       MessageSize = CSRSS_REQUEST_HEADER_SIZE + 
1111         sizeof(CSRSS_WRITE_CONSOLE_REQUEST) + Size;
1112       Status = CsrClientCallServer(Request,
1113                                    &Reply,
1114                                    MessageSize,
1115                                    sizeof(CSRSS_API_REPLY));
1116
1117       if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
1118         {
1119           RtlFreeHeap(GetProcessHeap(), 0, Request);
1120           SetLastErrorByStatus(Status);
1121           return(FALSE);
1122         }
1123       nNumberOfCharsToWrite -= Size;
1124       lpBuffer += Size;
1125     }
1126
1127   RtlFreeHeap(GetProcessHeap(), 0, Request);
1128
1129   return TRUE;
1130 }
1131
1132
1133 /*--------------------------------------------------------------
1134  *      ReadConsoleA
1135  *
1136  * @implemented
1137  */
1138 WINBOOL STDCALL ReadConsoleA(HANDLE hConsoleInput,
1139                              LPVOID lpBuffer,
1140                              DWORD nNumberOfCharsToRead,
1141                              LPDWORD lpNumberOfCharsRead,
1142                              LPVOID lpReserved)
1143 {
1144    CSRSS_API_REQUEST Request;
1145    PCSRSS_API_REPLY Reply;
1146    NTSTATUS Status;
1147    ULONG CharsRead = 0;
1148    
1149    Reply = RtlAllocateHeap(GetProcessHeap(),
1150                      HEAP_ZERO_MEMORY,
1151                      sizeof(CSRSS_API_REPLY) + nNumberOfCharsToRead);
1152    if (Reply == NULL)
1153      {
1154         SetLastError(ERROR_OUTOFMEMORY);
1155         return(FALSE);
1156      }
1157    
1158    Request.Type = CSRSS_READ_CONSOLE;
1159    Request.Data.ReadConsoleRequest.ConsoleHandle = hConsoleInput;
1160    Request.Data.ReadConsoleRequest.NrCharactersToRead = nNumberOfCharsToRead > CSRSS_MAX_READ_CONSOLE_REQUEST ? CSRSS_MAX_READ_CONSOLE_REQUEST : nNumberOfCharsToRead;
1161    Request.Data.ReadConsoleRequest.nCharsCanBeDeleted = 0;
1162    Status = CsrClientCallServer(&Request, 
1163                                 Reply,
1164                                 sizeof(CSRSS_API_REQUEST),
1165                                 sizeof(CSRSS_API_REPLY) + 
1166                                 Request.Data.ReadConsoleRequest.NrCharactersToRead);
1167    if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply->Status ))
1168      {
1169         DbgPrint( "CSR returned error in ReadConsole\n" );
1170         SetLastErrorByStatus ( Status );
1171         RtlFreeHeap( GetProcessHeap(), 0, Reply );
1172         return(FALSE);
1173      }
1174    if( Reply->Status == STATUS_NOTIFY_CLEANUP )
1175       Reply->Status = STATUS_PENDING;     // ignore backspace because we have no chars to backspace
1176    /* There may not be any chars or lines to read yet, so wait */
1177    while( Reply->Status == STATUS_PENDING )
1178      {
1179        /* some chars may have been returned, but not a whole line yet, so recompute buffer and try again */
1180        nNumberOfCharsToRead -= Reply->Data.ReadConsoleReply.NrCharactersRead;
1181        /* don't overflow caller's buffer, even if you still don't have a complete line */
1182        if( !nNumberOfCharsToRead )
1183          break;
1184        Request.Data.ReadConsoleRequest.NrCharactersToRead = nNumberOfCharsToRead > CSRSS_MAX_READ_CONSOLE_REQUEST ? CSRSS_MAX_READ_CONSOLE_REQUEST : nNumberOfCharsToRead;
1185        /* copy any chars already read to buffer */
1186        memcpy( lpBuffer + CharsRead, Reply->Data.ReadConsoleReply.Buffer, Reply->Data.ReadConsoleReply.NrCharactersRead );
1187        CharsRead += Reply->Data.ReadConsoleReply.NrCharactersRead;
1188        /* wait for csrss to signal there is more data to read, but not if we got STATUS_NOTIFY_CLEANUP for backspace */
1189        Status = NtWaitForSingleObject( Reply->Data.ReadConsoleReply.EventHandle, FALSE, 0 );
1190        if( !NT_SUCCESS( Status ) )
1191           {
1192              DbgPrint( "Wait for console input failed!\n" );
1193              RtlFreeHeap( GetProcessHeap(), 0, Reply );
1194              return FALSE;
1195           }
1196        Request.Data.ReadConsoleRequest.nCharsCanBeDeleted = CharsRead;
1197        Status = CsrClientCallServer( &Request, Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) + Request.Data.ReadConsoleRequest.NrCharactersToRead );
1198        if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply->Status ) )
1199          {
1200            SetLastErrorByStatus ( Status );
1201            RtlFreeHeap( GetProcessHeap(), 0, Reply );
1202            return FALSE;
1203          }
1204        if( Reply->Status == STATUS_NOTIFY_CLEANUP )
1205           {
1206              // delete last char
1207              if( CharsRead )
1208                 {
1209                    CharsRead--;
1210                    nNumberOfCharsToRead++;
1211                 }
1212              Reply->Status = STATUS_PENDING;  // retry
1213           }
1214      }
1215    /* copy data to buffer, count total returned, and return */
1216    memcpy( lpBuffer + CharsRead, Reply->Data.ReadConsoleReply.Buffer, Reply->Data.ReadConsoleReply.NrCharactersRead );
1217    CharsRead += Reply->Data.ReadConsoleReply.NrCharactersRead;
1218    if (lpNumberOfCharsRead != NULL)
1219      *lpNumberOfCharsRead = CharsRead;
1220    RtlFreeHeap(GetProcessHeap(),
1221             0,
1222             Reply);
1223    
1224    return(TRUE);
1225 }
1226
1227
1228 /*--------------------------------------------------------------
1229  *      AllocConsole
1230  *
1231  * @implemented
1232  */
1233 WINBOOL STDCALL AllocConsole(VOID)
1234 {
1235    CSRSS_API_REQUEST Request;
1236    CSRSS_API_REPLY Reply;
1237    NTSTATUS Status;
1238    HANDLE hStdError;
1239
1240    if(NtCurrentPeb()->ProcessParameters->hConsole)
1241    {
1242         DPRINT("AllocConsole: Allocate duplicate console to the same Process\n");
1243         SetLastErrorByStatus (STATUS_OBJECT_EXISTS); 
1244         return FALSE;    
1245    }
1246
1247    Request.Data.AllocConsoleRequest.CtrlDispatcher = (PCONTROLDISPATCHER) &ConsoleControlDispatcher;
1248
1249    Request.Type = CSRSS_ALLOC_CONSOLE;
1250    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
1251    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
1252       {
1253          SetLastErrorByStatus ( Status );
1254          return FALSE;
1255       }
1256    SetStdHandle( STD_INPUT_HANDLE, Reply.Data.AllocConsoleReply.InputHandle );
1257    SetStdHandle( STD_OUTPUT_HANDLE, Reply.Data.AllocConsoleReply.OutputHandle );
1258    hStdError = DuplicateConsoleHandle(Reply.Data.AllocConsoleReply.OutputHandle,
1259                                       0,
1260                                       TRUE,
1261                                       DUPLICATE_SAME_ACCESS);
1262    SetStdHandle( STD_ERROR_HANDLE, hStdError );
1263    return TRUE;
1264 }
1265
1266
1267 /*--------------------------------------------------------------
1268  *      FreeConsole
1269  *
1270  * @implemented
1271  */
1272 WINBOOL STDCALL FreeConsole(VOID)
1273 {
1274     // AG: I'm not sure if this is correct (what happens to std handles?)
1275     // but I just tried to reverse what AllocConsole() does...
1276
1277    CSRSS_API_REQUEST Request;
1278    CSRSS_API_REPLY Reply;
1279    NTSTATUS Status;
1280
1281    Request.Type = CSRSS_FREE_CONSOLE;
1282    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
1283    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
1284       {
1285          SetLastErrorByStatus ( Status );
1286          return FALSE;
1287       }
1288
1289    return TRUE;
1290 }
1291
1292
1293 /*--------------------------------------------------------------
1294  *      GetConsoleScreenBufferInfo
1295  *
1296  * @implemented
1297  */
1298 WINBOOL
1299 STDCALL
1300 GetConsoleScreenBufferInfo(
1301     HANDLE hConsoleOutput,
1302     PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo
1303     )
1304 {
1305    CSRSS_API_REQUEST Request;
1306    CSRSS_API_REPLY Reply;
1307    NTSTATUS Status;
1308
1309    Request.Type = CSRSS_SCREEN_BUFFER_INFO;
1310    Request.Data.ScreenBufferInfoRequest.ConsoleHandle = hConsoleOutput;
1311    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
1312    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
1313       {
1314          SetLastErrorByStatus ( Status );
1315          return FALSE;
1316       }
1317    *lpConsoleScreenBufferInfo = Reply.Data.ScreenBufferInfoReply.Info;
1318    return TRUE;
1319 }
1320
1321
1322 /*--------------------------------------------------------------
1323  *      SetConsoleCursorPosition
1324  *
1325  * @implemented
1326  */
1327 WINBOOL
1328 STDCALL
1329 SetConsoleCursorPosition(
1330     HANDLE hConsoleOutput,
1331     COORD dwCursorPosition
1332     )
1333 {
1334    CSRSS_API_REQUEST Request;
1335    CSRSS_API_REPLY Reply;
1336    NTSTATUS Status;
1337
1338    Request.Type = CSRSS_SET_CURSOR;
1339    Request.Data.SetCursorRequest.ConsoleHandle = hConsoleOutput;
1340    Request.Data.SetCursorRequest.Position = dwCursorPosition;
1341    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
1342    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
1343       {
1344          SetLastErrorByStatus ( Status );
1345          return FALSE;
1346       }
1347    return TRUE;
1348 }
1349
1350
1351 /*--------------------------------------------------------------
1352  *      FillConsoleOutputCharacterA
1353  *
1354  * @implemented
1355  */
1356 WINBOOL STDCALL
1357 FillConsoleOutputCharacterA(
1358         HANDLE          hConsoleOutput,
1359         CHAR            cCharacter,
1360         DWORD           nLength,
1361         COORD           dwWriteCoord,
1362         LPDWORD         lpNumberOfCharsWritten
1363         )
1364 {
1365   CSRSS_API_REQUEST Request;
1366   CSRSS_API_REPLY Reply;
1367   NTSTATUS Status;
1368
1369   Request.Type = CSRSS_FILL_OUTPUT;
1370   Request.Data.FillOutputRequest.ConsoleHandle = hConsoleOutput;
1371   Request.Data.FillOutputRequest.Char = cCharacter;
1372   Request.Data.FillOutputRequest.Position = dwWriteCoord;
1373   Request.Data.FillOutputRequest.Length = nLength;
1374   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
1375   if ( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
1376     {
1377       SetLastErrorByStatus(Status);
1378       return(FALSE);
1379     }
1380   if (lpNumberOfCharsWritten != NULL)
1381      *lpNumberOfCharsWritten = nLength;
1382   return(TRUE);
1383 }
1384
1385
1386 /*--------------------------------------------------------------
1387  *      FillConsoleOutputCharacterW
1388  *
1389  * @unimplemented
1390  */
1391 WINBOOL
1392 STDCALL
1393 FillConsoleOutputCharacterW(
1394         HANDLE          hConsoleOutput,
1395         WCHAR           cCharacter,
1396         DWORD           nLength,
1397         COORD           dwWriteCoord,
1398         LPDWORD         lpNumberOfCharsWritten
1399         )
1400 {
1401 /* TO DO */
1402         return FALSE;
1403 }
1404
1405
1406 /*--------------------------------------------------------------
1407  *      PeekConsoleInputA
1408  *
1409  * @implemented
1410  */
1411 WINBASEAPI
1412 BOOL
1413 WINAPI
1414 PeekConsoleInputA(
1415         HANDLE                  hConsoleInput,
1416         PINPUT_RECORD           lpBuffer,
1417         DWORD                   nLength,
1418         LPDWORD                 lpNumberOfEventsRead
1419         )
1420 {
1421   PCSRSS_API_REQUEST Request;
1422   CSRSS_API_REPLY Reply;
1423   NTSTATUS Status;
1424   PVOID BufferBase;
1425   PVOID BufferTargetBase;
1426   DWORD Size;
1427   
1428   if(lpBuffer == NULL)
1429   {
1430     SetLastError(ERROR_INVALID_PARAMETER);
1431     return FALSE;
1432   }
1433   
1434   Size = nLength * sizeof(INPUT_RECORD);
1435
1436   Status = CsrCaptureParameterBuffer((PVOID)lpBuffer, Size, &BufferBase, &BufferTargetBase);
1437   if(!NT_SUCCESS(Status))
1438   {
1439     SetLastErrorByStatus(Status);
1440     return FALSE;
1441   }
1442   
1443   Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSRSS_API_REQUEST));
1444   if(Request == NULL)
1445   {
1446     CsrReleaseParameterBuffer(BufferBase);
1447     SetLastError(ERROR_OUTOFMEMORY);
1448     return FALSE;
1449   }
1450   
1451   Request->Type = CSRSS_PEEK_CONSOLE_INPUT;
1452   Request->Data.PeekConsoleInputRequest.ConsoleHandle = hConsoleInput;
1453   Request->Data.PeekConsoleInputRequest.Length = nLength;
1454   Request->Data.PeekConsoleInputRequest.InputRecord = (INPUT_RECORD*)BufferTargetBase;
1455   
1456   Status = CsrClientCallServer(Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY));
1457   
1458   if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
1459   {
1460     RtlFreeHeap(GetProcessHeap(), 0, Request);
1461     CsrReleaseParameterBuffer(BufferBase);
1462     return FALSE;
1463   }
1464
1465   memcpy(lpBuffer, BufferBase, sizeof(INPUT_RECORD) * Reply.Data.PeekConsoleInputReply.Length);
1466
1467   if(lpNumberOfEventsRead != NULL)
1468     *lpNumberOfEventsRead = Reply.Data.PeekConsoleInputReply.Length;
1469
1470   RtlFreeHeap(GetProcessHeap(), 0, Request);
1471   CsrReleaseParameterBuffer(BufferBase);  
1472   
1473         return TRUE;
1474 }
1475
1476
1477 /*--------------------------------------------------------------
1478  *      PeekConsoleInputW
1479  *
1480  * @unimplemented
1481  */
1482 WINBASEAPI
1483 BOOL
1484 WINAPI
1485 PeekConsoleInputW(
1486         HANDLE                  hConsoleInput,
1487         PINPUT_RECORD           lpBuffer,
1488         DWORD                   nLength,
1489         LPDWORD                 lpNumberOfEventsRead
1490         )    
1491 {
1492 /* TO DO */
1493         return FALSE;
1494 }
1495
1496
1497 /*--------------------------------------------------------------
1498  *      ReadConsoleInputA
1499  *
1500  * @implemented
1501  */
1502 WINBASEAPI BOOL WINAPI
1503 ReadConsoleInputA(HANDLE hConsoleInput,
1504                   PINPUT_RECORD lpBuffer,
1505                   DWORD nLength,
1506                   LPDWORD lpNumberOfEventsRead)
1507 {
1508   CSRSS_API_REQUEST Request;
1509   CSRSS_API_REPLY Reply;
1510   DWORD NumEventsRead;
1511   NTSTATUS Status;
1512
1513   Request.Type = CSRSS_READ_INPUT;
1514   Request.Data.ReadInputRequest.ConsoleHandle = hConsoleInput;
1515   Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST),
1516                                 sizeof(CSRSS_API_REPLY));
1517   if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
1518     {
1519       SetLastErrorByStatus(Status);
1520       return(FALSE);
1521     }
1522   
1523   while (Status == STATUS_PENDING)
1524     {
1525       Status = NtWaitForSingleObject(Reply.Data.ReadInputReply.Event, FALSE, 
1526                                      0);
1527       if(!NT_SUCCESS(Status))
1528         {
1529           SetLastErrorByStatus(Status);
1530           return FALSE;
1531         }
1532       
1533       Request.Type = CSRSS_READ_INPUT;
1534       Request.Data.ReadInputRequest.ConsoleHandle = hConsoleInput;
1535       Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST),
1536                                    sizeof(CSRSS_API_REPLY));
1537       if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
1538         {
1539           SetLastErrorByStatus(Status);
1540           return(FALSE);
1541         }
1542     }
1543   
1544   NumEventsRead = 0;
1545   *lpBuffer = Reply.Data.ReadInputReply.Input;
1546   lpBuffer++;
1547   NumEventsRead++;
1548   
1549   while ((NumEventsRead < nLength) && (Reply.Data.ReadInputReply.MoreEvents))
1550     {
1551       Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST),
1552                                    sizeof(CSRSS_API_REPLY));
1553       if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
1554         {
1555           SetLastErrorByStatus(Status);
1556           return(FALSE);
1557         }
1558       
1559       if (Status == STATUS_PENDING)
1560         {
1561           break;
1562         }
1563       
1564       *lpBuffer = Reply.Data.ReadInputReply.Input;
1565       lpBuffer++;
1566       NumEventsRead++;
1567       
1568     }
1569   *lpNumberOfEventsRead = NumEventsRead;
1570   
1571   return TRUE;
1572 }
1573
1574
1575 /*--------------------------------------------------------------
1576  *      ReadConsoleInputW
1577  *
1578  * @unimplemented
1579  */
1580 WINBASEAPI
1581 BOOL
1582 WINAPI
1583 ReadConsoleInputW(
1584         HANDLE                  hConsoleInput,
1585         PINPUT_RECORD           lpBuffer,
1586         DWORD                   nLength,
1587         LPDWORD                 lpNumberOfEventsRead
1588         )
1589 {
1590 /* TO DO */
1591         return FALSE;
1592 }
1593
1594
1595 /*--------------------------------------------------------------
1596  *      WriteConsoleInputA
1597  *
1598  * @implemented
1599  */
1600 WINBASEAPI
1601 BOOL
1602 WINAPI
1603 WriteConsoleInputA(
1604         HANDLE                   hConsoleInput,
1605         CONST INPUT_RECORD      *lpBuffer,
1606         DWORD                    nLength,
1607         LPDWORD                  lpNumberOfEventsWritten
1608         )
1609 {
1610   PCSRSS_API_REQUEST Request;
1611   CSRSS_API_REPLY Reply;
1612   PVOID BufferBase, BufferTargetBase;
1613   NTSTATUS Status;
1614   DWORD Size;
1615   
1616   if(lpBuffer == NULL)
1617   {
1618     SetLastError(ERROR_INVALID_PARAMETER);
1619     return FALSE;
1620   }
1621   
1622   Size = nLength * sizeof(INPUT_RECORD);
1623
1624   Status = CsrCaptureParameterBuffer((PVOID)lpBuffer, Size, &BufferBase, &BufferTargetBase);
1625   if(!NT_SUCCESS(Status))
1626   {
1627     SetLastErrorByStatus(Status);
1628     return FALSE;
1629   }
1630   
1631   Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSRSS_API_REQUEST));
1632   if(Request == NULL)
1633   {
1634     SetLastError(ERROR_OUTOFMEMORY);
1635     CsrReleaseParameterBuffer(BufferBase);
1636     return FALSE;
1637   }
1638
1639   Request->Type = CSRSS_WRITE_CONSOLE_INPUT;
1640   Request->Data.WriteConsoleInputRequest.ConsoleHandle = hConsoleInput;
1641   Request->Data.WriteConsoleInputRequest.Length = nLength;
1642   Request->Data.WriteConsoleInputRequest.InputRecord = (PINPUT_RECORD)BufferTargetBase;
1643   
1644   Status = CsrClientCallServer(Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY));
1645   if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
1646   {
1647     RtlFreeHeap(GetProcessHeap(), 0, Request);
1648     CsrReleaseParameterBuffer(BufferBase);
1649     return FALSE;
1650   }
1651   
1652   if(lpNumberOfEventsWritten != NULL)
1653     *lpNumberOfEventsWritten = Reply.Data.WriteConsoleInputReply.Length;
1654   
1655   RtlFreeHeap(GetProcessHeap(), 0, Request);
1656   CsrReleaseParameterBuffer(BufferBase);
1657   
1658   return TRUE;
1659 }
1660
1661
1662 /*--------------------------------------------------------------
1663  *      WriteConsoleInputW
1664  *
1665  * @unimplemented
1666  */
1667 WINBASEAPI
1668 BOOL
1669 WINAPI
1670 WriteConsoleInputW(
1671         HANDLE                   hConsoleInput,
1672         CONST INPUT_RECORD      *lpBuffer,
1673         DWORD                    nLength,
1674         LPDWORD                  lpNumberOfEventsWritten
1675         )
1676 {
1677 /* TO DO */
1678         return FALSE;
1679 }
1680
1681
1682 /*--------------------------------------------------------------
1683  *      ReadConsoleOutputA
1684  *
1685  * @implemented
1686  */
1687 WINBASEAPI
1688 BOOL
1689 WINAPI
1690 ReadConsoleOutputA(
1691         HANDLE          hConsoleOutput,
1692         PCHAR_INFO      lpBuffer,
1693         COORD           dwBufferSize,
1694         COORD           dwBufferCoord,
1695         PSMALL_RECT     lpReadRegion
1696         )
1697 {
1698   PCSRSS_API_REQUEST Request;
1699   CSRSS_API_REPLY Reply;
1700   PVOID BufferBase;
1701   PVOID BufferTargetBase;
1702   NTSTATUS Status;
1703   DWORD Size, SizeX, SizeY;
1704   
1705   if(lpBuffer == NULL)
1706   {
1707     SetLastError(ERROR_INVALID_PARAMETER);
1708     return FALSE;
1709   }
1710   
1711   Size = dwBufferSize.X * dwBufferSize.Y * sizeof(CHAR_INFO);
1712
1713   Status = CsrCaptureParameterBuffer((PVOID)lpBuffer, Size, &BufferBase, &BufferTargetBase);
1714   if(!NT_SUCCESS(Status))
1715   {
1716     SetLastErrorByStatus(Status);
1717     return FALSE;
1718   }
1719   
1720   Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSRSS_API_REQUEST));
1721   if(Request == NULL)
1722   {
1723     SetLastError(ERROR_OUTOFMEMORY);
1724     CsrReleaseParameterBuffer(BufferBase);
1725     return FALSE;
1726   }
1727    
1728   Request->Type = CSRSS_READ_CONSOLE_OUTPUT;
1729   Request->Data.ReadConsoleOutputRequest.ConsoleHandle = hConsoleOutput;
1730   Request->Data.ReadConsoleOutputRequest.BufferSize = dwBufferSize;
1731   Request->Data.ReadConsoleOutputRequest.BufferCoord = dwBufferCoord;
1732   Request->Data.ReadConsoleOutputRequest.ReadRegion = *lpReadRegion;
1733   Request->Data.ReadConsoleOutputRequest.CharInfo = (PCHAR_INFO)BufferTargetBase;
1734   
1735   Status = CsrClientCallServer(Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY));
1736   if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
1737   {
1738     SetLastErrorByStatus(Status);
1739     RtlFreeHeap(GetProcessHeap(), 0, Request);
1740     CsrReleaseParameterBuffer(BufferBase);
1741     return FALSE;
1742   }
1743   
1744   SizeX = Reply.Data.ReadConsoleOutputReply.ReadRegion.Right - Reply.Data.ReadConsoleOutputReply.ReadRegion.Left + 1;
1745   SizeY = Reply.Data.ReadConsoleOutputReply.ReadRegion.Bottom - Reply.Data.ReadConsoleOutputReply.ReadRegion.Top + 1;
1746   
1747   memcpy(lpBuffer, BufferBase, sizeof(CHAR_INFO) * SizeX * SizeY);
1748   *lpReadRegion = Reply.Data.ReadConsoleOutputReply.ReadRegion;
1749   
1750   RtlFreeHeap(GetProcessHeap(), 0, Request);
1751   CsrReleaseParameterBuffer(BufferBase);
1752   
1753   return TRUE;
1754 }
1755
1756
1757 /*--------------------------------------------------------------
1758  *      ReadConsoleOutputW
1759  *
1760  * @unimplemented
1761  */
1762 WINBASEAPI
1763 BOOL
1764 WINAPI
1765 ReadConsoleOutputW(
1766         HANDLE          hConsoleOutput,
1767         PCHAR_INFO      lpBuffer,
1768         COORD           dwBufferSize,
1769         COORD           dwBufferCoord,
1770         PSMALL_RECT     lpReadRegion
1771         )
1772 {
1773 /* TO DO */
1774         return FALSE;
1775 }
1776
1777 /*--------------------------------------------------------------
1778  *      WriteConsoleOutputA
1779  *
1780  * @implemented
1781  */
1782 WINBASEAPI BOOL WINAPI
1783 WriteConsoleOutputA(HANDLE               hConsoleOutput,
1784                     CONST CHAR_INFO     *lpBuffer,
1785                     COORD                dwBufferSize,
1786                     COORD                dwBufferCoord,
1787                     PSMALL_RECT  lpWriteRegion)
1788 {
1789   PCSRSS_API_REQUEST Request;
1790   CSRSS_API_REPLY Reply;
1791   NTSTATUS Status;
1792   ULONG Size;
1793   PVOID BufferBase;
1794   PVOID BufferTargetBase;
1795
1796   Size = dwBufferSize.Y * dwBufferSize.X * sizeof(CHAR_INFO);
1797
1798   Status = CsrCaptureParameterBuffer((PVOID)lpBuffer,
1799                                      Size,
1800                                      &BufferBase,
1801                                      &BufferTargetBase);
1802   if (!NT_SUCCESS(Status))
1803     {
1804       SetLastErrorByStatus(Status);
1805       return(FALSE);
1806     }
1807   
1808   Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, 
1809                             sizeof(CSRSS_API_REQUEST));
1810   if (Request == NULL)
1811     {
1812       CsrReleaseParameterBuffer(BufferBase);
1813       SetLastError(ERROR_OUTOFMEMORY);
1814       return FALSE;
1815     }
1816   Request->Type = CSRSS_WRITE_CONSOLE_OUTPUT;
1817   Request->Data.WriteConsoleOutputRequest.ConsoleHandle = hConsoleOutput;
1818   Request->Data.WriteConsoleOutputRequest.BufferSize = dwBufferSize;
1819   Request->Data.WriteConsoleOutputRequest.BufferCoord = dwBufferCoord;
1820   Request->Data.WriteConsoleOutputRequest.WriteRegion = *lpWriteRegion;
1821   Request->Data.WriteConsoleOutputRequest.CharInfo = 
1822     (CHAR_INFO*)BufferTargetBase;
1823   
1824   Status = CsrClientCallServer(Request, &Reply, 
1825                                sizeof(CSRSS_API_REQUEST), 
1826                                sizeof(CSRSS_API_REPLY));
1827   if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
1828     {
1829       CsrReleaseParameterBuffer(BufferBase);
1830       RtlFreeHeap(GetProcessHeap(), 0, Request);
1831       SetLastErrorByStatus(Status);
1832       return FALSE;
1833     }
1834       
1835   *lpWriteRegion = Reply.Data.WriteConsoleOutputReply.WriteRegion;
1836   RtlFreeHeap(GetProcessHeap(), 0, Request);
1837   CsrReleaseParameterBuffer(BufferBase);
1838   return(TRUE);
1839 }
1840
1841
1842 /*--------------------------------------------------------------
1843  *      WriteConsoleOutputW
1844  *
1845  * @unimplemented
1846  */
1847 WINBASEAPI
1848 BOOL
1849 WINAPI
1850 WriteConsoleOutputW(
1851         HANDLE           hConsoleOutput,
1852         CONST CHAR_INFO *lpBuffer,
1853         COORD            dwBufferSize,
1854         COORD            dwBufferCoord,
1855         PSMALL_RECT      lpWriteRegion
1856         )
1857 {
1858 /* TO DO */
1859         return FALSE;
1860 }
1861
1862
1863 /*--------------------------------------------------------------
1864  *      ReadConsoleOutputCharacterA
1865  *
1866  * @implemented
1867  */
1868 WINBASEAPI
1869 BOOL
1870 WINAPI
1871 ReadConsoleOutputCharacterA(
1872         HANDLE          hConsoleOutput,
1873         LPSTR           lpCharacter,
1874         DWORD           nLength,
1875         COORD           dwReadCoord,
1876         LPDWORD         lpNumberOfCharsRead
1877         )
1878 {
1879   CSRSS_API_REQUEST Request;
1880   PCSRSS_API_REPLY Reply;
1881   NTSTATUS Status;
1882   DWORD Size;
1883
1884   Reply = RtlAllocateHeap(GetProcessHeap(),
1885                           HEAP_ZERO_MEMORY,
1886                           sizeof(CSRSS_API_REPLY) + CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR);
1887   if (Reply == NULL)
1888     {
1889       SetLastError(ERROR_OUTOFMEMORY);
1890       return(FALSE);
1891     }
1892
1893   if (lpNumberOfCharsRead != NULL)
1894     *lpNumberOfCharsRead = nLength;
1895
1896   Request.Type = CSRSS_READ_CONSOLE_OUTPUT_CHAR;
1897   Request.Data.ReadConsoleOutputCharRequest.ConsoleHandle = hConsoleOutput;
1898   Request.Data.ReadConsoleOutputCharRequest.ReadCoord = dwReadCoord;
1899
1900   while (nLength != 0)
1901     {
1902       if (nLength > CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR)
1903         Size = CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR;
1904       else
1905         Size = nLength;
1906
1907       Request.Data.ReadConsoleOutputCharRequest.NumCharsToRead = Size;
1908
1909       Status = CsrClientCallServer(&Request,
1910                                    Reply,
1911                                    sizeof(CSRSS_API_REQUEST),
1912                                    sizeof(CSRSS_API_REPLY) + Size);
1913       if (!NT_SUCCESS(Status) || !NT_SUCCESS(Reply->Status))
1914         {
1915           RtlFreeHeap(GetProcessHeap(), 0, Reply);
1916           SetLastErrorByStatus(Status);
1917           return(FALSE);
1918         }
1919
1920       memcpy(lpCharacter, &Reply->Data.ReadConsoleOutputCharReply.String[0], Size);
1921       lpCharacter += Size;
1922       nLength -= Size;
1923       Request.Data.ReadConsoleOutputCharRequest.ReadCoord = Reply->Data.ReadConsoleOutputCharReply.EndCoord;
1924     }
1925
1926   RtlFreeHeap(GetProcessHeap(), 0, Reply);
1927
1928   return(TRUE);
1929 }
1930
1931
1932 /*--------------------------------------------------------------
1933  *      ReadConsoleOutputCharacterW
1934  *
1935  * @unimplemented
1936  */
1937 WINBASEAPI
1938 BOOL
1939 WINAPI
1940 ReadConsoleOutputCharacterW(
1941         HANDLE          hConsoleOutput,
1942         LPWSTR          lpCharacter,
1943         DWORD           nLength,
1944         COORD           dwReadCoord,
1945         LPDWORD         lpNumberOfCharsRead
1946         )
1947 {
1948 /* TO DO */
1949         return FALSE;
1950 }
1951
1952
1953 /*--------------------------------------------------------------
1954  *      ReadConsoleOutputAttribute
1955  *
1956  * @implemented
1957  */
1958 WINBASEAPI
1959 BOOL
1960 WINAPI
1961 ReadConsoleOutputAttribute(
1962         HANDLE          hConsoleOutput,
1963         LPWORD          lpAttribute,
1964         DWORD           nLength,
1965         COORD           dwReadCoord,
1966         LPDWORD         lpNumberOfAttrsRead
1967         )
1968 {
1969   CSRSS_API_REQUEST Request;
1970   PCSRSS_API_REPLY Reply;
1971   NTSTATUS Status;
1972   DWORD Size, i;
1973   
1974   Reply = RtlAllocateHeap(GetProcessHeap(),
1975                           HEAP_ZERO_MEMORY,
1976                           sizeof(CSRSS_API_REPLY) + CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB);
1977   if (Reply == NULL)
1978     {
1979       SetLastError(ERROR_OUTOFMEMORY);
1980       return(FALSE);
1981     }
1982
1983   if (lpNumberOfAttrsRead != NULL)
1984     *lpNumberOfAttrsRead = nLength;
1985
1986   Request.Type = CSRSS_READ_CONSOLE_OUTPUT_ATTRIB;
1987   Request.Data.ReadConsoleOutputAttribRequest.ConsoleHandle = hConsoleOutput;
1988   Request.Data.ReadConsoleOutputAttribRequest.ReadCoord = dwReadCoord;
1989
1990   while (nLength != 0)
1991     {
1992       if (nLength > CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB)
1993         Size = CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB;
1994       else
1995         Size = nLength;
1996
1997       Request.Data.ReadConsoleOutputAttribRequest.NumAttrsToRead = Size;
1998
1999       Status = CsrClientCallServer(&Request,
2000                                    Reply,
2001                                    sizeof(CSRSS_API_REQUEST),
2002                                    sizeof(CSRSS_API_REPLY) + Size);
2003       if (!NT_SUCCESS(Status) || !NT_SUCCESS(Reply->Status))
2004         {
2005           RtlFreeHeap(GetProcessHeap(), 0, Reply);
2006           SetLastErrorByStatus(Status);
2007           return(FALSE);
2008         }
2009
2010       // Convert CHARs to WORDs
2011       for(i = 0; i < Size; ++i)
2012         *lpAttribute++ = Reply->Data.ReadConsoleOutputAttribReply.String[i];
2013       
2014       nLength -= Size;
2015       Request.Data.ReadConsoleOutputAttribRequest.ReadCoord = Reply->Data.ReadConsoleOutputAttribReply.EndCoord;
2016     }
2017
2018   RtlFreeHeap(GetProcessHeap(), 0, Reply);
2019
2020   return(TRUE);
2021 }
2022
2023
2024 /*--------------------------------------------------------------
2025  *      WriteConsoleOutputCharacterA
2026  *
2027  * @implemented
2028  */
2029 WINBASEAPI BOOL WINAPI
2030 WriteConsoleOutputCharacterA(HANDLE             hConsoleOutput,
2031                              LPCSTR             lpCharacter,
2032                              DWORD              nLength,
2033                              COORD              dwWriteCoord,
2034                              LPDWORD            lpNumberOfCharsWritten)
2035 {
2036   PCSRSS_API_REQUEST Request;
2037   CSRSS_API_REPLY Reply;
2038   NTSTATUS Status;
2039   WORD Size;
2040   
2041   Request = RtlAllocateHeap(GetProcessHeap(),
2042                             HEAP_ZERO_MEMORY,
2043                             sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR);
2044   if( !Request )
2045     {
2046       SetLastError( ERROR_OUTOFMEMORY );
2047       return FALSE;
2048     }
2049   Request->Type = CSRSS_WRITE_CONSOLE_OUTPUT_CHAR;
2050   Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle = hConsoleOutput;
2051   Request->Data.WriteConsoleOutputCharRequest.Coord = dwWriteCoord;
2052   if( lpNumberOfCharsWritten )
2053     *lpNumberOfCharsWritten = nLength;
2054   while( nLength )
2055     {
2056       Size = nLength > CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR ? CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR : nLength;
2057       Request->Data.WriteConsoleOutputCharRequest.Length = Size;
2058       memcpy( &Request->Data.WriteConsoleOutputCharRequest.String[0],
2059               lpCharacter,
2060               Size );
2061       Status = CsrClientCallServer( Request, &Reply, sizeof( CSRSS_API_REQUEST ) + Size, sizeof( CSRSS_API_REPLY ) );
2062       if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
2063         {
2064           RtlFreeHeap( GetProcessHeap(), 0, Request );
2065           SetLastErrorByStatus ( Status );
2066           return FALSE;
2067         }
2068       nLength -= Size;
2069       lpCharacter += Size;
2070       Request->Data.WriteConsoleOutputCharRequest.Coord = Reply.Data.WriteConsoleOutputCharReply.EndCoord;
2071     }
2072   
2073   RtlFreeHeap( GetProcessHeap(), 0, Request );  
2074   return TRUE;
2075 }
2076
2077
2078 /*--------------------------------------------------------------
2079  *      WriteConsoleOutputCharacterW
2080  *
2081  * @implemented
2082  */
2083 WINBASEAPI BOOL WINAPI
2084 WriteConsoleOutputCharacterW(HANDLE             hConsoleOutput,
2085                              LPCWSTR            lpCharacter,
2086                              DWORD              nLength,
2087                              COORD              dwWriteCoord,
2088                              LPDWORD            lpNumberOfCharsWritten)
2089 {
2090   PCSRSS_API_REQUEST Request;
2091   CSRSS_API_REPLY Reply;
2092   NTSTATUS Status;
2093   WORD Size;
2094   
2095   Request = RtlAllocateHeap(GetProcessHeap(),
2096                             HEAP_ZERO_MEMORY,
2097                             sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR);
2098   if( !Request )
2099     {
2100       SetLastError( ERROR_OUTOFMEMORY );
2101       return FALSE;
2102     }
2103   Request->Type = CSRSS_WRITE_CONSOLE_OUTPUT_CHAR;
2104   Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle = hConsoleOutput;
2105   Request->Data.WriteConsoleOutputCharRequest.Coord = dwWriteCoord;
2106   if( lpNumberOfCharsWritten )
2107     *lpNumberOfCharsWritten = nLength;
2108   while( nLength )
2109     {
2110       Size = nLength > CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR ? CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR : nLength;
2111       Request->Data.WriteConsoleOutputCharRequest.Length = Size;
2112       Status = RtlUnicodeToOemN (&Request->Data.WriteConsoleOutputCharRequest.String[0],
2113                                  Size,
2114                                  NULL,
2115                                  (PWCHAR)lpCharacter,
2116                                  Size * sizeof(WCHAR));
2117       if (!NT_SUCCESS(Status))
2118         {
2119           RtlFreeHeap (GetProcessHeap(), 0, Request);
2120           SetLastErrorByStatus (Status);
2121           return FALSE;
2122         }
2123
2124       Status = CsrClientCallServer( Request, &Reply, sizeof( CSRSS_API_REQUEST ) + Size, sizeof( CSRSS_API_REPLY ) );
2125       if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
2126         {
2127           RtlFreeHeap( GetProcessHeap(), 0, Request );
2128           SetLastErrorByStatus ( Status );
2129           return FALSE;
2130         }
2131       nLength -= Size;
2132       lpCharacter += Size;
2133       Request->Data.WriteConsoleOutputCharRequest.Coord = Reply.Data.WriteConsoleOutputCharReply.EndCoord;
2134     }
2135   
2136   RtlFreeHeap( GetProcessHeap(), 0, Request );
2137   return TRUE;
2138 }
2139
2140
2141 /*--------------------------------------------------------------
2142  *      WriteConsoleOutputAttribute
2143  *
2144  * @implemented
2145  */
2146 WINBASEAPI
2147 BOOL
2148 WINAPI
2149 WriteConsoleOutputAttribute(
2150         HANDLE           hConsoleOutput,
2151         CONST WORD      *lpAttribute,
2152         DWORD            nLength,
2153         COORD            dwWriteCoord,
2154         LPDWORD          lpNumberOfAttrsWritten
2155         )
2156 {
2157    PCSRSS_API_REQUEST Request;
2158    CSRSS_API_REPLY Reply;
2159    NTSTATUS Status;
2160    WORD Size;
2161    int c;
2162
2163    Request = RtlAllocateHeap(GetProcessHeap(),
2164                        HEAP_ZERO_MEMORY,
2165                        sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB);
2166    if( !Request )
2167      {
2168        SetLastError( ERROR_OUTOFMEMORY );
2169        return FALSE;
2170      }
2171    Request->Type = CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB;
2172    Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle = hConsoleOutput;
2173    Request->Data.WriteConsoleOutputAttribRequest.Coord = dwWriteCoord;
2174    if( lpNumberOfAttrsWritten )
2175       *lpNumberOfAttrsWritten = nLength;
2176    while( nLength )
2177       {
2178          Size = nLength > CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB ? CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB : nLength;
2179          Request->Data.WriteConsoleOutputAttribRequest.Length = Size;
2180          for( c = 0; c < ( Size * 2 ); c++ )
2181            Request->Data.WriteConsoleOutputAttribRequest.String[c] = (char)lpAttribute[c];
2182          Status = CsrClientCallServer( Request, &Reply, sizeof( CSRSS_API_REQUEST ) + (Size * 2), sizeof( CSRSS_API_REPLY ) );
2183          if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
2184             {
2185                RtlFreeHeap( GetProcessHeap(), 0, Request );
2186                SetLastErrorByStatus ( Status );
2187                return FALSE;
2188             }
2189          nLength -= Size;
2190          lpAttribute += Size;
2191          Request->Data.WriteConsoleOutputAttribRequest.Coord = Reply.Data.WriteConsoleOutputAttribReply.EndCoord;
2192       }
2193    
2194    RtlFreeHeap( GetProcessHeap(), 0, Request );
2195    return TRUE;
2196 }
2197
2198
2199 /*--------------------------------------------------------------
2200  *      FillConsoleOutputAttribute
2201  *
2202  * @implemented
2203  */
2204 WINBASEAPI
2205 BOOL
2206 WINAPI
2207 FillConsoleOutputAttribute(
2208         HANDLE          hConsoleOutput,
2209         WORD            wAttribute,
2210         DWORD           nLength,
2211         COORD           dwWriteCoord,
2212         LPDWORD         lpNumberOfAttrsWritten
2213         )
2214 {
2215    CSRSS_API_REQUEST Request;
2216    CSRSS_API_REPLY Reply;
2217    NTSTATUS Status;
2218
2219    Request.Type = CSRSS_FILL_OUTPUT_ATTRIB;
2220    Request.Data.FillOutputAttribRequest.ConsoleHandle = hConsoleOutput;
2221    Request.Data.FillOutputAttribRequest.Attribute = wAttribute;
2222    Request.Data.FillOutputAttribRequest.Coord = dwWriteCoord;
2223    Request.Data.FillOutputAttribRequest.Length = nLength;
2224    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
2225    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
2226       {
2227          SetLastErrorByStatus ( Status );
2228          return FALSE;
2229       }
2230    if( lpNumberOfAttrsWritten )
2231       *lpNumberOfAttrsWritten = nLength;
2232    return TRUE;
2233 }
2234
2235
2236 /*--------------------------------------------------------------
2237  *      GetConsoleMode
2238  *
2239  * @implemented
2240  */
2241 WINBASEAPI
2242 BOOL
2243 WINAPI
2244 GetConsoleMode(
2245         HANDLE          hConsoleHandle,
2246         LPDWORD         lpMode
2247         )
2248 {
2249   CSRSS_API_REQUEST Request;
2250   CSRSS_API_REPLY Reply;
2251   NTSTATUS Status;
2252   
2253   Request.Type = CSRSS_GET_MODE;
2254   Request.Data.GetConsoleModeRequest.ConsoleHandle = hConsoleHandle;
2255   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
2256   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
2257       {
2258         SetLastErrorByStatus ( Status );
2259         return FALSE;
2260       }
2261   *lpMode = Reply.Data.GetConsoleModeReply.ConsoleMode;
2262   return TRUE;
2263 }
2264
2265
2266 /*--------------------------------------------------------------
2267  *      GetNumberOfConsoleInputEvents
2268  *
2269  * @implemented
2270  */
2271 WINBASEAPI
2272 BOOL
2273 WINAPI
2274 GetNumberOfConsoleInputEvents(
2275         HANDLE          hConsoleInput,
2276         LPDWORD         lpNumberOfEvents
2277         )
2278 {
2279    CSRSS_API_REQUEST Request;
2280    CSRSS_API_REPLY Reply;
2281    NTSTATUS Status;
2282  
2283    if(lpNumberOfEvents == NULL)
2284    {
2285       SetLastError(ERROR_INVALID_PARAMETER);
2286       return FALSE;
2287    }
2288    
2289    Request.Type = CSRSS_GET_NUM_INPUT_EVENTS;
2290    Request.Data.GetNumInputEventsRequest.ConsoleHandle = hConsoleInput;
2291    Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY));
2292    if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
2293    {
2294       SetLastErrorByStatus(Status);
2295       return FALSE;
2296    }
2297    
2298    *lpNumberOfEvents = Reply.Data.GetNumInputEventsReply.NumInputEvents;
2299    
2300         return TRUE;
2301 }
2302
2303
2304 /*--------------------------------------------------------------
2305  *      GetLargestConsoleWindowSize
2306  *
2307  * @unimplemented
2308  */
2309 WINBASEAPI
2310 COORD
2311 WINAPI
2312 GetLargestConsoleWindowSize(
2313         HANDLE          hConsoleOutput
2314         )
2315 {
2316 #if 1   /* FIXME: */
2317         COORD Coord = {80,25};
2318
2319 /* TO DO */
2320         return Coord;
2321 #endif
2322 }
2323
2324
2325 /*--------------------------------------------------------------
2326  *      GetConsoleCursorInfo
2327  *
2328  * @implemented
2329  */
2330 WINBASEAPI
2331 BOOL
2332 WINAPI
2333 GetConsoleCursorInfo(
2334         HANDLE                  hConsoleOutput,
2335         PCONSOLE_CURSOR_INFO    lpConsoleCursorInfo
2336         )
2337 {
2338    CSRSS_API_REQUEST Request;
2339    CSRSS_API_REPLY Reply;
2340    NTSTATUS Status;
2341
2342    Request.Type = CSRSS_GET_CURSOR_INFO;
2343    Request.Data.GetCursorInfoRequest.ConsoleHandle = hConsoleOutput;
2344    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
2345
2346    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
2347       {
2348          SetLastErrorByStatus ( Status );
2349          return FALSE;
2350       }
2351    *lpConsoleCursorInfo = Reply.Data.GetCursorInfoReply.Info;
2352    return TRUE;
2353 }
2354
2355
2356 /*--------------------------------------------------------------
2357  *      GetNumberOfConsoleMouseButtons
2358  *
2359  * @unimplemented
2360  */
2361 WINBASEAPI
2362 BOOL
2363 WINAPI
2364 GetNumberOfConsoleMouseButtons(
2365         LPDWORD         lpNumberOfMouseButtons
2366         )
2367 {
2368 /* TO DO */
2369         return FALSE;
2370 }
2371
2372
2373 /*--------------------------------------------------------------
2374  *      SetConsoleMode
2375  *
2376  * @implemented
2377  */
2378 WINBASEAPI
2379 BOOL
2380 WINAPI
2381 SetConsoleMode(
2382         HANDLE          hConsoleHandle,
2383         DWORD           dwMode
2384         )
2385 {
2386   CSRSS_API_REQUEST Request;
2387   CSRSS_API_REPLY Reply;
2388   NTSTATUS Status;
2389   
2390   Request.Type = CSRSS_SET_MODE;
2391   Request.Data.SetConsoleModeRequest.ConsoleHandle = hConsoleHandle;
2392   Request.Data.SetConsoleModeRequest.Mode = dwMode;
2393   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
2394   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
2395       {
2396         SetLastErrorByStatus ( Status );
2397         return FALSE;
2398       }
2399   return TRUE;
2400 }
2401
2402
2403 /*--------------------------------------------------------------
2404  *      SetConsoleActiveScreenBuffer
2405  *
2406  * @implemented
2407  */
2408 WINBASEAPI
2409 BOOL
2410 WINAPI
2411 SetConsoleActiveScreenBuffer(
2412         HANDLE          hConsoleOutput
2413         )
2414 {
2415    CSRSS_API_REQUEST Request;
2416    CSRSS_API_REPLY Reply;
2417    NTSTATUS Status;
2418
2419    Request.Type = CSRSS_SET_SCREEN_BUFFER;
2420    Request.Data.SetActiveScreenBufferRequest.OutputHandle = hConsoleOutput;
2421    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
2422    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
2423       {
2424          SetLastErrorByStatus ( Status );
2425          return FALSE;
2426       }
2427    return TRUE;
2428 }
2429
2430
2431 /*--------------------------------------------------------------
2432  *      FlushConsoleInputBuffer
2433  *
2434  * @implemented
2435  */
2436 WINBASEAPI
2437 BOOL
2438 WINAPI
2439 FlushConsoleInputBuffer(
2440         HANDLE          hConsoleInput
2441         )
2442 {
2443    CSRSS_API_REQUEST Request;
2444    CSRSS_API_REPLY Reply;
2445    NTSTATUS Status;
2446
2447    Request.Type = CSRSS_FLUSH_INPUT_BUFFER;
2448    Request.Data.FlushInputBufferRequest.ConsoleInput = hConsoleInput;
2449    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
2450    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
2451       {
2452          SetLastErrorByStatus ( Status );
2453          return FALSE;
2454       }
2455    return TRUE;
2456 }
2457
2458
2459 /*--------------------------------------------------------------
2460  *      SetConsoleScreenBufferSize
2461  *
2462  * @unimplemented
2463  */
2464 WINBASEAPI
2465 BOOL
2466 WINAPI
2467 SetConsoleScreenBufferSize(
2468         HANDLE          hConsoleOutput,
2469         COORD           dwSize
2470         )
2471 {
2472 /* TO DO */
2473         return FALSE;
2474 }
2475
2476 /*--------------------------------------------------------------
2477  *      SetConsoleCursorInfo
2478  *
2479  * @implemented
2480  */
2481 WINBASEAPI
2482 BOOL
2483 WINAPI
2484 SetConsoleCursorInfo(
2485         HANDLE                           hConsoleOutput,
2486         CONST CONSOLE_CURSOR_INFO       *lpConsoleCursorInfo
2487         )
2488 {
2489    CSRSS_API_REQUEST Request;
2490    CSRSS_API_REPLY Reply;
2491    NTSTATUS Status;
2492
2493    Request.Type = CSRSS_SET_CURSOR_INFO;
2494    Request.Data.SetCursorInfoRequest.ConsoleHandle = hConsoleOutput;
2495    Request.Data.SetCursorInfoRequest.Info = *lpConsoleCursorInfo;
2496    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
2497
2498    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
2499       {
2500          SetLastErrorByStatus ( Status );
2501          return FALSE;
2502       }
2503    return TRUE;
2504 }
2505
2506
2507 /*--------------------------------------------------------------
2508  *      ScrollConsoleScreenBufferA
2509  *
2510  * @implemented
2511  */
2512 WINBASEAPI
2513 BOOL
2514 WINAPI
2515 ScrollConsoleScreenBufferA(
2516         HANDLE                   hConsoleOutput,
2517         CONST SMALL_RECT        *lpScrollRectangle,
2518         CONST SMALL_RECT        *lpClipRectangle,
2519         COORD                    dwDestinationOrigin,
2520         CONST CHAR_INFO         *lpFill
2521         )
2522 {
2523   CSRSS_API_REQUEST Request;
2524   CSRSS_API_REPLY Reply;
2525   NTSTATUS Status;
2526
2527   Request.Type = CSRSS_SCROLL_CONSOLE_SCREEN_BUFFER;
2528   Request.Data.ScrollConsoleScreenBufferRequest.ConsoleHandle = hConsoleOutput;
2529   Request.Data.ScrollConsoleScreenBufferRequest.ScrollRectangle = *lpScrollRectangle;
2530
2531   if (lpClipRectangle != NULL)
2532     {
2533   Request.Data.ScrollConsoleScreenBufferRequest.UseClipRectangle = TRUE;
2534   Request.Data.ScrollConsoleScreenBufferRequest.ClipRectangle = *lpClipRectangle;
2535     }
2536   else
2537     {
2538   Request.Data.ScrollConsoleScreenBufferRequest.UseClipRectangle = FALSE;
2539     }
2540
2541   Request.Data.ScrollConsoleScreenBufferRequest.DestinationOrigin = dwDestinationOrigin;
2542   Request.Data.ScrollConsoleScreenBufferRequest.Fill = *lpFill;
2543   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
2544
2545   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
2546     {
2547       SetLastErrorByStatus ( Status );
2548       return FALSE;
2549     }
2550   return TRUE;
2551 }
2552
2553
2554 /*--------------------------------------------------------------
2555  *      ScrollConsoleScreenBufferW
2556  *
2557  * @unimplemented
2558  */
2559 WINBASEAPI
2560 BOOL
2561 WINAPI
2562 ScrollConsoleScreenBufferW(
2563         HANDLE                   hConsoleOutput,
2564         CONST SMALL_RECT        *lpScrollRectangle,
2565         CONST SMALL_RECT        *lpClipRectangle,
2566         COORD                    dwDestinationOrigin,
2567         CONST CHAR_INFO         *lpFill
2568         )
2569 {
2570 /* TO DO */
2571         return FALSE;
2572 }
2573
2574
2575 /*--------------------------------------------------------------
2576  *      SetConsoleWindowInfo
2577  *
2578  * @unimplemented
2579  */
2580 WINBASEAPI
2581 BOOL
2582 WINAPI
2583 SetConsoleWindowInfo(
2584         HANDLE                   hConsoleOutput,
2585         BOOL                     bAbsolute,
2586         CONST SMALL_RECT        *lpConsoleWindow
2587         )
2588 {
2589 /* TO DO */
2590         return FALSE;
2591 }
2592
2593
2594 /*--------------------------------------------------------------
2595  *      SetConsoleTextAttribute
2596  *
2597  * @implemented
2598  */
2599 WINBASEAPI
2600 BOOL
2601 WINAPI
2602 SetConsoleTextAttribute(
2603         HANDLE          hConsoleOutput,
2604         WORD            wAttributes
2605         )
2606 {
2607    CSRSS_API_REQUEST Request;
2608    CSRSS_API_REPLY Reply;
2609    NTSTATUS Status;
2610
2611    Request.Type = CSRSS_SET_ATTRIB;
2612    Request.Data.SetAttribRequest.ConsoleHandle = hConsoleOutput;
2613    Request.Data.SetAttribRequest.Attrib = wAttributes;
2614    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
2615    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
2616       {
2617          SetLastErrorByStatus ( Status );
2618          return FALSE;
2619       }
2620    return TRUE;
2621 }
2622
2623
2624 BOOL STATIC
2625 AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
2626 {
2627   if (HandlerRoutine == NULL)
2628     {
2629       IgnoreCtrlEvents = TRUE;
2630       return(TRUE);
2631     }
2632   else
2633     {
2634       NrCtrlHandlers++;
2635       CtrlHandlers = 
2636         RtlReAllocateHeap(RtlGetProcessHeap(),
2637                            HEAP_ZERO_MEMORY,
2638                            (PVOID)CtrlHandlers,
2639                            NrCtrlHandlers * sizeof(PHANDLER_ROUTINE)); 
2640       if (CtrlHandlers == NULL)
2641         {
2642           NrCtrlHandlers = 0;
2643           SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2644           return(FALSE);
2645         }
2646       CtrlHandlers[NrCtrlHandlers - 1] = HandlerRoutine;
2647       return(TRUE);
2648     }
2649 }
2650
2651
2652 BOOL STATIC
2653 RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
2654 {
2655   ULONG i;
2656
2657   if (HandlerRoutine == NULL)
2658     {
2659       IgnoreCtrlEvents = FALSE;
2660       return(TRUE);
2661     }
2662   else
2663     {
2664       for (i = 0; i < NrCtrlHandlers; i++)
2665         {
2666           if ( ((void*)(CtrlHandlers[i])) == (void*)HandlerRoutine)
2667             {
2668               NrCtrlHandlers--;
2669               memmove(CtrlHandlers + i, CtrlHandlers + i + 1, 
2670                       (NrCtrlHandlers - i) * sizeof(PHANDLER_ROUTINE));
2671               CtrlHandlers = 
2672                 RtlReAllocateHeap(RtlGetProcessHeap(),
2673                                   HEAP_ZERO_MEMORY,
2674                                   (PVOID)CtrlHandlers,
2675                                   NrCtrlHandlers * sizeof(PHANDLER_ROUTINE));
2676               return(TRUE);
2677             }
2678         }
2679     }
2680   return(FALSE);
2681 }
2682
2683
2684 /*
2685  * @implemented
2686  */
2687 WINBASEAPI BOOL WINAPI
2688 SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine,
2689                       BOOL Add)
2690 {
2691   BOOLEAN Ret;
2692
2693   RtlEnterCriticalSection(&DllLock);
2694   if (Add)
2695     {
2696       Ret = AddConsoleCtrlHandler(HandlerRoutine);
2697     }
2698   else
2699     {
2700       Ret = RemoveConsoleCtrlHandler(HandlerRoutine);
2701     }
2702   RtlLeaveCriticalSection(&DllLock);
2703   return(Ret);
2704 }
2705
2706
2707 /*--------------------------------------------------------------
2708  *      GenerateConsoleCtrlEvent
2709  *
2710  * @unimplemented
2711  */
2712 WINBASEAPI BOOL WINAPI
2713 GenerateConsoleCtrlEvent(
2714         DWORD           dwCtrlEvent,
2715         DWORD           dwProcessGroupId
2716         )
2717 {
2718   /* TO DO */
2719   return FALSE;
2720 }
2721
2722
2723 /*--------------------------------------------------------------
2724  *      GetConsoleTitleW
2725  *
2726  * @implemented
2727  */
2728 WINBASEAPI
2729 DWORD
2730 WINAPI
2731 GetConsoleTitleW(
2732         LPWSTR          lpConsoleTitle,
2733         DWORD           nSize
2734         )
2735 {
2736    CSRSS_API_REQUEST Request;
2737    PCSRSS_API_REPLY Reply;
2738    NTSTATUS Status;
2739    HANDLE hConsole;
2740
2741    hConsole = CreateFileW(L"CONIN$", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2742    if (hConsole == INVALID_HANDLE_VALUE)
2743    {
2744       return 0;
2745    }
2746
2747    Reply = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSRSS_API_REPLY) + CSRSS_MAX_TITLE_LENGTH * sizeof(WCHAR));
2748    if(Reply == NULL)
2749    {
2750       CloseHandle(hConsole);   
2751       SetLastError(ERROR_OUTOFMEMORY);
2752       return 0;
2753    }
2754
2755    Request.Type = CSRSS_GET_TITLE;
2756    Request.Data.GetTitleRequest.ConsoleHandle = hConsole;
2757    
2758    Status = CsrClientCallServer(&Request, Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY) + CSRSS_MAX_TITLE_LENGTH * sizeof(WCHAR));
2759    CloseHandle(hConsole);
2760    if(!NT_SUCCESS(Status) || !(NT_SUCCESS(Status = Reply->Status)))
2761    {
2762       SetLastErrorByStatus(Status);
2763       RtlFreeHeap(GetProcessHeap(), 0, Reply);
2764       return 0;
2765    }
2766    
2767    if(nSize * sizeof(WCHAR) < Reply->Data.GetTitleReply.Length)
2768    {
2769       wcsncpy(lpConsoleTitle, Reply->Data.GetTitleReply.Title, nSize - 1);
2770       lpConsoleTitle[nSize--] = L'\0';
2771    }
2772    else
2773    {  
2774       nSize = Reply->Data.GetTitleReply.Length / sizeof (WCHAR);
2775       wcscpy(lpConsoleTitle, Reply->Data.GetTitleReply.Title);
2776       lpConsoleTitle[nSize] = L'\0';
2777    }
2778    
2779    RtlFreeHeap(GetProcessHeap(), 0, Reply);
2780    return nSize;
2781 }
2782
2783
2784 /*--------------------------------------------------------------
2785  *      GetConsoleTitleA
2786  *
2787  *      19990306 EA
2788  *
2789  * @implemented
2790  */
2791 WINBASEAPI
2792 DWORD
2793 WINAPI
2794 GetConsoleTitleA(
2795         LPSTR           lpConsoleTitle,
2796         DWORD           nSize
2797         )
2798 {
2799         wchar_t WideTitle [CSRSS_MAX_TITLE_LENGTH];
2800         DWORD   nWideTitle = sizeof WideTitle;
2801         DWORD   nWritten;
2802         
2803         if (!lpConsoleTitle || !nSize) return 0;
2804         nWideTitle = GetConsoleTitleW( (LPWSTR) WideTitle, nWideTitle );
2805         if (!nWideTitle) return 0;
2806
2807         if ( (nWritten = WideCharToMultiByte(
2808                 CP_ACP,                 // ANSI code page 
2809                 0,                      // performance and mapping flags 
2810                 (LPWSTR) WideTitle,     // address of wide-character string 
2811                 nWideTitle,             // number of characters in string 
2812                 lpConsoleTitle,         // address of buffer for new string 
2813                 nSize,                  // size of buffer 
2814                 NULL,                   // FAST
2815                 NULL                    // FAST
2816                 )))
2817         {
2818                 lpConsoleTitle[nWritten] = '\0';
2819                 return nWritten;
2820         }
2821
2822         return 0;
2823 }
2824
2825
2826 /*--------------------------------------------------------------
2827  *      SetConsoleTitleW
2828  *
2829  * @implemented
2830  */
2831 WINBASEAPI
2832 BOOL
2833 WINAPI
2834 SetConsoleTitleW(
2835         LPCWSTR         lpConsoleTitle
2836         )
2837 {
2838   PCSRSS_API_REQUEST Request;
2839   CSRSS_API_REPLY Reply;
2840   NTSTATUS Status;
2841   unsigned int c;
2842   HANDLE hConsole;
2843
2844   hConsole = CreateFileW(L"CONIN$", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2845   if (hConsole == INVALID_HANDLE_VALUE)
2846   {
2847      return FALSE;
2848   }
2849   
2850   Request = RtlAllocateHeap(GetProcessHeap(),
2851                             HEAP_ZERO_MEMORY,
2852                             sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_SET_TITLE_REQUEST);
2853   if (Request == NULL)
2854     {
2855       CloseHandle(hConsole);
2856       SetLastError(ERROR_OUTOFMEMORY);
2857       return(FALSE);
2858     }
2859   
2860   Request->Type = CSRSS_SET_TITLE;
2861   Request->Data.SetTitleRequest.Console = hConsole;
2862   
2863   for( c = 0; lpConsoleTitle[c] && c < CSRSS_MAX_TITLE_LENGTH; c++ )
2864     Request->Data.SetTitleRequest.Title[c] = lpConsoleTitle[c];
2865   // add null
2866   Request->Data.SetTitleRequest.Title[c] = 0;
2867   Request->Data.SetTitleRequest.Length = c;  
2868   Status = CsrClientCallServer(Request,
2869                                &Reply,
2870                                sizeof(CSRSS_API_REQUEST) + 
2871                                c * sizeof(WCHAR),
2872                                sizeof(CSRSS_API_REPLY));
2873   CloseHandle(hConsole);
2874   if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply.Status ) )
2875     {
2876       RtlFreeHeap( GetProcessHeap(), 0, Request );
2877       SetLastErrorByStatus (Status);
2878       return(FALSE);
2879     }
2880   RtlFreeHeap( GetProcessHeap(), 0, Request );
2881   return TRUE;
2882 }
2883
2884
2885 /*--------------------------------------------------------------
2886  *      SetConsoleTitleA
2887  *      
2888  *      19990204 EA     Added
2889  *
2890  * @implemented
2891  */
2892 WINBASEAPI
2893 BOOL
2894 WINAPI
2895 SetConsoleTitleA(
2896         LPCSTR          lpConsoleTitle
2897         )
2898 {
2899   PCSRSS_API_REQUEST Request;
2900   CSRSS_API_REPLY Reply;
2901   NTSTATUS Status;
2902   unsigned int c;
2903   HANDLE hConsole;
2904
2905   hConsole = CreateFileW(L"CONIN$", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2906   if (hConsole == INVALID_HANDLE_VALUE)
2907   {
2908      return FALSE;
2909   }
2910   
2911   Request = RtlAllocateHeap(GetProcessHeap(),
2912                             HEAP_ZERO_MEMORY,
2913                             sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_SET_TITLE_REQUEST);
2914   if (Request == NULL)
2915     {
2916       CloseHandle(hConsole);
2917       SetLastError(ERROR_OUTOFMEMORY);
2918       return(FALSE);
2919     }
2920   
2921   Request->Type = CSRSS_SET_TITLE;
2922   Request->Data.SetTitleRequest.Console = hConsole;
2923   
2924   for( c = 0; lpConsoleTitle[c] && c < CSRSS_MAX_TITLE_LENGTH; c++ )
2925     Request->Data.SetTitleRequest.Title[c] = lpConsoleTitle[c];
2926   // add null
2927   Request->Data.SetTitleRequest.Title[c] = 0;
2928   Request->Data.SetTitleRequest.Length = c;
2929   Status = CsrClientCallServer(Request,
2930                                &Reply,
2931                                sizeof(CSRSS_API_REQUEST) + 
2932                                c * sizeof(WCHAR),
2933                                sizeof(CSRSS_API_REPLY));
2934   CloseHandle(hConsole);
2935   if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply.Status ) )
2936     {
2937       RtlFreeHeap( GetProcessHeap(), 0, Request );
2938       SetLastErrorByStatus (Status);
2939       return(FALSE);
2940     }
2941   RtlFreeHeap( GetProcessHeap(), 0, Request );
2942   return TRUE;
2943 }
2944
2945
2946 /*--------------------------------------------------------------
2947  *      ReadConsoleW
2948  *
2949  * @unimplemented
2950  */
2951 WINBASEAPI
2952 BOOL
2953 WINAPI
2954 ReadConsoleW(
2955         HANDLE          hConsoleInput,
2956         LPVOID          lpBuffer,
2957         DWORD           nNumberOfCharsToRead,
2958         LPDWORD         lpNumberOfCharsRead,
2959         LPVOID          lpReserved
2960         )
2961 {
2962 /* --- TO DO --- */
2963         return FALSE;
2964 }
2965
2966
2967 /*--------------------------------------------------------------
2968  *      WriteConsoleW
2969  *
2970  * @unimplemented
2971  */
2972 WINBASEAPI
2973 BOOL
2974 WINAPI
2975 WriteConsoleW(
2976         HANDLE           hConsoleOutput,
2977         CONST VOID      *lpBuffer,
2978         DWORD            nNumberOfCharsToWrite,
2979         LPDWORD          lpNumberOfCharsWritten,
2980         LPVOID           lpReserved
2981         )
2982 {
2983 #if 0
2984   PCSRSS_API_REQUEST Request;
2985   CSRSS_API_REPLY Reply;
2986   NTSTATUS Status;
2987
2988   Request = RtlAllocateHeap(GetProcessHeap(),
2989                             HEAP_ZERO_MEMORY,
2990                             sizeof(CSRSS_API_REQUEST) + nNumberOfCharsToWrite * sizeof(WCHAR));
2991   if (Request == NULL)
2992     {
2993       SetLastError(ERROR_OUTOFMEMORY);
2994       return(FALSE);
2995     }
2996
2997   Request->Type = CSRSS_WRITE_CONSOLE;
2998   Request->Data.WriteConsoleRequest.ConsoleHandle = hConsoleOutput;
2999   Request->Data.WriteConsoleRequest.NrCharactersToWrite =
3000     nNumberOfCharsToWrite;
3001 //  DbgPrint("nNumberOfCharsToWrite %d\n", nNumberOfCharsToWrite);
3002 //  DbgPrint("Buffer %s\n", Request->Data.WriteConsoleRequest.Buffer);
3003   memcpy(Request->Data.WriteConsoleRequest.Buffer,
3004          lpBuffer,
3005          nNumberOfCharsToWrite * sizeof(WCHAR));
3006
3007   Status = CsrClientCallServer(Request,
3008                                &Reply,
3009                                sizeof(CSRSS_API_REQUEST) + nNumberOfCharsToWrite,
3010                                sizeof(CSRSS_API_REPLY));
3011
3012   RtlFreeHeap(GetProcessHeap(),
3013               0,
3014               Request);
3015
3016   if (!NT_SUCCESS(Status))
3017     {
3018       return(FALSE);
3019     }
3020
3021   if (lpNumberOfCharsWritten != NULL)
3022     {
3023       *lpNumberOfCharsWritten = 
3024           Reply.Data.WriteConsoleReply.NrCharactersWritten;
3025     }
3026
3027   return(TRUE);
3028 #endif
3029   return(FALSE);
3030 }
3031
3032
3033 /*--------------------------------------------------------------
3034  *      CreateConsoleScreenBuffer
3035  *
3036  * @implemented
3037  */
3038 WINBASEAPI
3039 HANDLE
3040 WINAPI
3041 CreateConsoleScreenBuffer(
3042         DWORD                            dwDesiredAccess,
3043         DWORD                            dwShareMode,
3044         CONST SECURITY_ATTRIBUTES       *lpSecurityAttributes,
3045         DWORD                            dwFlags,
3046         LPVOID                           lpScreenBufferData
3047         )
3048 {
3049    // FIXME: don't ignore access, share mode, and security
3050    CSRSS_API_REQUEST Request;
3051    CSRSS_API_REPLY Reply;
3052    NTSTATUS Status;
3053
3054    Request.Type = CSRSS_CREATE_SCREEN_BUFFER;
3055    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
3056    if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
3057       {
3058          SetLastErrorByStatus ( Status );
3059          return FALSE;
3060       }
3061    return Reply.Data.CreateScreenBufferReply.OutputHandle;
3062 }
3063
3064
3065 /*--------------------------------------------------------------
3066  *      GetConsoleCP
3067  *
3068  * @unimplemented
3069  */
3070 WINBASEAPI
3071 UINT
3072 WINAPI
3073 GetConsoleCP( VOID )
3074 {
3075 /* --- TO DO --- */
3076         return CP_OEMCP; /* FIXME */
3077 }
3078
3079
3080 /*--------------------------------------------------------------
3081  *      SetConsoleCP
3082  *
3083  * @unimplemented
3084  */
3085 WINBASEAPI
3086 BOOL
3087 WINAPI
3088 SetConsoleCP(
3089         UINT            wCodePageID
3090         )
3091 {
3092 /* --- TO DO --- */
3093         return FALSE;
3094 }
3095
3096
3097 /*--------------------------------------------------------------
3098  *      GetConsoleOutputCP
3099  *
3100  * @unimplemented
3101  */
3102 WINBASEAPI
3103 UINT
3104 WINAPI
3105 GetConsoleOutputCP( VOID )
3106 {
3107 /* --- TO DO --- */
3108         return 0; /* FIXME */
3109 }
3110
3111
3112 /*--------------------------------------------------------------
3113  *      SetConsoleOutputCP
3114  *
3115  * @unimplemented
3116  */
3117 WINBASEAPI
3118 BOOL
3119 WINAPI
3120 SetConsoleOutputCP(
3121         UINT            wCodePageID
3122         )
3123 {
3124 /* --- TO DO --- */
3125         return FALSE;
3126 }
3127
3128
3129 /*--------------------------------------------------------------
3130  *      GetConsoleProcessList
3131  *
3132  * @unimplemented
3133  */
3134 DWORD STDCALL
3135 GetConsoleProcessList(LPDWORD lpdwProcessList,
3136                   DWORD dwProcessCount)
3137 {
3138    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3139    return 0;
3140 }
3141
3142
3143
3144 /*--------------------------------------------------------------
3145  *      GetConsoleSelectionInfo
3146  *
3147  * @unimplemented
3148  */
3149 BOOL STDCALL
3150 GetConsoleSelectionInfo(PCONSOLE_SELECTION_INFO lpConsoleSelectionInfo)
3151 {
3152    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3153    return FALSE;
3154 }
3155
3156
3157
3158 /*--------------------------------------------------------------
3159  *      AttachConsole
3160  *
3161  * @unimplemented
3162  */
3163 BOOL STDCALL 
3164 AttachConsole(DWORD dwProcessId)
3165 {
3166    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3167    return FALSE;
3168 }
3169
3170 /*--------------------------------------------------------------
3171  *      GetConsoleWindow/0
3172  *
3173  * @implemented
3174  */
3175 HWND STDCALL
3176 GetConsoleWindow (VOID)
3177 {
3178   CSRSS_API_REQUEST Request;
3179   CSRSS_API_REPLY   Reply;
3180   NTSTATUS          Status;
3181    
3182   Request.Data.ConsoleWindowRequest.ConsoleHandle =
3183     OpenConsoleW (L"CONOUT$", (GENERIC_READ|GENERIC_WRITE), FALSE, OPEN_EXISTING);
3184   if (INVALID_HANDLE_VALUE == Request.Data.ConsoleWindowRequest.ConsoleHandle)
3185   {
3186     return (HWND) NULL;
3187   }
3188   Request.Type = CSRSS_GET_CONSOLE_WINDOW;
3189   Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
3190   if (!NT_SUCCESS(Status ) || !NT_SUCCESS(Status = Reply.Status))
3191   {
3192     SetLastErrorByStatus (Status);
3193     return (HWND) NULL;
3194   }
3195   return Reply.Data.ConsoleWindowReply.WindowHandle;
3196 }
3197
3198 /* EOF */