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