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