Reactos
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
20extern RTL_CRITICAL_SECTION ConsoleLock;
21extern BOOLEAN ConsoleInitialized;
22
23/* Console reserved "file" names */
24static LPCWSTR BaseConFileName = CONSOLE_FILE_NAME;
25static LPCWSTR BaseConInputFileName = CONSOLE_INPUT_FILE_NAME;
26static LPCWSTR BaseConOutputFileName = CONSOLE_OUTPUT_FILE_NAME;
27
28/* Console Control handling */
29static PHANDLER_ROUTINE InitialHandler[1];
30static PHANDLER_ROUTINE* CtrlHandlers;
31static ULONG NrCtrlHandlers;
32static ULONG NrAllocatedHandlers;
33static BOOLEAN LastCloseNotify = FALSE;
34
35extern BOOL WINAPI IsDebuggerPresent(VOID);
36
37/* Console Input facilities */
38HANDLE InputWaitHandle = INVALID_HANDLE_VALUE;
39
40#define EXENAME_LENGTH (255 + 1)
41static RTL_CRITICAL_SECTION ExeNameLock;
42static BOOLEAN ExeNameInitialized;
43static WCHAR ExeNameBuffer[EXENAME_LENGTH]; // NULL-terminated
44static USHORT ExeNameLength; // Count in number of characters without NULL
45static WCHAR StartDirBuffer[MAX_PATH + 1]; // NULL-terminated
46static USHORT StartDirLength; // Count in number of characters without NULL
47
48
49/* Default Console Control Handler ********************************************/
50
51static BOOL
52WINAPI
53DefaultConsoleCtrlHandler(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
87DWORD
88WINAPI
89ConsoleControlDispatcher(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
203VOID
204InitializeCtrlHandling(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
215VOID
216InitExeName(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 */
263VOID
264SetUpAppName(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
315USHORT
316GetCurrentExeName(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
344LPCWSTR
345IntCheckForConsoleFileName(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 */
393HMENU
394WINAPI
395DECLSPEC_HOTPATCH
396ConsoleMenuControl(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 */
421HANDLE
422WINAPI
423DECLSPEC_HOTPATCH
424DuplicateConsoleHandle(HANDLE hSourceHandle,
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 = hSourceHandle;
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 */
463BOOL
464WINAPI
465GetConsoleHandleInformation(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 */
493BOOL
494WINAPI
495SetConsoleHandleInformation(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 */
524BOOL
525WINAPI
526GetConsoleDisplayMode(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 https://cboard.cprogramming.com/windows-programming/102187-console-font-size.html
558 */
559DWORD
560WINAPI
561GetConsoleFontInfo(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 */
610COORD
611WINAPI
612DECLSPEC_HOTPATCH
613GetConsoleFontSize(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 */
641BOOL
642WINAPI
643GetConsoleHardwareState(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 */
681HANDLE
682WINAPI
683GetConsoleInputWaitHandle(VOID)
684{
685 return InputWaitHandle;
686}
687
688
689/*
690 * @implemented
691 */
692BOOL
693WINAPI
694GetCurrentConsoleFont(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 https://cboard.cprogramming.com/windows-programming/102187-console-font-size.html
725 */
726DWORD
727WINAPI
728DECLSPEC_HOTPATCH
729GetNumberOfConsoleFonts(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 */
754BOOL
755WINAPI
756InvalidateConsoleDIBits(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 */
789HANDLE
790WINAPI
791OpenConsoleW(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 */
845BOOL
846WINAPI
847DECLSPEC_HOTPATCH
848SetConsoleCursor(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 */
875BOOL
876WINAPI
877SetConsoleDisplayMode(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 https://cboard.cprogramming.com/windows-programming/102187-console-font-size.html
911 */
912BOOL
913WINAPI
914DECLSPEC_HOTPATCH
915SetConsoleFont(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 */
942BOOL
943WINAPI
944SetConsoleHardwareState(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 */
975BOOL
976WINAPI
977DECLSPEC_HOTPATCH
978SetConsoleKeyShortcuts(
979 _In_ BOOL bSet,
980 _In_ BYTE bReserveKeys,
981 _In_reads_(dwNumAppKeys) LPAPPKEY lpAppKeys,
982 _In_ DWORD dwNumAppKeys)
983{
984 DPRINT1("SetConsoleKeyShortcuts(%lu, 0x%x, 0x%p, 0x%x) UNIMPLEMENTED!\n",
985 bSet, bReserveKeys, lpAppKeys, dwNumAppKeys);
986 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
987 return FALSE;
988}
989
990
991/*
992 * @implemented (Undocumented)
993 * @note See http://undoc.airesoft.co.uk/kernel32.dll/SetConsoleMaximumWindowSize.php
994 * Does nothing, returns TRUE only. Checked on Windows Server 2003.
995 */
996BOOL
997WINAPI
998SetConsoleMaximumWindowSize(HANDLE hConsoleOutput,
999 COORD dwMaximumSize)
1000{
1001 DPRINT1("SetConsoleMaximumWindowSize(0x%p, {%d, %d}) does nothing\n",
1002 hConsoleOutput, dwMaximumSize.X, dwMaximumSize.Y);
1003 return TRUE;
1004}
1005
1006
1007/*
1008 * @implemented (Undocumented)
1009 */
1010BOOL
1011WINAPI
1012DECLSPEC_HOTPATCH
1013SetConsoleMenuClose(BOOL bEnable)
1014{
1015 CONSOLE_API_MESSAGE ApiMessage;
1016 PCONSOLE_SETMENUCLOSE SetMenuCloseRequest = &ApiMessage.Data.SetMenuCloseRequest;
1017
1018 SetMenuCloseRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1019 SetMenuCloseRequest->Enable = bEnable;
1020
1021 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1022 NULL,
1023 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetMenuClose),
1024 sizeof(*SetMenuCloseRequest));
1025 if (!NT_SUCCESS(ApiMessage.Status))
1026 {
1027 BaseSetLastNTError(ApiMessage.Status);
1028 return FALSE;
1029 }
1030
1031 return TRUE;
1032}
1033
1034
1035/*
1036 * @implemented (Undocumented)
1037 * @note See http://comments.gmane.org/gmane.comp.lang.harbour.devel/27844 (DEAD_LINK)
1038 * Usage example: https://github.com/harbour/core/commit/d79a1b7b812cbde6ddf718ebfd6939a24f633e52
1039 */
1040BOOL
1041WINAPI
1042DECLSPEC_HOTPATCH
1043SetConsolePalette(HANDLE hConsoleOutput,
1044 HPALETTE hPalette,
1045 UINT dwUsage)
1046{
1047 CONSOLE_API_MESSAGE ApiMessage;
1048 PCONSOLE_SETPALETTE SetPaletteRequest = &ApiMessage.Data.SetPaletteRequest;
1049
1050 SetPaletteRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1051 SetPaletteRequest->OutputHandle = hConsoleOutput;
1052 SetPaletteRequest->PaletteHandle = hPalette;
1053 SetPaletteRequest->Usage = dwUsage;
1054
1055 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1056 NULL,
1057 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetPalette),
1058 sizeof(*SetPaletteRequest));
1059 if (!NT_SUCCESS(ApiMessage.Status))
1060 {
1061 BaseSetLastNTError(ApiMessage.Status);
1062 return FALSE;
1063 }
1064
1065 return TRUE;
1066}
1067
1068/*
1069 * @implemented (Undocumented)
1070 * @note See http://undoc.airesoft.co.uk/kernel32.dll/ShowConsoleCursor.php
1071 */
1072INT
1073WINAPI
1074DECLSPEC_HOTPATCH
1075ShowConsoleCursor(HANDLE hConsoleOutput,
1076 BOOL bShow)
1077{
1078 CONSOLE_API_MESSAGE ApiMessage;
1079 PCONSOLE_SHOWCURSOR ShowCursorRequest = &ApiMessage.Data.ShowCursorRequest;
1080
1081 ShowCursorRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1082 ShowCursorRequest->OutputHandle = hConsoleOutput;
1083 ShowCursorRequest->Show = bShow;
1084 ShowCursorRequest->RefCount = 0;
1085
1086 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1087 NULL,
1088 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepShowCursor),
1089 sizeof(*ShowCursorRequest));
1090
1091 return ShowCursorRequest->RefCount;
1092}
1093
1094
1095/*
1096 * FUNCTION: Checks whether the given handle is a valid console handle.
1097 *
1098 * ARGUMENTS:
1099 * hIoHandle - Handle to be checked.
1100 *
1101 * RETURNS:
1102 * TRUE : Handle is a valid console handle.
1103 * FALSE: Handle is not a valid console handle.
1104 *
1105 * STATUS: Officially undocumented
1106 *
1107 * @implemented
1108 */
1109BOOL
1110WINAPI
1111DECLSPEC_HOTPATCH
1112VerifyConsoleIoHandle(HANDLE hIoHandle)
1113{
1114 CONSOLE_API_MESSAGE ApiMessage;
1115 PCONSOLE_VERIFYHANDLE VerifyHandleRequest = &ApiMessage.Data.VerifyHandleRequest;
1116
1117 VerifyHandleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1118 VerifyHandleRequest->Handle = hIoHandle;
1119 VerifyHandleRequest->IsValid = FALSE;
1120
1121 /* If the process is not attached to a console, return invalid handle */
1122 if (VerifyHandleRequest->ConsoleHandle == NULL) return FALSE;
1123
1124 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1125 NULL,
1126 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepVerifyIoHandle),
1127 sizeof(*VerifyHandleRequest));
1128 if (!NT_SUCCESS(ApiMessage.Status))
1129 {
1130 BaseSetLastNTError(ApiMessage.Status);
1131 return FALSE;
1132 }
1133
1134 return VerifyHandleRequest->IsValid;
1135}
1136
1137
1138/*
1139 * @implemented (Undocumented)
1140 */
1141BOOL
1142WINAPI
1143DECLSPEC_HOTPATCH
1144CloseConsoleHandle(HANDLE hHandle)
1145{
1146 CONSOLE_API_MESSAGE ApiMessage;
1147 PCONSOLE_CLOSEHANDLE CloseHandleRequest = &ApiMessage.Data.CloseHandleRequest;
1148
1149 CloseHandleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1150 CloseHandleRequest->Handle = hHandle;
1151
1152 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1153 NULL,
1154 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepCloseHandle),
1155 sizeof(*CloseHandleRequest));
1156 if (!NT_SUCCESS(ApiMessage.Status))
1157 {
1158 BaseSetLastNTError(ApiMessage.Status);
1159 return FALSE;
1160 }
1161
1162 return TRUE;
1163}
1164
1165
1166/*
1167 * @implemented
1168 */
1169HANDLE
1170WINAPI
1171DECLSPEC_HOTPATCH
1172GetStdHandle(DWORD nStdHandle)
1173/*
1174 * FUNCTION: Get a handle for the standard input, standard output
1175 * and a standard error device.
1176 *
1177 * ARGUMENTS:
1178 * nStdHandle - Specifies the device for which to return the handle.
1179 *
1180 * RETURNS: If the function succeeds, the return value is the handle
1181 * of the specified device. Otherwise the value is INVALID_HANDLE_VALUE.
1182 */
1183{
1184 PRTL_USER_PROCESS_PARAMETERS Ppb = NtCurrentPeb()->ProcessParameters;
1185 HANDLE Handle = INVALID_HANDLE_VALUE;
1186
1187 switch (nStdHandle)
1188 {
1189 case STD_INPUT_HANDLE:
1190 Handle = Ppb->StandardInput;
1191 break;
1192
1193 case STD_OUTPUT_HANDLE:
1194 Handle = Ppb->StandardOutput;
1195 break;
1196
1197 case STD_ERROR_HANDLE:
1198 Handle = Ppb->StandardError;
1199 break;
1200 }
1201
1202 /* If the returned handle is invalid, set last error */
1203 if (Handle == INVALID_HANDLE_VALUE) SetLastError(ERROR_INVALID_HANDLE);
1204
1205 return Handle;
1206}
1207
1208
1209/*
1210 * @implemented
1211 */
1212BOOL
1213WINAPI
1214DECLSPEC_HOTPATCH
1215SetStdHandle(DWORD nStdHandle,
1216 HANDLE hHandle)
1217/*
1218 * FUNCTION: Set the handle for the standard input, standard output or
1219 * the standard error device.
1220 *
1221 * ARGUMENTS:
1222 * nStdHandle - Specifies the handle to be set.
1223 * hHandle - The handle to set.
1224 *
1225 * RETURNS: TRUE if the function succeeds, FALSE otherwise.
1226 */
1227{
1228 PRTL_USER_PROCESS_PARAMETERS Ppb = NtCurrentPeb()->ProcessParameters;
1229
1230 /* No need to check if hHandle == INVALID_HANDLE_VALUE */
1231
1232 switch (nStdHandle)
1233 {
1234 case STD_INPUT_HANDLE:
1235 Ppb->StandardInput = hHandle;
1236 return TRUE;
1237
1238 case STD_OUTPUT_HANDLE:
1239 Ppb->StandardOutput = hHandle;
1240 return TRUE;
1241
1242 case STD_ERROR_HANDLE:
1243 Ppb->StandardError = hHandle;
1244 return TRUE;
1245 }
1246
1247 /* nStdHandle was invalid, bail out */
1248 SetLastError(ERROR_INVALID_HANDLE);
1249 return FALSE;
1250}
1251
1252
1253/*
1254 * @implemented
1255 */
1256static BOOL
1257IntAllocConsole(LPWSTR Title,
1258 DWORD TitleLength,
1259 LPWSTR Desktop,
1260 DWORD DesktopLength,
1261 LPWSTR CurDir,
1262 DWORD CurDirLength,
1263 LPWSTR AppName,
1264 DWORD AppNameLength,
1265 LPTHREAD_START_ROUTINE CtrlRoutine,
1266 LPTHREAD_START_ROUTINE PropRoutine,
1267 PCONSOLE_START_INFO ConsoleStartInfo)
1268{
1269 BOOL Success = TRUE;
1270 NTSTATUS Status;
1271
1272 CONSOLE_API_MESSAGE ApiMessage;
1273 PCONSOLE_ALLOCCONSOLE AllocConsoleRequest = &ApiMessage.Data.AllocConsoleRequest;
1274 PCSR_CAPTURE_BUFFER CaptureBuffer;
1275
1276 AllocConsoleRequest->CtrlRoutine = CtrlRoutine;
1277 AllocConsoleRequest->PropRoutine = PropRoutine;
1278
1279 CaptureBuffer = CsrAllocateCaptureBuffer(5, TitleLength +
1280 DesktopLength +
1281 CurDirLength +
1282 AppNameLength +
1283 sizeof(CONSOLE_START_INFO));
1284 if (CaptureBuffer == NULL)
1285 {
1286 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1287 Success = FALSE;
1288 goto Quit;
1289 }
1290
1291 CsrCaptureMessageBuffer(CaptureBuffer,
1292 ConsoleStartInfo,
1293 sizeof(CONSOLE_START_INFO),
1294 (PVOID*)&AllocConsoleRequest->ConsoleStartInfo);
1295
1296 AllocConsoleRequest->TitleLength = TitleLength;
1297 CsrCaptureMessageBuffer(CaptureBuffer,
1298 Title,
1299 TitleLength,
1300 (PVOID*)&AllocConsoleRequest->ConsoleTitle);
1301
1302 AllocConsoleRequest->DesktopLength = DesktopLength;
1303 CsrCaptureMessageBuffer(CaptureBuffer,
1304 Desktop,
1305 DesktopLength,
1306 (PVOID*)&AllocConsoleRequest->Desktop);
1307
1308 AllocConsoleRequest->CurDirLength = CurDirLength;
1309 CsrCaptureMessageBuffer(CaptureBuffer,
1310 CurDir,
1311 CurDirLength,
1312 (PVOID*)&AllocConsoleRequest->CurDir);
1313
1314 AllocConsoleRequest->AppNameLength = AppNameLength;
1315 CsrCaptureMessageBuffer(CaptureBuffer,
1316 AppName,
1317 AppNameLength,
1318 (PVOID*)&AllocConsoleRequest->AppName);
1319
1320 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1321 CaptureBuffer,
1322 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAlloc),
1323 sizeof(*AllocConsoleRequest));
1324 if (!NT_SUCCESS(ApiMessage.Status))
1325 {
1326 BaseSetLastNTError(ApiMessage.Status);
1327 Success = FALSE;
1328 goto Quit;
1329 }
1330
1331 // Is AllocConsoleRequest->ConsoleStartInfo->InitEvents aligned on handle boundary ????
1332 Status = NtWaitForMultipleObjects(MAX_INIT_EVENTS,
1333 AllocConsoleRequest->ConsoleStartInfo->InitEvents,
1334 WaitAny, FALSE, NULL);
1335 if (!NT_SUCCESS(Status))
1336 {
1337 BaseSetLastNTError(Status);
1338 Success = FALSE;
1339 goto Quit;
1340 }
1341
1342 NtClose(AllocConsoleRequest->ConsoleStartInfo->InitEvents[INIT_SUCCESS]);
1343 NtClose(AllocConsoleRequest->ConsoleStartInfo->InitEvents[INIT_FAILURE]);
1344 if (Status != INIT_SUCCESS)
1345 {
1346 NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
1347 Success = FALSE;
1348 }
1349 else
1350 {
1351 RtlCopyMemory(ConsoleStartInfo,
1352 AllocConsoleRequest->ConsoleStartInfo,
1353 sizeof(CONSOLE_START_INFO));
1354 Success = TRUE;
1355 }
1356
1357Quit:
1358 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
1359 return Success;
1360}
1361
1362BOOL
1363WINAPI
1364DECLSPEC_HOTPATCH
1365AllocConsole(VOID)
1366{
1367 BOOL Success;
1368 CONSOLE_START_INFO ConsoleStartInfo;
1369
1370 PWCHAR ConsoleTitle;
1371 PWCHAR Desktop;
1372 PWCHAR AppName;
1373 PWCHAR CurDir;
1374
1375 ULONG TitleLength = (MAX_PATH + 1) * sizeof(WCHAR);
1376 ULONG DesktopLength = (MAX_PATH + 1) * sizeof(WCHAR);
1377 ULONG AppNameLength = 128 * sizeof(WCHAR);
1378 ULONG CurDirLength = (MAX_PATH + 1) * sizeof(WCHAR);
1379
1380 RtlEnterCriticalSection(&ConsoleLock);
1381
1382 if (NtCurrentPeb()->ProcessParameters->ConsoleHandle)
1383 {
1384 DPRINT1("AllocConsole: Allocating a console to a process already having one\n");
1385 SetLastError(ERROR_ACCESS_DENIED);
1386 Success = FALSE;
1387 goto Quit;
1388 }
1389
1390 /* Set up the console properties */
1391 SetUpConsoleInfo(FALSE,
1392 &TitleLength,
1393 &ConsoleTitle,
1394 &DesktopLength,
1395 &Desktop,
1396 &ConsoleStartInfo);
1397 DPRINT("ConsoleTitle = '%S' - Desktop = '%S'\n",
1398 ConsoleTitle, Desktop);
1399
1400 /* Initialize the Input EXE name */
1401 InitExeName();
1402 SetUpAppName(FALSE,
1403 &CurDirLength,
1404 &CurDir,
1405 &AppNameLength,
1406 &AppName);
1407 DPRINT("CurDir = '%S' - AppName = '%S'\n",
1408 CurDir, AppName);
1409
1410 Success = IntAllocConsole(ConsoleTitle,
1411 TitleLength,
1412 Desktop,
1413 DesktopLength,
1414 CurDir,
1415 CurDirLength,
1416 AppName,
1417 AppNameLength,
1418 ConsoleControlDispatcher,
1419 PropDialogHandler,
1420 &ConsoleStartInfo);
1421 if (Success)
1422 {
1423 /* Set up the handles */
1424 SetUpHandles(&ConsoleStartInfo);
1425 InputWaitHandle = ConsoleStartInfo.InputWaitHandle;
1426
1427 /* Initialize Console Ctrl Handling */
1428 InitializeCtrlHandling();
1429
1430 /* Sync the current thread's LangId with the console's one */
1431 SetTEBLangID();
1432 }
1433
1434Quit:
1435 RtlLeaveCriticalSection(&ConsoleLock);
1436 return Success;
1437}
1438
1439
1440/*
1441 * @implemented
1442 */
1443BOOL
1444WINAPI
1445DECLSPEC_HOTPATCH
1446FreeConsole(VOID)
1447{
1448 BOOL Success = TRUE;
1449 CONSOLE_API_MESSAGE ApiMessage;
1450 PCONSOLE_FREECONSOLE FreeConsoleRequest = &ApiMessage.Data.FreeConsoleRequest;
1451 HANDLE ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1452
1453 RtlEnterCriticalSection(&ConsoleLock);
1454
1455 /* We must have a non-trivial handle to close */
1456 if (ConsoleHandle == NULL) // IsConsoleHandle(ConsoleHandle)
1457 {
1458 SetLastError(ERROR_INVALID_PARAMETER);
1459 Success = FALSE;
1460 goto Quit;
1461 }
1462
1463 /* Set up the data to send to the Console Server */
1464 FreeConsoleRequest->ConsoleHandle = ConsoleHandle;
1465
1466 /* Call the server */
1467 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1468 NULL,
1469 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFree),
1470 sizeof(*FreeConsoleRequest));
1471
1472 /* Check for success */
1473 if (!NT_SUCCESS(ApiMessage.Status))
1474 {
1475 BaseSetLastNTError(ApiMessage.Status);
1476 Success = FALSE;
1477 goto Quit;
1478 }
1479
1480 /* Reset the console handle */
1481 NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
1482
1483 /* Close the associated input handle */
1484 CloseHandle(InputWaitHandle);
1485 InputWaitHandle = INVALID_HANDLE_VALUE;
1486
1487Quit:
1488 RtlLeaveCriticalSection(&ConsoleLock);
1489 return Success;
1490}
1491
1492
1493/*
1494 * @implemented
1495 */
1496BOOL
1497WINAPI
1498GetConsoleScreenBufferInfo(HANDLE hConsoleOutput,
1499 PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)
1500{
1501 CONSOLE_API_MESSAGE ApiMessage;
1502 PCONSOLE_GETSCREENBUFFERINFO ScreenBufferInfoRequest = &ApiMessage.Data.ScreenBufferInfoRequest;
1503
1504 if (lpConsoleScreenBufferInfo == NULL)
1505 {
1506 SetLastError(ERROR_INVALID_PARAMETER);
1507 return FALSE;
1508 }
1509
1510 ScreenBufferInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1511 ScreenBufferInfoRequest->OutputHandle = hConsoleOutput;
1512
1513 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1514 NULL,
1515 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetScreenBufferInfo),
1516 sizeof(*ScreenBufferInfoRequest));
1517 if (!NT_SUCCESS(ApiMessage.Status))
1518 {
1519 BaseSetLastNTError(ApiMessage.Status);
1520 return FALSE;
1521 }
1522
1523 lpConsoleScreenBufferInfo->dwSize = ScreenBufferInfoRequest->ScreenBufferSize;
1524 lpConsoleScreenBufferInfo->dwCursorPosition = ScreenBufferInfoRequest->CursorPosition;
1525 lpConsoleScreenBufferInfo->wAttributes = ScreenBufferInfoRequest->Attributes;
1526 lpConsoleScreenBufferInfo->srWindow.Left = ScreenBufferInfoRequest->ViewOrigin.X;
1527 lpConsoleScreenBufferInfo->srWindow.Top = ScreenBufferInfoRequest->ViewOrigin.Y;
1528 lpConsoleScreenBufferInfo->srWindow.Right = ScreenBufferInfoRequest->ViewOrigin.X + ScreenBufferInfoRequest->ViewSize.X - 1;
1529 lpConsoleScreenBufferInfo->srWindow.Bottom = ScreenBufferInfoRequest->ViewOrigin.Y + ScreenBufferInfoRequest->ViewSize.Y - 1;
1530 lpConsoleScreenBufferInfo->dwMaximumWindowSize = ScreenBufferInfoRequest->MaximumViewSize;
1531
1532 return TRUE;
1533}
1534
1535
1536/*
1537 * @implemented
1538 */
1539BOOL
1540WINAPI
1541DECLSPEC_HOTPATCH
1542SetConsoleCursorPosition(HANDLE hConsoleOutput,
1543 COORD dwCursorPosition)
1544{
1545 CONSOLE_API_MESSAGE ApiMessage;
1546 PCONSOLE_SETCURSORPOSITION SetCursorPositionRequest = &ApiMessage.Data.SetCursorPositionRequest;
1547
1548 SetCursorPositionRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1549 SetCursorPositionRequest->OutputHandle = hConsoleOutput;
1550 SetCursorPositionRequest->Position = dwCursorPosition;
1551
1552 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1553 NULL,
1554 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCursorPosition),
1555 sizeof(*SetCursorPositionRequest));
1556 if (!NT_SUCCESS(ApiMessage.Status))
1557 {
1558 BaseSetLastNTError(ApiMessage.Status);
1559 return FALSE;
1560 }
1561
1562 return TRUE;
1563}
1564
1565
1566/*
1567 * @implemented
1568 */
1569BOOL
1570WINAPI
1571GetConsoleMode(HANDLE hConsoleHandle,
1572 LPDWORD lpMode)
1573{
1574 CONSOLE_API_MESSAGE ApiMessage;
1575 PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &ApiMessage.Data.ConsoleModeRequest;
1576
1577 if (lpMode == NULL)
1578 {
1579 SetLastError(ERROR_INVALID_PARAMETER);
1580 return FALSE;
1581 }
1582
1583 ConsoleModeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1584 ConsoleModeRequest->Handle = hConsoleHandle;
1585
1586 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1587 NULL,
1588 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetMode),
1589 sizeof(*ConsoleModeRequest));
1590 if (!NT_SUCCESS(ApiMessage.Status))
1591 {
1592 BaseSetLastNTError(ApiMessage.Status);
1593 return FALSE;
1594 }
1595
1596 *lpMode = ConsoleModeRequest->Mode;
1597
1598 return TRUE;
1599}
1600
1601
1602/*
1603 * @implemented
1604 */
1605BOOL
1606WINAPI
1607DECLSPEC_HOTPATCH
1608SetConsoleMode(HANDLE hConsoleHandle,
1609 DWORD dwMode)
1610{
1611 CONSOLE_API_MESSAGE ApiMessage;
1612 PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &ApiMessage.Data.ConsoleModeRequest;
1613
1614 ConsoleModeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1615 ConsoleModeRequest->Handle = hConsoleHandle;
1616 ConsoleModeRequest->Mode = dwMode;
1617
1618 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1619 NULL,
1620 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetMode),
1621 sizeof(*ConsoleModeRequest));
1622 if (!NT_SUCCESS(ApiMessage.Status))
1623 {
1624 BaseSetLastNTError(ApiMessage.Status);
1625 return FALSE;
1626 }
1627
1628 return TRUE;
1629}
1630
1631
1632/*
1633 * @implemented
1634 */
1635BOOL
1636WINAPI
1637GetNumberOfConsoleInputEvents(HANDLE hConsoleInput,
1638 LPDWORD lpNumberOfEvents)
1639{
1640 CONSOLE_API_MESSAGE ApiMessage;
1641 PCONSOLE_GETNUMINPUTEVENTS GetNumInputEventsRequest = &ApiMessage.Data.GetNumInputEventsRequest;
1642
1643 GetNumInputEventsRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1644 GetNumInputEventsRequest->InputHandle = hConsoleInput;
1645 GetNumInputEventsRequest->NumberOfEvents = 0;
1646
1647 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1648 NULL,
1649 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetNumberOfInputEvents),
1650 sizeof(*GetNumInputEventsRequest));
1651 if (!NT_SUCCESS(ApiMessage.Status))
1652 {
1653 BaseSetLastNTError(ApiMessage.Status);
1654 return FALSE;
1655 }
1656
1657 if (lpNumberOfEvents == NULL)
1658 {
1659 SetLastError(ERROR_INVALID_ACCESS);
1660 return FALSE;
1661 }
1662
1663 *lpNumberOfEvents = GetNumInputEventsRequest->NumberOfEvents;
1664
1665 return TRUE;
1666}
1667
1668
1669/*
1670 * @implemented
1671 */
1672COORD
1673WINAPI
1674DECLSPEC_HOTPATCH
1675GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
1676{
1677 CONSOLE_API_MESSAGE ApiMessage;
1678 PCONSOLE_GETLARGESTWINDOWSIZE GetLargestWindowSizeRequest = &ApiMessage.Data.GetLargestWindowSizeRequest;
1679
1680 GetLargestWindowSizeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1681 GetLargestWindowSizeRequest->OutputHandle = hConsoleOutput;
1682 GetLargestWindowSizeRequest->Size.X = 0;
1683 GetLargestWindowSizeRequest->Size.Y = 0;
1684
1685 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1686 NULL,
1687 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetLargestWindowSize),
1688 sizeof(*GetLargestWindowSizeRequest));
1689 if (!NT_SUCCESS(ApiMessage.Status))
1690 {
1691 BaseSetLastNTError(ApiMessage.Status);
1692 }
1693
1694 DPRINT("GetLargestConsoleWindowSize, X = %d, Y = %d\n", GetLargestWindowSizeRequest->Size.X, GetLargestWindowSizeRequest->Size.Y);
1695 return GetLargestWindowSizeRequest->Size;
1696}
1697
1698
1699/*
1700 * @implemented
1701 */
1702BOOL
1703WINAPI
1704GetConsoleCursorInfo(HANDLE hConsoleOutput,
1705 PCONSOLE_CURSOR_INFO lpConsoleCursorInfo)
1706{
1707 CONSOLE_API_MESSAGE ApiMessage;
1708 PCONSOLE_GETSETCURSORINFO CursorInfoRequest = &ApiMessage.Data.CursorInfoRequest;
1709
1710 if (!lpConsoleCursorInfo)
1711 {
1712 if (!hConsoleOutput)
1713 SetLastError(ERROR_INVALID_HANDLE);
1714 else
1715 SetLastError(ERROR_INVALID_ACCESS);
1716
1717 return FALSE;
1718 }
1719
1720 CursorInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1721 CursorInfoRequest->OutputHandle = hConsoleOutput;
1722
1723 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1724 NULL,
1725 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCursorInfo),
1726 sizeof(*CursorInfoRequest));
1727 if (!NT_SUCCESS(ApiMessage.Status))
1728 {
1729 BaseSetLastNTError(ApiMessage.Status);
1730 return FALSE;
1731 }
1732
1733 *lpConsoleCursorInfo = CursorInfoRequest->Info;
1734
1735 return TRUE;
1736}
1737
1738
1739/*
1740 * @implemented
1741 */
1742BOOL
1743WINAPI
1744SetConsoleCursorInfo(HANDLE hConsoleOutput,
1745 CONST CONSOLE_CURSOR_INFO *lpConsoleCursorInfo)
1746{
1747 CONSOLE_API_MESSAGE ApiMessage;
1748 PCONSOLE_GETSETCURSORINFO CursorInfoRequest = &ApiMessage.Data.CursorInfoRequest;
1749
1750 CursorInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1751 CursorInfoRequest->OutputHandle = hConsoleOutput;
1752 CursorInfoRequest->Info = *lpConsoleCursorInfo;
1753
1754 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1755 NULL,
1756 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCursorInfo),
1757 sizeof(*CursorInfoRequest));
1758 if (!NT_SUCCESS(ApiMessage.Status))
1759 {
1760 BaseSetLastNTError(ApiMessage.Status);
1761 return FALSE;
1762 }
1763
1764 return TRUE;
1765}
1766
1767
1768/*
1769 * @implemented
1770 */
1771BOOL
1772WINAPI
1773GetNumberOfConsoleMouseButtons(LPDWORD lpNumberOfMouseButtons)
1774{
1775 CONSOLE_API_MESSAGE ApiMessage;
1776 PCONSOLE_GETMOUSEINFO GetMouseInfoRequest = &ApiMessage.Data.GetMouseInfoRequest;
1777
1778 GetMouseInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1779
1780 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1781 NULL,
1782 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetMouseInfo),
1783 sizeof(*GetMouseInfoRequest));
1784 if (!NT_SUCCESS(ApiMessage.Status))
1785 {
1786 BaseSetLastNTError(ApiMessage.Status);
1787 return FALSE;
1788 }
1789
1790 *lpNumberOfMouseButtons = GetMouseInfoRequest->NumButtons;
1791 return TRUE;
1792}
1793
1794
1795/*
1796 * @implemented
1797 */
1798BOOL
1799WINAPI
1800DECLSPEC_HOTPATCH
1801SetConsoleActiveScreenBuffer(HANDLE hConsoleOutput)
1802{
1803 CONSOLE_API_MESSAGE ApiMessage;
1804 PCONSOLE_SETACTIVESCREENBUFFER SetScreenBufferRequest = &ApiMessage.Data.SetScreenBufferRequest;
1805
1806 SetScreenBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1807 SetScreenBufferRequest->OutputHandle = hConsoleOutput;
1808
1809 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1810 NULL,
1811 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetActiveScreenBuffer),
1812 sizeof(*SetScreenBufferRequest));
1813 if (!NT_SUCCESS(ApiMessage.Status))
1814 {
1815 BaseSetLastNTError(ApiMessage.Status);
1816 return FALSE;
1817 }
1818
1819 return TRUE;
1820}
1821
1822
1823/*
1824 * @implemented
1825 */
1826BOOL
1827WINAPI
1828DECLSPEC_HOTPATCH
1829FlushConsoleInputBuffer(HANDLE hConsoleInput)
1830{
1831 CONSOLE_API_MESSAGE ApiMessage;
1832 PCONSOLE_FLUSHINPUTBUFFER FlushInputBufferRequest = &ApiMessage.Data.FlushInputBufferRequest;
1833
1834 FlushInputBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1835 FlushInputBufferRequest->InputHandle = hConsoleInput;
1836
1837 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1838 NULL,
1839 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFlushInputBuffer),
1840 sizeof(*FlushInputBufferRequest));
1841 if (!NT_SUCCESS(ApiMessage.Status))
1842 {
1843 BaseSetLastNTError(ApiMessage.Status);
1844 return FALSE;
1845 }
1846
1847 return TRUE;
1848}
1849
1850
1851/*
1852 * @implemented
1853 */
1854BOOL
1855WINAPI
1856DECLSPEC_HOTPATCH
1857SetConsoleScreenBufferSize(HANDLE hConsoleOutput,
1858 COORD dwSize)
1859{
1860 CONSOLE_API_MESSAGE ApiMessage;
1861 PCONSOLE_SETSCREENBUFFERSIZE SetScreenBufferSizeRequest = &ApiMessage.Data.SetScreenBufferSizeRequest;
1862
1863 SetScreenBufferSizeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1864 SetScreenBufferSizeRequest->OutputHandle = hConsoleOutput;
1865 SetScreenBufferSizeRequest->Size = dwSize;
1866
1867 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1868 NULL,
1869 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetScreenBufferSize),
1870 sizeof(*SetScreenBufferSizeRequest));
1871 if (!NT_SUCCESS(ApiMessage.Status))
1872 {
1873 BaseSetLastNTError(ApiMessage.Status);
1874 return FALSE;
1875 }
1876
1877 return TRUE;
1878}
1879
1880
1881static
1882BOOL
1883IntScrollConsoleScreenBuffer(HANDLE hConsoleOutput,
1884 CONST SMALL_RECT* lpScrollRectangle,
1885 CONST SMALL_RECT* lpClipRectangle,
1886 COORD dwDestinationOrigin,
1887 CONST CHAR_INFO* lpFill,
1888 BOOL bUnicode)
1889{
1890 CONSOLE_API_MESSAGE ApiMessage;
1891 PCONSOLE_SCROLLSCREENBUFFER ScrollScreenBufferRequest = &ApiMessage.Data.ScrollScreenBufferRequest;
1892
1893 ScrollScreenBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1894 ScrollScreenBufferRequest->OutputHandle = hConsoleOutput;
1895 ScrollScreenBufferRequest->ScrollRectangle = *lpScrollRectangle;
1896
1897 if (lpClipRectangle != NULL)
1898 {
1899 ScrollScreenBufferRequest->UseClipRectangle = TRUE;
1900 ScrollScreenBufferRequest->ClipRectangle = *lpClipRectangle;
1901 }
1902 else
1903 {
1904 ScrollScreenBufferRequest->UseClipRectangle = FALSE;
1905 }
1906
1907 ScrollScreenBufferRequest->DestinationOrigin = dwDestinationOrigin;
1908 ScrollScreenBufferRequest->Fill = *lpFill;
1909 ScrollScreenBufferRequest->Unicode = bUnicode;
1910
1911 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1912 NULL,
1913 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepScrollScreenBuffer),
1914 sizeof(*ScrollScreenBufferRequest));
1915 if (!NT_SUCCESS(ApiMessage.Status))
1916 {
1917 BaseSetLastNTError(ApiMessage.Status);
1918 return FALSE;
1919 }
1920
1921 return TRUE;
1922}
1923
1924
1925/*
1926 * @implemented
1927 */
1928BOOL
1929WINAPI
1930DECLSPEC_HOTPATCH
1931ScrollConsoleScreenBufferA(HANDLE hConsoleOutput,
1932 CONST SMALL_RECT* lpScrollRectangle,
1933 CONST SMALL_RECT* lpClipRectangle,
1934 COORD dwDestinationOrigin,
1935 CONST CHAR_INFO* lpFill)
1936{
1937 return IntScrollConsoleScreenBuffer(hConsoleOutput,
1938 lpScrollRectangle,
1939 lpClipRectangle,
1940 dwDestinationOrigin,
1941 lpFill,
1942 FALSE);
1943}
1944
1945
1946/*
1947 * @implemented
1948 */
1949BOOL
1950WINAPI
1951DECLSPEC_HOTPATCH
1952ScrollConsoleScreenBufferW(HANDLE hConsoleOutput,
1953 CONST SMALL_RECT *lpScrollRectangle,
1954 CONST SMALL_RECT *lpClipRectangle,
1955 COORD dwDestinationOrigin,
1956 CONST CHAR_INFO *lpFill)
1957{
1958 return IntScrollConsoleScreenBuffer(hConsoleOutput,
1959 lpScrollRectangle,
1960 lpClipRectangle,
1961 dwDestinationOrigin,
1962 lpFill,
1963 TRUE);
1964}
1965
1966
1967/*
1968 * @implemented
1969 */
1970BOOL
1971WINAPI
1972SetConsoleWindowInfo(HANDLE hConsoleOutput,
1973 BOOL bAbsolute,
1974 CONST SMALL_RECT *lpConsoleWindow)
1975{
1976 CONSOLE_API_MESSAGE ApiMessage;
1977 PCONSOLE_SETWINDOWINFO SetWindowInfoRequest = &ApiMessage.Data.SetWindowInfoRequest;
1978
1979 if (lpConsoleWindow == NULL)
1980 {
1981 SetLastError(ERROR_INVALID_PARAMETER);
1982 return FALSE;
1983 }
1984
1985 SetWindowInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1986 SetWindowInfoRequest->OutputHandle = hConsoleOutput;
1987 SetWindowInfoRequest->Absolute = bAbsolute;
1988 SetWindowInfoRequest->WindowRect = *lpConsoleWindow;
1989
1990 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1991 NULL,
1992 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetWindowInfo),
1993 sizeof(*SetWindowInfoRequest));
1994 if (!NT_SUCCESS(ApiMessage.Status))
1995 {
1996 BaseSetLastNTError(ApiMessage.Status);
1997 return FALSE;
1998 }
1999
2000 return TRUE;
2001}
2002
2003
2004/*
2005 * @implemented
2006 */
2007BOOL
2008WINAPI
2009DECLSPEC_HOTPATCH
2010SetConsoleTextAttribute(HANDLE hConsoleOutput,
2011 WORD wAttributes)
2012{
2013 CONSOLE_API_MESSAGE ApiMessage;
2014 PCONSOLE_SETTEXTATTRIB SetTextAttribRequest = &ApiMessage.Data.SetTextAttribRequest;
2015
2016 SetTextAttribRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2017 SetTextAttribRequest->OutputHandle = hConsoleOutput;
2018 SetTextAttribRequest->Attributes = wAttributes;
2019
2020 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2021 NULL,
2022 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetTextAttribute),
2023 sizeof(*SetTextAttribRequest));
2024 if (!NT_SUCCESS(ApiMessage.Status))
2025 {
2026 BaseSetLastNTError(ApiMessage.Status);
2027 return FALSE;
2028 }
2029
2030 return TRUE;
2031}
2032
2033
2034static
2035BOOL
2036AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
2037{
2038 PHANDLER_ROUTINE* NewCtrlHandlers = NULL;
2039
2040 if (HandlerRoutine == NULL)
2041 {
2042 NtCurrentPeb()->ProcessParameters->ConsoleFlags = TRUE;
2043 return TRUE;
2044 }
2045
2046 if (NrCtrlHandlers == NrAllocatedHandlers)
2047 {
2048 NewCtrlHandlers = RtlAllocateHeap(RtlGetProcessHeap(),
2049 0,
2050 (NrCtrlHandlers + 4) * sizeof(PHANDLER_ROUTINE));
2051 if (NewCtrlHandlers == NULL)
2052 {
2053 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2054 return FALSE;
2055 }
2056
2057 memmove(NewCtrlHandlers, CtrlHandlers, sizeof(PHANDLER_ROUTINE) * NrCtrlHandlers);
2058
2059 if (NrAllocatedHandlers > 1) RtlFreeHeap(RtlGetProcessHeap(), 0, CtrlHandlers);
2060
2061 CtrlHandlers = NewCtrlHandlers;
2062 NrAllocatedHandlers += 4;
2063 }
2064
2065 ASSERT(NrCtrlHandlers < NrAllocatedHandlers);
2066
2067 CtrlHandlers[NrCtrlHandlers++] = HandlerRoutine;
2068 return TRUE;
2069}
2070
2071
2072static
2073BOOL
2074RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
2075{
2076 ULONG i;
2077
2078 if (HandlerRoutine == NULL)
2079 {
2080 NtCurrentPeb()->ProcessParameters->ConsoleFlags = FALSE;
2081 return TRUE;
2082 }
2083
2084 for (i = 0; i < NrCtrlHandlers; i++)
2085 {
2086 if (CtrlHandlers[i] == HandlerRoutine)
2087 {
2088 if (i < (NrCtrlHandlers - 1))
2089 {
2090 memmove(&CtrlHandlers[i],
2091 &CtrlHandlers[i+1],
2092 (NrCtrlHandlers - i + 1) * sizeof(PHANDLER_ROUTINE));
2093 }
2094
2095 NrCtrlHandlers--;
2096 return TRUE;
2097 }
2098 }
2099
2100 SetLastError(ERROR_INVALID_PARAMETER);
2101 return FALSE;
2102}
2103
2104
2105/*
2106 * @implemented
2107 */
2108BOOL
2109WINAPI
2110DECLSPEC_HOTPATCH
2111SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine,
2112 BOOL Add)
2113{
2114 BOOL Ret;
2115
2116 RtlEnterCriticalSection(&ConsoleLock);
2117
2118 if (Add)
2119 Ret = AddConsoleCtrlHandler(HandlerRoutine);
2120 else
2121 Ret = RemoveConsoleCtrlHandler(HandlerRoutine);
2122
2123 RtlLeaveCriticalSection(&ConsoleLock);
2124 return Ret;
2125}
2126
2127
2128/*
2129 * @implemented
2130 */
2131BOOL
2132WINAPI
2133DECLSPEC_HOTPATCH
2134GenerateConsoleCtrlEvent(DWORD dwCtrlEvent,
2135 DWORD dwProcessGroupId)
2136{
2137 CONSOLE_API_MESSAGE ApiMessage;
2138 PCONSOLE_GENERATECTRLEVENT GenerateCtrlEventRequest = &ApiMessage.Data.GenerateCtrlEventRequest;
2139
2140 if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT)
2141 {
2142 SetLastError(ERROR_INVALID_PARAMETER);
2143 return FALSE;
2144 }
2145
2146 GenerateCtrlEventRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2147 GenerateCtrlEventRequest->CtrlEvent = dwCtrlEvent;
2148 GenerateCtrlEventRequest->ProcessGroupId = dwProcessGroupId;
2149
2150 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2151 NULL,
2152 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGenerateCtrlEvent),
2153 sizeof(*GenerateCtrlEventRequest));
2154 if (!NT_SUCCESS(ApiMessage.Status))
2155 {
2156 BaseSetLastNTError(ApiMessage.Status);
2157 return FALSE;
2158 }
2159
2160 return TRUE;
2161}
2162
2163
2164static DWORD
2165IntGetConsoleTitle(LPVOID lpConsoleTitle, DWORD dwNumChars, BOOLEAN bUnicode)
2166{
2167 CONSOLE_API_MESSAGE ApiMessage;
2168 PCONSOLE_GETSETCONSOLETITLE TitleRequest = &ApiMessage.Data.TitleRequest;
2169 PCSR_CAPTURE_BUFFER CaptureBuffer;
2170
2171 if (dwNumChars == 0) return 0;
2172
2173 TitleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2174 TitleRequest->Length = dwNumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
2175 TitleRequest->Unicode = bUnicode;
2176
2177 CaptureBuffer = CsrAllocateCaptureBuffer(1, TitleRequest->Length);
2178 if (CaptureBuffer == NULL)
2179 {
2180 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
2181 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2182 return 0;
2183 }
2184
2185 CsrAllocateMessagePointer(CaptureBuffer,
2186 TitleRequest->Length,
2187 (PVOID*)&TitleRequest->Title);
2188
2189 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2190 CaptureBuffer,
2191 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetTitle),
2192 sizeof(*TitleRequest));
2193 if (!NT_SUCCESS(ApiMessage.Status))
2194 {
2195 CsrFreeCaptureBuffer(CaptureBuffer);
2196 BaseSetLastNTError(ApiMessage.Status);
2197 return 0;
2198 }
2199
2200 dwNumChars = TitleRequest->Length / (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
2201
2202 if (dwNumChars > 0)
2203 {
2204 RtlCopyMemory(lpConsoleTitle, TitleRequest->Title, TitleRequest->Length);
2205
2206 if (bUnicode)
2207 ((LPWSTR)lpConsoleTitle)[dwNumChars] = UNICODE_NULL;
2208 else
2209 ((LPSTR)lpConsoleTitle)[dwNumChars] = ANSI_NULL;
2210 }
2211
2212 CsrFreeCaptureBuffer(CaptureBuffer);
2213
2214 return dwNumChars;
2215}
2216
2217
2218/*
2219 * @implemented
2220 */
2221DWORD
2222WINAPI
2223DECLSPEC_HOTPATCH
2224GetConsoleTitleW(LPWSTR lpConsoleTitle,
2225 DWORD nSize)
2226{
2227 return IntGetConsoleTitle(lpConsoleTitle, nSize, TRUE);
2228}
2229
2230
2231/*
2232 * @implemented
2233 */
2234DWORD
2235WINAPI
2236DECLSPEC_HOTPATCH
2237GetConsoleTitleA(LPSTR lpConsoleTitle,
2238 DWORD nSize)
2239{
2240 return IntGetConsoleTitle(lpConsoleTitle, nSize, FALSE);
2241}
2242
2243
2244static BOOL
2245IntSetConsoleTitle(CONST VOID *lpConsoleTitle, BOOLEAN bUnicode)
2246{
2247 CONSOLE_API_MESSAGE ApiMessage;
2248 PCONSOLE_GETSETCONSOLETITLE TitleRequest = &ApiMessage.Data.TitleRequest;
2249 PCSR_CAPTURE_BUFFER CaptureBuffer;
2250
2251 ULONG NumChars = (ULONG)(lpConsoleTitle ? (bUnicode ? wcslen(lpConsoleTitle) : strlen(lpConsoleTitle)) : 0);
2252
2253 TitleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2254 TitleRequest->Length = NumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
2255 TitleRequest->Unicode = bUnicode;
2256
2257 CaptureBuffer = CsrAllocateCaptureBuffer(1, TitleRequest->Length);
2258 if (CaptureBuffer == NULL)
2259 {
2260 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
2261 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2262 return FALSE;
2263 }
2264
2265 CsrCaptureMessageBuffer(CaptureBuffer,
2266 (PVOID)lpConsoleTitle,
2267 TitleRequest->Length,
2268 (PVOID*)&TitleRequest->Title);
2269
2270 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2271 CaptureBuffer,
2272 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetTitle),
2273 sizeof(*TitleRequest));
2274
2275 CsrFreeCaptureBuffer(CaptureBuffer);
2276
2277 if (!NT_SUCCESS(ApiMessage.Status))
2278 {
2279 BaseSetLastNTError(ApiMessage.Status);
2280 return FALSE;
2281 }
2282
2283 return TRUE;
2284}
2285
2286/*
2287 * @implemented
2288 */
2289BOOL
2290WINAPI
2291DECLSPEC_HOTPATCH
2292SetConsoleTitleW(LPCWSTR lpConsoleTitle)
2293{
2294 return IntSetConsoleTitle(lpConsoleTitle, TRUE);
2295}
2296
2297
2298/*
2299 * @implemented
2300 */
2301BOOL
2302WINAPI
2303DECLSPEC_HOTPATCH
2304SetConsoleTitleA(LPCSTR lpConsoleTitle)
2305{
2306 return IntSetConsoleTitle(lpConsoleTitle, FALSE);
2307}
2308
2309
2310/*
2311 * @implemented
2312 */
2313HANDLE
2314WINAPI
2315CreateConsoleScreenBuffer(DWORD dwDesiredAccess,
2316 DWORD dwShareMode,
2317 CONST SECURITY_ATTRIBUTES *lpSecurityAttributes,
2318 DWORD dwFlags,
2319 LPVOID lpScreenBufferData)
2320{
2321 CONSOLE_API_MESSAGE ApiMessage;
2322 PCONSOLE_CREATESCREENBUFFER CreateScreenBufferRequest = &ApiMessage.Data.CreateScreenBufferRequest;
2323 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
2324 PCONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo = lpScreenBufferData;
2325
2326 if ( (dwDesiredAccess & ~(GENERIC_READ | GENERIC_WRITE)) ||
2327 (dwShareMode & ~(FILE_SHARE_READ | FILE_SHARE_WRITE)) ||
2328 (dwFlags != CONSOLE_TEXTMODE_BUFFER && dwFlags != CONSOLE_GRAPHICS_BUFFER) )
2329 {
2330 SetLastError(ERROR_INVALID_PARAMETER);
2331 return INVALID_HANDLE_VALUE;
2332 }
2333
2334 CreateScreenBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2335 CreateScreenBufferRequest->DesiredAccess = dwDesiredAccess;
2336 CreateScreenBufferRequest->InheritHandle =
2337 (lpSecurityAttributes ? lpSecurityAttributes->bInheritHandle : FALSE);
2338 CreateScreenBufferRequest->ShareMode = dwShareMode;
2339 CreateScreenBufferRequest->ScreenBufferType = dwFlags;
2340
2341 if (dwFlags == CONSOLE_GRAPHICS_BUFFER)
2342 {
2343 if (CreateScreenBufferRequest->InheritHandle || GraphicsBufferInfo == NULL)
2344 {
2345 SetLastError(ERROR_INVALID_PARAMETER);
2346 return INVALID_HANDLE_VALUE;
2347 }
2348
2349 CreateScreenBufferRequest->GraphicsBufferInfo = *GraphicsBufferInfo;
2350
2351 CaptureBuffer = CsrAllocateCaptureBuffer(1, GraphicsBufferInfo->dwBitMapInfoLength);
2352 if (CaptureBuffer == NULL)
2353 {
2354 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2355 return INVALID_HANDLE_VALUE;
2356 }
2357
2358 CsrCaptureMessageBuffer(CaptureBuffer,
2359 (PVOID)GraphicsBufferInfo->lpBitMapInfo,
2360 GraphicsBufferInfo->dwBitMapInfoLength,
2361 (PVOID*)&CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMapInfo);
2362 }
2363
2364 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2365 CaptureBuffer,
2366 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepCreateScreenBuffer),
2367 sizeof(*CreateScreenBufferRequest));
2368
2369 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
2370
2371 if (!NT_SUCCESS(ApiMessage.Status))
2372 {
2373 BaseSetLastNTError(ApiMessage.Status);
2374 return INVALID_HANDLE_VALUE;
2375 }
2376
2377 if (dwFlags == CONSOLE_GRAPHICS_BUFFER && GraphicsBufferInfo)
2378 {
2379 GraphicsBufferInfo->hMutex = CreateScreenBufferRequest->hMutex ; // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex ;
2380 GraphicsBufferInfo->lpBitMap = CreateScreenBufferRequest->lpBitMap; // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap;
2381 }
2382
2383 return CreateScreenBufferRequest->OutputHandle;
2384}
2385
2386
2387/*
2388 * @implemented
2389 */
2390UINT
2391WINAPI
2392DECLSPEC_HOTPATCH
2393GetConsoleCP(VOID)
2394{
2395 CONSOLE_API_MESSAGE ApiMessage;
2396 PCONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest = &ApiMessage.Data.GetConsoleCPRequest;
2397
2398 /* Get the Input Code Page */
2399 GetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2400 GetConsoleCPRequest->OutputCP = FALSE;
2401
2402 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2403 NULL,
2404 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCP),
2405 sizeof(*GetConsoleCPRequest));
2406 if (!NT_SUCCESS(ApiMessage.Status))
2407 {
2408 BaseSetLastNTError(ApiMessage.Status);
2409 return 0;
2410 }
2411
2412 return GetConsoleCPRequest->CodePage;
2413}
2414
2415
2416/*
2417 * @implemented
2418 */
2419BOOL
2420WINAPI
2421DECLSPEC_HOTPATCH
2422SetConsoleCP(UINT wCodePageID)
2423{
2424 CONSOLE_API_MESSAGE ApiMessage;
2425 PCONSOLE_SETINPUTOUTPUTCP SetConsoleCPRequest = &ApiMessage.Data.SetConsoleCPRequest;
2426
2427 /* Set the Input Code Page */
2428 SetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2429 SetConsoleCPRequest->CodePage = wCodePageID;
2430 SetConsoleCPRequest->OutputCP = FALSE;
2431 /* SetConsoleCPRequest->EventHandle; */
2432
2433 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2434 NULL,
2435 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCP),
2436 sizeof(*SetConsoleCPRequest));
2437 if (!NT_SUCCESS(ApiMessage.Status))
2438 {
2439 BaseSetLastNTError(ApiMessage.Status);
2440 return FALSE;
2441 }
2442
2443 return TRUE;
2444}
2445
2446
2447/*
2448 * @implemented
2449 */
2450UINT
2451WINAPI
2452DECLSPEC_HOTPATCH
2453GetConsoleOutputCP(VOID)
2454{
2455 CONSOLE_API_MESSAGE ApiMessage;
2456 PCONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest = &ApiMessage.Data.GetConsoleCPRequest;
2457
2458 /* Get the Output Code Page */
2459 GetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2460 GetConsoleCPRequest->OutputCP = TRUE;
2461
2462 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2463 NULL,
2464 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCP),
2465 sizeof(*GetConsoleCPRequest));
2466 if (!NT_SUCCESS(ApiMessage.Status))
2467 {
2468 BaseSetLastNTError(ApiMessage.Status);
2469 return 0;
2470 }
2471
2472 return GetConsoleCPRequest->CodePage;
2473}
2474
2475
2476/*
2477 * @implemented
2478 */
2479BOOL
2480WINAPI
2481DECLSPEC_HOTPATCH
2482SetConsoleOutputCP(UINT wCodePageID)
2483{
2484 CONSOLE_API_MESSAGE ApiMessage;
2485 PCONSOLE_SETINPUTOUTPUTCP SetConsoleCPRequest = &ApiMessage.Data.SetConsoleCPRequest;
2486
2487 /* Set the Output Code Page */
2488 SetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2489 SetConsoleCPRequest->CodePage = wCodePageID;
2490 SetConsoleCPRequest->OutputCP = TRUE;
2491 /* SetConsoleCPRequest->EventHandle; */
2492
2493 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2494 NULL,
2495 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCP),
2496 sizeof(*SetConsoleCPRequest));
2497 if (!NT_SUCCESS(ApiMessage.Status))
2498 {
2499 BaseSetLastNTError(ApiMessage.Status);
2500 return FALSE;
2501 }
2502
2503 /* Sync the current thread's LangId with the console's one */
2504 SetTEBLangID();
2505
2506 return TRUE;
2507}
2508
2509
2510/*
2511 * @implemented
2512 */
2513DWORD
2514WINAPI
2515GetConsoleProcessList(LPDWORD lpdwProcessList,
2516 DWORD dwProcessCount)
2517{
2518 CONSOLE_API_MESSAGE ApiMessage;
2519 PCONSOLE_GETPROCESSLIST GetProcessListRequest = &ApiMessage.Data.GetProcessListRequest;
2520 PCSR_CAPTURE_BUFFER CaptureBuffer;
2521 ULONG nProcesses = 0;
2522
2523 if (lpdwProcessList == NULL || dwProcessCount == 0)
2524 {
2525 SetLastError(ERROR_INVALID_PARAMETER);
2526 return 0;
2527 }
2528
2529 CaptureBuffer = CsrAllocateCaptureBuffer(1, dwProcessCount * sizeof(DWORD));
2530 if (CaptureBuffer == NULL)
2531 {
2532 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
2533 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2534 return 0;
2535 }
2536
2537 GetProcessListRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2538 GetProcessListRequest->ProcessCount = dwProcessCount;
2539
2540 CsrAllocateMessagePointer(CaptureBuffer,
2541 dwProcessCount * sizeof(DWORD),
2542 (PVOID*)&GetProcessListRequest->ProcessIdsList);
2543
2544 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2545 CaptureBuffer,
2546 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetProcessList),
2547 sizeof(*GetProcessListRequest));
2548 if (!NT_SUCCESS(ApiMessage.Status))
2549 {
2550 BaseSetLastNTError(ApiMessage.Status);
2551 }
2552 else
2553 {
2554 nProcesses = GetProcessListRequest->ProcessCount;
2555 if (dwProcessCount >= nProcesses)
2556 {
2557 RtlCopyMemory(lpdwProcessList, GetProcessListRequest->ProcessIdsList, nProcesses * sizeof(DWORD));
2558 }
2559 }
2560
2561 CsrFreeCaptureBuffer(CaptureBuffer);
2562 return nProcesses;
2563}
2564
2565
2566/*
2567 * @implemented
2568 */
2569BOOL
2570WINAPI
2571GetConsoleSelectionInfo(PCONSOLE_SELECTION_INFO lpConsoleSelectionInfo)
2572{
2573 CONSOLE_API_MESSAGE ApiMessage;
2574 PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest = &ApiMessage.Data.GetSelectionInfoRequest;
2575
2576 if (lpConsoleSelectionInfo == NULL)
2577 {
2578 SetLastError(ERROR_INVALID_PARAMETER);
2579 return FALSE;
2580 }
2581
2582 GetSelectionInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2583
2584 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2585 NULL,
2586 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetSelectionInfo),
2587 sizeof(*GetSelectionInfoRequest));
2588 if (!NT_SUCCESS(ApiMessage.Status))
2589 {
2590 BaseSetLastNTError(ApiMessage.Status);
2591 return FALSE;
2592 }
2593
2594 *lpConsoleSelectionInfo = GetSelectionInfoRequest->Info;
2595
2596 return TRUE;
2597}
2598
2599
2600/*
2601 * @implemented
2602 * @note Strongly inspired by AllocConsole.
2603 */
2604static BOOL
2605IntAttachConsole(DWORD ProcessId,
2606 LPTHREAD_START_ROUTINE CtrlRoutine,
2607 LPTHREAD_START_ROUTINE PropRoutine,
2608 PCONSOLE_START_INFO ConsoleStartInfo)
2609{
2610 BOOL Success = TRUE;
2611 NTSTATUS Status;
2612
2613 CONSOLE_API_MESSAGE ApiMessage;
2614 PCONSOLE_ATTACHCONSOLE AttachConsoleRequest = &ApiMessage.Data.AttachConsoleRequest;
2615 PCSR_CAPTURE_BUFFER CaptureBuffer;
2616
2617 AttachConsoleRequest->ProcessId = ProcessId;
2618 AttachConsoleRequest->CtrlRoutine = CtrlRoutine;
2619 AttachConsoleRequest->PropRoutine = PropRoutine;
2620
2621 CaptureBuffer = CsrAllocateCaptureBuffer(1, sizeof(CONSOLE_START_INFO));
2622 if (CaptureBuffer == NULL)
2623 {
2624 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2625 Success = FALSE;
2626 goto Quit;
2627 }
2628
2629 CsrCaptureMessageBuffer(CaptureBuffer,
2630 ConsoleStartInfo,
2631 sizeof(CONSOLE_START_INFO),
2632 (PVOID*)&AttachConsoleRequest->ConsoleStartInfo);
2633
2634 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2635 CaptureBuffer,
2636 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAttach),
2637 sizeof(*AttachConsoleRequest));
2638 if (!NT_SUCCESS(ApiMessage.Status))
2639 {
2640 BaseSetLastNTError(ApiMessage.Status);
2641 Success = FALSE;
2642 goto Quit;
2643 }
2644
2645 // Is AttachConsoleRequest->ConsoleStartInfo->InitEvents aligned on handle boundary ????
2646 Status = NtWaitForMultipleObjects(MAX_INIT_EVENTS,
2647 AttachConsoleRequest->ConsoleStartInfo->InitEvents,
2648 WaitAny, FALSE, NULL);
2649 if (!NT_SUCCESS(Status))
2650 {
2651 BaseSetLastNTError(Status);
2652 Success = FALSE;
2653 goto Quit;
2654 }
2655
2656 NtClose(AttachConsoleRequest->ConsoleStartInfo->InitEvents[INIT_SUCCESS]);
2657 NtClose(AttachConsoleRequest->ConsoleStartInfo->InitEvents[INIT_FAILURE]);
2658 if (Status != INIT_SUCCESS)
2659 {
2660 NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
2661 Success = FALSE;
2662 }
2663 else
2664 {
2665 RtlCopyMemory(ConsoleStartInfo,
2666 AttachConsoleRequest->ConsoleStartInfo,
2667 sizeof(CONSOLE_START_INFO));
2668 Success = TRUE;
2669 }
2670
2671Quit:
2672 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
2673 return Success;
2674}
2675
2676BOOL
2677WINAPI
2678AttachConsole(DWORD dwProcessId)
2679{
2680 BOOL Success;
2681 CONSOLE_START_INFO ConsoleStartInfo;
2682 DWORD dummy;
2683
2684 RtlEnterCriticalSection(&ConsoleLock);
2685
2686 if (NtCurrentPeb()->ProcessParameters->ConsoleHandle)
2687 {
2688 DPRINT1("AttachConsole: Attaching a console to a process already having one\n");
2689 SetLastError(ERROR_ACCESS_DENIED);
2690 Success = FALSE;
2691 goto Quit;
2692 }
2693
2694 /* Set up the console properties */
2695 SetUpConsoleInfo(FALSE,
2696 &dummy,
2697 NULL,
2698 &dummy,
2699 NULL,
2700 &ConsoleStartInfo);
2701
2702 Success = IntAttachConsole(dwProcessId,
2703 ConsoleControlDispatcher,
2704 PropDialogHandler,
2705 &ConsoleStartInfo);
2706 if (Success)
2707 {
2708 /* Set up the handles */
2709 SetUpHandles(&ConsoleStartInfo);
2710 InputWaitHandle = ConsoleStartInfo.InputWaitHandle;
2711
2712 /* Initialize Console Ctrl Handling */
2713 InitializeCtrlHandling();
2714
2715 /* Sync the current thread's LangId with the console's one */
2716 SetTEBLangID();
2717 }
2718
2719Quit:
2720 RtlLeaveCriticalSection(&ConsoleLock);
2721 return Success;
2722}
2723
2724
2725/*
2726 * @implemented
2727 */
2728HWND
2729WINAPI
2730DECLSPEC_HOTPATCH
2731GetConsoleWindow(VOID)
2732{
2733 CONSOLE_API_MESSAGE ApiMessage;
2734 PCONSOLE_GETWINDOW GetWindowRequest = &ApiMessage.Data.GetWindowRequest;
2735
2736 GetWindowRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2737
2738 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2739 NULL,
2740 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetConsoleWindow),
2741 sizeof(*GetWindowRequest));
2742 if (!NT_SUCCESS(ApiMessage.Status))
2743 {
2744 BaseSetLastNTError(ApiMessage.Status);
2745 return (HWND)NULL;
2746 }
2747
2748 return GetWindowRequest->WindowHandle;
2749}
2750
2751
2752/*
2753 * @implemented
2754 */
2755BOOL
2756WINAPI
2757DECLSPEC_HOTPATCH
2758SetConsoleIcon(HICON hIcon)
2759{
2760 CONSOLE_API_MESSAGE ApiMessage;
2761 PCONSOLE_SETICON SetIconRequest = &ApiMessage.Data.SetIconRequest;
2762
2763 SetIconRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2764 SetIconRequest->IconHandle = hIcon;
2765
2766 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2767 NULL,
2768 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetIcon),
2769 sizeof(*SetIconRequest));
2770 if (!NT_SUCCESS(ApiMessage.Status))
2771 {
2772 BaseSetLastNTError(ApiMessage.Status);
2773 return FALSE;
2774 }
2775
2776 return TRUE;
2777}
2778
2779
2780/******************************************************************************
2781 * \name SetConsoleInputExeNameW
2782 * \brief Sets the console input file name from a unicode string.
2783 * \param lpExeName Pointer to a unicode string with the name.
2784 * \return TRUE if successful, FALSE if unsuccessful.
2785 * \remarks If lpExeName is 0 or the string length is 0 or greater than 255,
2786 * the function fails and sets last error to ERROR_INVALID_PARAMETER.
2787 */
2788BOOL
2789WINAPI
2790DECLSPEC_HOTPATCH
2791SetConsoleInputExeNameW(IN LPCWSTR lpExeName)
2792{
2793 DWORD ExeLength;
2794
2795 ExeLength = lstrlenW(lpExeName);
2796 if ((ExeLength == 0) || (ExeLength >= EXENAME_LENGTH))
2797 {
2798 /* Fail if string is empty or too long */
2799 SetLastError(ERROR_INVALID_PARAMETER);
2800 return FALSE;
2801 }
2802
2803 RtlEnterCriticalSection(&ExeNameLock);
2804 _SEH2_TRY
2805 {
2806 /* Set the input EXE name, not NULL terminated */
2807 RtlCopyMemory(ExeNameBuffer, lpExeName, ExeLength * sizeof(WCHAR));
2808 ExeNameLength = (USHORT)ExeLength;
2809 }
2810 _SEH2_FINALLY
2811 {
2812 RtlLeaveCriticalSection(&ExeNameLock);
2813 }
2814 _SEH2_END;
2815
2816 return TRUE;
2817}
2818
2819
2820/******************************************************************************
2821 * \name SetConsoleInputExeNameA
2822 * \brief Sets the console input file name from an ansi string.
2823 * \param lpExeName Pointer to an ansi string with the name.
2824 * \return TRUE if successful, FALSE if unsuccessful.
2825 * \remarks If lpExeName is 0 or the string length is 0 or greater than 255,
2826 * the function fails and sets last error to ERROR_INVALID_PARAMETER.
2827 */
2828BOOL
2829WINAPI
2830DECLSPEC_HOTPATCH
2831SetConsoleInputExeNameA(IN LPCSTR lpExeName)
2832{
2833 NTSTATUS Status;
2834#ifdef USE_TEB_STATIC_USTR
2835 PUNICODE_STRING ExeNameU;
2836#else
2837 UNICODE_STRING ExeNameU;
2838#endif
2839 ANSI_STRING ExeNameA;
2840#ifndef USE_TEB_STATIC_USTR
2841 WCHAR Buffer[EXENAME_LENGTH];
2842#endif
2843
2844#ifdef USE_TEB_STATIC_USTR
2845 /*
2846 * Use the TEB static UNICODE string for storage. It is already
2847 * initialized at process creation time by the Memory Manager.
2848 */
2849 ExeNameU = &NtCurrentTeb()->StaticUnicodeString;
2850#endif
2851
2852 /* Initialize string for conversion */
2853 RtlInitAnsiString(&ExeNameA, lpExeName);
2854
2855#if 1
2856 if ((ExeNameA.Length == 0) || (ExeNameA.Length >= EXENAME_LENGTH))
2857 {
2858 /* Fail if string is empty or too long */
2859 SetLastError(ERROR_INVALID_PARAMETER);
2860 return FALSE;
2861 }
2862#endif
2863#ifndef USE_TEB_STATIC_USTR
2864 ExeNameU.Length = 0;
2865 ExeNameU.MaximumLength = (USHORT)sizeof(Buffer);
2866 ExeNameU.Buffer = Buffer;
2867#endif
2868
2869#ifdef USE_TEB_STATIC_USTR
2870 Status = RtlAnsiStringToUnicodeString(ExeNameU, &ExeNameA, FALSE);
2871#else
2872 Status = RtlAnsiStringToUnicodeString(&ExeNameU, &ExeNameA, FALSE);
2873#endif
2874 if (!NT_SUCCESS(Status))
2875 {
2876 /* Fail if string is empty or too long */
2877 if (Status == STATUS_BUFFER_OVERFLOW)
2878 SetLastError(ERROR_FILENAME_EXCED_RANGE);
2879 else
2880 SetLastError(ERROR_INVALID_PARAMETER);
2881
2882 return FALSE;
2883 }
2884
2885#ifdef USE_TEB_STATIC_USTR
2886 return SetConsoleInputExeNameW(ExeNameU->Buffer);
2887#else
2888 return SetConsoleInputExeNameW(ExeNameU.Buffer);
2889#endif
2890}
2891
2892
2893/******************************************************************************
2894 * \name GetConsoleInputExeNameW
2895 * \brief Retrieves the console input file name as unicode string.
2896 * \param nBufferLength Length of the buffer in WCHARs.
2897 * Specify 0 to receive the needed buffer length.
2898 * \param lpBuffer Pointer to a buffer that receives the string.
2899 * \return Needed buffer size if \p nBufferLength is 0.
2900 * Otherwise 1 if successful, 2 if buffer is too small.
2901 * \remarks Sets last error value to ERROR_BUFFER_OVERFLOW if the buffer
2902 * is not big enough.
2903 */
2904DWORD
2905WINAPI
2906DECLSPEC_HOTPATCH
2907GetConsoleInputExeNameW(IN DWORD nBufferLength,
2908 OUT LPWSTR lpExeName)
2909{
2910 if (nBufferLength <= ExeNameLength)
2911 {
2912 /* Buffer is not large enough! Return the correct size. */
2913 SetLastError(ERROR_BUFFER_OVERFLOW);
2914 return ExeNameLength + 1;
2915 }
2916
2917 RtlEnterCriticalSection(&ExeNameLock);
2918 _SEH2_TRY
2919 {
2920 /* Copy the input EXE name and NULL-terminate it */
2921 RtlCopyMemory(lpExeName, ExeNameBuffer, ExeNameLength * sizeof(WCHAR));
2922 lpExeName[ExeNameLength] = UNICODE_NULL;
2923 }
2924 _SEH2_FINALLY
2925 {
2926 RtlLeaveCriticalSection(&ExeNameLock);
2927 }
2928 _SEH2_END;
2929
2930 return TRUE;
2931}
2932
2933
2934/******************************************************************************
2935 * \name GetConsoleInputExeNameA
2936 * \brief Retrieves the console input file name as ansi string.
2937 * \param nBufferLength Length of the buffer in CHARs.
2938 * \param lpBuffer Pointer to a buffer that receives the string.
2939 * \return 1 if successful, 2 if buffer is too small.
2940 * \remarks Sets last error value to ERROR_BUFFER_OVERFLOW if the buffer
2941 * is not big enough. The buffer receives as much characters as fit.
2942 */
2943DWORD
2944WINAPI
2945DECLSPEC_HOTPATCH
2946GetConsoleInputExeNameA(IN DWORD nBufferLength,
2947 OUT LPSTR lpExeName)
2948{
2949 NTSTATUS Status;
2950 DWORD ExeLength;
2951 UNICODE_STRING BufferU;
2952 ANSI_STRING BufferA;
2953 WCHAR Buffer[EXENAME_LENGTH];
2954
2955 /* Get the UNICODE name */
2956 ExeLength = GetConsoleInputExeNameW(EXENAME_LENGTH, Buffer);
2957
2958 if ((ExeLength == 0) || (ExeLength >= EXENAME_LENGTH))
2959 return ExeLength;
2960
2961 /* Initialize the strings for conversion */
2962 RtlInitUnicodeString(&BufferU, Buffer);
2963 BufferA.Length = 0;
2964 BufferA.MaximumLength = (USHORT)nBufferLength;
2965 BufferA.Buffer = lpExeName;
2966
2967 /* Convert UNICODE name to ANSI, copying as much chars as it can fit */
2968 Status = RtlUnicodeStringToAnsiString(&BufferA, &BufferU, FALSE);
2969 if (!NT_SUCCESS(Status))
2970 {
2971 if (Status == STATUS_BUFFER_OVERFLOW)
2972 {
2973 SetLastError(ERROR_BUFFER_OVERFLOW);
2974 return ExeLength + 1;
2975 }
2976 SetLastError(ERROR_INVALID_PARAMETER);
2977 }
2978
2979 return ExeLength;
2980}
2981
2982BOOL
2983WINAPI
2984GetConsoleCharType(HANDLE hConsole, COORD Coord, PDWORD Type)
2985{
2986 STUB;
2987 return FALSE;
2988}
2989
2990BOOL
2991WINAPI
2992DECLSPEC_HOTPATCH
2993GetConsoleCursorMode(HANDLE hConsole, PBOOL pUnknown1, PBOOL pUnknown2)
2994{
2995 STUB;
2996 return FALSE;
2997}
2998
2999BOOL
3000WINAPI
3001DECLSPEC_HOTPATCH
3002SetConsoleCursorMode(HANDLE hConsole, BOOL Unknown1, BOOL Unknown2)
3003{
3004 STUB;
3005 return FALSE;
3006}
3007
3008BOOL
3009WINAPI
3010DECLSPEC_HOTPATCH
3011GetConsoleNlsMode(HANDLE hConsole, LPDWORD lpMode)
3012{
3013 STUB;
3014 return FALSE;
3015}
3016
3017BOOL
3018WINAPI
3019DECLSPEC_HOTPATCH
3020SetConsoleNlsMode(HANDLE hConsole, DWORD dwMode)
3021{
3022 STUB;
3023 return FALSE;
3024}
3025
3026BOOL
3027WINAPI
3028DECLSPEC_HOTPATCH
3029SetConsoleLocalEUDC(
3030 _In_ HANDLE hConsoleHandle,
3031 _In_ WORD wCodePoint,
3032 _In_ COORD cFontSize,
3033 _In_ PCHAR lpSB)
3034{
3035 STUB;
3036 return FALSE;
3037}
3038
3039static BOOL
3040IntRegisterConsoleIME(
3041 _In_ HWND hWnd,
3042 _In_ DWORD dwThreadId,
3043 _In_opt_ SIZE_T cbDesktop,
3044 _In_opt_ PWSTR pDesktop,
3045 _Out_opt_ PDWORD pdwAttachToThreadId)
3046{
3047 CONSOLE_API_MESSAGE ApiMessage;
3048 PCONSOLE_REGISTERCONSOLEIME RegisterConsoleIME = &ApiMessage.Data.RegisterConsoleIME;
3049 PCSR_CAPTURE_BUFFER CaptureBuffer;
3050
3051 if (!cbDesktop || !pDesktop)
3052 {
3053 pDesktop = NtCurrentPeb()->ProcessParameters->DesktopInfo.Buffer;
3054 cbDesktop = NtCurrentPeb()->ProcessParameters->DesktopInfo.Length;
3055 }
3056
3057 cbDesktop = min(cbDesktop, (MAX_PATH + 1) * sizeof(WCHAR));
3058
3059 RegisterConsoleIME->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
3060 RegisterConsoleIME->hWnd = hWnd;
3061 RegisterConsoleIME->dwThreadId = dwThreadId;
3062 RegisterConsoleIME->cbDesktop = cbDesktop;
3063
3064 CaptureBuffer = CsrAllocateCaptureBuffer(1, cbDesktop);
3065 if (!CaptureBuffer)
3066 {
3067 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3068 return FALSE;
3069 }
3070
3071 CsrCaptureMessageBuffer(CaptureBuffer,
3072 pDesktop,
3073 cbDesktop,
3074 (PVOID*)&RegisterConsoleIME->pDesktop);
3075
3076 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
3077 CaptureBuffer,
3078 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepRegisterConsoleIME),
3079 sizeof(*RegisterConsoleIME));
3080
3081 CsrFreeCaptureBuffer(CaptureBuffer);
3082
3083 if (!NT_SUCCESS(ApiMessage.Status))
3084 {
3085 BaseSetLastNTError(ApiMessage.Status);
3086 return FALSE;
3087 }
3088
3089 if (pdwAttachToThreadId)
3090 {
3091 _SEH2_TRY
3092 {
3093 *pdwAttachToThreadId = RegisterConsoleIME->dwAttachToThreadId;
3094 }
3095 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3096 {
3097 BaseSetLastNTError(STATUS_ACCESS_VIOLATION);
3098 _SEH2_YIELD(return FALSE);
3099 }
3100 _SEH2_END;
3101 }
3102
3103 return TRUE;
3104}
3105
3106static BOOL
3107IntUnregisterConsoleIME(
3108 _In_ DWORD dwThreadId)
3109{
3110 CONSOLE_API_MESSAGE ApiMessage;
3111 PCONSOLE_UNREGISTERCONSOLEIME UnregisterConsoleIME = &ApiMessage.Data.UnregisterConsoleIME;
3112
3113 UnregisterConsoleIME->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
3114 UnregisterConsoleIME->dwThreadId = dwThreadId;
3115
3116 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
3117 NULL,
3118 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepUnregisterConsoleIME),
3119 sizeof(*UnregisterConsoleIME));
3120 if (!NT_SUCCESS(ApiMessage.Status))
3121 {
3122 BaseSetLastNTError(ApiMessage.Status);
3123 return FALSE;
3124 }
3125
3126 return TRUE;
3127}
3128
3129/* This function is called by CONIME.EXE */
3130BOOL
3131WINAPI
3132DECLSPEC_HOTPATCH
3133RegisterConsoleIME(
3134 _In_ HWND hWnd,
3135 _Out_opt_ LPDWORD pdwAttachToThreadId)
3136{
3137 return IntRegisterConsoleIME(hWnd,
3138 GetCurrentThreadId(),
3139 0,
3140 NULL,
3141 pdwAttachToThreadId);
3142}
3143
3144BOOL
3145WINAPI
3146DECLSPEC_HOTPATCH
3147RegisterConsoleOS2(BOOL bUnknown)
3148{
3149 STUB;
3150 return FALSE;
3151}
3152
3153BOOL
3154WINAPI
3155DECLSPEC_HOTPATCH
3156SetConsoleOS2OemFormat(BOOL bUnknown)
3157{
3158 STUB;
3159 return FALSE;
3160}
3161
3162/* This function is called by CONIME.EXE */
3163BOOL
3164WINAPI
3165DECLSPEC_HOTPATCH
3166UnregisterConsoleIME(VOID)
3167{
3168 return IntUnregisterConsoleIME(GetCurrentThreadId());
3169}
3170
3171/**
3172 * @brief
3173 * Internal helper function used to synchronize the current
3174 * thread's language ID with the one from the console.
3175 **/
3176VOID
3177SetTEBLangID(VOID)
3178{
3179 CONSOLE_API_MESSAGE ApiMessage;
3180 PCONSOLE_GETLANGID LangIdRequest = &ApiMessage.Data.LangIdRequest;
3181
3182 /* Retrieve the "best-suited" language ID corresponding
3183 * to the active console output code page. */
3184 LangIdRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
3185
3186 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
3187 NULL,
3188 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetLangId),
3189 sizeof(*LangIdRequest));
3190 if (!NT_SUCCESS(ApiMessage.Status))
3191 {
3192 /*
3193 * No best console language ID: keep the current thread's one.
3194 * Since this internal function only modifies an optional setting,
3195 * don't set any last error, as it could otherwise mess with the
3196 * main last error set by the caller.
3197 */
3198 return;
3199 }
3200
3201 /*
3202 * We succeeded, set the current thread's language ID by
3203 * modifying its locale -- Windows <= 2003 does not have
3204 * the concept of a separate thread UI language.
3205 * Ignore the returned value.
3206 */
3207 if (!SetThreadLocale(MAKELCID(LangIdRequest->LangId, SORT_DEFAULT)))
3208 {
3209 DPRINT1("SetTEBLangID: Could not set thread locale to console lang ID %lu\n",
3210 LangIdRequest->LangId);
3211 }
3212}
3213
3214static
3215BOOL
3216IntGetConsoleKeyboardLayoutName(OUT PVOID pszLayoutName,
3217 IN BOOL bAnsi)
3218{
3219 CONSOLE_API_MESSAGE ApiMessage;
3220 PCONSOLE_GETKBDLAYOUTNAME GetKbdLayoutNameRequest = &ApiMessage.Data.GetKbdLayoutNameRequest;
3221
3222 /* Set up the data to send to the Console Server */
3223 GetKbdLayoutNameRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
3224 GetKbdLayoutNameRequest->Ansi = bAnsi;
3225
3226 /* Call the server */
3227 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
3228 NULL,
3229 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetKeyboardLayoutName),
3230 sizeof(*GetKbdLayoutNameRequest));
3231
3232 /* Check for success */
3233 if (!NT_SUCCESS(ApiMessage.Status))
3234 {
3235 BaseSetLastNTError(ApiMessage.Status);
3236 return FALSE;
3237 }
3238
3239 /* Retrieve the results */
3240 _SEH2_TRY
3241 {
3242 /* Copy only KL_NAMELENGTH == 9 characters, ANSI or UNICODE */
3243 if (bAnsi)
3244 strncpy(pszLayoutName, (PCHAR)GetKbdLayoutNameRequest->LayoutBuffer, KL_NAMELENGTH);
3245 else
3246 wcsncpy(pszLayoutName, (PWCHAR)GetKbdLayoutNameRequest->LayoutBuffer, KL_NAMELENGTH);
3247 }
3248 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3249 {
3250 SetLastError(ERROR_INVALID_ACCESS);
3251 _SEH2_YIELD(return FALSE);
3252 }
3253 _SEH2_END;
3254
3255 return TRUE;
3256}
3257
3258/*
3259 * @implemented (undocumented)
3260 */
3261BOOL
3262WINAPI
3263DECLSPEC_HOTPATCH
3264GetConsoleKeyboardLayoutNameA(OUT LPSTR pszLayoutName)
3265{
3266 return IntGetConsoleKeyboardLayoutName(pszLayoutName, TRUE);
3267}
3268
3269/*
3270 * @implemented (undocumented)
3271 */
3272BOOL
3273WINAPI
3274DECLSPEC_HOTPATCH
3275GetConsoleKeyboardLayoutNameW(OUT LPWSTR pszLayoutName)
3276{
3277 return IntGetConsoleKeyboardLayoutName(pszLayoutName, FALSE);
3278}
3279
3280/*
3281 * @implemented
3282 */
3283DWORD
3284WINAPI
3285SetLastConsoleEventActive(VOID)
3286{
3287 CONSOLE_API_MESSAGE ApiMessage;
3288 PCONSOLE_NOTIFYLASTCLOSE NotifyLastCloseRequest = &ApiMessage.Data.NotifyLastCloseRequest;
3289
3290 /* Set the flag used by the console control dispatcher */
3291 LastCloseNotify = TRUE;
3292
3293 /* Set up the input arguments */
3294 NotifyLastCloseRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
3295
3296 /* Call CSRSS; just return the NTSTATUS cast to DWORD */
3297 return CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
3298 NULL,
3299 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepNotifyLastClose),
3300 sizeof(*NotifyLastCloseRequest));
3301}
3302
3303/* EOF */