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