1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS system libraries
4  * FILE:            dll/win32/kernel32/client/console/console.c
5  * PURPOSE:         Win32 server console functions
6  * PROGRAMMERS:     James Tabor <jimtabor@adsl-64-217-116-74.dsl.hstntx.swbell.net>
7  *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8  */
9 
10 /* INCLUDES *******************************************************************/
11 
12 #include <k32.h>
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 
18 /* GLOBALS ********************************************************************/
19 
20 extern RTL_CRITICAL_SECTION ConsoleLock;
21 extern BOOLEAN ConsoleInitialized;
22 
23 /* Console reserved "file" names */
24 static LPCWSTR BaseConFileName       = CONSOLE_FILE_NAME;
25 static LPCWSTR BaseConInputFileName  = CONSOLE_INPUT_FILE_NAME;
26 static LPCWSTR BaseConOutputFileName = CONSOLE_OUTPUT_FILE_NAME;
27 
28 /* Console Control handling */
29 static PHANDLER_ROUTINE InitialHandler[1];
30 static PHANDLER_ROUTINE* CtrlHandlers;
31 static ULONG NrCtrlHandlers;
32 static ULONG NrAllocatedHandlers;
33 static BOOLEAN LastCloseNotify = FALSE;
34 
35 extern BOOL WINAPI IsDebuggerPresent(VOID);
36 
37 /* Console Input facilities */
38 HANDLE InputWaitHandle = INVALID_HANDLE_VALUE;
39 
40 #define EXENAME_LENGTH 255 + 1
41 static RTL_CRITICAL_SECTION ExeNameLock;
42 static BOOLEAN ExeNameInitialized;
43 static WCHAR ExeNameBuffer[EXENAME_LENGTH]; // NULL-terminated
44 static USHORT ExeNameLength;    // Count in number of characters without NULL
45 static WCHAR StartDirBuffer[MAX_PATH + 1];  // NULL-terminated
46 static USHORT StartDirLength;   // Count in number of characters without NULL
47 
48 
49 /* Default Console Control Handler ********************************************/
50 
51 static BOOL
52 WINAPI
53 DefaultConsoleCtrlHandler(DWORD Event)
54 {
55     DPRINT("Default handler called: %lx\n", Event);
56     switch(Event)
57     {
58         case CTRL_C_EVENT:
59             DPRINT("Ctrl-C Event\n");
60             break;
61 
62         case CTRL_BREAK_EVENT:
63             DPRINT("Ctrl-Break Event\n");
64             break;
65 
66         case CTRL_CLOSE_EVENT:
67             DPRINT("Ctrl Close Event\n");
68             break;
69 
70         case CTRL_LAST_CLOSE_EVENT:
71             DPRINT("Ctrl Last Close Event\n");
72             break;
73 
74         case CTRL_LOGOFF_EVENT:
75             DPRINT("Ctrl Logoff Event\n");
76             break;
77 
78         case CTRL_SHUTDOWN_EVENT:
79             DPRINT("Ctrl Shutdown Event\n");
80             break;
81     }
82 
83     ExitProcess(CONTROL_C_EXIT);
84     return TRUE;
85 }
86 
87 DWORD
88 WINAPI
89 ConsoleControlDispatcher(IN LPVOID lpThreadParameter)
90 {
91     DWORD nExitCode = 0;
92     DWORD CodeAndFlag = PtrToUlong(lpThreadParameter);
93     DWORD nCode = CodeAndFlag & MAXLONG;
94     UINT i;
95     EXCEPTION_RECORD erException;
96 
97     DPRINT1("Console Dispatcher Active: %lx %lx\n", CodeAndFlag, nCode);
98     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
99 
100     switch(nCode)
101     {
102         case CTRL_C_EVENT:
103         case CTRL_BREAK_EVENT:
104         {
105             if (IsDebuggerPresent())
106             {
107                 erException.ExceptionCode = (nCode == CTRL_C_EVENT ?
108                                              DBG_CONTROL_C : DBG_CONTROL_BREAK);
109                 erException.ExceptionFlags = 0;
110                 erException.ExceptionRecord = NULL;
111                 erException.ExceptionAddress = DefaultConsoleCtrlHandler;
112                 erException.NumberParameters = 0;
113 
114                 _SEH2_TRY
115                 {
116                     RtlRaiseException(&erException);
117                 }
118                 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
119                 {
120                     RtlEnterCriticalSection(&ConsoleLock);
121 
122                     if ((nCode != CTRL_C_EVENT) ||
123                         (NtCurrentPeb()->ProcessParameters->ConsoleFlags != 1))
124                     {
125                         for (i = NrCtrlHandlers; i > 0; i--)
126                         {
127                             if (CtrlHandlers[i - 1](nCode)) break;
128                         }
129                     }
130 
131                     RtlLeaveCriticalSection(&ConsoleLock);
132                 }
133                 _SEH2_END;
134 
135                 ExitThread(0);
136             }
137             break;
138         }
139 
140         case CTRL_CLOSE_EVENT:
141         case CTRL_LOGOFF_EVENT:
142         case CTRL_SHUTDOWN_EVENT:
143             break;
144 
145         case CTRL_LAST_CLOSE_EVENT:
146             /*
147              * In case the console app hasn't register for last close notification,
148              * just kill this console handler thread. We don't want that such apps
149              * get killed for unexpected reasons. On the contrary apps that registered
150              * can be killed because they expect to be.
151              */
152             if (!LastCloseNotify) ExitThread(0);
153             break;
154 
155         case 4:
156             ExitProcess(CONTROL_C_EXIT);
157             break;
158 
159         default:
160             ASSERT(FALSE);
161             break;
162     }
163 
164     ASSERT(ConsoleInitialized);
165 
166     RtlEnterCriticalSection(&ConsoleLock);
167 
168     nExitCode = 0;
169     if ((nCode != CTRL_C_EVENT) || (NtCurrentPeb()->ProcessParameters->ConsoleFlags != 1))
170     {
171         for (i = NrCtrlHandlers; i > 0; i--)
172         {
173             if ((i == 1) &&
174                 (CodeAndFlag & MINLONG) &&
175                 ((nCode == CTRL_LOGOFF_EVENT) || (nCode == CTRL_SHUTDOWN_EVENT)))
176             {
177                 DPRINT("Skipping system/service apps\n");
178                 break;
179             }
180 
181             if (CtrlHandlers[i - 1](nCode))
182             {
183                 switch(nCode)
184                 {
185                     case CTRL_CLOSE_EVENT:
186                     case CTRL_LAST_CLOSE_EVENT:
187                     case CTRL_LOGOFF_EVENT:
188                     case CTRL_SHUTDOWN_EVENT:
189                         nExitCode = CodeAndFlag;
190                         break;
191                 }
192                 break;
193             }
194         }
195     }
196 
197     RtlLeaveCriticalSection(&ConsoleLock);
198 
199     ExitThread(nExitCode);
200     return STATUS_SUCCESS;
201 }
202 
203 VOID
204 InitializeCtrlHandling(VOID)
205 {
206     /* Initialize Console Ctrl Handler */
207     NrAllocatedHandlers = NrCtrlHandlers = 1;
208     CtrlHandlers = InitialHandler;
209     CtrlHandlers[0] = DefaultConsoleCtrlHandler;
210 }
211 
212 
213 /* Input EXE Name Support *****************************************************/
214 
215 VOID
216 InitExeName(VOID)
217 {
218     NTSTATUS Status;
219     PPEB Peb = NtCurrentPeb();
220     PCURDIR CurrentDirectory = &Peb->ProcessParameters->CurrentDirectory;
221     PLDR_DATA_TABLE_ENTRY ImageEntry;
222 
223     if (ExeNameInitialized) return;
224 
225     /* Initialize the EXE name lock */
226     Status = RtlInitializeCriticalSection(&ExeNameLock);
227     if (!NT_SUCCESS(Status)) return;
228     ExeNameInitialized = TRUE;
229 
230     ImageEntry = CONTAINING_RECORD(Peb->Ldr->InLoadOrderModuleList.Flink,
231                                    LDR_DATA_TABLE_ENTRY,
232                                    InLoadOrderLinks);
233 
234     /* Retrieve the EXE name, NULL-terminate it... */
235     ExeNameLength = min(sizeof(ExeNameBuffer)/sizeof(ExeNameBuffer[0]),
236                         ImageEntry->BaseDllName.Length / sizeof(WCHAR));
237     RtlCopyMemory(ExeNameBuffer,
238                   ImageEntry->BaseDllName.Buffer,
239                   ImageEntry->BaseDllName.Length);
240     ExeNameBuffer[ExeNameLength] = UNICODE_NULL;
241 
242     /* ... and retrieve the current directory path and NULL-terminate it. */
243     StartDirLength = min(sizeof(StartDirBuffer)/sizeof(StartDirBuffer[0]),
244                          CurrentDirectory->DosPath.Length / sizeof(WCHAR));
245     RtlCopyMemory(StartDirBuffer,
246                   CurrentDirectory->DosPath.Buffer,
247                   CurrentDirectory->DosPath.Length);
248     StartDirBuffer[StartDirLength] = UNICODE_NULL;
249 }
250 
251 /*
252  * NOTE:
253  * The "LPDWORD Length" parameters point on input to the maximum size of
254  * the buffers that can hold data (if != 0), and on output they hold the
255  * real size of the data. If "Length" are == 0 on input, then on output
256  * they receive the full size of the data.
257  * The "LPWSTR* String" parameters have a double meaning:
258  * - when "CaptureStrings" is TRUE, data is copied to the buffers pointed
259  *   by the pointers (*String).
260  * - when "CaptureStrings" is FALSE, "*String" are set to the addresses of
261  *   the source data.
262  */
263 VOID
264 SetUpAppName(IN BOOLEAN CaptureStrings,
265              IN OUT LPDWORD CurDirLength,
266              IN OUT LPWSTR* CurDir,
267              IN OUT LPDWORD AppNameLength,
268              IN OUT LPWSTR* AppName)
269 {
270     DWORD Length;
271 
272     /* Retrieve the needed buffer size */
273     Length = (StartDirLength + 1) * sizeof(WCHAR);
274     if (*CurDirLength > 0) Length = min(Length, *CurDirLength);
275     *CurDirLength = Length;
276 
277     /* Capture the data if needed, or, return a pointer to it */
278     if (CaptureStrings)
279     {
280         /*
281          * Length is always >= sizeof(WCHAR). Copy everything but the
282          * possible trailing NULL character, and then NULL-terminate.
283          */
284         Length -= sizeof(WCHAR);
285         RtlCopyMemory(*CurDir, StartDirBuffer, Length);
286         (*CurDir)[Length / sizeof(WCHAR)] = UNICODE_NULL;
287     }
288     else
289     {
290         *CurDir = StartDirBuffer;
291     }
292 
293     /* Retrieve the needed buffer size */
294     Length = (ExeNameLength + 1) * sizeof(WCHAR);
295     if (*AppNameLength > 0) Length = min(Length, *AppNameLength);
296     *AppNameLength = Length;
297 
298     /* Capture the data if needed, or, return a pointer to it */
299     if (CaptureStrings)
300     {
301         /*
302          * Length is always >= sizeof(WCHAR). Copy everything but the
303          * possible trailing NULL character, and then NULL-terminate.
304          */
305         Length -= sizeof(WCHAR);
306         RtlCopyMemory(*AppName, ExeNameBuffer, Length);
307         (*AppName)[Length / sizeof(WCHAR)] = UNICODE_NULL;
308     }
309     else
310     {
311         *AppName = ExeNameBuffer;
312     }
313 }
314 
315 USHORT
316 GetCurrentExeName(OUT PWCHAR ExeName,
317                   IN USHORT BufferSize)
318 {
319     USHORT ExeLength;
320 
321     if (ExeNameInitialized)
322     {
323         RtlEnterCriticalSection(&ExeNameLock);
324 
325         if (BufferSize > ExeNameLength * sizeof(WCHAR))
326             BufferSize = ExeNameLength * sizeof(WCHAR);
327 
328         RtlCopyMemory(ExeName, ExeNameBuffer, BufferSize);
329 
330         RtlLeaveCriticalSection(&ExeNameLock);
331         ExeLength = BufferSize;
332     }
333     else
334     {
335         *ExeName  = UNICODE_NULL;
336         ExeLength = 0;
337     }
338 
339     return ExeLength;
340 }
341 
342 /* FUNCTIONS ******************************************************************/
343 
344 LPCWSTR
345 IntCheckForConsoleFileName(IN LPCWSTR pszName,
346                            IN DWORD dwDesiredAccess)
347 {
348     LPCWSTR ConsoleName = pszName;
349     ULONG DeviceNameInfo;
350 
351     /*
352      * Check whether we deal with a DOS device, and if so,
353      * strip the path till the file name.
354      * Therefore, things like \\.\CON or C:\some_path\CONIN$
355      * are transformed into CON or CONIN$, for example.
356      */
357     DeviceNameInfo = RtlIsDosDeviceName_U(pszName);
358     if (DeviceNameInfo != 0)
359     {
360         ConsoleName = (LPCWSTR)((ULONG_PTR)ConsoleName + ((DeviceNameInfo >> 16) & 0xFFFF));
361     }
362 
363     /* Return a standard console "file" name according to what we passed in parameters */
364     if (_wcsicmp(ConsoleName, BaseConInputFileName) == 0)
365     {
366         return BaseConInputFileName;
367     }
368     else if (_wcsicmp(ConsoleName, BaseConOutputFileName) == 0)
369     {
370         return BaseConOutputFileName;
371     }
372     else if (_wcsicmp(ConsoleName, BaseConFileName) == 0)
373     {
374         if ((dwDesiredAccess & (GENERIC_READ | GENERIC_WRITE)) == GENERIC_READ)
375         {
376             return BaseConInputFileName;
377         }
378         else if ((dwDesiredAccess & (GENERIC_READ | GENERIC_WRITE)) == GENERIC_WRITE)
379         {
380             return BaseConOutputFileName;
381         }
382     }
383 
384     /* If we are there, that means that either the file name or the desired access are wrong */
385     return NULL;
386 }
387 
388 
389 /*
390  * @implemented (Undocumented)
391  * @note See http://undoc.airesoft.co.uk/kernel32.dll/ConsoleMenuControl.php
392  */
393 HMENU
394 WINAPI
395 DECLSPEC_HOTPATCH
396 ConsoleMenuControl(HANDLE hConsoleOutput,
397                    DWORD dwCmdIdLow,
398                    DWORD dwCmdIdHigh)
399 {
400     CONSOLE_API_MESSAGE ApiMessage;
401     PCONSOLE_MENUCONTROL MenuControlRequest = &ApiMessage.Data.MenuControlRequest;
402 
403     MenuControlRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
404     MenuControlRequest->OutputHandle  = hConsoleOutput;
405     MenuControlRequest->CmdIdLow      = dwCmdIdLow;
406     MenuControlRequest->CmdIdHigh     = dwCmdIdHigh;
407     MenuControlRequest->MenuHandle    = NULL;
408 
409     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
410                         NULL,
411                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepMenuControl),
412                         sizeof(*MenuControlRequest));
413 
414     return MenuControlRequest->MenuHandle;
415 }
416 
417 
418 /*
419  * @implemented
420  */
421 HANDLE
422 WINAPI
423 DECLSPEC_HOTPATCH
424 DuplicateConsoleHandle(HANDLE hConsole,
425                        DWORD dwDesiredAccess,
426                        BOOL bInheritHandle,
427                        DWORD dwOptions)
428 {
429     CONSOLE_API_MESSAGE ApiMessage;
430     PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest = &ApiMessage.Data.DuplicateHandleRequest;
431 
432     if ( (dwOptions & ~(DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) ||
433          (!(dwOptions & DUPLICATE_SAME_ACCESS) &&
434            (dwDesiredAccess & ~(GENERIC_READ | GENERIC_WRITE))) )
435     {
436         SetLastError(ERROR_INVALID_PARAMETER);
437         return INVALID_HANDLE_VALUE;
438     }
439 
440     DuplicateHandleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
441     DuplicateHandleRequest->SourceHandle  = hConsole;
442     DuplicateHandleRequest->DesiredAccess = dwDesiredAccess;
443     DuplicateHandleRequest->InheritHandle = bInheritHandle;
444     DuplicateHandleRequest->Options       = dwOptions;
445 
446     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
447                         NULL,
448                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepDuplicateHandle),
449                         sizeof(*DuplicateHandleRequest));
450     if (!NT_SUCCESS(ApiMessage.Status))
451     {
452         BaseSetLastNTError(ApiMessage.Status);
453         return INVALID_HANDLE_VALUE;
454     }
455 
456     return DuplicateHandleRequest->TargetHandle;
457 }
458 
459 
460 /*
461  * @implemented
462  */
463 BOOL
464 WINAPI
465 GetConsoleHandleInformation(IN HANDLE hHandle,
466                             OUT LPDWORD lpdwFlags)
467 {
468     CONSOLE_API_MESSAGE ApiMessage;
469     PCONSOLE_GETHANDLEINFO GetHandleInfoRequest = &ApiMessage.Data.GetHandleInfoRequest;
470 
471     GetHandleInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
472     GetHandleInfoRequest->Handle        = hHandle;
473 
474     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
475                         NULL,
476                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetHandleInformation),
477                         sizeof(*GetHandleInfoRequest));
478     if (!NT_SUCCESS(ApiMessage.Status))
479     {
480         BaseSetLastNTError(ApiMessage.Status);
481         return FALSE;
482     }
483 
484     *lpdwFlags = GetHandleInfoRequest->Flags;
485 
486     return TRUE;
487 }
488 
489 
490 /*
491  * @implemented
492  */
493 BOOL
494 WINAPI
495 SetConsoleHandleInformation(IN HANDLE hHandle,
496                             IN DWORD dwMask,
497                             IN DWORD dwFlags)
498 {
499     CONSOLE_API_MESSAGE ApiMessage;
500     PCONSOLE_SETHANDLEINFO SetHandleInfoRequest = &ApiMessage.Data.SetHandleInfoRequest;
501 
502     SetHandleInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
503     SetHandleInfoRequest->Handle        = hHandle;
504     SetHandleInfoRequest->Mask          = dwMask;
505     SetHandleInfoRequest->Flags         = dwFlags;
506 
507     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
508                         NULL,
509                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetHandleInformation),
510                         sizeof(*SetHandleInfoRequest));
511     if (!NT_SUCCESS(ApiMessage.Status))
512     {
513         BaseSetLastNTError(ApiMessage.Status);
514         return FALSE;
515     }
516 
517     return TRUE;
518 }
519 
520 
521 /*
522  * @implemented
523  */
524 BOOL
525 WINAPI
526 GetConsoleDisplayMode(LPDWORD lpModeFlags)
527 {
528     CONSOLE_API_MESSAGE ApiMessage;
529     PCONSOLE_GETDISPLAYMODE GetDisplayModeRequest = &ApiMessage.Data.GetDisplayModeRequest;
530 
531     if (lpModeFlags == NULL)
532     {
533         SetLastError(ERROR_INVALID_PARAMETER);
534         return FALSE;
535     }
536 
537     GetDisplayModeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
538 
539     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
540                         NULL,
541                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetDisplayMode),
542                         sizeof(*GetDisplayModeRequest));
543     if (!NT_SUCCESS(ApiMessage.Status))
544     {
545         BaseSetLastNTError(ApiMessage.Status);
546         return FALSE;
547     }
548 
549     *lpModeFlags = GetDisplayModeRequest->DisplayMode; // ModeFlags
550 
551     return TRUE;
552 }
553 
554 
555 /*
556  * @implemented (Undocumented)
557  * @note See http://cboard.cprogramming.com/windows-programming/102187-console-font-size.html
558  */
559 DWORD
560 WINAPI
561 GetConsoleFontInfo(IN HANDLE hConsoleOutput,
562                    IN BOOL bMaximumWindow,
563                    IN DWORD nFontCount,
564                    OUT PCONSOLE_FONT_INFO lpConsoleFontInfo)
565 {
566     CONSOLE_API_MESSAGE ApiMessage;
567     PCONSOLE_GETFONTINFO GetFontInfoRequest = &ApiMessage.Data.GetFontInfoRequest;
568     PCSR_CAPTURE_BUFFER CaptureBuffer;
569 
570     GetFontInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
571     GetFontInfoRequest->OutputHandle  = hConsoleOutput;
572     GetFontInfoRequest->MaximumWindow = bMaximumWindow;
573     GetFontInfoRequest->NumFonts      = nFontCount;
574 
575     CaptureBuffer = CsrAllocateCaptureBuffer(1, nFontCount * sizeof(CONSOLE_FONT_INFO));
576     if (CaptureBuffer == NULL)
577     {
578         DPRINT1("CsrAllocateCaptureBuffer failed!\n");
579         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
580         return 0;
581     }
582 
583     CsrAllocateMessagePointer(CaptureBuffer,
584                               nFontCount * sizeof(CONSOLE_FONT_INFO),
585                               (PVOID*)&GetFontInfoRequest->FontInfo);
586 
587     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
588                         CaptureBuffer,
589                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetFontInfo),
590                         sizeof(*GetFontInfoRequest));
591     if (!NT_SUCCESS(ApiMessage.Status))
592     {
593         BaseSetLastNTError(ApiMessage.Status);
594     }
595     else
596     {
597         RtlCopyMemory(lpConsoleFontInfo,
598                       GetFontInfoRequest->FontInfo,
599                       GetFontInfoRequest->NumFonts * sizeof(CONSOLE_FONT_INFO));
600     }
601 
602     CsrFreeCaptureBuffer(CaptureBuffer);
603     return GetFontInfoRequest->NumFonts;
604 }
605 
606 
607 /*
608  * @implemented
609  */
610 COORD
611 WINAPI
612 DECLSPEC_HOTPATCH
613 GetConsoleFontSize(IN HANDLE hConsoleOutput,
614                    IN DWORD nFont)
615 {
616     CONSOLE_API_MESSAGE ApiMessage;
617     PCONSOLE_GETFONTSIZE GetFontSizeRequest = &ApiMessage.Data.GetFontSizeRequest;
618     COORD Empty = {0, 0};
619 
620     GetFontSizeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
621     GetFontSizeRequest->OutputHandle  = hConsoleOutput;
622     GetFontSizeRequest->FontIndex     = nFont;
623 
624     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
625                         NULL,
626                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetFontSize),
627                         sizeof(*GetFontSizeRequest));
628     if (!NT_SUCCESS(ApiMessage.Status))
629     {
630         BaseSetLastNTError(ApiMessage.Status);
631         return Empty;
632     }
633 
634     return GetFontSizeRequest->FontSize;
635 }
636 
637 
638 /*
639  * @implemented (Undocumented)
640  */
641 BOOL
642 WINAPI
643 GetConsoleHardwareState(HANDLE hConsoleOutput,
644                         PDWORD Flags,
645                         PDWORD State)
646 {
647     CONSOLE_API_MESSAGE ApiMessage;
648     PCONSOLE_GETSETHWSTATE HardwareStateRequest = &ApiMessage.Data.HardwareStateRequest;
649 
650     DPRINT1("GetConsoleHardwareState(%lu, 0x%p) UNIMPLEMENTED!\n", Flags, State);
651 
652     if (Flags == NULL || State == NULL)
653     {
654         SetLastError(ERROR_INVALID_PARAMETER);
655         return FALSE;
656     }
657 
658     HardwareStateRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
659     HardwareStateRequest->OutputHandle  = hConsoleOutput;
660 
661     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
662                         NULL,
663                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetHardwareState),
664                         sizeof(*HardwareStateRequest));
665     if (!NT_SUCCESS(ApiMessage.Status))
666     {
667         BaseSetLastNTError(ApiMessage.Status);
668         return FALSE;
669     }
670 
671     *Flags = HardwareStateRequest->Flags;
672     *State = HardwareStateRequest->State;
673 
674     return TRUE;
675 }
676 
677 
678 /*
679  * @implemented (Undocumented)
680  */
681 HANDLE
682 WINAPI
683 GetConsoleInputWaitHandle(VOID)
684 {
685     return InputWaitHandle;
686 }
687 
688 
689 /*
690  * @implemented
691  */
692 BOOL
693 WINAPI
694 GetCurrentConsoleFont(IN HANDLE hConsoleOutput,
695                       IN BOOL bMaximumWindow,
696                       OUT PCONSOLE_FONT_INFO lpConsoleCurrentFont)
697 {
698     CONSOLE_API_MESSAGE ApiMessage;
699     PCONSOLE_GETCURRENTFONT GetCurrentFontRequest = &ApiMessage.Data.GetCurrentFontRequest;
700 
701     GetCurrentFontRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
702     GetCurrentFontRequest->OutputHandle  = hConsoleOutput;
703     GetCurrentFontRequest->MaximumWindow = bMaximumWindow;
704 
705     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
706                         NULL,
707                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCurrentFont),
708                         sizeof(*GetCurrentFontRequest));
709     if (!NT_SUCCESS(ApiMessage.Status))
710     {
711         BaseSetLastNTError(ApiMessage.Status);
712         return FALSE;
713     }
714 
715     lpConsoleCurrentFont->dwFontSize = GetCurrentFontRequest->FontSize;
716     lpConsoleCurrentFont->nFont      = GetCurrentFontRequest->FontIndex;
717 
718     return TRUE;
719 }
720 
721 
722 /*
723  * @implemented (Undocumented)
724  * @note See http://cboard.cprogramming.com/windows-programming/102187-console-font-size.html
725  */
726 DWORD
727 WINAPI
728 DECLSPEC_HOTPATCH
729 GetNumberOfConsoleFonts(VOID)
730 {
731     CONSOLE_API_MESSAGE ApiMessage;
732     PCONSOLE_GETNUMFONTS GetNumFontsRequest = &ApiMessage.Data.GetNumFontsRequest;
733 
734     GetNumFontsRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
735 
736     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
737                         NULL,
738                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetNumberOfFonts),
739                         sizeof(*GetNumFontsRequest));
740     if (!NT_SUCCESS(ApiMessage.Status))
741     {
742         BaseSetLastNTError(ApiMessage.Status);
743         return 0;
744     }
745 
746     return GetNumFontsRequest->NumFonts;
747 }
748 
749 
750 /*
751  * @implemented (Undocumented)
752  * @note See http://blog.airesoft.co.uk/2012/10/things-ms-can-do-that-they-dont-tell-you-about-console-graphics/
753  */
754 BOOL
755 WINAPI
756 InvalidateConsoleDIBits(IN HANDLE hConsoleOutput,
757                         IN PSMALL_RECT lpRect)
758 {
759     CONSOLE_API_MESSAGE ApiMessage;
760     PCONSOLE_INVALIDATEDIBITS InvalidateDIBitsRequest = &ApiMessage.Data.InvalidateDIBitsRequest;
761 
762     if (lpRect == NULL)
763     {
764         SetLastError(ERROR_INVALID_PARAMETER);
765         return FALSE;
766     }
767 
768     InvalidateDIBitsRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
769     InvalidateDIBitsRequest->OutputHandle  = hConsoleOutput;
770     InvalidateDIBitsRequest->Region        = *lpRect;
771 
772     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
773                         NULL,
774                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepInvalidateBitMapRect),
775                         sizeof(*InvalidateDIBitsRequest));
776     if (!NT_SUCCESS(ApiMessage.Status))
777     {
778         BaseSetLastNTError(ApiMessage.Status);
779         return FALSE;
780     }
781 
782     return TRUE;
783 }
784 
785 
786 /*
787  * @implemented (Undocumented)
788  */
789 HANDLE
790 WINAPI
791 OpenConsoleW(LPCWSTR wsName,
792              DWORD dwDesiredAccess,
793              BOOL bInheritHandle,
794              DWORD dwShareMode)
795 {
796     CONSOLE_API_MESSAGE ApiMessage;
797     PCONSOLE_OPENCONSOLE OpenConsoleRequest = &ApiMessage.Data.OpenConsoleRequest;
798     CONSOLE_HANDLE_TYPE HandleType;
799 
800     if (wsName && (_wcsicmp(wsName, BaseConInputFileName) == 0))
801     {
802         HandleType = HANDLE_INPUT;
803     }
804     else if (wsName && (_wcsicmp(wsName, BaseConOutputFileName) == 0))
805     {
806         HandleType = HANDLE_OUTPUT;
807     }
808     else
809     {
810         SetLastError(ERROR_INVALID_PARAMETER);
811         return INVALID_HANDLE_VALUE;
812     }
813 
814     if ( (dwDesiredAccess & ~(GENERIC_READ | GENERIC_WRITE)) ||
815          (dwShareMode & ~(FILE_SHARE_READ | FILE_SHARE_WRITE)) )
816     {
817         SetLastError(ERROR_INVALID_PARAMETER);
818         return INVALID_HANDLE_VALUE;
819     }
820 
821     OpenConsoleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
822     OpenConsoleRequest->HandleType    = HandleType;
823     OpenConsoleRequest->DesiredAccess = dwDesiredAccess;
824     OpenConsoleRequest->InheritHandle = bInheritHandle;
825     OpenConsoleRequest->ShareMode     = dwShareMode;
826 
827     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
828                         NULL,
829                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepOpenConsole),
830                         sizeof(*OpenConsoleRequest));
831     if (!NT_SUCCESS(ApiMessage.Status))
832     {
833         BaseSetLastNTError(ApiMessage.Status);
834         return INVALID_HANDLE_VALUE;
835     }
836 
837     return OpenConsoleRequest->Handle;
838 }
839 
840 
841 /*
842  * @implemented (Undocumented)
843  * @note See http://undoc.airesoft.co.uk/kernel32.dll/SetConsoleCursor.php
844  */
845 BOOL
846 WINAPI
847 DECLSPEC_HOTPATCH
848 SetConsoleCursor(HANDLE  hConsoleOutput,
849                  HCURSOR hCursor)
850 {
851     CONSOLE_API_MESSAGE ApiMessage;
852     PCONSOLE_SETCURSOR SetCursorRequest = &ApiMessage.Data.SetCursorRequest;
853 
854     SetCursorRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
855     SetCursorRequest->OutputHandle  = hConsoleOutput;
856     SetCursorRequest->CursorHandle  = hCursor;
857 
858     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
859                         NULL,
860                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCursor),
861                         sizeof(*SetCursorRequest));
862     if (!NT_SUCCESS(ApiMessage.Status))
863     {
864         BaseSetLastNTError(ApiMessage.Status);
865         return FALSE;
866     }
867 
868     return TRUE;
869 }
870 
871 
872 /*
873  * @implemented
874  */
875 BOOL
876 WINAPI
877 SetConsoleDisplayMode(HANDLE hConsoleOutput,
878                       DWORD  dwFlags, // dwModeFlags
879                       PCOORD lpNewScreenBufferDimensions)
880 {
881     CONSOLE_API_MESSAGE ApiMessage;
882     PCONSOLE_SETDISPLAYMODE SetDisplayModeRequest = &ApiMessage.Data.SetDisplayModeRequest;
883 
884     SetDisplayModeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
885     SetDisplayModeRequest->OutputHandle  = hConsoleOutput;
886     SetDisplayModeRequest->DisplayMode   = dwFlags; // ModeFlags ; dwModeFlags
887     SetDisplayModeRequest->NewSBDim.X    = 0;
888     SetDisplayModeRequest->NewSBDim.Y    = 0;
889     /* SetDisplayModeRequest->EventHandle; */
890 
891     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
892                         NULL,
893                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetDisplayMode),
894                         sizeof(*SetDisplayModeRequest));
895     if (!NT_SUCCESS(ApiMessage.Status))
896     {
897         BaseSetLastNTError(ApiMessage.Status);
898         return FALSE;
899     }
900 
901     if (lpNewScreenBufferDimensions)
902         *lpNewScreenBufferDimensions = SetDisplayModeRequest->NewSBDim;
903 
904     return TRUE;
905 }
906 
907 
908 /*
909  * @implemented (Undocumented)
910  * @note See http://cboard.cprogramming.com/windows-programming/102187-console-font-size.html
911  */
912 BOOL
913 WINAPI
914 DECLSPEC_HOTPATCH
915 SetConsoleFont(IN HANDLE hConsoleOutput,
916                IN DWORD nFont)
917 {
918     CONSOLE_API_MESSAGE ApiMessage;
919     PCONSOLE_SETFONT SetFontRequest = &ApiMessage.Data.SetFontRequest;
920 
921     SetFontRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
922     SetFontRequest->OutputHandle  = hConsoleOutput;
923     SetFontRequest->FontIndex     = nFont;
924 
925     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
926                         NULL,
927                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetFont),
928                         sizeof(*SetFontRequest));
929     if (!NT_SUCCESS(ApiMessage.Status))
930     {
931         BaseSetLastNTError(ApiMessage.Status);
932         return FALSE;
933     }
934 
935     return TRUE;
936 }
937 
938 
939 /*
940  * @implemented (Undocumented)
941  */
942 BOOL
943 WINAPI
944 SetConsoleHardwareState(HANDLE hConsoleOutput,
945                         DWORD Flags,
946                         DWORD State)
947 {
948     CONSOLE_API_MESSAGE ApiMessage;
949     PCONSOLE_GETSETHWSTATE HardwareStateRequest = &ApiMessage.Data.HardwareStateRequest;
950 
951     DPRINT1("SetConsoleHardwareState(%lu, %lu) UNIMPLEMENTED!\n", Flags, State);
952 
953     HardwareStateRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
954     HardwareStateRequest->OutputHandle  = hConsoleOutput;
955     HardwareStateRequest->Flags         = Flags;
956     HardwareStateRequest->State         = State;
957 
958     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
959                         NULL,
960                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetHardwareState),
961                         sizeof(*HardwareStateRequest));
962     if (!NT_SUCCESS(ApiMessage.Status))
963     {
964         BaseSetLastNTError(ApiMessage.Status);
965         return FALSE;
966     }
967 
968     return TRUE;
969 }
970 
971 
972 /*
973  * @unimplemented (Undocumented)
974  */
975 BOOL
976 WINAPI
977 DECLSPEC_HOTPATCH
978 SetConsoleKeyShortcuts(DWORD Unknown0,
979                        DWORD Unknown1,
980                        DWORD Unknown2,
981                        DWORD Unknown3)
982 {
983     DPRINT1("SetConsoleKeyShortcuts(0x%x, 0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2, Unknown3);
984     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
985     return FALSE;
986 }
987 
988 
989 /*
990  * @implemented (Undocumented)
991  * @note See http://undoc.airesoft.co.uk/kernel32.dll/SetConsoleMaximumWindowSize.php
992  *       Does nothing, returns TRUE only. Checked on Windows Server 2003.
993  */
994 BOOL
995 WINAPI
996 SetConsoleMaximumWindowSize(HANDLE hConsoleOutput,
997                             COORD dwMaximumSize)
998 {
999     DPRINT1("SetConsoleMaximumWindowSize(0x%p, {%d, %d}) does nothing\n",
1000             hConsoleOutput, dwMaximumSize.X, dwMaximumSize.Y);
1001     return TRUE;
1002 }
1003 
1004 
1005 /*
1006  * @implemented (Undocumented)
1007  */
1008 BOOL
1009 WINAPI
1010 DECLSPEC_HOTPATCH
1011 SetConsoleMenuClose(BOOL bEnable)
1012 {
1013     CONSOLE_API_MESSAGE ApiMessage;
1014     PCONSOLE_SETMENUCLOSE SetMenuCloseRequest = &ApiMessage.Data.SetMenuCloseRequest;
1015 
1016     SetMenuCloseRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1017     SetMenuCloseRequest->Enable        = bEnable;
1018 
1019     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1020                         NULL,
1021                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetMenuClose),
1022                         sizeof(*SetMenuCloseRequest));
1023     if (!NT_SUCCESS(ApiMessage.Status))
1024     {
1025         BaseSetLastNTError(ApiMessage.Status);
1026         return FALSE;
1027     }
1028 
1029     return TRUE;
1030 }
1031 
1032 
1033 /*
1034  * @implemented (Undocumented)
1035  * @note See http://comments.gmane.org/gmane.comp.lang.harbour.devel/27844
1036  *       Usage example: https://github.com/harbour/core/commit/d79a1b7b812cbde6ddf718ebfd6939a24f633e52
1037  */
1038 BOOL
1039 WINAPI
1040 DECLSPEC_HOTPATCH
1041 SetConsolePalette(HANDLE hConsoleOutput,
1042                   HPALETTE hPalette,
1043                   UINT dwUsage)
1044 {
1045     CONSOLE_API_MESSAGE ApiMessage;
1046     PCONSOLE_SETPALETTE SetPaletteRequest = &ApiMessage.Data.SetPaletteRequest;
1047 
1048     SetPaletteRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1049     SetPaletteRequest->OutputHandle  = hConsoleOutput;
1050     SetPaletteRequest->PaletteHandle = hPalette;
1051     SetPaletteRequest->Usage         = dwUsage;
1052 
1053     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1054                         NULL,
1055                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetPalette),
1056                         sizeof(*SetPaletteRequest));
1057     if (!NT_SUCCESS(ApiMessage.Status))
1058     {
1059         BaseSetLastNTError(ApiMessage.Status);
1060         return FALSE;
1061     }
1062 
1063     return TRUE;
1064 }
1065 
1066 /*
1067  * @implemented (Undocumented)
1068  * @note See http://undoc.airesoft.co.uk/kernel32.dll/ShowConsoleCursor.php
1069  */
1070 INT
1071 WINAPI
1072 DECLSPEC_HOTPATCH
1073 ShowConsoleCursor(HANDLE hConsoleOutput,
1074                   BOOL bShow)
1075 {
1076     CONSOLE_API_MESSAGE ApiMessage;
1077     PCONSOLE_SHOWCURSOR ShowCursorRequest = &ApiMessage.Data.ShowCursorRequest;
1078 
1079     ShowCursorRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1080     ShowCursorRequest->OutputHandle  = hConsoleOutput;
1081     ShowCursorRequest->Show          = bShow;
1082     ShowCursorRequest->RefCount      = 0;
1083 
1084     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1085                         NULL,
1086                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepShowCursor),
1087                         sizeof(*ShowCursorRequest));
1088 
1089     return ShowCursorRequest->RefCount;
1090 }
1091 
1092 
1093 /*
1094  * FUNCTION: Checks whether the given handle is a valid console handle.
1095  *
1096  * ARGUMENTS:
1097  *      hIoHandle - Handle to be checked.
1098  *
1099  * RETURNS:
1100  *      TRUE : Handle is a valid console handle.
1101  *      FALSE: Handle is not a valid console handle.
1102  *
1103  * STATUS: Officially undocumented
1104  *
1105  * @implemented
1106  */
1107 BOOL
1108 WINAPI
1109 DECLSPEC_HOTPATCH
1110 VerifyConsoleIoHandle(HANDLE hIoHandle)
1111 {
1112     CONSOLE_API_MESSAGE ApiMessage;
1113     PCONSOLE_VERIFYHANDLE VerifyHandleRequest = &ApiMessage.Data.VerifyHandleRequest;
1114 
1115     VerifyHandleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1116     VerifyHandleRequest->Handle        = hIoHandle;
1117     VerifyHandleRequest->IsValid       = FALSE;
1118 
1119     /* If the process is not attached to a console, return invalid handle */
1120     if (VerifyHandleRequest->ConsoleHandle == NULL) return FALSE;
1121 
1122     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1123                         NULL,
1124                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepVerifyIoHandle),
1125                         sizeof(*VerifyHandleRequest));
1126     if (!NT_SUCCESS(ApiMessage.Status))
1127     {
1128         BaseSetLastNTError(ApiMessage.Status);
1129         return FALSE;
1130     }
1131 
1132     return VerifyHandleRequest->IsValid;
1133 }
1134 
1135 
1136 /*
1137  * @implemented (Undocumented)
1138  */
1139 BOOL
1140 WINAPI
1141 DECLSPEC_HOTPATCH
1142 CloseConsoleHandle(HANDLE hHandle)
1143 {
1144     CONSOLE_API_MESSAGE ApiMessage;
1145     PCONSOLE_CLOSEHANDLE CloseHandleRequest = &ApiMessage.Data.CloseHandleRequest;
1146 
1147     CloseHandleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1148     CloseHandleRequest->Handle        = hHandle;
1149 
1150     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1151                         NULL,
1152                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepCloseHandle),
1153                         sizeof(*CloseHandleRequest));
1154     if (!NT_SUCCESS(ApiMessage.Status))
1155     {
1156         BaseSetLastNTError(ApiMessage.Status);
1157         return FALSE;
1158     }
1159 
1160     return TRUE;
1161 }
1162 
1163 
1164 /*
1165  * @implemented
1166  */
1167 HANDLE
1168 WINAPI
1169 DECLSPEC_HOTPATCH
1170 GetStdHandle(DWORD nStdHandle)
1171 /*
1172  * FUNCTION: Get a handle for the standard input, standard output
1173  * and a standard error device.
1174  *
1175  * ARGUMENTS:
1176  *       nStdHandle - Specifies the device for which to return the handle.
1177  *
1178  * RETURNS: If the function succeeds, the return value is the handle
1179  * of the specified device. Otherwise the value is INVALID_HANDLE_VALUE.
1180  */
1181 {
1182     PRTL_USER_PROCESS_PARAMETERS Ppb = NtCurrentPeb()->ProcessParameters;
1183     HANDLE Handle = INVALID_HANDLE_VALUE;
1184 
1185     switch (nStdHandle)
1186     {
1187         case STD_INPUT_HANDLE:
1188             Handle = Ppb->StandardInput;
1189             break;
1190 
1191         case STD_OUTPUT_HANDLE:
1192             Handle = Ppb->StandardOutput;
1193             break;
1194 
1195         case STD_ERROR_HANDLE:
1196             Handle = Ppb->StandardError;
1197             break;
1198     }
1199 
1200     /* If the returned handle is invalid, set last error */
1201     if (Handle == INVALID_HANDLE_VALUE) SetLastError(ERROR_INVALID_HANDLE);
1202 
1203     return Handle;
1204 }
1205 
1206 
1207 /*
1208  * @implemented
1209  */
1210 BOOL
1211 WINAPI
1212 DECLSPEC_HOTPATCH
1213 SetStdHandle(DWORD  nStdHandle,
1214              HANDLE hHandle)
1215 /*
1216  * FUNCTION: Set the handle for the standard input, standard output or
1217  * the standard error device.
1218  *
1219  * ARGUMENTS:
1220  *        nStdHandle - Specifies the handle to be set.
1221  *        hHandle - The handle to set.
1222  *
1223  * RETURNS: TRUE if the function succeeds, FALSE otherwise.
1224  */
1225 {
1226     PRTL_USER_PROCESS_PARAMETERS Ppb = NtCurrentPeb()->ProcessParameters;
1227 
1228     /* No need to check if hHandle == INVALID_HANDLE_VALUE */
1229 
1230     switch (nStdHandle)
1231     {
1232         case STD_INPUT_HANDLE:
1233             Ppb->StandardInput = hHandle;
1234             return TRUE;
1235 
1236         case STD_OUTPUT_HANDLE:
1237             Ppb->StandardOutput = hHandle;
1238             return TRUE;
1239 
1240         case STD_ERROR_HANDLE:
1241             Ppb->StandardError = hHandle;
1242             return TRUE;
1243     }
1244 
1245     /* nStdHandle was invalid, bail out */
1246     SetLastError(ERROR_INVALID_HANDLE);
1247     return FALSE;
1248 }
1249 
1250 
1251 /*
1252  * @implemented
1253  */
1254 static BOOL
1255 IntAllocConsole(LPWSTR Title,
1256                 DWORD TitleLength,
1257                 LPWSTR Desktop,
1258                 DWORD DesktopLength,
1259                 LPWSTR CurDir,
1260                 DWORD CurDirLength,
1261                 LPWSTR AppName,
1262                 DWORD AppNameLength,
1263                 LPTHREAD_START_ROUTINE CtrlRoutine,
1264                 LPTHREAD_START_ROUTINE PropRoutine,
1265                 PCONSOLE_START_INFO ConsoleStartInfo)
1266 {
1267     BOOL Success = TRUE;
1268     NTSTATUS Status;
1269 
1270     CONSOLE_API_MESSAGE ApiMessage;
1271     PCONSOLE_ALLOCCONSOLE AllocConsoleRequest = &ApiMessage.Data.AllocConsoleRequest;
1272     PCSR_CAPTURE_BUFFER CaptureBuffer;
1273 
1274     AllocConsoleRequest->CtrlRoutine = CtrlRoutine;
1275     AllocConsoleRequest->PropRoutine = PropRoutine;
1276 
1277     CaptureBuffer = CsrAllocateCaptureBuffer(5, TitleLength   +
1278                                                 DesktopLength +
1279                                                 CurDirLength  +
1280                                                 AppNameLength +
1281                                                 sizeof(CONSOLE_START_INFO));
1282     if (CaptureBuffer == NULL)
1283     {
1284         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1285         Success = FALSE;
1286         goto Quit;
1287     }
1288 
1289     CsrCaptureMessageBuffer(CaptureBuffer,
1290                             ConsoleStartInfo,
1291                             sizeof(CONSOLE_START_INFO),
1292                             (PVOID*)&AllocConsoleRequest->ConsoleStartInfo);
1293 
1294     AllocConsoleRequest->TitleLength = TitleLength;
1295     CsrCaptureMessageBuffer(CaptureBuffer,
1296                             Title,
1297                             TitleLength,
1298                             (PVOID*)&AllocConsoleRequest->ConsoleTitle);
1299 
1300     AllocConsoleRequest->DesktopLength = DesktopLength;
1301     CsrCaptureMessageBuffer(CaptureBuffer,
1302                             Desktop,
1303                             DesktopLength,
1304                             (PVOID*)&AllocConsoleRequest->Desktop);
1305 
1306     AllocConsoleRequest->CurDirLength = CurDirLength;
1307     CsrCaptureMessageBuffer(CaptureBuffer,
1308                             CurDir,
1309                             CurDirLength,
1310                             (PVOID*)&AllocConsoleRequest->CurDir);
1311 
1312     AllocConsoleRequest->AppNameLength = AppNameLength;
1313     CsrCaptureMessageBuffer(CaptureBuffer,
1314                             AppName,
1315                             AppNameLength,
1316                             (PVOID*)&AllocConsoleRequest->AppName);
1317 
1318     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1319                         CaptureBuffer,
1320                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAlloc),
1321                         sizeof(*AllocConsoleRequest));
1322     if (!NT_SUCCESS(ApiMessage.Status))
1323     {
1324         BaseSetLastNTError(ApiMessage.Status);
1325         Success = FALSE;
1326         goto Quit;
1327     }
1328 
1329     // Is AllocConsoleRequest->ConsoleStartInfo->InitEvents aligned on handle boundary ????
1330     Status = NtWaitForMultipleObjects(MAX_INIT_EVENTS,
1331                                       AllocConsoleRequest->ConsoleStartInfo->InitEvents,
1332                                       WaitAny, FALSE, NULL);
1333     if (!NT_SUCCESS(Status))
1334     {
1335         BaseSetLastNTError(Status);
1336         Success = FALSE;
1337         goto Quit;
1338     }
1339 
1340     NtClose(AllocConsoleRequest->ConsoleStartInfo->InitEvents[INIT_SUCCESS]);
1341     NtClose(AllocConsoleRequest->ConsoleStartInfo->InitEvents[INIT_FAILURE]);
1342     if (Status != INIT_SUCCESS)
1343     {
1344         NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
1345         Success = FALSE;
1346     }
1347     else
1348     {
1349         RtlCopyMemory(ConsoleStartInfo,
1350                       AllocConsoleRequest->ConsoleStartInfo,
1351                       sizeof(CONSOLE_START_INFO));
1352         Success = TRUE;
1353     }
1354 
1355 Quit:
1356     if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
1357     return Success;
1358 }
1359 
1360 BOOL
1361 WINAPI
1362 DECLSPEC_HOTPATCH
1363 AllocConsole(VOID)
1364 {
1365     BOOL Success;
1366     CONSOLE_START_INFO ConsoleStartInfo;
1367 
1368     PWCHAR ConsoleTitle;
1369     PWCHAR Desktop;
1370     PWCHAR AppName;
1371     PWCHAR CurDir;
1372 
1373     ULONG TitleLength   = (MAX_PATH + 1) * sizeof(WCHAR);
1374     ULONG DesktopLength = (MAX_PATH + 1) * sizeof(WCHAR);
1375     ULONG AppNameLength = 128 * sizeof(WCHAR);
1376     ULONG CurDirLength  = (MAX_PATH + 1) * sizeof(WCHAR);
1377 
1378     LCID lcid;
1379 
1380     RtlEnterCriticalSection(&ConsoleLock);
1381 
1382     if (NtCurrentPeb()->ProcessParameters->ConsoleHandle)
1383     {
1384         DPRINT1("AllocConsole: Allocating a console to a process already having one\n");
1385         SetLastError(ERROR_ACCESS_DENIED);
1386         Success = FALSE;
1387         goto Quit;
1388     }
1389 
1390     /* Set up the console properties */
1391     SetUpConsoleInfo(FALSE,
1392                      &TitleLength,
1393                      &ConsoleTitle,
1394                      &DesktopLength,
1395                      &Desktop,
1396                      &ConsoleStartInfo);
1397     DPRINT("ConsoleTitle = '%S' - Desktop = '%S'\n",
1398            ConsoleTitle, Desktop);
1399 
1400     /* Initialize the Input EXE name */
1401     InitExeName();
1402     SetUpAppName(FALSE,
1403                  &CurDirLength,
1404                  &CurDir,
1405                  &AppNameLength,
1406                  &AppName);
1407     DPRINT("CurDir = '%S' - AppName = '%S'\n",
1408            CurDir, AppName);
1409 
1410     Success = IntAllocConsole(ConsoleTitle,
1411                               TitleLength,
1412                               Desktop,
1413                               DesktopLength,
1414                               CurDir,
1415                               CurDirLength,
1416                               AppName,
1417                               AppNameLength,
1418                               ConsoleControlDispatcher,
1419                               PropDialogHandler,
1420                               &ConsoleStartInfo);
1421     if (Success)
1422     {
1423         /* Set up the handles */
1424         SetUpHandles(&ConsoleStartInfo);
1425         InputWaitHandle = ConsoleStartInfo.InputWaitHandle;
1426 
1427         /* Initialize Console Ctrl Handling */
1428         InitializeCtrlHandling();
1429 
1430         /* Sets the current console locale for this thread */
1431         SetTEBLangID(lcid);
1432     }
1433 
1434 Quit:
1435     RtlLeaveCriticalSection(&ConsoleLock);
1436     return Success;
1437 }
1438 
1439 
1440 /*
1441  * @implemented
1442  */
1443 BOOL
1444 WINAPI
1445 DECLSPEC_HOTPATCH
1446 FreeConsole(VOID)
1447 {
1448     BOOL Success = TRUE;
1449     CONSOLE_API_MESSAGE ApiMessage;
1450     PCONSOLE_FREECONSOLE FreeConsoleRequest = &ApiMessage.Data.FreeConsoleRequest;
1451     HANDLE ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1452 
1453     RtlEnterCriticalSection(&ConsoleLock);
1454 
1455     /* We must have a non-trivial handle to close */
1456     if (ConsoleHandle == NULL) // IsConsoleHandle(ConsoleHandle)
1457     {
1458         SetLastError(ERROR_INVALID_PARAMETER);
1459         Success = FALSE;
1460         goto Quit;
1461     }
1462 
1463     /* Set up the data to send to the Console Server */
1464     FreeConsoleRequest->ConsoleHandle = ConsoleHandle;
1465 
1466     /* Call the server */
1467     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1468                         NULL,
1469                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFree),
1470                         sizeof(*FreeConsoleRequest));
1471 
1472     /* Check for success */
1473     if (!NT_SUCCESS(ApiMessage.Status))
1474     {
1475         BaseSetLastNTError(ApiMessage.Status);
1476         Success = FALSE;
1477         goto Quit;
1478     }
1479 
1480     /* Reset the console handle */
1481     NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
1482 
1483     /* Close the associated input handle */
1484     CloseHandle(InputWaitHandle);
1485     InputWaitHandle = INVALID_HANDLE_VALUE;
1486 
1487 Quit:
1488     RtlLeaveCriticalSection(&ConsoleLock);
1489     return Success;
1490 }
1491 
1492 
1493 /*
1494  * @implemented
1495  */
1496 BOOL
1497 WINAPI
1498 GetConsoleScreenBufferInfo(HANDLE hConsoleOutput,
1499                            PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)
1500 {
1501     CONSOLE_API_MESSAGE ApiMessage;
1502     PCONSOLE_GETSCREENBUFFERINFO ScreenBufferInfoRequest = &ApiMessage.Data.ScreenBufferInfoRequest;
1503 
1504     if (lpConsoleScreenBufferInfo == NULL)
1505     {
1506         SetLastError(ERROR_INVALID_PARAMETER);
1507         return FALSE;
1508     }
1509 
1510     ScreenBufferInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1511     ScreenBufferInfoRequest->OutputHandle  = hConsoleOutput;
1512 
1513     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1514                         NULL,
1515                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetScreenBufferInfo),
1516                         sizeof(*ScreenBufferInfoRequest));
1517     if (!NT_SUCCESS(ApiMessage.Status))
1518     {
1519         BaseSetLastNTError(ApiMessage.Status);
1520         return FALSE;
1521     }
1522 
1523     lpConsoleScreenBufferInfo->dwSize              = ScreenBufferInfoRequest->ScreenBufferSize;
1524     lpConsoleScreenBufferInfo->dwCursorPosition    = ScreenBufferInfoRequest->CursorPosition;
1525     lpConsoleScreenBufferInfo->wAttributes         = ScreenBufferInfoRequest->Attributes;
1526     lpConsoleScreenBufferInfo->srWindow.Left       = ScreenBufferInfoRequest->ViewOrigin.X;
1527     lpConsoleScreenBufferInfo->srWindow.Top        = ScreenBufferInfoRequest->ViewOrigin.Y;
1528     lpConsoleScreenBufferInfo->srWindow.Right      = ScreenBufferInfoRequest->ViewOrigin.X + ScreenBufferInfoRequest->ViewSize.X - 1;
1529     lpConsoleScreenBufferInfo->srWindow.Bottom     = ScreenBufferInfoRequest->ViewOrigin.Y + ScreenBufferInfoRequest->ViewSize.Y - 1;
1530     lpConsoleScreenBufferInfo->dwMaximumWindowSize = ScreenBufferInfoRequest->MaximumViewSize;
1531 
1532     return TRUE;
1533 }
1534 
1535 
1536 /*
1537  * @implemented
1538  */
1539 BOOL
1540 WINAPI
1541 DECLSPEC_HOTPATCH
1542 SetConsoleCursorPosition(HANDLE hConsoleOutput,
1543                          COORD dwCursorPosition)
1544 {
1545     CONSOLE_API_MESSAGE ApiMessage;
1546     PCONSOLE_SETCURSORPOSITION SetCursorPositionRequest = &ApiMessage.Data.SetCursorPositionRequest;
1547 
1548     SetCursorPositionRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1549     SetCursorPositionRequest->OutputHandle  = hConsoleOutput;
1550     SetCursorPositionRequest->Position      = dwCursorPosition;
1551 
1552     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1553                         NULL,
1554                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCursorPosition),
1555                         sizeof(*SetCursorPositionRequest));
1556     if (!NT_SUCCESS(ApiMessage.Status))
1557     {
1558         BaseSetLastNTError(ApiMessage.Status);
1559         return FALSE;
1560     }
1561 
1562     return TRUE;
1563 }
1564 
1565 
1566 /*
1567  * @implemented
1568  */
1569 BOOL
1570 WINAPI
1571 GetConsoleMode(HANDLE hConsoleHandle,
1572                LPDWORD lpMode)
1573 {
1574     CONSOLE_API_MESSAGE ApiMessage;
1575     PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &ApiMessage.Data.ConsoleModeRequest;
1576 
1577     if (lpMode == NULL)
1578     {
1579         SetLastError(ERROR_INVALID_PARAMETER);
1580         return FALSE;
1581     }
1582 
1583     ConsoleModeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1584     ConsoleModeRequest->Handle        = hConsoleHandle;
1585 
1586     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1587                         NULL,
1588                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetMode),
1589                         sizeof(*ConsoleModeRequest));
1590     if (!NT_SUCCESS(ApiMessage.Status))
1591     {
1592         BaseSetLastNTError(ApiMessage.Status);
1593         return FALSE;
1594     }
1595 
1596     *lpMode = ConsoleModeRequest->Mode;
1597 
1598     return TRUE;
1599 }
1600 
1601 
1602 /*
1603  * @implemented
1604  */
1605 BOOL
1606 WINAPI
1607 DECLSPEC_HOTPATCH
1608 SetConsoleMode(HANDLE hConsoleHandle,
1609                DWORD dwMode)
1610 {
1611     CONSOLE_API_MESSAGE ApiMessage;
1612     PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &ApiMessage.Data.ConsoleModeRequest;
1613 
1614     ConsoleModeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1615     ConsoleModeRequest->Handle        = hConsoleHandle;
1616     ConsoleModeRequest->Mode          = dwMode;
1617 
1618     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1619                         NULL,
1620                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetMode),
1621                         sizeof(*ConsoleModeRequest));
1622     if (!NT_SUCCESS(ApiMessage.Status))
1623     {
1624         BaseSetLastNTError(ApiMessage.Status);
1625         return FALSE;
1626     }
1627 
1628     return TRUE;
1629 }
1630 
1631 
1632 /*
1633  * @implemented
1634  */
1635 BOOL
1636 WINAPI
1637 GetNumberOfConsoleInputEvents(HANDLE hConsoleInput,
1638                               LPDWORD lpNumberOfEvents)
1639 {
1640     CONSOLE_API_MESSAGE ApiMessage;
1641     PCONSOLE_GETNUMINPUTEVENTS GetNumInputEventsRequest = &ApiMessage.Data.GetNumInputEventsRequest;
1642 
1643     GetNumInputEventsRequest->ConsoleHandle  = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1644     GetNumInputEventsRequest->InputHandle    = hConsoleInput;
1645     GetNumInputEventsRequest->NumberOfEvents = 0;
1646 
1647     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1648                         NULL,
1649                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetNumberOfInputEvents),
1650                         sizeof(*GetNumInputEventsRequest));
1651     if (!NT_SUCCESS(ApiMessage.Status))
1652     {
1653         BaseSetLastNTError(ApiMessage.Status);
1654         return FALSE;
1655     }
1656 
1657     if (lpNumberOfEvents == NULL)
1658     {
1659         SetLastError(ERROR_INVALID_ACCESS);
1660         return FALSE;
1661     }
1662 
1663     *lpNumberOfEvents = GetNumInputEventsRequest->NumberOfEvents;
1664 
1665     return TRUE;
1666 }
1667 
1668 
1669 /*
1670  * @implemented
1671  */
1672 COORD
1673 WINAPI
1674 DECLSPEC_HOTPATCH
1675 GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
1676 {
1677     CONSOLE_API_MESSAGE ApiMessage;
1678     PCONSOLE_GETLARGESTWINDOWSIZE GetLargestWindowSizeRequest = &ApiMessage.Data.GetLargestWindowSizeRequest;
1679 
1680     GetLargestWindowSizeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1681     GetLargestWindowSizeRequest->OutputHandle  = hConsoleOutput;
1682     GetLargestWindowSizeRequest->Size.X = 0;
1683     GetLargestWindowSizeRequest->Size.Y = 0;
1684 
1685     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1686                         NULL,
1687                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetLargestWindowSize),
1688                         sizeof(*GetLargestWindowSizeRequest));
1689     if (!NT_SUCCESS(ApiMessage.Status))
1690     {
1691         BaseSetLastNTError(ApiMessage.Status);
1692     }
1693 
1694     DPRINT("GetLargestConsoleWindowSize, X = %d, Y = %d\n", GetLargestWindowSizeRequest->Size.X, GetLargestWindowSizeRequest->Size.Y);
1695     return GetLargestWindowSizeRequest->Size;
1696 }
1697 
1698 
1699 /*
1700  * @implemented
1701  */
1702 BOOL
1703 WINAPI
1704 GetConsoleCursorInfo(HANDLE hConsoleOutput,
1705                      PCONSOLE_CURSOR_INFO lpConsoleCursorInfo)
1706 {
1707     CONSOLE_API_MESSAGE ApiMessage;
1708     PCONSOLE_GETSETCURSORINFO CursorInfoRequest = &ApiMessage.Data.CursorInfoRequest;
1709 
1710     if (!lpConsoleCursorInfo)
1711     {
1712         if (!hConsoleOutput)
1713             SetLastError(ERROR_INVALID_HANDLE);
1714         else
1715             SetLastError(ERROR_INVALID_ACCESS);
1716 
1717         return FALSE;
1718     }
1719 
1720     CursorInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1721     CursorInfoRequest->OutputHandle  = hConsoleOutput;
1722 
1723     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1724                         NULL,
1725                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCursorInfo),
1726                         sizeof(*CursorInfoRequest));
1727     if (!NT_SUCCESS(ApiMessage.Status))
1728     {
1729         BaseSetLastNTError(ApiMessage.Status);
1730         return FALSE;
1731     }
1732 
1733     *lpConsoleCursorInfo = CursorInfoRequest->Info;
1734 
1735     return TRUE;
1736 }
1737 
1738 
1739 /*
1740  * @implemented
1741  */
1742 BOOL
1743 WINAPI
1744 SetConsoleCursorInfo(HANDLE hConsoleOutput,
1745                      CONST CONSOLE_CURSOR_INFO *lpConsoleCursorInfo)
1746 {
1747     CONSOLE_API_MESSAGE ApiMessage;
1748     PCONSOLE_GETSETCURSORINFO CursorInfoRequest = &ApiMessage.Data.CursorInfoRequest;
1749 
1750     CursorInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1751     CursorInfoRequest->OutputHandle  = hConsoleOutput;
1752     CursorInfoRequest->Info          = *lpConsoleCursorInfo;
1753 
1754     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1755                         NULL,
1756                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCursorInfo),
1757                         sizeof(*CursorInfoRequest));
1758     if (!NT_SUCCESS(ApiMessage.Status))
1759     {
1760         BaseSetLastNTError(ApiMessage.Status);
1761         return FALSE;
1762     }
1763 
1764     return TRUE;
1765 }
1766 
1767 
1768 /*
1769  * @implemented
1770  */
1771 BOOL
1772 WINAPI
1773 GetNumberOfConsoleMouseButtons(LPDWORD lpNumberOfMouseButtons)
1774 {
1775     CONSOLE_API_MESSAGE ApiMessage;
1776     PCONSOLE_GETMOUSEINFO GetMouseInfoRequest = &ApiMessage.Data.GetMouseInfoRequest;
1777 
1778     GetMouseInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1779 
1780     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1781                         NULL,
1782                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetMouseInfo),
1783                         sizeof(*GetMouseInfoRequest));
1784     if (!NT_SUCCESS(ApiMessage.Status))
1785     {
1786         BaseSetLastNTError(ApiMessage.Status);
1787         return FALSE;
1788     }
1789 
1790     *lpNumberOfMouseButtons = GetMouseInfoRequest->NumButtons;
1791     return TRUE;
1792 }
1793 
1794 
1795 /*
1796  * @implemented
1797  */
1798 BOOL
1799 WINAPI
1800 DECLSPEC_HOTPATCH
1801 SetConsoleActiveScreenBuffer(HANDLE hConsoleOutput)
1802 {
1803     CONSOLE_API_MESSAGE ApiMessage;
1804     PCONSOLE_SETACTIVESCREENBUFFER SetScreenBufferRequest = &ApiMessage.Data.SetScreenBufferRequest;
1805 
1806     SetScreenBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1807     SetScreenBufferRequest->OutputHandle  = hConsoleOutput;
1808 
1809     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1810                         NULL,
1811                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetActiveScreenBuffer),
1812                         sizeof(*SetScreenBufferRequest));
1813     if (!NT_SUCCESS(ApiMessage.Status))
1814     {
1815         BaseSetLastNTError(ApiMessage.Status);
1816         return FALSE;
1817     }
1818 
1819     return TRUE;
1820 }
1821 
1822 
1823 /*
1824  * @implemented
1825  */
1826 BOOL
1827 WINAPI
1828 DECLSPEC_HOTPATCH
1829 FlushConsoleInputBuffer(HANDLE hConsoleInput)
1830 {
1831     CONSOLE_API_MESSAGE ApiMessage;
1832     PCONSOLE_FLUSHINPUTBUFFER FlushInputBufferRequest = &ApiMessage.Data.FlushInputBufferRequest;
1833 
1834     FlushInputBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1835     FlushInputBufferRequest->InputHandle   = hConsoleInput;
1836 
1837     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1838                         NULL,
1839                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFlushInputBuffer),
1840                         sizeof(*FlushInputBufferRequest));
1841     if (!NT_SUCCESS(ApiMessage.Status))
1842     {
1843         BaseSetLastNTError(ApiMessage.Status);
1844         return FALSE;
1845     }
1846 
1847     return TRUE;
1848 }
1849 
1850 
1851 /*
1852  * @implemented
1853  */
1854 BOOL
1855 WINAPI
1856 DECLSPEC_HOTPATCH
1857 SetConsoleScreenBufferSize(HANDLE hConsoleOutput,
1858                            COORD dwSize)
1859 {
1860     CONSOLE_API_MESSAGE ApiMessage;
1861     PCONSOLE_SETSCREENBUFFERSIZE SetScreenBufferSizeRequest = &ApiMessage.Data.SetScreenBufferSizeRequest;
1862 
1863     SetScreenBufferSizeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1864     SetScreenBufferSizeRequest->OutputHandle  = hConsoleOutput;
1865     SetScreenBufferSizeRequest->Size          = dwSize;
1866 
1867     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1868                         NULL,
1869                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetScreenBufferSize),
1870                         sizeof(*SetScreenBufferSizeRequest));
1871     if (!NT_SUCCESS(ApiMessage.Status))
1872     {
1873         BaseSetLastNTError(ApiMessage.Status);
1874         return FALSE;
1875     }
1876 
1877     return TRUE;
1878 }
1879 
1880 
1881 static
1882 BOOL
1883 IntScrollConsoleScreenBuffer(HANDLE hConsoleOutput,
1884                              CONST SMALL_RECT* lpScrollRectangle,
1885                              CONST SMALL_RECT* lpClipRectangle,
1886                              COORD dwDestinationOrigin,
1887                              CONST CHAR_INFO* lpFill,
1888                              BOOL bUnicode)
1889 {
1890     CONSOLE_API_MESSAGE ApiMessage;
1891     PCONSOLE_SCROLLSCREENBUFFER ScrollScreenBufferRequest = &ApiMessage.Data.ScrollScreenBufferRequest;
1892 
1893     ScrollScreenBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1894     ScrollScreenBufferRequest->OutputHandle  = hConsoleOutput;
1895     ScrollScreenBufferRequest->ScrollRectangle = *lpScrollRectangle;
1896 
1897     if (lpClipRectangle != NULL)
1898     {
1899         ScrollScreenBufferRequest->UseClipRectangle = TRUE;
1900         ScrollScreenBufferRequest->ClipRectangle = *lpClipRectangle;
1901     }
1902     else
1903     {
1904         ScrollScreenBufferRequest->UseClipRectangle = FALSE;
1905     }
1906 
1907     ScrollScreenBufferRequest->DestinationOrigin = dwDestinationOrigin;
1908     ScrollScreenBufferRequest->Fill    = *lpFill;
1909     ScrollScreenBufferRequest->Unicode = bUnicode;
1910 
1911     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1912                         NULL,
1913                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepScrollScreenBuffer),
1914                         sizeof(*ScrollScreenBufferRequest));
1915     if (!NT_SUCCESS(ApiMessage.Status))
1916     {
1917         BaseSetLastNTError(ApiMessage.Status);
1918         return FALSE;
1919     }
1920 
1921     return TRUE;
1922 }
1923 
1924 
1925 /*
1926  * @implemented
1927  */
1928 BOOL
1929 WINAPI
1930 DECLSPEC_HOTPATCH
1931 ScrollConsoleScreenBufferA(HANDLE hConsoleOutput,
1932                            CONST SMALL_RECT* lpScrollRectangle,
1933                            CONST SMALL_RECT* lpClipRectangle,
1934                            COORD dwDestinationOrigin,
1935                            CONST CHAR_INFO* lpFill)
1936 {
1937     return IntScrollConsoleScreenBuffer(hConsoleOutput,
1938                                         lpScrollRectangle,
1939                                         lpClipRectangle,
1940                                         dwDestinationOrigin,
1941                                         lpFill,
1942                                         FALSE);
1943 }
1944 
1945 
1946 /*
1947  * @implemented
1948  */
1949 BOOL
1950 WINAPI
1951 DECLSPEC_HOTPATCH
1952 ScrollConsoleScreenBufferW(HANDLE hConsoleOutput,
1953                            CONST SMALL_RECT *lpScrollRectangle,
1954                            CONST SMALL_RECT *lpClipRectangle,
1955                            COORD dwDestinationOrigin,
1956                            CONST CHAR_INFO *lpFill)
1957 {
1958     return IntScrollConsoleScreenBuffer(hConsoleOutput,
1959                                         lpScrollRectangle,
1960                                         lpClipRectangle,
1961                                         dwDestinationOrigin,
1962                                         lpFill,
1963                                         TRUE);
1964 }
1965 
1966 
1967 /*
1968  * @implemented
1969  */
1970 BOOL
1971 WINAPI
1972 SetConsoleWindowInfo(HANDLE hConsoleOutput,
1973                      BOOL bAbsolute,
1974                      CONST SMALL_RECT *lpConsoleWindow)
1975 {
1976     CONSOLE_API_MESSAGE ApiMessage;
1977     PCONSOLE_SETWINDOWINFO SetWindowInfoRequest = &ApiMessage.Data.SetWindowInfoRequest;
1978 
1979     if (lpConsoleWindow == NULL)
1980     {
1981         SetLastError(ERROR_INVALID_PARAMETER);
1982         return FALSE;
1983     }
1984 
1985     SetWindowInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1986     SetWindowInfoRequest->OutputHandle  = hConsoleOutput;
1987     SetWindowInfoRequest->Absolute      = bAbsolute;
1988     SetWindowInfoRequest->WindowRect    = *lpConsoleWindow;
1989 
1990     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1991                         NULL,
1992                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetWindowInfo),
1993                         sizeof(*SetWindowInfoRequest));
1994     if (!NT_SUCCESS(ApiMessage.Status))
1995     {
1996         BaseSetLastNTError(ApiMessage.Status);
1997         return FALSE;
1998     }
1999 
2000     return TRUE;
2001 }
2002 
2003 
2004 /*
2005  * @implemented
2006  */
2007 BOOL
2008 WINAPI
2009 DECLSPEC_HOTPATCH
2010 SetConsoleTextAttribute(HANDLE hConsoleOutput,
2011                         WORD wAttributes)
2012 {
2013     CONSOLE_API_MESSAGE ApiMessage;
2014     PCONSOLE_SETTEXTATTRIB SetTextAttribRequest = &ApiMessage.Data.SetTextAttribRequest;
2015 
2016     SetTextAttribRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2017     SetTextAttribRequest->OutputHandle  = hConsoleOutput;
2018     SetTextAttribRequest->Attributes    = wAttributes;
2019 
2020     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2021                         NULL,
2022                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetTextAttribute),
2023                         sizeof(*SetTextAttribRequest));
2024     if (!NT_SUCCESS(ApiMessage.Status))
2025     {
2026         BaseSetLastNTError(ApiMessage.Status);
2027         return FALSE;
2028     }
2029 
2030     return TRUE;
2031 }
2032 
2033 
2034 static
2035 BOOL
2036 AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
2037 {
2038     PHANDLER_ROUTINE* NewCtrlHandlers = NULL;
2039 
2040     if (HandlerRoutine == NULL)
2041     {
2042         NtCurrentPeb()->ProcessParameters->ConsoleFlags = TRUE;
2043         return TRUE;
2044     }
2045 
2046     if (NrCtrlHandlers == NrAllocatedHandlers)
2047     {
2048         NewCtrlHandlers = RtlAllocateHeap(RtlGetProcessHeap(),
2049                                           0,
2050                                           (NrCtrlHandlers + 4) * sizeof(PHANDLER_ROUTINE));
2051         if (NewCtrlHandlers == NULL)
2052         {
2053             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2054             return FALSE;
2055         }
2056 
2057         memmove(NewCtrlHandlers, CtrlHandlers, sizeof(PHANDLER_ROUTINE) * NrCtrlHandlers);
2058 
2059         if (NrAllocatedHandlers > 1) RtlFreeHeap(RtlGetProcessHeap(), 0, CtrlHandlers);
2060 
2061         CtrlHandlers = NewCtrlHandlers;
2062         NrAllocatedHandlers += 4;
2063     }
2064 
2065     ASSERT(NrCtrlHandlers < NrAllocatedHandlers);
2066 
2067     CtrlHandlers[NrCtrlHandlers++] = HandlerRoutine;
2068     return TRUE;
2069 }
2070 
2071 
2072 static
2073 BOOL
2074 RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
2075 {
2076     ULONG i;
2077 
2078     if (HandlerRoutine == NULL)
2079     {
2080         NtCurrentPeb()->ProcessParameters->ConsoleFlags = FALSE;
2081         return TRUE;
2082     }
2083 
2084     for (i = 0; i < NrCtrlHandlers; i++)
2085     {
2086         if (CtrlHandlers[i] == HandlerRoutine)
2087         {
2088             if (i < (NrCtrlHandlers - 1))
2089             {
2090                 memmove(&CtrlHandlers[i],
2091                         &CtrlHandlers[i+1],
2092                         (NrCtrlHandlers - i + 1) * sizeof(PHANDLER_ROUTINE));
2093             }
2094 
2095             NrCtrlHandlers--;
2096             return TRUE;
2097         }
2098     }
2099 
2100     SetLastError(ERROR_INVALID_PARAMETER);
2101     return FALSE;
2102 }
2103 
2104 
2105 /*
2106  * @implemented
2107  */
2108 BOOL
2109 WINAPI
2110 DECLSPEC_HOTPATCH
2111 SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine,
2112                       BOOL Add)
2113 {
2114     BOOL Ret;
2115 
2116     RtlEnterCriticalSection(&ConsoleLock);
2117 
2118     if (Add)
2119         Ret = AddConsoleCtrlHandler(HandlerRoutine);
2120     else
2121         Ret = RemoveConsoleCtrlHandler(HandlerRoutine);
2122 
2123     RtlLeaveCriticalSection(&ConsoleLock);
2124     return Ret;
2125 }
2126 
2127 
2128 /*
2129  * @implemented
2130  */
2131 BOOL
2132 WINAPI
2133 DECLSPEC_HOTPATCH
2134 GenerateConsoleCtrlEvent(DWORD dwCtrlEvent,
2135                          DWORD dwProcessGroupId)
2136 {
2137     CONSOLE_API_MESSAGE ApiMessage;
2138     PCONSOLE_GENERATECTRLEVENT GenerateCtrlEventRequest = &ApiMessage.Data.GenerateCtrlEventRequest;
2139 
2140     if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT)
2141     {
2142         SetLastError(ERROR_INVALID_PARAMETER);
2143         return FALSE;
2144     }
2145 
2146     GenerateCtrlEventRequest->ConsoleHandle  = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2147     GenerateCtrlEventRequest->CtrlEvent      = dwCtrlEvent;
2148     GenerateCtrlEventRequest->ProcessGroupId = dwProcessGroupId;
2149 
2150     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2151                         NULL,
2152                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGenerateCtrlEvent),
2153                         sizeof(*GenerateCtrlEventRequest));
2154     if (!NT_SUCCESS(ApiMessage.Status))
2155     {
2156         BaseSetLastNTError(ApiMessage.Status);
2157         return FALSE;
2158     }
2159 
2160     return TRUE;
2161 }
2162 
2163 
2164 static DWORD
2165 IntGetConsoleTitle(LPVOID lpConsoleTitle, DWORD dwNumChars, BOOLEAN bUnicode)
2166 {
2167     CONSOLE_API_MESSAGE ApiMessage;
2168     PCONSOLE_GETSETCONSOLETITLE TitleRequest = &ApiMessage.Data.TitleRequest;
2169     PCSR_CAPTURE_BUFFER CaptureBuffer;
2170 
2171     if (dwNumChars == 0) return 0;
2172 
2173     TitleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2174     TitleRequest->Length        = dwNumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
2175     TitleRequest->Unicode       = bUnicode;
2176 
2177     CaptureBuffer = CsrAllocateCaptureBuffer(1, TitleRequest->Length);
2178     if (CaptureBuffer == NULL)
2179     {
2180         DPRINT1("CsrAllocateCaptureBuffer failed!\n");
2181         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2182         return 0;
2183     }
2184 
2185     CsrAllocateMessagePointer(CaptureBuffer,
2186                               TitleRequest->Length,
2187                               (PVOID*)&TitleRequest->Title);
2188 
2189     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2190                         CaptureBuffer,
2191                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetTitle),
2192                         sizeof(*TitleRequest));
2193     if (!NT_SUCCESS(ApiMessage.Status))
2194     {
2195         CsrFreeCaptureBuffer(CaptureBuffer);
2196         BaseSetLastNTError(ApiMessage.Status);
2197         return 0;
2198     }
2199 
2200     dwNumChars = TitleRequest->Length / (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
2201 
2202     if (dwNumChars > 0)
2203     {
2204         RtlCopyMemory(lpConsoleTitle, TitleRequest->Title, TitleRequest->Length);
2205 
2206         if (bUnicode)
2207             ((LPWSTR)lpConsoleTitle)[dwNumChars] = UNICODE_NULL;
2208         else
2209             ((LPSTR)lpConsoleTitle)[dwNumChars] = ANSI_NULL;
2210     }
2211 
2212     CsrFreeCaptureBuffer(CaptureBuffer);
2213 
2214     return dwNumChars;
2215 }
2216 
2217 
2218 /*
2219  * @implemented
2220  */
2221 DWORD
2222 WINAPI
2223 DECLSPEC_HOTPATCH
2224 GetConsoleTitleW(LPWSTR lpConsoleTitle,
2225                  DWORD nSize)
2226 {
2227     return IntGetConsoleTitle(lpConsoleTitle, nSize, TRUE);
2228 }
2229 
2230 
2231 /*
2232  * @implemented
2233  */
2234 DWORD
2235 WINAPI
2236 DECLSPEC_HOTPATCH
2237 GetConsoleTitleA(LPSTR lpConsoleTitle,
2238                  DWORD nSize)
2239 {
2240     return IntGetConsoleTitle(lpConsoleTitle, nSize, FALSE);
2241 }
2242 
2243 
2244 static BOOL
2245 IntSetConsoleTitle(CONST VOID *lpConsoleTitle, BOOLEAN bUnicode)
2246 {
2247     CONSOLE_API_MESSAGE ApiMessage;
2248     PCONSOLE_GETSETCONSOLETITLE TitleRequest = &ApiMessage.Data.TitleRequest;
2249     PCSR_CAPTURE_BUFFER CaptureBuffer;
2250 
2251     ULONG NumChars = (ULONG)(lpConsoleTitle ? (bUnicode ? wcslen(lpConsoleTitle) : strlen(lpConsoleTitle)) : 0);
2252 
2253     TitleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2254     TitleRequest->Length        = NumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
2255     TitleRequest->Unicode       = bUnicode;
2256 
2257     CaptureBuffer = CsrAllocateCaptureBuffer(1, TitleRequest->Length);
2258     if (CaptureBuffer == NULL)
2259     {
2260         DPRINT1("CsrAllocateCaptureBuffer failed!\n");
2261         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2262         return FALSE;
2263     }
2264 
2265     CsrCaptureMessageBuffer(CaptureBuffer,
2266                             (PVOID)lpConsoleTitle,
2267                             TitleRequest->Length,
2268                             (PVOID*)&TitleRequest->Title);
2269 
2270     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2271                         CaptureBuffer,
2272                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetTitle),
2273                         sizeof(*TitleRequest));
2274 
2275     CsrFreeCaptureBuffer(CaptureBuffer);
2276 
2277     if (!NT_SUCCESS(ApiMessage.Status))
2278     {
2279         BaseSetLastNTError(ApiMessage.Status);
2280         return FALSE;
2281     }
2282 
2283     return TRUE;
2284 }
2285 
2286 /*
2287  * @implemented
2288  */
2289 BOOL
2290 WINAPI
2291 DECLSPEC_HOTPATCH
2292 SetConsoleTitleW(LPCWSTR lpConsoleTitle)
2293 {
2294     return IntSetConsoleTitle(lpConsoleTitle, TRUE);
2295 }
2296 
2297 
2298 /*
2299  * @implemented
2300  */
2301 BOOL
2302 WINAPI
2303 DECLSPEC_HOTPATCH
2304 SetConsoleTitleA(LPCSTR lpConsoleTitle)
2305 {
2306     return IntSetConsoleTitle(lpConsoleTitle, FALSE);
2307 }
2308 
2309 
2310 /*
2311  * @implemented
2312  */
2313 HANDLE
2314 WINAPI
2315 CreateConsoleScreenBuffer(DWORD dwDesiredAccess,
2316                           DWORD dwShareMode,
2317                           CONST SECURITY_ATTRIBUTES *lpSecurityAttributes,
2318                           DWORD dwFlags,
2319                           LPVOID lpScreenBufferData)
2320 {
2321     CONSOLE_API_MESSAGE ApiMessage;
2322     PCONSOLE_CREATESCREENBUFFER CreateScreenBufferRequest = &ApiMessage.Data.CreateScreenBufferRequest;
2323     PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
2324     PCONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo = lpScreenBufferData;
2325 
2326     if ( (dwDesiredAccess & ~(GENERIC_READ | GENERIC_WRITE))    ||
2327          (dwShareMode & ~(FILE_SHARE_READ | FILE_SHARE_WRITE))  ||
2328          (dwFlags != CONSOLE_TEXTMODE_BUFFER && dwFlags != CONSOLE_GRAPHICS_BUFFER) )
2329     {
2330         SetLastError(ERROR_INVALID_PARAMETER);
2331         return INVALID_HANDLE_VALUE;
2332     }
2333 
2334     CreateScreenBufferRequest->ConsoleHandle    = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2335     CreateScreenBufferRequest->DesiredAccess    = dwDesiredAccess;
2336     CreateScreenBufferRequest->InheritHandle    =
2337         (lpSecurityAttributes ? lpSecurityAttributes->bInheritHandle : FALSE);
2338     CreateScreenBufferRequest->ShareMode        = dwShareMode;
2339     CreateScreenBufferRequest->ScreenBufferType = dwFlags;
2340 
2341     if (dwFlags == CONSOLE_GRAPHICS_BUFFER)
2342     {
2343         if (CreateScreenBufferRequest->InheritHandle || GraphicsBufferInfo == NULL)
2344         {
2345             SetLastError(ERROR_INVALID_PARAMETER);
2346             return INVALID_HANDLE_VALUE;
2347         }
2348 
2349         CreateScreenBufferRequest->GraphicsBufferInfo = *GraphicsBufferInfo;
2350 
2351         CaptureBuffer = CsrAllocateCaptureBuffer(1, GraphicsBufferInfo->dwBitMapInfoLength);
2352         if (CaptureBuffer == NULL)
2353         {
2354             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2355             return INVALID_HANDLE_VALUE;
2356         }
2357 
2358         CsrCaptureMessageBuffer(CaptureBuffer,
2359                                 (PVOID)GraphicsBufferInfo->lpBitMapInfo,
2360                                 GraphicsBufferInfo->dwBitMapInfoLength,
2361                                 (PVOID*)&CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMapInfo);
2362     }
2363 
2364     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2365                         CaptureBuffer,
2366                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepCreateScreenBuffer),
2367                         sizeof(*CreateScreenBufferRequest));
2368 
2369     if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
2370 
2371     if (!NT_SUCCESS(ApiMessage.Status))
2372     {
2373         BaseSetLastNTError(ApiMessage.Status);
2374         return INVALID_HANDLE_VALUE;
2375     }
2376 
2377     if (dwFlags == CONSOLE_GRAPHICS_BUFFER && GraphicsBufferInfo)
2378     {
2379         GraphicsBufferInfo->hMutex   = CreateScreenBufferRequest->hMutex  ; // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex  ;
2380         GraphicsBufferInfo->lpBitMap = CreateScreenBufferRequest->lpBitMap; // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap;
2381     }
2382 
2383     return CreateScreenBufferRequest->OutputHandle;
2384 }
2385 
2386 
2387 /*
2388  * @implemented
2389  */
2390 UINT
2391 WINAPI
2392 DECLSPEC_HOTPATCH
2393 GetConsoleCP(VOID)
2394 {
2395     CONSOLE_API_MESSAGE ApiMessage;
2396     PCONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest = &ApiMessage.Data.GetConsoleCPRequest;
2397 
2398     /* Get the Input Code Page */
2399     GetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2400     GetConsoleCPRequest->OutputCP      = FALSE;
2401 
2402     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2403                         NULL,
2404                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCP),
2405                         sizeof(*GetConsoleCPRequest));
2406     if (!NT_SUCCESS(ApiMessage.Status))
2407     {
2408         BaseSetLastNTError(ApiMessage.Status);
2409         return 0;
2410     }
2411 
2412     return GetConsoleCPRequest->CodePage;
2413 }
2414 
2415 
2416 /*
2417  * @implemented
2418  */
2419 BOOL
2420 WINAPI
2421 DECLSPEC_HOTPATCH
2422 SetConsoleCP(UINT wCodePageID)
2423 {
2424     CONSOLE_API_MESSAGE ApiMessage;
2425     PCONSOLE_SETINPUTOUTPUTCP SetConsoleCPRequest = &ApiMessage.Data.SetConsoleCPRequest;
2426 
2427     /* Set the Input Code Page */
2428     SetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2429     SetConsoleCPRequest->CodePage      = wCodePageID;
2430     SetConsoleCPRequest->OutputCP      = FALSE;
2431     /* SetConsoleCPRequest->EventHandle; */
2432 
2433     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2434                         NULL,
2435                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCP),
2436                         sizeof(*SetConsoleCPRequest));
2437     if (!NT_SUCCESS(ApiMessage.Status))
2438     {
2439         BaseSetLastNTError(ApiMessage.Status);
2440         return FALSE;
2441     }
2442 
2443     return TRUE;
2444 }
2445 
2446 
2447 /*
2448  * @implemented
2449  */
2450 UINT
2451 WINAPI
2452 DECLSPEC_HOTPATCH
2453 GetConsoleOutputCP(VOID)
2454 {
2455     CONSOLE_API_MESSAGE ApiMessage;
2456     PCONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest = &ApiMessage.Data.GetConsoleCPRequest;
2457 
2458     /* Get the Output Code Page */
2459     GetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2460     GetConsoleCPRequest->OutputCP      = TRUE;
2461 
2462     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2463                         NULL,
2464                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCP),
2465                         sizeof(*GetConsoleCPRequest));
2466     if (!NT_SUCCESS(ApiMessage.Status))
2467     {
2468         BaseSetLastNTError(ApiMessage.Status);
2469         return 0;
2470     }
2471 
2472     return GetConsoleCPRequest->CodePage;
2473 }
2474 
2475 
2476 /*
2477  * @implemented
2478  */
2479 BOOL
2480 WINAPI
2481 DECLSPEC_HOTPATCH
2482 SetConsoleOutputCP(UINT wCodePageID)
2483 {
2484     CONSOLE_API_MESSAGE ApiMessage;
2485     PCONSOLE_SETINPUTOUTPUTCP SetConsoleCPRequest = &ApiMessage.Data.SetConsoleCPRequest;
2486 
2487     /* Set the Output Code Page */
2488     SetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2489     SetConsoleCPRequest->CodePage      = wCodePageID;
2490     SetConsoleCPRequest->OutputCP      = TRUE;
2491     /* SetConsoleCPRequest->EventHandle; */
2492 
2493     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2494                         NULL,
2495                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCP),
2496                         sizeof(*SetConsoleCPRequest));
2497     if (!NT_SUCCESS(ApiMessage.Status))
2498     {
2499         BaseSetLastNTError(ApiMessage.Status);
2500         return FALSE;
2501     }
2502 
2503     return TRUE;
2504 }
2505 
2506 
2507 /*
2508  * @implemented
2509  */
2510 DWORD
2511 WINAPI
2512 GetConsoleProcessList(LPDWORD lpdwProcessList,
2513                       DWORD dwProcessCount)
2514 {
2515     CONSOLE_API_MESSAGE ApiMessage;
2516     PCONSOLE_GETPROCESSLIST GetProcessListRequest = &ApiMessage.Data.GetProcessListRequest;
2517     PCSR_CAPTURE_BUFFER CaptureBuffer;
2518     ULONG nProcesses = 0;
2519 
2520     if (lpdwProcessList == NULL || dwProcessCount == 0)
2521     {
2522         SetLastError(ERROR_INVALID_PARAMETER);
2523         return 0;
2524     }
2525 
2526     CaptureBuffer = CsrAllocateCaptureBuffer(1, dwProcessCount * sizeof(DWORD));
2527     if (CaptureBuffer == NULL)
2528     {
2529         DPRINT1("CsrAllocateCaptureBuffer failed!\n");
2530         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2531         return 0;
2532     }
2533 
2534     GetProcessListRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2535     GetProcessListRequest->ProcessCount  = dwProcessCount;
2536 
2537     CsrAllocateMessagePointer(CaptureBuffer,
2538                               dwProcessCount * sizeof(DWORD),
2539                               (PVOID*)&GetProcessListRequest->ProcessIdsList);
2540 
2541     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2542                         CaptureBuffer,
2543                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetProcessList),
2544                         sizeof(*GetProcessListRequest));
2545     if (!NT_SUCCESS(ApiMessage.Status))
2546     {
2547         BaseSetLastNTError(ApiMessage.Status);
2548     }
2549     else
2550     {
2551         nProcesses = GetProcessListRequest->ProcessCount;
2552         if (dwProcessCount >= nProcesses)
2553         {
2554             RtlCopyMemory(lpdwProcessList, GetProcessListRequest->ProcessIdsList, nProcesses * sizeof(DWORD));
2555         }
2556     }
2557 
2558     CsrFreeCaptureBuffer(CaptureBuffer);
2559     return nProcesses;
2560 }
2561 
2562 
2563 /*
2564  * @implemented
2565  */
2566 BOOL
2567 WINAPI
2568 GetConsoleSelectionInfo(PCONSOLE_SELECTION_INFO lpConsoleSelectionInfo)
2569 {
2570     CONSOLE_API_MESSAGE ApiMessage;
2571     PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest = &ApiMessage.Data.GetSelectionInfoRequest;
2572 
2573     if (lpConsoleSelectionInfo == NULL)
2574     {
2575         SetLastError(ERROR_INVALID_PARAMETER);
2576         return FALSE;
2577     }
2578 
2579     GetSelectionInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2580 
2581     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2582                         NULL,
2583                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetSelectionInfo),
2584                         sizeof(*GetSelectionInfoRequest));
2585     if (!NT_SUCCESS(ApiMessage.Status))
2586     {
2587         BaseSetLastNTError(ApiMessage.Status);
2588         return FALSE;
2589     }
2590 
2591     *lpConsoleSelectionInfo = GetSelectionInfoRequest->Info;
2592 
2593     return TRUE;
2594 }
2595 
2596 
2597 /*
2598  * @implemented
2599  * @note Strongly inspired by AllocConsole.
2600  */
2601 static BOOL
2602 IntAttachConsole(DWORD ProcessId,
2603                  LPTHREAD_START_ROUTINE CtrlRoutine,
2604                  LPTHREAD_START_ROUTINE PropRoutine,
2605                  PCONSOLE_START_INFO ConsoleStartInfo)
2606 {
2607     BOOL Success = TRUE;
2608     NTSTATUS Status;
2609 
2610     CONSOLE_API_MESSAGE ApiMessage;
2611     PCONSOLE_ATTACHCONSOLE AttachConsoleRequest = &ApiMessage.Data.AttachConsoleRequest;
2612     PCSR_CAPTURE_BUFFER CaptureBuffer;
2613 
2614     AttachConsoleRequest->ProcessId   = ProcessId;
2615     AttachConsoleRequest->CtrlRoutine = CtrlRoutine;
2616     AttachConsoleRequest->PropRoutine = PropRoutine;
2617 
2618     CaptureBuffer = CsrAllocateCaptureBuffer(1, sizeof(CONSOLE_START_INFO));
2619     if (CaptureBuffer == NULL)
2620     {
2621         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2622         Success = FALSE;
2623         goto Quit;
2624     }
2625 
2626     CsrCaptureMessageBuffer(CaptureBuffer,
2627                             ConsoleStartInfo,
2628                             sizeof(CONSOLE_START_INFO),
2629                             (PVOID*)&AttachConsoleRequest->ConsoleStartInfo);
2630 
2631     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2632                         CaptureBuffer,
2633                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAttach),
2634                         sizeof(*AttachConsoleRequest));
2635     if (!NT_SUCCESS(ApiMessage.Status))
2636     {
2637         BaseSetLastNTError(ApiMessage.Status);
2638         Success = FALSE;
2639         goto Quit;
2640     }
2641 
2642     // Is AttachConsoleRequest->ConsoleStartInfo->InitEvents aligned on handle boundary ????
2643     Status = NtWaitForMultipleObjects(MAX_INIT_EVENTS,
2644                                       AttachConsoleRequest->ConsoleStartInfo->InitEvents,
2645                                       WaitAny, FALSE, NULL);
2646     if (!NT_SUCCESS(Status))
2647     {
2648         BaseSetLastNTError(Status);
2649         Success = FALSE;
2650         goto Quit;
2651     }
2652 
2653     NtClose(AttachConsoleRequest->ConsoleStartInfo->InitEvents[INIT_SUCCESS]);
2654     NtClose(AttachConsoleRequest->ConsoleStartInfo->InitEvents[INIT_FAILURE]);
2655     if (Status != INIT_SUCCESS)
2656     {
2657         NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
2658         Success = FALSE;
2659     }
2660     else
2661     {
2662         RtlCopyMemory(ConsoleStartInfo,
2663                       AttachConsoleRequest->ConsoleStartInfo,
2664                       sizeof(CONSOLE_START_INFO));
2665         Success = TRUE;
2666     }
2667 
2668 Quit:
2669     if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
2670     return Success;
2671 }
2672 
2673 BOOL
2674 WINAPI
2675 AttachConsole(DWORD dwProcessId)
2676 {
2677     BOOL Success;
2678     CONSOLE_START_INFO ConsoleStartInfo;
2679 
2680     DWORD dummy;
2681     LCID lcid;
2682 
2683     RtlEnterCriticalSection(&ConsoleLock);
2684 
2685     if (NtCurrentPeb()->ProcessParameters->ConsoleHandle)
2686     {
2687         DPRINT1("AttachConsole: Attaching a console to a process already having one\n");
2688         SetLastError(ERROR_ACCESS_DENIED);
2689         Success = FALSE;
2690         goto Quit;
2691     }
2692 
2693     /* Set up the console properties */
2694     SetUpConsoleInfo(FALSE,
2695                      &dummy,
2696                      NULL,
2697                      &dummy,
2698                      NULL,
2699                      &ConsoleStartInfo);
2700 
2701     Success = IntAttachConsole(dwProcessId,
2702                                ConsoleControlDispatcher,
2703                                PropDialogHandler,
2704                                &ConsoleStartInfo);
2705     if (Success)
2706     {
2707         /* Set up the handles */
2708         SetUpHandles(&ConsoleStartInfo);
2709         InputWaitHandle = ConsoleStartInfo.InputWaitHandle;
2710 
2711         /* Initialize Console Ctrl Handling */
2712         InitializeCtrlHandling();
2713 
2714         /* Sets the current console locale for this thread */
2715         SetTEBLangID(lcid);
2716     }
2717 
2718 Quit:
2719     RtlLeaveCriticalSection(&ConsoleLock);
2720     return Success;
2721 }
2722 
2723 
2724 /*
2725  * @implemented
2726  */
2727 HWND
2728 WINAPI
2729 DECLSPEC_HOTPATCH
2730 GetConsoleWindow(VOID)
2731 {
2732     CONSOLE_API_MESSAGE ApiMessage;
2733     PCONSOLE_GETWINDOW GetWindowRequest = &ApiMessage.Data.GetWindowRequest;
2734 
2735     GetWindowRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2736 
2737     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2738                         NULL,
2739                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetConsoleWindow),
2740                         sizeof(*GetWindowRequest));
2741     if (!NT_SUCCESS(ApiMessage.Status))
2742     {
2743         BaseSetLastNTError(ApiMessage.Status);
2744         return (HWND)NULL;
2745     }
2746 
2747     return GetWindowRequest->WindowHandle;
2748 }
2749 
2750 
2751 /*
2752  * @implemented
2753  */
2754 BOOL
2755 WINAPI
2756 DECLSPEC_HOTPATCH
2757 SetConsoleIcon(HICON hIcon)
2758 {
2759     CONSOLE_API_MESSAGE ApiMessage;
2760     PCONSOLE_SETICON SetIconRequest = &ApiMessage.Data.SetIconRequest;
2761 
2762     SetIconRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2763     SetIconRequest->IconHandle    = hIcon;
2764 
2765     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2766                         NULL,
2767                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetIcon),
2768                         sizeof(*SetIconRequest));
2769     if (!NT_SUCCESS(ApiMessage.Status))
2770     {
2771         BaseSetLastNTError(ApiMessage.Status);
2772         return FALSE;
2773     }
2774 
2775     return TRUE;
2776 }
2777 
2778 
2779 /******************************************************************************
2780  * \name SetConsoleInputExeNameW
2781  * \brief Sets the console input file name from a unicode string.
2782  * \param lpExeName Pointer to a unicode string with the name.
2783  * \return TRUE if successful, FALSE if unsuccessful.
2784  * \remarks If lpExeName is 0 or the string length is 0 or greater than 255,
2785  *          the function fails and sets last error to ERROR_INVALID_PARAMETER.
2786  */
2787 BOOL
2788 WINAPI
2789 DECLSPEC_HOTPATCH
2790 SetConsoleInputExeNameW(IN LPWSTR lpExeName)
2791 {
2792     DWORD ExeLength;
2793 
2794     ExeLength = lstrlenW(lpExeName);
2795     if ((ExeLength == 0) || (ExeLength >= EXENAME_LENGTH))
2796     {
2797         /* Fail if string is empty or too long */
2798         SetLastError(ERROR_INVALID_PARAMETER);
2799         return FALSE;
2800     }
2801 
2802     RtlEnterCriticalSection(&ExeNameLock);
2803     _SEH2_TRY
2804     {
2805         /* Set the input EXE name, not NULL terminated */
2806         RtlCopyMemory(ExeNameBuffer, lpExeName, ExeLength * sizeof(WCHAR));
2807         ExeNameLength = (USHORT)ExeLength;
2808     }
2809     _SEH2_FINALLY
2810     {
2811         RtlLeaveCriticalSection(&ExeNameLock);
2812     }
2813     _SEH2_END;
2814 
2815     return TRUE;
2816 }
2817 
2818 
2819 /******************************************************************************
2820  * \name SetConsoleInputExeNameA
2821  * \brief Sets the console input file name from an ansi string.
2822  * \param lpExeName Pointer to an ansi string with the name.
2823  * \return TRUE if successful, FALSE if unsuccessful.
2824  * \remarks If lpExeName is 0 or the string length is 0 or greater than 255,
2825  *          the function fails and sets last error to ERROR_INVALID_PARAMETER.
2826  */
2827 BOOL
2828 WINAPI
2829 DECLSPEC_HOTPATCH
2830 SetConsoleInputExeNameA(IN LPSTR lpExeName)
2831 {
2832     NTSTATUS Status;
2833 #ifdef USE_TEB_STATIC_USTR
2834     PUNICODE_STRING ExeNameU;
2835 #else
2836     UNICODE_STRING ExeNameU;
2837 #endif
2838     ANSI_STRING ExeNameA;
2839 #ifndef USE_TEB_STATIC_USTR
2840     WCHAR Buffer[EXENAME_LENGTH];
2841 #endif
2842 
2843 #ifdef USE_TEB_STATIC_USTR
2844     /*
2845      * Use the TEB static UNICODE string for storage. It is already
2846      * initialized at process creation time by the Memory Manager.
2847      */
2848     ExeNameU = &NtCurrentTeb()->StaticUnicodeString;
2849 #endif
2850 
2851     /* Initialize string for conversion */
2852     RtlInitAnsiString(&ExeNameA, lpExeName);
2853 
2854 #if 1
2855     if ((ExeNameA.Length == 0) || (ExeNameA.Length >= EXENAME_LENGTH))
2856     {
2857         /* Fail if string is empty or too long */
2858         SetLastError(ERROR_INVALID_PARAMETER);
2859         return FALSE;
2860     }
2861 #endif
2862 #ifndef USE_TEB_STATIC_USTR
2863     ExeNameU.Length = 0;
2864     ExeNameU.MaximumLength = (USHORT)sizeof(Buffer);
2865     ExeNameU.Buffer = Buffer;
2866 #endif
2867 
2868 #ifdef USE_TEB_STATIC_USTR
2869     Status = RtlAnsiStringToUnicodeString(ExeNameU, &ExeNameA, FALSE);
2870 #else
2871     Status = RtlAnsiStringToUnicodeString(&ExeNameU, &ExeNameA, FALSE);
2872 #endif
2873     if (!NT_SUCCESS(Status))
2874     {
2875         /* Fail if string is empty or too long */
2876         if (Status == STATUS_BUFFER_OVERFLOW)
2877             SetLastError(ERROR_FILENAME_EXCED_RANGE);
2878         else
2879             SetLastError(ERROR_INVALID_PARAMETER);
2880 
2881         return FALSE;
2882     }
2883 
2884 #ifdef USE_TEB_STATIC_USTR
2885     return SetConsoleInputExeNameW(ExeNameU->Buffer);
2886 #else
2887     return SetConsoleInputExeNameW(ExeNameU.Buffer);
2888 #endif
2889 }
2890 
2891 
2892 /******************************************************************************
2893  * \name GetConsoleInputExeNameW
2894  * \brief Retrieves the console input file name as unicode string.
2895  * \param nBufferLength Length of the buffer in WCHARs.
2896  *        Specify 0 to receive the needed buffer length.
2897  * \param lpBuffer Pointer to a buffer that receives the string.
2898  * \return Needed buffer size if \p nBufferLength is 0.
2899  *         Otherwise 1 if successful, 2 if buffer is too small.
2900  * \remarks Sets last error value to ERROR_BUFFER_OVERFLOW if the buffer
2901  *          is not big enough.
2902  */
2903 DWORD
2904 WINAPI
2905 DECLSPEC_HOTPATCH
2906 GetConsoleInputExeNameW(IN DWORD nBufferLength,
2907                         OUT LPWSTR lpExeName)
2908 {
2909     if (nBufferLength <= ExeNameLength)
2910     {
2911         /* Buffer is not large enough! Return the correct size. */
2912         SetLastError(ERROR_BUFFER_OVERFLOW);
2913         return ExeNameLength + 1;
2914     }
2915 
2916     RtlEnterCriticalSection(&ExeNameLock);
2917     _SEH2_TRY
2918     {
2919         /* Copy the input EXE name and NULL-terminate it */
2920         RtlCopyMemory(lpExeName, ExeNameBuffer, ExeNameLength * sizeof(WCHAR));
2921         lpExeName[ExeNameLength] = UNICODE_NULL;
2922     }
2923     _SEH2_FINALLY
2924     {
2925         RtlLeaveCriticalSection(&ExeNameLock);
2926     }
2927     _SEH2_END;
2928 
2929     return TRUE;
2930 }
2931 
2932 
2933 /******************************************************************************
2934  * \name GetConsoleInputExeNameA
2935  * \brief Retrieves the console input file name as ansi string.
2936  * \param nBufferLength Length of the buffer in CHARs.
2937  * \param lpBuffer Pointer to a buffer that receives the string.
2938  * \return 1 if successful, 2 if buffer is too small.
2939  * \remarks Sets last error value to ERROR_BUFFER_OVERFLOW if the buffer
2940  *          is not big enough. The buffer receives as much characters as fit.
2941  */
2942 DWORD
2943 WINAPI
2944 DECLSPEC_HOTPATCH
2945 GetConsoleInputExeNameA(IN DWORD nBufferLength,
2946                         OUT LPSTR lpExeName)
2947 {
2948     NTSTATUS Status;
2949     DWORD ExeLength;
2950     UNICODE_STRING BufferU;
2951     ANSI_STRING BufferA;
2952     WCHAR Buffer[EXENAME_LENGTH];
2953 
2954     /* Get the UNICODE name */
2955     ExeLength = GetConsoleInputExeNameW(EXENAME_LENGTH, Buffer);
2956 
2957     if ((ExeLength == 0) || (ExeLength >= EXENAME_LENGTH))
2958         return ExeLength;
2959 
2960     /* Initialize the strings for conversion */
2961     RtlInitUnicodeString(&BufferU, Buffer);
2962     BufferA.Length = 0;
2963     BufferA.MaximumLength = (USHORT)nBufferLength;
2964     BufferA.Buffer = lpExeName;
2965 
2966     /* Convert UNICODE name to ANSI, copying as much chars as it can fit */
2967     Status = RtlUnicodeStringToAnsiString(&BufferA, &BufferU, FALSE);
2968     if (!NT_SUCCESS(Status))
2969     {
2970         if (Status == STATUS_BUFFER_OVERFLOW)
2971         {
2972             SetLastError(ERROR_BUFFER_OVERFLOW);
2973             return ExeLength + 1;
2974         }
2975         SetLastError(ERROR_INVALID_PARAMETER);
2976     }
2977 
2978     return ExeLength;
2979 }
2980 
2981 BOOL
2982 WINAPI
2983 GetConsoleCharType(HANDLE hConsole, COORD Coord, PDWORD Type)
2984 {
2985     STUB;
2986     return FALSE;
2987 }
2988 
2989 BOOL
2990 WINAPI
2991 DECLSPEC_HOTPATCH
2992 GetConsoleCursorMode(HANDLE hConsole, PBOOL pUnknown1, PBOOL pUnknown2)
2993 {
2994     STUB;
2995     return FALSE;
2996 }
2997 
2998 BOOL
2999 WINAPI
3000 DECLSPEC_HOTPATCH
3001 SetConsoleCursorMode(HANDLE hConsole, BOOL Unknown1, BOOL Unknown2)
3002 {
3003     STUB;
3004     return FALSE;
3005 }
3006 
3007 BOOL
3008 WINAPI
3009 DECLSPEC_HOTPATCH
3010 GetConsoleNlsMode(HANDLE hConsole, LPDWORD lpMode)
3011 {
3012     STUB;
3013     return FALSE;
3014 }
3015 
3016 BOOL
3017 WINAPI
3018 DECLSPEC_HOTPATCH
3019 SetConsoleNlsMode(HANDLE hConsole, DWORD dwMode)
3020 {
3021     STUB;
3022     return FALSE;
3023 }
3024 
3025 BOOL
3026 WINAPI
3027 DECLSPEC_HOTPATCH
3028 SetConsoleLocalEUDC(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4)
3029 {
3030     STUB;
3031     return FALSE;
3032 }
3033 
3034 BOOL
3035 WINAPI
3036 DECLSPEC_HOTPATCH
3037 RegisterConsoleIME(HWND hWnd, LPDWORD ThreadId)
3038 {
3039     STUB;
3040     return FALSE;
3041 }
3042 
3043 BOOL
3044 WINAPI
3045 DECLSPEC_HOTPATCH
3046 RegisterConsoleOS2(BOOL bUnknown)
3047 {
3048     STUB;
3049     return FALSE;
3050 }
3051 
3052 BOOL
3053 WINAPI
3054 DECLSPEC_HOTPATCH
3055 SetConsoleOS2OemFormat(BOOL bUnknown)
3056 {
3057     STUB;
3058     return FALSE;
3059 }
3060 
3061 BOOL
3062 WINAPI
3063 DECLSPEC_HOTPATCH
3064 UnregisterConsoleIME(VOID)
3065 {
3066     STUB;
3067     return FALSE;
3068 }
3069 
3070 
3071 static
3072 BOOL
3073 IntGetConsoleKeyboardLayoutName(OUT PVOID pszLayoutName,
3074                                 IN BOOL bAnsi)
3075 {
3076     CONSOLE_API_MESSAGE ApiMessage;
3077     PCONSOLE_GETKBDLAYOUTNAME GetKbdLayoutNameRequest = &ApiMessage.Data.GetKbdLayoutNameRequest;
3078 
3079     /* Set up the data to send to the Console Server */
3080     GetKbdLayoutNameRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
3081     GetKbdLayoutNameRequest->Ansi          = bAnsi;
3082 
3083     /* Call the server */
3084     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
3085                         NULL,
3086                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetKeyboardLayoutName),
3087                         sizeof(*GetKbdLayoutNameRequest));
3088 
3089     /* Check for success */
3090     if (!NT_SUCCESS(ApiMessage.Status))
3091     {
3092         BaseSetLastNTError(ApiMessage.Status);
3093         return FALSE;
3094     }
3095 
3096     /* Retrieve the results */
3097     _SEH2_TRY
3098     {
3099         /* Copy only KL_NAMELENGTH == 9 characters, ANSI or UNICODE */
3100         if (bAnsi)
3101             strncpy(pszLayoutName, (PCHAR)GetKbdLayoutNameRequest->LayoutBuffer, KL_NAMELENGTH);
3102         else
3103             wcsncpy(pszLayoutName, (PWCHAR)GetKbdLayoutNameRequest->LayoutBuffer, KL_NAMELENGTH);
3104     }
3105     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3106     {
3107         SetLastError(ERROR_INVALID_ACCESS);
3108         _SEH2_YIELD(return FALSE);
3109     }
3110     _SEH2_END;
3111 
3112     return TRUE;
3113 }
3114 
3115 /*
3116  * @implemented (undocumented)
3117  */
3118 BOOL
3119 WINAPI
3120 DECLSPEC_HOTPATCH
3121 GetConsoleKeyboardLayoutNameA(OUT LPSTR pszLayoutName)
3122 {
3123     return IntGetConsoleKeyboardLayoutName(pszLayoutName, TRUE);
3124 }
3125 
3126 /*
3127  * @implemented (undocumented)
3128  */
3129 BOOL
3130 WINAPI
3131 DECLSPEC_HOTPATCH
3132 GetConsoleKeyboardLayoutNameW(OUT LPWSTR pszLayoutName)
3133 {
3134     return IntGetConsoleKeyboardLayoutName(pszLayoutName, FALSE);
3135 }
3136 
3137 /*
3138  * @implemented
3139  */
3140 DWORD
3141 WINAPI
3142 SetLastConsoleEventActive(VOID)
3143 {
3144     CONSOLE_API_MESSAGE ApiMessage;
3145     PCONSOLE_NOTIFYLASTCLOSE NotifyLastCloseRequest = &ApiMessage.Data.NotifyLastCloseRequest;
3146 
3147     /* Set the flag used by the console control dispatcher */
3148     LastCloseNotify = TRUE;
3149 
3150     /* Set up the input arguments */
3151     NotifyLastCloseRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
3152 
3153     /* Call CSRSS; just return the NTSTATUS cast to DWORD */
3154     return CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
3155                                NULL,
3156                                CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepNotifyLastClose),
3157                                sizeof(*NotifyLastCloseRequest));
3158 }
3159 
3160 /* EOF */
3161