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
DefaultConsoleCtrlHandler(DWORD Event)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
ConsoleControlDispatcher(IN LPVOID lpThreadParameter)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
InitializeCtrlHandling(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
InitExeName(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
SetUpAppName(IN BOOLEAN CaptureStrings,IN OUT LPDWORD CurDirLength,IN OUT LPWSTR * CurDir,IN OUT LPDWORD AppNameLength,IN OUT LPWSTR * AppName)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
GetCurrentExeName(OUT PWCHAR ExeName,IN USHORT BufferSize)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
IntCheckForConsoleFileName(IN LPCWSTR pszName,IN DWORD dwDesiredAccess)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
ConsoleMenuControl(HANDLE hConsoleOutput,DWORD dwCmdIdLow,DWORD dwCmdIdHigh)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
DuplicateConsoleHandle(HANDLE hConsole,DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwOptions)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
GetConsoleHandleInformation(IN HANDLE hHandle,OUT LPDWORD lpdwFlags)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
SetConsoleHandleInformation(IN HANDLE hHandle,IN DWORD dwMask,IN DWORD dwFlags)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
GetConsoleDisplayMode(LPDWORD lpModeFlags)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
GetConsoleFontInfo(IN HANDLE hConsoleOutput,IN BOOL bMaximumWindow,IN DWORD nFontCount,OUT PCONSOLE_FONT_INFO lpConsoleFontInfo)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
GetConsoleFontSize(IN HANDLE hConsoleOutput,IN DWORD nFont)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
GetConsoleHardwareState(HANDLE hConsoleOutput,PDWORD Flags,PDWORD State)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
GetConsoleInputWaitHandle(VOID)683 GetConsoleInputWaitHandle(VOID)
684 {
685     return InputWaitHandle;
686 }
687 
688 
689 /*
690  * @implemented
691  */
692 BOOL
693 WINAPI
GetCurrentConsoleFont(IN HANDLE hConsoleOutput,IN BOOL bMaximumWindow,OUT PCONSOLE_FONT_INFO lpConsoleCurrentFont)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
GetNumberOfConsoleFonts(VOID)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
InvalidateConsoleDIBits(IN HANDLE hConsoleOutput,IN PSMALL_RECT lpRect)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
OpenConsoleW(LPCWSTR wsName,DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwShareMode)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
SetConsoleCursor(HANDLE hConsoleOutput,HCURSOR hCursor)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
SetConsoleDisplayMode(HANDLE hConsoleOutput,DWORD dwFlags,PCOORD lpNewScreenBufferDimensions)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
SetConsoleFont(IN HANDLE hConsoleOutput,IN DWORD nFont)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
SetConsoleHardwareState(HANDLE hConsoleOutput,DWORD Flags,DWORD State)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
SetConsoleKeyShortcuts(DWORD Unknown0,DWORD Unknown1,DWORD Unknown2,DWORD Unknown3)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
SetConsoleMaximumWindowSize(HANDLE hConsoleOutput,COORD dwMaximumSize)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
SetConsoleMenuClose(BOOL bEnable)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
SetConsolePalette(HANDLE hConsoleOutput,HPALETTE hPalette,UINT dwUsage)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
ShowConsoleCursor(HANDLE hConsoleOutput,BOOL bShow)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
VerifyConsoleIoHandle(HANDLE hIoHandle)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
CloseConsoleHandle(HANDLE hHandle)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
GetStdHandle(DWORD nStdHandle)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
SetStdHandle(DWORD nStdHandle,HANDLE hHandle)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
IntAllocConsole(LPWSTR Title,DWORD TitleLength,LPWSTR Desktop,DWORD DesktopLength,LPWSTR CurDir,DWORD CurDirLength,LPWSTR AppName,DWORD AppNameLength,LPTHREAD_START_ROUTINE CtrlRoutine,LPTHREAD_START_ROUTINE PropRoutine,PCONSOLE_START_INFO ConsoleStartInfo)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
AllocConsole(VOID)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     RtlEnterCriticalSection(&ConsoleLock);
1379 
1380     if (NtCurrentPeb()->ProcessParameters->ConsoleHandle)
1381     {
1382         DPRINT1("AllocConsole: Allocating a console to a process already having one\n");
1383         SetLastError(ERROR_ACCESS_DENIED);
1384         Success = FALSE;
1385         goto Quit;
1386     }
1387 
1388     /* Set up the console properties */
1389     SetUpConsoleInfo(FALSE,
1390                      &TitleLength,
1391                      &ConsoleTitle,
1392                      &DesktopLength,
1393                      &Desktop,
1394                      &ConsoleStartInfo);
1395     DPRINT("ConsoleTitle = '%S' - Desktop = '%S'\n",
1396            ConsoleTitle, Desktop);
1397 
1398     /* Initialize the Input EXE name */
1399     InitExeName();
1400     SetUpAppName(FALSE,
1401                  &CurDirLength,
1402                  &CurDir,
1403                  &AppNameLength,
1404                  &AppName);
1405     DPRINT("CurDir = '%S' - AppName = '%S'\n",
1406            CurDir, AppName);
1407 
1408     Success = IntAllocConsole(ConsoleTitle,
1409                               TitleLength,
1410                               Desktop,
1411                               DesktopLength,
1412                               CurDir,
1413                               CurDirLength,
1414                               AppName,
1415                               AppNameLength,
1416                               ConsoleControlDispatcher,
1417                               PropDialogHandler,
1418                               &ConsoleStartInfo);
1419     if (Success)
1420     {
1421         /* Set up the handles */
1422         SetUpHandles(&ConsoleStartInfo);
1423         InputWaitHandle = ConsoleStartInfo.InputWaitHandle;
1424 
1425         /* Initialize Console Ctrl Handling */
1426         InitializeCtrlHandling();
1427 
1428         /* Sync the current thread's LangId with the console's one */
1429         SetTEBLangID();
1430     }
1431 
1432 Quit:
1433     RtlLeaveCriticalSection(&ConsoleLock);
1434     return Success;
1435 }
1436 
1437 
1438 /*
1439  * @implemented
1440  */
1441 BOOL
1442 WINAPI
1443 DECLSPEC_HOTPATCH
FreeConsole(VOID)1444 FreeConsole(VOID)
1445 {
1446     BOOL Success = TRUE;
1447     CONSOLE_API_MESSAGE ApiMessage;
1448     PCONSOLE_FREECONSOLE FreeConsoleRequest = &ApiMessage.Data.FreeConsoleRequest;
1449     HANDLE ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1450 
1451     RtlEnterCriticalSection(&ConsoleLock);
1452 
1453     /* We must have a non-trivial handle to close */
1454     if (ConsoleHandle == NULL) // IsConsoleHandle(ConsoleHandle)
1455     {
1456         SetLastError(ERROR_INVALID_PARAMETER);
1457         Success = FALSE;
1458         goto Quit;
1459     }
1460 
1461     /* Set up the data to send to the Console Server */
1462     FreeConsoleRequest->ConsoleHandle = ConsoleHandle;
1463 
1464     /* Call the server */
1465     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1466                         NULL,
1467                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFree),
1468                         sizeof(*FreeConsoleRequest));
1469 
1470     /* Check for success */
1471     if (!NT_SUCCESS(ApiMessage.Status))
1472     {
1473         BaseSetLastNTError(ApiMessage.Status);
1474         Success = FALSE;
1475         goto Quit;
1476     }
1477 
1478     /* Reset the console handle */
1479     NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
1480 
1481     /* Close the associated input handle */
1482     CloseHandle(InputWaitHandle);
1483     InputWaitHandle = INVALID_HANDLE_VALUE;
1484 
1485 Quit:
1486     RtlLeaveCriticalSection(&ConsoleLock);
1487     return Success;
1488 }
1489 
1490 
1491 /*
1492  * @implemented
1493  */
1494 BOOL
1495 WINAPI
GetConsoleScreenBufferInfo(HANDLE hConsoleOutput,PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)1496 GetConsoleScreenBufferInfo(HANDLE hConsoleOutput,
1497                            PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)
1498 {
1499     CONSOLE_API_MESSAGE ApiMessage;
1500     PCONSOLE_GETSCREENBUFFERINFO ScreenBufferInfoRequest = &ApiMessage.Data.ScreenBufferInfoRequest;
1501 
1502     if (lpConsoleScreenBufferInfo == NULL)
1503     {
1504         SetLastError(ERROR_INVALID_PARAMETER);
1505         return FALSE;
1506     }
1507 
1508     ScreenBufferInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1509     ScreenBufferInfoRequest->OutputHandle  = hConsoleOutput;
1510 
1511     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1512                         NULL,
1513                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetScreenBufferInfo),
1514                         sizeof(*ScreenBufferInfoRequest));
1515     if (!NT_SUCCESS(ApiMessage.Status))
1516     {
1517         BaseSetLastNTError(ApiMessage.Status);
1518         return FALSE;
1519     }
1520 
1521     lpConsoleScreenBufferInfo->dwSize              = ScreenBufferInfoRequest->ScreenBufferSize;
1522     lpConsoleScreenBufferInfo->dwCursorPosition    = ScreenBufferInfoRequest->CursorPosition;
1523     lpConsoleScreenBufferInfo->wAttributes         = ScreenBufferInfoRequest->Attributes;
1524     lpConsoleScreenBufferInfo->srWindow.Left       = ScreenBufferInfoRequest->ViewOrigin.X;
1525     lpConsoleScreenBufferInfo->srWindow.Top        = ScreenBufferInfoRequest->ViewOrigin.Y;
1526     lpConsoleScreenBufferInfo->srWindow.Right      = ScreenBufferInfoRequest->ViewOrigin.X + ScreenBufferInfoRequest->ViewSize.X - 1;
1527     lpConsoleScreenBufferInfo->srWindow.Bottom     = ScreenBufferInfoRequest->ViewOrigin.Y + ScreenBufferInfoRequest->ViewSize.Y - 1;
1528     lpConsoleScreenBufferInfo->dwMaximumWindowSize = ScreenBufferInfoRequest->MaximumViewSize;
1529 
1530     return TRUE;
1531 }
1532 
1533 
1534 /*
1535  * @implemented
1536  */
1537 BOOL
1538 WINAPI
1539 DECLSPEC_HOTPATCH
SetConsoleCursorPosition(HANDLE hConsoleOutput,COORD dwCursorPosition)1540 SetConsoleCursorPosition(HANDLE hConsoleOutput,
1541                          COORD dwCursorPosition)
1542 {
1543     CONSOLE_API_MESSAGE ApiMessage;
1544     PCONSOLE_SETCURSORPOSITION SetCursorPositionRequest = &ApiMessage.Data.SetCursorPositionRequest;
1545 
1546     SetCursorPositionRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1547     SetCursorPositionRequest->OutputHandle  = hConsoleOutput;
1548     SetCursorPositionRequest->Position      = dwCursorPosition;
1549 
1550     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1551                         NULL,
1552                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCursorPosition),
1553                         sizeof(*SetCursorPositionRequest));
1554     if (!NT_SUCCESS(ApiMessage.Status))
1555     {
1556         BaseSetLastNTError(ApiMessage.Status);
1557         return FALSE;
1558     }
1559 
1560     return TRUE;
1561 }
1562 
1563 
1564 /*
1565  * @implemented
1566  */
1567 BOOL
1568 WINAPI
GetConsoleMode(HANDLE hConsoleHandle,LPDWORD lpMode)1569 GetConsoleMode(HANDLE hConsoleHandle,
1570                LPDWORD lpMode)
1571 {
1572     CONSOLE_API_MESSAGE ApiMessage;
1573     PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &ApiMessage.Data.ConsoleModeRequest;
1574 
1575     if (lpMode == NULL)
1576     {
1577         SetLastError(ERROR_INVALID_PARAMETER);
1578         return FALSE;
1579     }
1580 
1581     ConsoleModeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1582     ConsoleModeRequest->Handle        = hConsoleHandle;
1583 
1584     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1585                         NULL,
1586                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetMode),
1587                         sizeof(*ConsoleModeRequest));
1588     if (!NT_SUCCESS(ApiMessage.Status))
1589     {
1590         BaseSetLastNTError(ApiMessage.Status);
1591         return FALSE;
1592     }
1593 
1594     *lpMode = ConsoleModeRequest->Mode;
1595 
1596     return TRUE;
1597 }
1598 
1599 
1600 /*
1601  * @implemented
1602  */
1603 BOOL
1604 WINAPI
1605 DECLSPEC_HOTPATCH
SetConsoleMode(HANDLE hConsoleHandle,DWORD dwMode)1606 SetConsoleMode(HANDLE hConsoleHandle,
1607                DWORD dwMode)
1608 {
1609     CONSOLE_API_MESSAGE ApiMessage;
1610     PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &ApiMessage.Data.ConsoleModeRequest;
1611 
1612     ConsoleModeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1613     ConsoleModeRequest->Handle        = hConsoleHandle;
1614     ConsoleModeRequest->Mode          = dwMode;
1615 
1616     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1617                         NULL,
1618                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetMode),
1619                         sizeof(*ConsoleModeRequest));
1620     if (!NT_SUCCESS(ApiMessage.Status))
1621     {
1622         BaseSetLastNTError(ApiMessage.Status);
1623         return FALSE;
1624     }
1625 
1626     return TRUE;
1627 }
1628 
1629 
1630 /*
1631  * @implemented
1632  */
1633 BOOL
1634 WINAPI
GetNumberOfConsoleInputEvents(HANDLE hConsoleInput,LPDWORD lpNumberOfEvents)1635 GetNumberOfConsoleInputEvents(HANDLE hConsoleInput,
1636                               LPDWORD lpNumberOfEvents)
1637 {
1638     CONSOLE_API_MESSAGE ApiMessage;
1639     PCONSOLE_GETNUMINPUTEVENTS GetNumInputEventsRequest = &ApiMessage.Data.GetNumInputEventsRequest;
1640 
1641     GetNumInputEventsRequest->ConsoleHandle  = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1642     GetNumInputEventsRequest->InputHandle    = hConsoleInput;
1643     GetNumInputEventsRequest->NumberOfEvents = 0;
1644 
1645     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1646                         NULL,
1647                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetNumberOfInputEvents),
1648                         sizeof(*GetNumInputEventsRequest));
1649     if (!NT_SUCCESS(ApiMessage.Status))
1650     {
1651         BaseSetLastNTError(ApiMessage.Status);
1652         return FALSE;
1653     }
1654 
1655     if (lpNumberOfEvents == NULL)
1656     {
1657         SetLastError(ERROR_INVALID_ACCESS);
1658         return FALSE;
1659     }
1660 
1661     *lpNumberOfEvents = GetNumInputEventsRequest->NumberOfEvents;
1662 
1663     return TRUE;
1664 }
1665 
1666 
1667 /*
1668  * @implemented
1669  */
1670 COORD
1671 WINAPI
1672 DECLSPEC_HOTPATCH
GetLargestConsoleWindowSize(HANDLE hConsoleOutput)1673 GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
1674 {
1675     CONSOLE_API_MESSAGE ApiMessage;
1676     PCONSOLE_GETLARGESTWINDOWSIZE GetLargestWindowSizeRequest = &ApiMessage.Data.GetLargestWindowSizeRequest;
1677 
1678     GetLargestWindowSizeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1679     GetLargestWindowSizeRequest->OutputHandle  = hConsoleOutput;
1680     GetLargestWindowSizeRequest->Size.X = 0;
1681     GetLargestWindowSizeRequest->Size.Y = 0;
1682 
1683     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1684                         NULL,
1685                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetLargestWindowSize),
1686                         sizeof(*GetLargestWindowSizeRequest));
1687     if (!NT_SUCCESS(ApiMessage.Status))
1688     {
1689         BaseSetLastNTError(ApiMessage.Status);
1690     }
1691 
1692     DPRINT("GetLargestConsoleWindowSize, X = %d, Y = %d\n", GetLargestWindowSizeRequest->Size.X, GetLargestWindowSizeRequest->Size.Y);
1693     return GetLargestWindowSizeRequest->Size;
1694 }
1695 
1696 
1697 /*
1698  * @implemented
1699  */
1700 BOOL
1701 WINAPI
GetConsoleCursorInfo(HANDLE hConsoleOutput,PCONSOLE_CURSOR_INFO lpConsoleCursorInfo)1702 GetConsoleCursorInfo(HANDLE hConsoleOutput,
1703                      PCONSOLE_CURSOR_INFO lpConsoleCursorInfo)
1704 {
1705     CONSOLE_API_MESSAGE ApiMessage;
1706     PCONSOLE_GETSETCURSORINFO CursorInfoRequest = &ApiMessage.Data.CursorInfoRequest;
1707 
1708     if (!lpConsoleCursorInfo)
1709     {
1710         if (!hConsoleOutput)
1711             SetLastError(ERROR_INVALID_HANDLE);
1712         else
1713             SetLastError(ERROR_INVALID_ACCESS);
1714 
1715         return FALSE;
1716     }
1717 
1718     CursorInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1719     CursorInfoRequest->OutputHandle  = hConsoleOutput;
1720 
1721     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1722                         NULL,
1723                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCursorInfo),
1724                         sizeof(*CursorInfoRequest));
1725     if (!NT_SUCCESS(ApiMessage.Status))
1726     {
1727         BaseSetLastNTError(ApiMessage.Status);
1728         return FALSE;
1729     }
1730 
1731     *lpConsoleCursorInfo = CursorInfoRequest->Info;
1732 
1733     return TRUE;
1734 }
1735 
1736 
1737 /*
1738  * @implemented
1739  */
1740 BOOL
1741 WINAPI
SetConsoleCursorInfo(HANDLE hConsoleOutput,CONST CONSOLE_CURSOR_INFO * lpConsoleCursorInfo)1742 SetConsoleCursorInfo(HANDLE hConsoleOutput,
1743                      CONST CONSOLE_CURSOR_INFO *lpConsoleCursorInfo)
1744 {
1745     CONSOLE_API_MESSAGE ApiMessage;
1746     PCONSOLE_GETSETCURSORINFO CursorInfoRequest = &ApiMessage.Data.CursorInfoRequest;
1747 
1748     CursorInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1749     CursorInfoRequest->OutputHandle  = hConsoleOutput;
1750     CursorInfoRequest->Info          = *lpConsoleCursorInfo;
1751 
1752     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1753                         NULL,
1754                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCursorInfo),
1755                         sizeof(*CursorInfoRequest));
1756     if (!NT_SUCCESS(ApiMessage.Status))
1757     {
1758         BaseSetLastNTError(ApiMessage.Status);
1759         return FALSE;
1760     }
1761 
1762     return TRUE;
1763 }
1764 
1765 
1766 /*
1767  * @implemented
1768  */
1769 BOOL
1770 WINAPI
GetNumberOfConsoleMouseButtons(LPDWORD lpNumberOfMouseButtons)1771 GetNumberOfConsoleMouseButtons(LPDWORD lpNumberOfMouseButtons)
1772 {
1773     CONSOLE_API_MESSAGE ApiMessage;
1774     PCONSOLE_GETMOUSEINFO GetMouseInfoRequest = &ApiMessage.Data.GetMouseInfoRequest;
1775 
1776     GetMouseInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1777 
1778     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1779                         NULL,
1780                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetMouseInfo),
1781                         sizeof(*GetMouseInfoRequest));
1782     if (!NT_SUCCESS(ApiMessage.Status))
1783     {
1784         BaseSetLastNTError(ApiMessage.Status);
1785         return FALSE;
1786     }
1787 
1788     *lpNumberOfMouseButtons = GetMouseInfoRequest->NumButtons;
1789     return TRUE;
1790 }
1791 
1792 
1793 /*
1794  * @implemented
1795  */
1796 BOOL
1797 WINAPI
1798 DECLSPEC_HOTPATCH
SetConsoleActiveScreenBuffer(HANDLE hConsoleOutput)1799 SetConsoleActiveScreenBuffer(HANDLE hConsoleOutput)
1800 {
1801     CONSOLE_API_MESSAGE ApiMessage;
1802     PCONSOLE_SETACTIVESCREENBUFFER SetScreenBufferRequest = &ApiMessage.Data.SetScreenBufferRequest;
1803 
1804     SetScreenBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1805     SetScreenBufferRequest->OutputHandle  = hConsoleOutput;
1806 
1807     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1808                         NULL,
1809                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetActiveScreenBuffer),
1810                         sizeof(*SetScreenBufferRequest));
1811     if (!NT_SUCCESS(ApiMessage.Status))
1812     {
1813         BaseSetLastNTError(ApiMessage.Status);
1814         return FALSE;
1815     }
1816 
1817     return TRUE;
1818 }
1819 
1820 
1821 /*
1822  * @implemented
1823  */
1824 BOOL
1825 WINAPI
1826 DECLSPEC_HOTPATCH
FlushConsoleInputBuffer(HANDLE hConsoleInput)1827 FlushConsoleInputBuffer(HANDLE hConsoleInput)
1828 {
1829     CONSOLE_API_MESSAGE ApiMessage;
1830     PCONSOLE_FLUSHINPUTBUFFER FlushInputBufferRequest = &ApiMessage.Data.FlushInputBufferRequest;
1831 
1832     FlushInputBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1833     FlushInputBufferRequest->InputHandle   = hConsoleInput;
1834 
1835     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1836                         NULL,
1837                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFlushInputBuffer),
1838                         sizeof(*FlushInputBufferRequest));
1839     if (!NT_SUCCESS(ApiMessage.Status))
1840     {
1841         BaseSetLastNTError(ApiMessage.Status);
1842         return FALSE;
1843     }
1844 
1845     return TRUE;
1846 }
1847 
1848 
1849 /*
1850  * @implemented
1851  */
1852 BOOL
1853 WINAPI
1854 DECLSPEC_HOTPATCH
SetConsoleScreenBufferSize(HANDLE hConsoleOutput,COORD dwSize)1855 SetConsoleScreenBufferSize(HANDLE hConsoleOutput,
1856                            COORD dwSize)
1857 {
1858     CONSOLE_API_MESSAGE ApiMessage;
1859     PCONSOLE_SETSCREENBUFFERSIZE SetScreenBufferSizeRequest = &ApiMessage.Data.SetScreenBufferSizeRequest;
1860 
1861     SetScreenBufferSizeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1862     SetScreenBufferSizeRequest->OutputHandle  = hConsoleOutput;
1863     SetScreenBufferSizeRequest->Size          = dwSize;
1864 
1865     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1866                         NULL,
1867                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetScreenBufferSize),
1868                         sizeof(*SetScreenBufferSizeRequest));
1869     if (!NT_SUCCESS(ApiMessage.Status))
1870     {
1871         BaseSetLastNTError(ApiMessage.Status);
1872         return FALSE;
1873     }
1874 
1875     return TRUE;
1876 }
1877 
1878 
1879 static
1880 BOOL
IntScrollConsoleScreenBuffer(HANDLE hConsoleOutput,CONST SMALL_RECT * lpScrollRectangle,CONST SMALL_RECT * lpClipRectangle,COORD dwDestinationOrigin,CONST CHAR_INFO * lpFill,BOOL bUnicode)1881 IntScrollConsoleScreenBuffer(HANDLE hConsoleOutput,
1882                              CONST SMALL_RECT* lpScrollRectangle,
1883                              CONST SMALL_RECT* lpClipRectangle,
1884                              COORD dwDestinationOrigin,
1885                              CONST CHAR_INFO* lpFill,
1886                              BOOL bUnicode)
1887 {
1888     CONSOLE_API_MESSAGE ApiMessage;
1889     PCONSOLE_SCROLLSCREENBUFFER ScrollScreenBufferRequest = &ApiMessage.Data.ScrollScreenBufferRequest;
1890 
1891     ScrollScreenBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1892     ScrollScreenBufferRequest->OutputHandle  = hConsoleOutput;
1893     ScrollScreenBufferRequest->ScrollRectangle = *lpScrollRectangle;
1894 
1895     if (lpClipRectangle != NULL)
1896     {
1897         ScrollScreenBufferRequest->UseClipRectangle = TRUE;
1898         ScrollScreenBufferRequest->ClipRectangle = *lpClipRectangle;
1899     }
1900     else
1901     {
1902         ScrollScreenBufferRequest->UseClipRectangle = FALSE;
1903     }
1904 
1905     ScrollScreenBufferRequest->DestinationOrigin = dwDestinationOrigin;
1906     ScrollScreenBufferRequest->Fill    = *lpFill;
1907     ScrollScreenBufferRequest->Unicode = bUnicode;
1908 
1909     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1910                         NULL,
1911                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepScrollScreenBuffer),
1912                         sizeof(*ScrollScreenBufferRequest));
1913     if (!NT_SUCCESS(ApiMessage.Status))
1914     {
1915         BaseSetLastNTError(ApiMessage.Status);
1916         return FALSE;
1917     }
1918 
1919     return TRUE;
1920 }
1921 
1922 
1923 /*
1924  * @implemented
1925  */
1926 BOOL
1927 WINAPI
1928 DECLSPEC_HOTPATCH
ScrollConsoleScreenBufferA(HANDLE hConsoleOutput,CONST SMALL_RECT * lpScrollRectangle,CONST SMALL_RECT * lpClipRectangle,COORD dwDestinationOrigin,CONST CHAR_INFO * lpFill)1929 ScrollConsoleScreenBufferA(HANDLE hConsoleOutput,
1930                            CONST SMALL_RECT* lpScrollRectangle,
1931                            CONST SMALL_RECT* lpClipRectangle,
1932                            COORD dwDestinationOrigin,
1933                            CONST CHAR_INFO* lpFill)
1934 {
1935     return IntScrollConsoleScreenBuffer(hConsoleOutput,
1936                                         lpScrollRectangle,
1937                                         lpClipRectangle,
1938                                         dwDestinationOrigin,
1939                                         lpFill,
1940                                         FALSE);
1941 }
1942 
1943 
1944 /*
1945  * @implemented
1946  */
1947 BOOL
1948 WINAPI
1949 DECLSPEC_HOTPATCH
ScrollConsoleScreenBufferW(HANDLE hConsoleOutput,CONST SMALL_RECT * lpScrollRectangle,CONST SMALL_RECT * lpClipRectangle,COORD dwDestinationOrigin,CONST CHAR_INFO * lpFill)1950 ScrollConsoleScreenBufferW(HANDLE hConsoleOutput,
1951                            CONST SMALL_RECT *lpScrollRectangle,
1952                            CONST SMALL_RECT *lpClipRectangle,
1953                            COORD dwDestinationOrigin,
1954                            CONST CHAR_INFO *lpFill)
1955 {
1956     return IntScrollConsoleScreenBuffer(hConsoleOutput,
1957                                         lpScrollRectangle,
1958                                         lpClipRectangle,
1959                                         dwDestinationOrigin,
1960                                         lpFill,
1961                                         TRUE);
1962 }
1963 
1964 
1965 /*
1966  * @implemented
1967  */
1968 BOOL
1969 WINAPI
SetConsoleWindowInfo(HANDLE hConsoleOutput,BOOL bAbsolute,CONST SMALL_RECT * lpConsoleWindow)1970 SetConsoleWindowInfo(HANDLE hConsoleOutput,
1971                      BOOL bAbsolute,
1972                      CONST SMALL_RECT *lpConsoleWindow)
1973 {
1974     CONSOLE_API_MESSAGE ApiMessage;
1975     PCONSOLE_SETWINDOWINFO SetWindowInfoRequest = &ApiMessage.Data.SetWindowInfoRequest;
1976 
1977     if (lpConsoleWindow == NULL)
1978     {
1979         SetLastError(ERROR_INVALID_PARAMETER);
1980         return FALSE;
1981     }
1982 
1983     SetWindowInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1984     SetWindowInfoRequest->OutputHandle  = hConsoleOutput;
1985     SetWindowInfoRequest->Absolute      = bAbsolute;
1986     SetWindowInfoRequest->WindowRect    = *lpConsoleWindow;
1987 
1988     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1989                         NULL,
1990                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetWindowInfo),
1991                         sizeof(*SetWindowInfoRequest));
1992     if (!NT_SUCCESS(ApiMessage.Status))
1993     {
1994         BaseSetLastNTError(ApiMessage.Status);
1995         return FALSE;
1996     }
1997 
1998     return TRUE;
1999 }
2000 
2001 
2002 /*
2003  * @implemented
2004  */
2005 BOOL
2006 WINAPI
2007 DECLSPEC_HOTPATCH
SetConsoleTextAttribute(HANDLE hConsoleOutput,WORD wAttributes)2008 SetConsoleTextAttribute(HANDLE hConsoleOutput,
2009                         WORD wAttributes)
2010 {
2011     CONSOLE_API_MESSAGE ApiMessage;
2012     PCONSOLE_SETTEXTATTRIB SetTextAttribRequest = &ApiMessage.Data.SetTextAttribRequest;
2013 
2014     SetTextAttribRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2015     SetTextAttribRequest->OutputHandle  = hConsoleOutput;
2016     SetTextAttribRequest->Attributes    = wAttributes;
2017 
2018     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2019                         NULL,
2020                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetTextAttribute),
2021                         sizeof(*SetTextAttribRequest));
2022     if (!NT_SUCCESS(ApiMessage.Status))
2023     {
2024         BaseSetLastNTError(ApiMessage.Status);
2025         return FALSE;
2026     }
2027 
2028     return TRUE;
2029 }
2030 
2031 
2032 static
2033 BOOL
AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)2034 AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
2035 {
2036     PHANDLER_ROUTINE* NewCtrlHandlers = NULL;
2037 
2038     if (HandlerRoutine == NULL)
2039     {
2040         NtCurrentPeb()->ProcessParameters->ConsoleFlags = TRUE;
2041         return TRUE;
2042     }
2043 
2044     if (NrCtrlHandlers == NrAllocatedHandlers)
2045     {
2046         NewCtrlHandlers = RtlAllocateHeap(RtlGetProcessHeap(),
2047                                           0,
2048                                           (NrCtrlHandlers + 4) * sizeof(PHANDLER_ROUTINE));
2049         if (NewCtrlHandlers == NULL)
2050         {
2051             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2052             return FALSE;
2053         }
2054 
2055         memmove(NewCtrlHandlers, CtrlHandlers, sizeof(PHANDLER_ROUTINE) * NrCtrlHandlers);
2056 
2057         if (NrAllocatedHandlers > 1) RtlFreeHeap(RtlGetProcessHeap(), 0, CtrlHandlers);
2058 
2059         CtrlHandlers = NewCtrlHandlers;
2060         NrAllocatedHandlers += 4;
2061     }
2062 
2063     ASSERT(NrCtrlHandlers < NrAllocatedHandlers);
2064 
2065     CtrlHandlers[NrCtrlHandlers++] = HandlerRoutine;
2066     return TRUE;
2067 }
2068 
2069 
2070 static
2071 BOOL
RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)2072 RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
2073 {
2074     ULONG i;
2075 
2076     if (HandlerRoutine == NULL)
2077     {
2078         NtCurrentPeb()->ProcessParameters->ConsoleFlags = FALSE;
2079         return TRUE;
2080     }
2081 
2082     for (i = 0; i < NrCtrlHandlers; i++)
2083     {
2084         if (CtrlHandlers[i] == HandlerRoutine)
2085         {
2086             if (i < (NrCtrlHandlers - 1))
2087             {
2088                 memmove(&CtrlHandlers[i],
2089                         &CtrlHandlers[i+1],
2090                         (NrCtrlHandlers - i + 1) * sizeof(PHANDLER_ROUTINE));
2091             }
2092 
2093             NrCtrlHandlers--;
2094             return TRUE;
2095         }
2096     }
2097 
2098     SetLastError(ERROR_INVALID_PARAMETER);
2099     return FALSE;
2100 }
2101 
2102 
2103 /*
2104  * @implemented
2105  */
2106 BOOL
2107 WINAPI
2108 DECLSPEC_HOTPATCH
SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine,BOOL Add)2109 SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine,
2110                       BOOL Add)
2111 {
2112     BOOL Ret;
2113 
2114     RtlEnterCriticalSection(&ConsoleLock);
2115 
2116     if (Add)
2117         Ret = AddConsoleCtrlHandler(HandlerRoutine);
2118     else
2119         Ret = RemoveConsoleCtrlHandler(HandlerRoutine);
2120 
2121     RtlLeaveCriticalSection(&ConsoleLock);
2122     return Ret;
2123 }
2124 
2125 
2126 /*
2127  * @implemented
2128  */
2129 BOOL
2130 WINAPI
2131 DECLSPEC_HOTPATCH
GenerateConsoleCtrlEvent(DWORD dwCtrlEvent,DWORD dwProcessGroupId)2132 GenerateConsoleCtrlEvent(DWORD dwCtrlEvent,
2133                          DWORD dwProcessGroupId)
2134 {
2135     CONSOLE_API_MESSAGE ApiMessage;
2136     PCONSOLE_GENERATECTRLEVENT GenerateCtrlEventRequest = &ApiMessage.Data.GenerateCtrlEventRequest;
2137 
2138     if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT)
2139     {
2140         SetLastError(ERROR_INVALID_PARAMETER);
2141         return FALSE;
2142     }
2143 
2144     GenerateCtrlEventRequest->ConsoleHandle  = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2145     GenerateCtrlEventRequest->CtrlEvent      = dwCtrlEvent;
2146     GenerateCtrlEventRequest->ProcessGroupId = dwProcessGroupId;
2147 
2148     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2149                         NULL,
2150                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGenerateCtrlEvent),
2151                         sizeof(*GenerateCtrlEventRequest));
2152     if (!NT_SUCCESS(ApiMessage.Status))
2153     {
2154         BaseSetLastNTError(ApiMessage.Status);
2155         return FALSE;
2156     }
2157 
2158     return TRUE;
2159 }
2160 
2161 
2162 static DWORD
IntGetConsoleTitle(LPVOID lpConsoleTitle,DWORD dwNumChars,BOOLEAN bUnicode)2163 IntGetConsoleTitle(LPVOID lpConsoleTitle, DWORD dwNumChars, BOOLEAN bUnicode)
2164 {
2165     CONSOLE_API_MESSAGE ApiMessage;
2166     PCONSOLE_GETSETCONSOLETITLE TitleRequest = &ApiMessage.Data.TitleRequest;
2167     PCSR_CAPTURE_BUFFER CaptureBuffer;
2168 
2169     if (dwNumChars == 0) return 0;
2170 
2171     TitleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2172     TitleRequest->Length        = dwNumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
2173     TitleRequest->Unicode       = bUnicode;
2174 
2175     CaptureBuffer = CsrAllocateCaptureBuffer(1, TitleRequest->Length);
2176     if (CaptureBuffer == NULL)
2177     {
2178         DPRINT1("CsrAllocateCaptureBuffer failed!\n");
2179         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2180         return 0;
2181     }
2182 
2183     CsrAllocateMessagePointer(CaptureBuffer,
2184                               TitleRequest->Length,
2185                               (PVOID*)&TitleRequest->Title);
2186 
2187     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2188                         CaptureBuffer,
2189                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetTitle),
2190                         sizeof(*TitleRequest));
2191     if (!NT_SUCCESS(ApiMessage.Status))
2192     {
2193         CsrFreeCaptureBuffer(CaptureBuffer);
2194         BaseSetLastNTError(ApiMessage.Status);
2195         return 0;
2196     }
2197 
2198     dwNumChars = TitleRequest->Length / (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
2199 
2200     if (dwNumChars > 0)
2201     {
2202         RtlCopyMemory(lpConsoleTitle, TitleRequest->Title, TitleRequest->Length);
2203 
2204         if (bUnicode)
2205             ((LPWSTR)lpConsoleTitle)[dwNumChars] = UNICODE_NULL;
2206         else
2207             ((LPSTR)lpConsoleTitle)[dwNumChars] = ANSI_NULL;
2208     }
2209 
2210     CsrFreeCaptureBuffer(CaptureBuffer);
2211 
2212     return dwNumChars;
2213 }
2214 
2215 
2216 /*
2217  * @implemented
2218  */
2219 DWORD
2220 WINAPI
2221 DECLSPEC_HOTPATCH
GetConsoleTitleW(LPWSTR lpConsoleTitle,DWORD nSize)2222 GetConsoleTitleW(LPWSTR lpConsoleTitle,
2223                  DWORD nSize)
2224 {
2225     return IntGetConsoleTitle(lpConsoleTitle, nSize, TRUE);
2226 }
2227 
2228 
2229 /*
2230  * @implemented
2231  */
2232 DWORD
2233 WINAPI
2234 DECLSPEC_HOTPATCH
GetConsoleTitleA(LPSTR lpConsoleTitle,DWORD nSize)2235 GetConsoleTitleA(LPSTR lpConsoleTitle,
2236                  DWORD nSize)
2237 {
2238     return IntGetConsoleTitle(lpConsoleTitle, nSize, FALSE);
2239 }
2240 
2241 
2242 static BOOL
IntSetConsoleTitle(CONST VOID * lpConsoleTitle,BOOLEAN bUnicode)2243 IntSetConsoleTitle(CONST VOID *lpConsoleTitle, BOOLEAN bUnicode)
2244 {
2245     CONSOLE_API_MESSAGE ApiMessage;
2246     PCONSOLE_GETSETCONSOLETITLE TitleRequest = &ApiMessage.Data.TitleRequest;
2247     PCSR_CAPTURE_BUFFER CaptureBuffer;
2248 
2249     ULONG NumChars = (ULONG)(lpConsoleTitle ? (bUnicode ? wcslen(lpConsoleTitle) : strlen(lpConsoleTitle)) : 0);
2250 
2251     TitleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2252     TitleRequest->Length        = NumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
2253     TitleRequest->Unicode       = bUnicode;
2254 
2255     CaptureBuffer = CsrAllocateCaptureBuffer(1, TitleRequest->Length);
2256     if (CaptureBuffer == NULL)
2257     {
2258         DPRINT1("CsrAllocateCaptureBuffer failed!\n");
2259         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2260         return FALSE;
2261     }
2262 
2263     CsrCaptureMessageBuffer(CaptureBuffer,
2264                             (PVOID)lpConsoleTitle,
2265                             TitleRequest->Length,
2266                             (PVOID*)&TitleRequest->Title);
2267 
2268     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2269                         CaptureBuffer,
2270                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetTitle),
2271                         sizeof(*TitleRequest));
2272 
2273     CsrFreeCaptureBuffer(CaptureBuffer);
2274 
2275     if (!NT_SUCCESS(ApiMessage.Status))
2276     {
2277         BaseSetLastNTError(ApiMessage.Status);
2278         return FALSE;
2279     }
2280 
2281     return TRUE;
2282 }
2283 
2284 /*
2285  * @implemented
2286  */
2287 BOOL
2288 WINAPI
2289 DECLSPEC_HOTPATCH
SetConsoleTitleW(LPCWSTR lpConsoleTitle)2290 SetConsoleTitleW(LPCWSTR lpConsoleTitle)
2291 {
2292     return IntSetConsoleTitle(lpConsoleTitle, TRUE);
2293 }
2294 
2295 
2296 /*
2297  * @implemented
2298  */
2299 BOOL
2300 WINAPI
2301 DECLSPEC_HOTPATCH
SetConsoleTitleA(LPCSTR lpConsoleTitle)2302 SetConsoleTitleA(LPCSTR lpConsoleTitle)
2303 {
2304     return IntSetConsoleTitle(lpConsoleTitle, FALSE);
2305 }
2306 
2307 
2308 /*
2309  * @implemented
2310  */
2311 HANDLE
2312 WINAPI
CreateConsoleScreenBuffer(DWORD dwDesiredAccess,DWORD dwShareMode,CONST SECURITY_ATTRIBUTES * lpSecurityAttributes,DWORD dwFlags,LPVOID lpScreenBufferData)2313 CreateConsoleScreenBuffer(DWORD dwDesiredAccess,
2314                           DWORD dwShareMode,
2315                           CONST SECURITY_ATTRIBUTES *lpSecurityAttributes,
2316                           DWORD dwFlags,
2317                           LPVOID lpScreenBufferData)
2318 {
2319     CONSOLE_API_MESSAGE ApiMessage;
2320     PCONSOLE_CREATESCREENBUFFER CreateScreenBufferRequest = &ApiMessage.Data.CreateScreenBufferRequest;
2321     PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
2322     PCONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo = lpScreenBufferData;
2323 
2324     if ( (dwDesiredAccess & ~(GENERIC_READ | GENERIC_WRITE))    ||
2325          (dwShareMode & ~(FILE_SHARE_READ | FILE_SHARE_WRITE))  ||
2326          (dwFlags != CONSOLE_TEXTMODE_BUFFER && dwFlags != CONSOLE_GRAPHICS_BUFFER) )
2327     {
2328         SetLastError(ERROR_INVALID_PARAMETER);
2329         return INVALID_HANDLE_VALUE;
2330     }
2331 
2332     CreateScreenBufferRequest->ConsoleHandle    = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2333     CreateScreenBufferRequest->DesiredAccess    = dwDesiredAccess;
2334     CreateScreenBufferRequest->InheritHandle    =
2335         (lpSecurityAttributes ? lpSecurityAttributes->bInheritHandle : FALSE);
2336     CreateScreenBufferRequest->ShareMode        = dwShareMode;
2337     CreateScreenBufferRequest->ScreenBufferType = dwFlags;
2338 
2339     if (dwFlags == CONSOLE_GRAPHICS_BUFFER)
2340     {
2341         if (CreateScreenBufferRequest->InheritHandle || GraphicsBufferInfo == NULL)
2342         {
2343             SetLastError(ERROR_INVALID_PARAMETER);
2344             return INVALID_HANDLE_VALUE;
2345         }
2346 
2347         CreateScreenBufferRequest->GraphicsBufferInfo = *GraphicsBufferInfo;
2348 
2349         CaptureBuffer = CsrAllocateCaptureBuffer(1, GraphicsBufferInfo->dwBitMapInfoLength);
2350         if (CaptureBuffer == NULL)
2351         {
2352             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2353             return INVALID_HANDLE_VALUE;
2354         }
2355 
2356         CsrCaptureMessageBuffer(CaptureBuffer,
2357                                 (PVOID)GraphicsBufferInfo->lpBitMapInfo,
2358                                 GraphicsBufferInfo->dwBitMapInfoLength,
2359                                 (PVOID*)&CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMapInfo);
2360     }
2361 
2362     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2363                         CaptureBuffer,
2364                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepCreateScreenBuffer),
2365                         sizeof(*CreateScreenBufferRequest));
2366 
2367     if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
2368 
2369     if (!NT_SUCCESS(ApiMessage.Status))
2370     {
2371         BaseSetLastNTError(ApiMessage.Status);
2372         return INVALID_HANDLE_VALUE;
2373     }
2374 
2375     if (dwFlags == CONSOLE_GRAPHICS_BUFFER && GraphicsBufferInfo)
2376     {
2377         GraphicsBufferInfo->hMutex   = CreateScreenBufferRequest->hMutex  ; // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex  ;
2378         GraphicsBufferInfo->lpBitMap = CreateScreenBufferRequest->lpBitMap; // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap;
2379     }
2380 
2381     return CreateScreenBufferRequest->OutputHandle;
2382 }
2383 
2384 
2385 /*
2386  * @implemented
2387  */
2388 UINT
2389 WINAPI
2390 DECLSPEC_HOTPATCH
GetConsoleCP(VOID)2391 GetConsoleCP(VOID)
2392 {
2393     CONSOLE_API_MESSAGE ApiMessage;
2394     PCONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest = &ApiMessage.Data.GetConsoleCPRequest;
2395 
2396     /* Get the Input Code Page */
2397     GetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2398     GetConsoleCPRequest->OutputCP      = FALSE;
2399 
2400     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2401                         NULL,
2402                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCP),
2403                         sizeof(*GetConsoleCPRequest));
2404     if (!NT_SUCCESS(ApiMessage.Status))
2405     {
2406         BaseSetLastNTError(ApiMessage.Status);
2407         return 0;
2408     }
2409 
2410     return GetConsoleCPRequest->CodePage;
2411 }
2412 
2413 
2414 /*
2415  * @implemented
2416  */
2417 BOOL
2418 WINAPI
2419 DECLSPEC_HOTPATCH
SetConsoleCP(UINT wCodePageID)2420 SetConsoleCP(UINT wCodePageID)
2421 {
2422     CONSOLE_API_MESSAGE ApiMessage;
2423     PCONSOLE_SETINPUTOUTPUTCP SetConsoleCPRequest = &ApiMessage.Data.SetConsoleCPRequest;
2424 
2425     /* Set the Input Code Page */
2426     SetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2427     SetConsoleCPRequest->CodePage      = wCodePageID;
2428     SetConsoleCPRequest->OutputCP      = FALSE;
2429     /* SetConsoleCPRequest->EventHandle; */
2430 
2431     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2432                         NULL,
2433                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCP),
2434                         sizeof(*SetConsoleCPRequest));
2435     if (!NT_SUCCESS(ApiMessage.Status))
2436     {
2437         BaseSetLastNTError(ApiMessage.Status);
2438         return FALSE;
2439     }
2440 
2441     return TRUE;
2442 }
2443 
2444 
2445 /*
2446  * @implemented
2447  */
2448 UINT
2449 WINAPI
2450 DECLSPEC_HOTPATCH
GetConsoleOutputCP(VOID)2451 GetConsoleOutputCP(VOID)
2452 {
2453     CONSOLE_API_MESSAGE ApiMessage;
2454     PCONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest = &ApiMessage.Data.GetConsoleCPRequest;
2455 
2456     /* Get the Output Code Page */
2457     GetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2458     GetConsoleCPRequest->OutputCP      = TRUE;
2459 
2460     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2461                         NULL,
2462                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCP),
2463                         sizeof(*GetConsoleCPRequest));
2464     if (!NT_SUCCESS(ApiMessage.Status))
2465     {
2466         BaseSetLastNTError(ApiMessage.Status);
2467         return 0;
2468     }
2469 
2470     return GetConsoleCPRequest->CodePage;
2471 }
2472 
2473 
2474 /*
2475  * @implemented
2476  */
2477 BOOL
2478 WINAPI
2479 DECLSPEC_HOTPATCH
SetConsoleOutputCP(UINT wCodePageID)2480 SetConsoleOutputCP(UINT wCodePageID)
2481 {
2482     CONSOLE_API_MESSAGE ApiMessage;
2483     PCONSOLE_SETINPUTOUTPUTCP SetConsoleCPRequest = &ApiMessage.Data.SetConsoleCPRequest;
2484 
2485     /* Set the Output Code Page */
2486     SetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2487     SetConsoleCPRequest->CodePage      = wCodePageID;
2488     SetConsoleCPRequest->OutputCP      = TRUE;
2489     /* SetConsoleCPRequest->EventHandle; */
2490 
2491     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2492                         NULL,
2493                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCP),
2494                         sizeof(*SetConsoleCPRequest));
2495     if (!NT_SUCCESS(ApiMessage.Status))
2496     {
2497         BaseSetLastNTError(ApiMessage.Status);
2498         return FALSE;
2499     }
2500 
2501     /* Sync the current thread's LangId with the console's one */
2502     SetTEBLangID();
2503 
2504     return TRUE;
2505 }
2506 
2507 
2508 /*
2509  * @implemented
2510  */
2511 DWORD
2512 WINAPI
GetConsoleProcessList(LPDWORD lpdwProcessList,DWORD dwProcessCount)2513 GetConsoleProcessList(LPDWORD lpdwProcessList,
2514                       DWORD dwProcessCount)
2515 {
2516     CONSOLE_API_MESSAGE ApiMessage;
2517     PCONSOLE_GETPROCESSLIST GetProcessListRequest = &ApiMessage.Data.GetProcessListRequest;
2518     PCSR_CAPTURE_BUFFER CaptureBuffer;
2519     ULONG nProcesses = 0;
2520 
2521     if (lpdwProcessList == NULL || dwProcessCount == 0)
2522     {
2523         SetLastError(ERROR_INVALID_PARAMETER);
2524         return 0;
2525     }
2526 
2527     CaptureBuffer = CsrAllocateCaptureBuffer(1, dwProcessCount * sizeof(DWORD));
2528     if (CaptureBuffer == NULL)
2529     {
2530         DPRINT1("CsrAllocateCaptureBuffer failed!\n");
2531         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2532         return 0;
2533     }
2534 
2535     GetProcessListRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2536     GetProcessListRequest->ProcessCount  = dwProcessCount;
2537 
2538     CsrAllocateMessagePointer(CaptureBuffer,
2539                               dwProcessCount * sizeof(DWORD),
2540                               (PVOID*)&GetProcessListRequest->ProcessIdsList);
2541 
2542     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2543                         CaptureBuffer,
2544                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetProcessList),
2545                         sizeof(*GetProcessListRequest));
2546     if (!NT_SUCCESS(ApiMessage.Status))
2547     {
2548         BaseSetLastNTError(ApiMessage.Status);
2549     }
2550     else
2551     {
2552         nProcesses = GetProcessListRequest->ProcessCount;
2553         if (dwProcessCount >= nProcesses)
2554         {
2555             RtlCopyMemory(lpdwProcessList, GetProcessListRequest->ProcessIdsList, nProcesses * sizeof(DWORD));
2556         }
2557     }
2558 
2559     CsrFreeCaptureBuffer(CaptureBuffer);
2560     return nProcesses;
2561 }
2562 
2563 
2564 /*
2565  * @implemented
2566  */
2567 BOOL
2568 WINAPI
GetConsoleSelectionInfo(PCONSOLE_SELECTION_INFO lpConsoleSelectionInfo)2569 GetConsoleSelectionInfo(PCONSOLE_SELECTION_INFO lpConsoleSelectionInfo)
2570 {
2571     CONSOLE_API_MESSAGE ApiMessage;
2572     PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest = &ApiMessage.Data.GetSelectionInfoRequest;
2573 
2574     if (lpConsoleSelectionInfo == NULL)
2575     {
2576         SetLastError(ERROR_INVALID_PARAMETER);
2577         return FALSE;
2578     }
2579 
2580     GetSelectionInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2581 
2582     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2583                         NULL,
2584                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetSelectionInfo),
2585                         sizeof(*GetSelectionInfoRequest));
2586     if (!NT_SUCCESS(ApiMessage.Status))
2587     {
2588         BaseSetLastNTError(ApiMessage.Status);
2589         return FALSE;
2590     }
2591 
2592     *lpConsoleSelectionInfo = GetSelectionInfoRequest->Info;
2593 
2594     return TRUE;
2595 }
2596 
2597 
2598 /*
2599  * @implemented
2600  * @note Strongly inspired by AllocConsole.
2601  */
2602 static BOOL
IntAttachConsole(DWORD ProcessId,LPTHREAD_START_ROUTINE CtrlRoutine,LPTHREAD_START_ROUTINE PropRoutine,PCONSOLE_START_INFO ConsoleStartInfo)2603 IntAttachConsole(DWORD ProcessId,
2604                  LPTHREAD_START_ROUTINE CtrlRoutine,
2605                  LPTHREAD_START_ROUTINE PropRoutine,
2606                  PCONSOLE_START_INFO ConsoleStartInfo)
2607 {
2608     BOOL Success = TRUE;
2609     NTSTATUS Status;
2610 
2611     CONSOLE_API_MESSAGE ApiMessage;
2612     PCONSOLE_ATTACHCONSOLE AttachConsoleRequest = &ApiMessage.Data.AttachConsoleRequest;
2613     PCSR_CAPTURE_BUFFER CaptureBuffer;
2614 
2615     AttachConsoleRequest->ProcessId   = ProcessId;
2616     AttachConsoleRequest->CtrlRoutine = CtrlRoutine;
2617     AttachConsoleRequest->PropRoutine = PropRoutine;
2618 
2619     CaptureBuffer = CsrAllocateCaptureBuffer(1, sizeof(CONSOLE_START_INFO));
2620     if (CaptureBuffer == NULL)
2621     {
2622         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2623         Success = FALSE;
2624         goto Quit;
2625     }
2626 
2627     CsrCaptureMessageBuffer(CaptureBuffer,
2628                             ConsoleStartInfo,
2629                             sizeof(CONSOLE_START_INFO),
2630                             (PVOID*)&AttachConsoleRequest->ConsoleStartInfo);
2631 
2632     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2633                         CaptureBuffer,
2634                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAttach),
2635                         sizeof(*AttachConsoleRequest));
2636     if (!NT_SUCCESS(ApiMessage.Status))
2637     {
2638         BaseSetLastNTError(ApiMessage.Status);
2639         Success = FALSE;
2640         goto Quit;
2641     }
2642 
2643     // Is AttachConsoleRequest->ConsoleStartInfo->InitEvents aligned on handle boundary ????
2644     Status = NtWaitForMultipleObjects(MAX_INIT_EVENTS,
2645                                       AttachConsoleRequest->ConsoleStartInfo->InitEvents,
2646                                       WaitAny, FALSE, NULL);
2647     if (!NT_SUCCESS(Status))
2648     {
2649         BaseSetLastNTError(Status);
2650         Success = FALSE;
2651         goto Quit;
2652     }
2653 
2654     NtClose(AttachConsoleRequest->ConsoleStartInfo->InitEvents[INIT_SUCCESS]);
2655     NtClose(AttachConsoleRequest->ConsoleStartInfo->InitEvents[INIT_FAILURE]);
2656     if (Status != INIT_SUCCESS)
2657     {
2658         NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
2659         Success = FALSE;
2660     }
2661     else
2662     {
2663         RtlCopyMemory(ConsoleStartInfo,
2664                       AttachConsoleRequest->ConsoleStartInfo,
2665                       sizeof(CONSOLE_START_INFO));
2666         Success = TRUE;
2667     }
2668 
2669 Quit:
2670     if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
2671     return Success;
2672 }
2673 
2674 BOOL
2675 WINAPI
AttachConsole(DWORD dwProcessId)2676 AttachConsole(DWORD dwProcessId)
2677 {
2678     BOOL Success;
2679     CONSOLE_START_INFO ConsoleStartInfo;
2680     DWORD dummy;
2681 
2682     RtlEnterCriticalSection(&ConsoleLock);
2683 
2684     if (NtCurrentPeb()->ProcessParameters->ConsoleHandle)
2685     {
2686         DPRINT1("AttachConsole: Attaching a console to a process already having one\n");
2687         SetLastError(ERROR_ACCESS_DENIED);
2688         Success = FALSE;
2689         goto Quit;
2690     }
2691 
2692     /* Set up the console properties */
2693     SetUpConsoleInfo(FALSE,
2694                      &dummy,
2695                      NULL,
2696                      &dummy,
2697                      NULL,
2698                      &ConsoleStartInfo);
2699 
2700     Success = IntAttachConsole(dwProcessId,
2701                                ConsoleControlDispatcher,
2702                                PropDialogHandler,
2703                                &ConsoleStartInfo);
2704     if (Success)
2705     {
2706         /* Set up the handles */
2707         SetUpHandles(&ConsoleStartInfo);
2708         InputWaitHandle = ConsoleStartInfo.InputWaitHandle;
2709 
2710         /* Initialize Console Ctrl Handling */
2711         InitializeCtrlHandling();
2712 
2713         /* Sync the current thread's LangId with the console's one */
2714         SetTEBLangID();
2715     }
2716 
2717 Quit:
2718     RtlLeaveCriticalSection(&ConsoleLock);
2719     return Success;
2720 }
2721 
2722 
2723 /*
2724  * @implemented
2725  */
2726 HWND
2727 WINAPI
2728 DECLSPEC_HOTPATCH
GetConsoleWindow(VOID)2729 GetConsoleWindow(VOID)
2730 {
2731     CONSOLE_API_MESSAGE ApiMessage;
2732     PCONSOLE_GETWINDOW GetWindowRequest = &ApiMessage.Data.GetWindowRequest;
2733 
2734     GetWindowRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2735 
2736     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2737                         NULL,
2738                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetConsoleWindow),
2739                         sizeof(*GetWindowRequest));
2740     if (!NT_SUCCESS(ApiMessage.Status))
2741     {
2742         BaseSetLastNTError(ApiMessage.Status);
2743         return (HWND)NULL;
2744     }
2745 
2746     return GetWindowRequest->WindowHandle;
2747 }
2748 
2749 
2750 /*
2751  * @implemented
2752  */
2753 BOOL
2754 WINAPI
2755 DECLSPEC_HOTPATCH
SetConsoleIcon(HICON hIcon)2756 SetConsoleIcon(HICON hIcon)
2757 {
2758     CONSOLE_API_MESSAGE ApiMessage;
2759     PCONSOLE_SETICON SetIconRequest = &ApiMessage.Data.SetIconRequest;
2760 
2761     SetIconRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2762     SetIconRequest->IconHandle    = hIcon;
2763 
2764     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2765                         NULL,
2766                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetIcon),
2767                         sizeof(*SetIconRequest));
2768     if (!NT_SUCCESS(ApiMessage.Status))
2769     {
2770         BaseSetLastNTError(ApiMessage.Status);
2771         return FALSE;
2772     }
2773 
2774     return TRUE;
2775 }
2776 
2777 
2778 /******************************************************************************
2779  * \name SetConsoleInputExeNameW
2780  * \brief Sets the console input file name from a unicode string.
2781  * \param lpExeName Pointer to a unicode string with the name.
2782  * \return TRUE if successful, FALSE if unsuccessful.
2783  * \remarks If lpExeName is 0 or the string length is 0 or greater than 255,
2784  *          the function fails and sets last error to ERROR_INVALID_PARAMETER.
2785  */
2786 BOOL
2787 WINAPI
2788 DECLSPEC_HOTPATCH
SetConsoleInputExeNameW(IN LPCWSTR lpExeName)2789 SetConsoleInputExeNameW(IN LPCWSTR lpExeName)
2790 {
2791     DWORD ExeLength;
2792 
2793     ExeLength = lstrlenW(lpExeName);
2794     if ((ExeLength == 0) || (ExeLength >= EXENAME_LENGTH))
2795     {
2796         /* Fail if string is empty or too long */
2797         SetLastError(ERROR_INVALID_PARAMETER);
2798         return FALSE;
2799     }
2800 
2801     RtlEnterCriticalSection(&ExeNameLock);
2802     _SEH2_TRY
2803     {
2804         /* Set the input EXE name, not NULL terminated */
2805         RtlCopyMemory(ExeNameBuffer, lpExeName, ExeLength * sizeof(WCHAR));
2806         ExeNameLength = (USHORT)ExeLength;
2807     }
2808     _SEH2_FINALLY
2809     {
2810         RtlLeaveCriticalSection(&ExeNameLock);
2811     }
2812     _SEH2_END;
2813 
2814     return TRUE;
2815 }
2816 
2817 
2818 /******************************************************************************
2819  * \name SetConsoleInputExeNameA
2820  * \brief Sets the console input file name from an ansi string.
2821  * \param lpExeName Pointer to an ansi string with the name.
2822  * \return TRUE if successful, FALSE if unsuccessful.
2823  * \remarks If lpExeName is 0 or the string length is 0 or greater than 255,
2824  *          the function fails and sets last error to ERROR_INVALID_PARAMETER.
2825  */
2826 BOOL
2827 WINAPI
2828 DECLSPEC_HOTPATCH
SetConsoleInputExeNameA(IN LPCSTR lpExeName)2829 SetConsoleInputExeNameA(IN LPCSTR lpExeName)
2830 {
2831     NTSTATUS Status;
2832 #ifdef USE_TEB_STATIC_USTR
2833     PUNICODE_STRING ExeNameU;
2834 #else
2835     UNICODE_STRING ExeNameU;
2836 #endif
2837     ANSI_STRING ExeNameA;
2838 #ifndef USE_TEB_STATIC_USTR
2839     WCHAR Buffer[EXENAME_LENGTH];
2840 #endif
2841 
2842 #ifdef USE_TEB_STATIC_USTR
2843     /*
2844      * Use the TEB static UNICODE string for storage. It is already
2845      * initialized at process creation time by the Memory Manager.
2846      */
2847     ExeNameU = &NtCurrentTeb()->StaticUnicodeString;
2848 #endif
2849 
2850     /* Initialize string for conversion */
2851     RtlInitAnsiString(&ExeNameA, lpExeName);
2852 
2853 #if 1
2854     if ((ExeNameA.Length == 0) || (ExeNameA.Length >= EXENAME_LENGTH))
2855     {
2856         /* Fail if string is empty or too long */
2857         SetLastError(ERROR_INVALID_PARAMETER);
2858         return FALSE;
2859     }
2860 #endif
2861 #ifndef USE_TEB_STATIC_USTR
2862     ExeNameU.Length = 0;
2863     ExeNameU.MaximumLength = (USHORT)sizeof(Buffer);
2864     ExeNameU.Buffer = Buffer;
2865 #endif
2866 
2867 #ifdef USE_TEB_STATIC_USTR
2868     Status = RtlAnsiStringToUnicodeString(ExeNameU, &ExeNameA, FALSE);
2869 #else
2870     Status = RtlAnsiStringToUnicodeString(&ExeNameU, &ExeNameA, FALSE);
2871 #endif
2872     if (!NT_SUCCESS(Status))
2873     {
2874         /* Fail if string is empty or too long */
2875         if (Status == STATUS_BUFFER_OVERFLOW)
2876             SetLastError(ERROR_FILENAME_EXCED_RANGE);
2877         else
2878             SetLastError(ERROR_INVALID_PARAMETER);
2879 
2880         return FALSE;
2881     }
2882 
2883 #ifdef USE_TEB_STATIC_USTR
2884     return SetConsoleInputExeNameW(ExeNameU->Buffer);
2885 #else
2886     return SetConsoleInputExeNameW(ExeNameU.Buffer);
2887 #endif
2888 }
2889 
2890 
2891 /******************************************************************************
2892  * \name GetConsoleInputExeNameW
2893  * \brief Retrieves the console input file name as unicode string.
2894  * \param nBufferLength Length of the buffer in WCHARs.
2895  *        Specify 0 to receive the needed buffer length.
2896  * \param lpBuffer Pointer to a buffer that receives the string.
2897  * \return Needed buffer size if \p nBufferLength is 0.
2898  *         Otherwise 1 if successful, 2 if buffer is too small.
2899  * \remarks Sets last error value to ERROR_BUFFER_OVERFLOW if the buffer
2900  *          is not big enough.
2901  */
2902 DWORD
2903 WINAPI
2904 DECLSPEC_HOTPATCH
GetConsoleInputExeNameW(IN DWORD nBufferLength,OUT LPWSTR lpExeName)2905 GetConsoleInputExeNameW(IN DWORD nBufferLength,
2906                         OUT LPWSTR lpExeName)
2907 {
2908     if (nBufferLength <= ExeNameLength)
2909     {
2910         /* Buffer is not large enough! Return the correct size. */
2911         SetLastError(ERROR_BUFFER_OVERFLOW);
2912         return ExeNameLength + 1;
2913     }
2914 
2915     RtlEnterCriticalSection(&ExeNameLock);
2916     _SEH2_TRY
2917     {
2918         /* Copy the input EXE name and NULL-terminate it */
2919         RtlCopyMemory(lpExeName, ExeNameBuffer, ExeNameLength * sizeof(WCHAR));
2920         lpExeName[ExeNameLength] = UNICODE_NULL;
2921     }
2922     _SEH2_FINALLY
2923     {
2924         RtlLeaveCriticalSection(&ExeNameLock);
2925     }
2926     _SEH2_END;
2927 
2928     return TRUE;
2929 }
2930 
2931 
2932 /******************************************************************************
2933  * \name GetConsoleInputExeNameA
2934  * \brief Retrieves the console input file name as ansi string.
2935  * \param nBufferLength Length of the buffer in CHARs.
2936  * \param lpBuffer Pointer to a buffer that receives the string.
2937  * \return 1 if successful, 2 if buffer is too small.
2938  * \remarks Sets last error value to ERROR_BUFFER_OVERFLOW if the buffer
2939  *          is not big enough. The buffer receives as much characters as fit.
2940  */
2941 DWORD
2942 WINAPI
2943 DECLSPEC_HOTPATCH
GetConsoleInputExeNameA(IN DWORD nBufferLength,OUT LPSTR lpExeName)2944 GetConsoleInputExeNameA(IN DWORD nBufferLength,
2945                         OUT LPSTR lpExeName)
2946 {
2947     NTSTATUS Status;
2948     DWORD ExeLength;
2949     UNICODE_STRING BufferU;
2950     ANSI_STRING BufferA;
2951     WCHAR Buffer[EXENAME_LENGTH];
2952 
2953     /* Get the UNICODE name */
2954     ExeLength = GetConsoleInputExeNameW(EXENAME_LENGTH, Buffer);
2955 
2956     if ((ExeLength == 0) || (ExeLength >= EXENAME_LENGTH))
2957         return ExeLength;
2958 
2959     /* Initialize the strings for conversion */
2960     RtlInitUnicodeString(&BufferU, Buffer);
2961     BufferA.Length = 0;
2962     BufferA.MaximumLength = (USHORT)nBufferLength;
2963     BufferA.Buffer = lpExeName;
2964 
2965     /* Convert UNICODE name to ANSI, copying as much chars as it can fit */
2966     Status = RtlUnicodeStringToAnsiString(&BufferA, &BufferU, FALSE);
2967     if (!NT_SUCCESS(Status))
2968     {
2969         if (Status == STATUS_BUFFER_OVERFLOW)
2970         {
2971             SetLastError(ERROR_BUFFER_OVERFLOW);
2972             return ExeLength + 1;
2973         }
2974         SetLastError(ERROR_INVALID_PARAMETER);
2975     }
2976 
2977     return ExeLength;
2978 }
2979 
2980 BOOL
2981 WINAPI
GetConsoleCharType(HANDLE hConsole,COORD Coord,PDWORD Type)2982 GetConsoleCharType(HANDLE hConsole, COORD Coord, PDWORD Type)
2983 {
2984     STUB;
2985     return FALSE;
2986 }
2987 
2988 BOOL
2989 WINAPI
2990 DECLSPEC_HOTPATCH
GetConsoleCursorMode(HANDLE hConsole,PBOOL pUnknown1,PBOOL pUnknown2)2991 GetConsoleCursorMode(HANDLE hConsole, PBOOL pUnknown1, PBOOL pUnknown2)
2992 {
2993     STUB;
2994     return FALSE;
2995 }
2996 
2997 BOOL
2998 WINAPI
2999 DECLSPEC_HOTPATCH
SetConsoleCursorMode(HANDLE hConsole,BOOL Unknown1,BOOL Unknown2)3000 SetConsoleCursorMode(HANDLE hConsole, BOOL Unknown1, BOOL Unknown2)
3001 {
3002     STUB;
3003     return FALSE;
3004 }
3005 
3006 BOOL
3007 WINAPI
3008 DECLSPEC_HOTPATCH
GetConsoleNlsMode(HANDLE hConsole,LPDWORD lpMode)3009 GetConsoleNlsMode(HANDLE hConsole, LPDWORD lpMode)
3010 {
3011     STUB;
3012     return FALSE;
3013 }
3014 
3015 BOOL
3016 WINAPI
3017 DECLSPEC_HOTPATCH
SetConsoleNlsMode(HANDLE hConsole,DWORD dwMode)3018 SetConsoleNlsMode(HANDLE hConsole, DWORD dwMode)
3019 {
3020     STUB;
3021     return FALSE;
3022 }
3023 
3024 BOOL
3025 WINAPI
3026 DECLSPEC_HOTPATCH
SetConsoleLocalEUDC(DWORD Unknown1,DWORD Unknown2,DWORD Unknown3,DWORD Unknown4)3027 SetConsoleLocalEUDC(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4)
3028 {
3029     STUB;
3030     return FALSE;
3031 }
3032 
3033 static BOOL
IntRegisterConsoleIME(_In_ HWND hWnd,_In_ DWORD dwThreadId,_In_opt_ SIZE_T cbDesktop,_In_opt_ PWSTR pDesktop,_Out_opt_ PDWORD pdwAttachToThreadId)3034 IntRegisterConsoleIME(
3035     _In_ HWND hWnd,
3036     _In_ DWORD dwThreadId,
3037     _In_opt_ SIZE_T cbDesktop,
3038     _In_opt_ PWSTR pDesktop,
3039     _Out_opt_ PDWORD pdwAttachToThreadId)
3040 {
3041     CONSOLE_API_MESSAGE ApiMessage;
3042     PCONSOLE_REGISTERCONSOLEIME RegisterConsoleIME = &ApiMessage.Data.RegisterConsoleIME;
3043     PCSR_CAPTURE_BUFFER CaptureBuffer;
3044 
3045     if (!cbDesktop || !pDesktop)
3046     {
3047         pDesktop = NtCurrentPeb()->ProcessParameters->DesktopInfo.Buffer;
3048         cbDesktop = NtCurrentPeb()->ProcessParameters->DesktopInfo.Length;
3049     }
3050 
3051     cbDesktop = min(cbDesktop, (MAX_PATH + 1) * sizeof(WCHAR));
3052 
3053     RegisterConsoleIME->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
3054     RegisterConsoleIME->hWnd = hWnd;
3055     RegisterConsoleIME->dwThreadId = dwThreadId;
3056     RegisterConsoleIME->cbDesktop = cbDesktop;
3057 
3058     CaptureBuffer = CsrAllocateCaptureBuffer(1, cbDesktop);
3059     if (!CaptureBuffer)
3060     {
3061         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3062         return FALSE;
3063     }
3064 
3065     CsrCaptureMessageBuffer(CaptureBuffer,
3066                             pDesktop,
3067                             cbDesktop,
3068                             (PVOID*)&RegisterConsoleIME->pDesktop);
3069 
3070     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
3071                         CaptureBuffer,
3072                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepRegisterConsoleIME),
3073                         sizeof(*RegisterConsoleIME));
3074 
3075     CsrFreeCaptureBuffer(CaptureBuffer);
3076 
3077     if (!NT_SUCCESS(ApiMessage.Status))
3078     {
3079         BaseSetLastNTError(ApiMessage.Status);
3080         return FALSE;
3081     }
3082 
3083     if (pdwAttachToThreadId)
3084     {
3085         _SEH2_TRY
3086         {
3087             *pdwAttachToThreadId = RegisterConsoleIME->dwAttachToThreadId;
3088         }
3089         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3090         {
3091             BaseSetLastNTError(STATUS_ACCESS_VIOLATION);
3092             _SEH2_YIELD(return FALSE);
3093         }
3094         _SEH2_END;
3095     }
3096 
3097     return TRUE;
3098 }
3099 
3100 static BOOL
IntUnregisterConsoleIME(_In_ DWORD dwThreadId)3101 IntUnregisterConsoleIME(
3102     _In_ DWORD dwThreadId)
3103 {
3104     CONSOLE_API_MESSAGE ApiMessage;
3105     PCONSOLE_UNREGISTERCONSOLEIME UnregisterConsoleIME = &ApiMessage.Data.UnregisterConsoleIME;
3106 
3107     UnregisterConsoleIME->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
3108     UnregisterConsoleIME->dwThreadId = dwThreadId;
3109 
3110     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
3111                         NULL,
3112                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepUnregisterConsoleIME),
3113                         sizeof(*UnregisterConsoleIME));
3114     if (!NT_SUCCESS(ApiMessage.Status))
3115     {
3116         BaseSetLastNTError(ApiMessage.Status);
3117         return FALSE;
3118     }
3119 
3120     return TRUE;
3121 }
3122 
3123 /* This function is called by CONIME.EXE */
3124 BOOL
3125 WINAPI
3126 DECLSPEC_HOTPATCH
RegisterConsoleIME(_In_ HWND hWnd,_Out_opt_ LPDWORD pdwAttachToThreadId)3127 RegisterConsoleIME(
3128     _In_ HWND hWnd,
3129     _Out_opt_ LPDWORD pdwAttachToThreadId)
3130 {
3131     return IntRegisterConsoleIME(hWnd,
3132                                  GetCurrentThreadId(),
3133                                  0,
3134                                  NULL,
3135                                  pdwAttachToThreadId);
3136 }
3137 
3138 BOOL
3139 WINAPI
3140 DECLSPEC_HOTPATCH
RegisterConsoleOS2(BOOL bUnknown)3141 RegisterConsoleOS2(BOOL bUnknown)
3142 {
3143     STUB;
3144     return FALSE;
3145 }
3146 
3147 BOOL
3148 WINAPI
3149 DECLSPEC_HOTPATCH
SetConsoleOS2OemFormat(BOOL bUnknown)3150 SetConsoleOS2OemFormat(BOOL bUnknown)
3151 {
3152     STUB;
3153     return FALSE;
3154 }
3155 
3156 /* This function is called by CONIME.EXE */
3157 BOOL
3158 WINAPI
3159 DECLSPEC_HOTPATCH
UnregisterConsoleIME(VOID)3160 UnregisterConsoleIME(VOID)
3161 {
3162     return IntUnregisterConsoleIME(GetCurrentThreadId());
3163 }
3164 
3165 /**
3166  * @brief
3167  * Internal helper function used to synchronize the current
3168  * thread's language ID with the one from the console.
3169  **/
3170 VOID
SetTEBLangID(VOID)3171 SetTEBLangID(VOID)
3172 {
3173     CONSOLE_API_MESSAGE ApiMessage;
3174     PCONSOLE_GETLANGID LangIdRequest = &ApiMessage.Data.LangIdRequest;
3175 
3176     /* Retrieve the "best-suited" language ID corresponding
3177      * to the active console output code page. */
3178     LangIdRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
3179 
3180     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
3181                         NULL,
3182                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetLangId),
3183                         sizeof(*LangIdRequest));
3184     if (!NT_SUCCESS(ApiMessage.Status))
3185     {
3186         /*
3187          * No best console language ID: keep the current thread's one.
3188          * Since this internal function only modifies an optional setting,
3189          * don't set any last error, as it could otherwise mess with the
3190          * main last error set by the caller.
3191          */
3192         return;
3193     }
3194 
3195     /*
3196      * We succeeded, set the current thread's language ID by
3197      * modifying its locale -- Windows <= 2003 does not have
3198      * the concept of a separate thread UI language.
3199      * Ignore the returned value.
3200      */
3201     if (!SetThreadLocale(MAKELCID(LangIdRequest->LangId, SORT_DEFAULT)))
3202     {
3203         DPRINT1("SetTEBLangID: Could not set thread locale to console lang ID %lu\n",
3204                 LangIdRequest->LangId);
3205     }
3206 }
3207 
3208 static
3209 BOOL
IntGetConsoleKeyboardLayoutName(OUT PVOID pszLayoutName,IN BOOL bAnsi)3210 IntGetConsoleKeyboardLayoutName(OUT PVOID pszLayoutName,
3211                                 IN BOOL bAnsi)
3212 {
3213     CONSOLE_API_MESSAGE ApiMessage;
3214     PCONSOLE_GETKBDLAYOUTNAME GetKbdLayoutNameRequest = &ApiMessage.Data.GetKbdLayoutNameRequest;
3215 
3216     /* Set up the data to send to the Console Server */
3217     GetKbdLayoutNameRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
3218     GetKbdLayoutNameRequest->Ansi          = bAnsi;
3219 
3220     /* Call the server */
3221     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
3222                         NULL,
3223                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetKeyboardLayoutName),
3224                         sizeof(*GetKbdLayoutNameRequest));
3225 
3226     /* Check for success */
3227     if (!NT_SUCCESS(ApiMessage.Status))
3228     {
3229         BaseSetLastNTError(ApiMessage.Status);
3230         return FALSE;
3231     }
3232 
3233     /* Retrieve the results */
3234     _SEH2_TRY
3235     {
3236         /* Copy only KL_NAMELENGTH == 9 characters, ANSI or UNICODE */
3237         if (bAnsi)
3238             strncpy(pszLayoutName, (PCHAR)GetKbdLayoutNameRequest->LayoutBuffer, KL_NAMELENGTH);
3239         else
3240             wcsncpy(pszLayoutName, (PWCHAR)GetKbdLayoutNameRequest->LayoutBuffer, KL_NAMELENGTH);
3241     }
3242     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3243     {
3244         SetLastError(ERROR_INVALID_ACCESS);
3245         _SEH2_YIELD(return FALSE);
3246     }
3247     _SEH2_END;
3248 
3249     return TRUE;
3250 }
3251 
3252 /*
3253  * @implemented (undocumented)
3254  */
3255 BOOL
3256 WINAPI
3257 DECLSPEC_HOTPATCH
GetConsoleKeyboardLayoutNameA(OUT LPSTR pszLayoutName)3258 GetConsoleKeyboardLayoutNameA(OUT LPSTR pszLayoutName)
3259 {
3260     return IntGetConsoleKeyboardLayoutName(pszLayoutName, TRUE);
3261 }
3262 
3263 /*
3264  * @implemented (undocumented)
3265  */
3266 BOOL
3267 WINAPI
3268 DECLSPEC_HOTPATCH
GetConsoleKeyboardLayoutNameW(OUT LPWSTR pszLayoutName)3269 GetConsoleKeyboardLayoutNameW(OUT LPWSTR pszLayoutName)
3270 {
3271     return IntGetConsoleKeyboardLayoutName(pszLayoutName, FALSE);
3272 }
3273 
3274 /*
3275  * @implemented
3276  */
3277 DWORD
3278 WINAPI
SetLastConsoleEventActive(VOID)3279 SetLastConsoleEventActive(VOID)
3280 {
3281     CONSOLE_API_MESSAGE ApiMessage;
3282     PCONSOLE_NOTIFYLASTCLOSE NotifyLastCloseRequest = &ApiMessage.Data.NotifyLastCloseRequest;
3283 
3284     /* Set the flag used by the console control dispatcher */
3285     LastCloseNotify = TRUE;
3286 
3287     /* Set up the input arguments */
3288     NotifyLastCloseRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
3289 
3290     /* Call CSRSS; just return the NTSTATUS cast to DWORD */
3291     return CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
3292                                NULL,
3293                                CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepNotifyLastClose),
3294                                sizeof(*NotifyLastCloseRequest));
3295 }
3296 
3297 /* EOF */
3298