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