* Sync up to trunk head (r65394).
[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 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 #ifdef USE_CONSOLE_INIT_HANDLES
1170 NTSTATUS Status;
1171 #endif
1172
1173 CONSOLE_API_MESSAGE ApiMessage;
1174 PCONSOLE_ALLOCCONSOLE AllocConsoleRequest = &ApiMessage.Data.AllocConsoleRequest;
1175 PCSR_CAPTURE_BUFFER CaptureBuffer;
1176
1177 AllocConsoleRequest->CtrlRoutine = CtrlRoutine;
1178 AllocConsoleRequest->PropRoutine = PropRoutine;
1179
1180 CaptureBuffer = CsrAllocateCaptureBuffer(5, TitleLength +
1181 DesktopLength +
1182 CurDirLength +
1183 AppNameLength +
1184 sizeof(CONSOLE_START_INFO));
1185 if (CaptureBuffer == NULL)
1186 {
1187 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1188 Success = FALSE;
1189 goto Quit;
1190 }
1191
1192 CsrCaptureMessageBuffer(CaptureBuffer,
1193 ConsoleStartInfo,
1194 sizeof(CONSOLE_START_INFO),
1195 (PVOID*)&AllocConsoleRequest->ConsoleStartInfo);
1196
1197 AllocConsoleRequest->TitleLength = TitleLength;
1198 CsrCaptureMessageBuffer(CaptureBuffer,
1199 Title,
1200 TitleLength,
1201 (PVOID*)&AllocConsoleRequest->ConsoleTitle);
1202
1203 AllocConsoleRequest->DesktopLength = DesktopLength;
1204 CsrCaptureMessageBuffer(CaptureBuffer,
1205 Desktop,
1206 DesktopLength,
1207 (PVOID*)&AllocConsoleRequest->Desktop);
1208
1209 AllocConsoleRequest->CurDirLength = CurDirLength;
1210 CsrCaptureMessageBuffer(CaptureBuffer,
1211 CurDir,
1212 CurDirLength,
1213 (PVOID*)&AllocConsoleRequest->CurDir);
1214
1215 AllocConsoleRequest->AppNameLength = AppNameLength;
1216 CsrCaptureMessageBuffer(CaptureBuffer,
1217 AppName,
1218 AppNameLength,
1219 (PVOID*)&AllocConsoleRequest->AppName);
1220
1221 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1222 CaptureBuffer,
1223 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAlloc),
1224 sizeof(*AllocConsoleRequest));
1225 if (!NT_SUCCESS(ApiMessage.Status))
1226 {
1227 BaseSetLastNTError(ApiMessage.Status);
1228 Success = FALSE;
1229 goto Quit;
1230 }
1231
1232 #ifdef USE_CONSOLE_INIT_HANDLES
1233 // Is AllocConsoleRequest->ConsoleStartInfo->Events aligned on handle boundary ????
1234 Status = NtWaitForMultipleObjects(2, AllocConsoleRequest->ConsoleStartInfo->Events,
1235 WaitAny, FALSE, NULL);
1236 if (!NT_SUCCESS(Status))
1237 {
1238 BaseSetLastNTError(Status);
1239 Success = FALSE;
1240 goto Quit;
1241 }
1242
1243 NtClose(AllocConsoleRequest->ConsoleStartInfo->Events[0]);
1244 NtClose(AllocConsoleRequest->ConsoleStartInfo->Events[1]);
1245 if (Status != STATUS_SUCCESS)
1246 {
1247 NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
1248 Success = FALSE;
1249 }
1250 else
1251 #endif
1252 {
1253 RtlCopyMemory(ConsoleStartInfo,
1254 AllocConsoleRequest->ConsoleStartInfo,
1255 sizeof(CONSOLE_START_INFO));
1256 Success = TRUE;
1257 }
1258
1259 Quit:
1260 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
1261 return Success;
1262 }
1263
1264 BOOL
1265 WINAPI
1266 DECLSPEC_HOTPATCH
1267 AllocConsole(VOID)
1268 {
1269 BOOL Success;
1270 CONSOLE_START_INFO ConsoleStartInfo;
1271
1272 PWCHAR ConsoleTitle;
1273 PWCHAR Desktop;
1274 PWCHAR AppName;
1275 PWCHAR CurDir;
1276
1277 ULONG TitleLength = (MAX_PATH + 1) * sizeof(WCHAR);
1278 ULONG DesktopLength = (MAX_PATH + 1) * sizeof(WCHAR);
1279 ULONG AppNameLength = 128 * sizeof(WCHAR);
1280 ULONG CurDirLength = (MAX_PATH + 1) * sizeof(WCHAR);
1281
1282 LCID lcid;
1283
1284 RtlEnterCriticalSection(&ConsoleLock);
1285
1286 if (NtCurrentPeb()->ProcessParameters->ConsoleHandle)
1287 {
1288 DPRINT1("AllocConsole: Allocating a console to a process already having one\n");
1289 SetLastError(ERROR_ACCESS_DENIED);
1290 Success = FALSE;
1291 goto Quit;
1292 }
1293
1294 /* Set up the console properties */
1295 SetUpConsoleInfo(FALSE,
1296 &TitleLength,
1297 &ConsoleTitle,
1298 &DesktopLength,
1299 &Desktop,
1300 &ConsoleStartInfo);
1301 DPRINT("ConsoleTitle = '%S' - Desktop = '%S'\n",
1302 ConsoleTitle, Desktop);
1303
1304 /* Initialize the Input EXE name */
1305 InitExeName();
1306 SetUpAppName(FALSE,
1307 &CurDirLength,
1308 &CurDir,
1309 &AppNameLength,
1310 &AppName);
1311 DPRINT("CurDir = '%S' - AppName = '%S'\n",
1312 CurDir, AppName);
1313
1314 Success = IntAllocConsole(ConsoleTitle,
1315 TitleLength,
1316 Desktop,
1317 DesktopLength,
1318 CurDir,
1319 CurDirLength,
1320 AppName,
1321 AppNameLength,
1322 ConsoleControlDispatcher,
1323 PropDialogHandler,
1324 &ConsoleStartInfo);
1325 if (Success)
1326 {
1327 /* Set up the handles */
1328 SetUpHandles(&ConsoleStartInfo);
1329 InputWaitHandle = ConsoleStartInfo.InputWaitHandle;
1330
1331 /* Initialize Console Ctrl Handling */
1332 InitializeCtrlHandling();
1333
1334 /* Sets the current console locale for this thread */
1335 SetTEBLangID(lcid);
1336 }
1337
1338 Quit:
1339 RtlLeaveCriticalSection(&ConsoleLock);
1340 return Success;
1341 }
1342
1343
1344 /*
1345 * @implemented
1346 */
1347 BOOL
1348 WINAPI
1349 DECLSPEC_HOTPATCH
1350 FreeConsole(VOID)
1351 {
1352 CONSOLE_API_MESSAGE ApiMessage;
1353 PCONSOLE_FREECONSOLE FreeConsoleRequest = &ApiMessage.Data.FreeConsoleRequest;
1354 HANDLE ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1355
1356 /* We must have a non-trivial handle to close */
1357 if (ConsoleHandle == NULL) // IsConsoleHandle(ConsoleHandle)
1358 {
1359 SetLastError(ERROR_INVALID_PARAMETER);
1360 return FALSE;
1361 }
1362
1363 /* Set up the data to send to the Console Server */
1364 FreeConsoleRequest->ConsoleHandle = ConsoleHandle;
1365
1366 /* Call the server */
1367 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1368 NULL,
1369 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFree),
1370 sizeof(*FreeConsoleRequest));
1371
1372 /* Check for success */
1373 if (!NT_SUCCESS(ApiMessage.Status))
1374 {
1375 BaseSetLastNTError(ApiMessage.Status);
1376 return FALSE;
1377 }
1378
1379 /* Reset the console handle */
1380 NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
1381
1382 /* Close the associated input handle */
1383 CloseHandle(InputWaitHandle);
1384 InputWaitHandle = INVALID_HANDLE_VALUE;
1385
1386 return TRUE;
1387 }
1388
1389
1390 /*
1391 * @implemented
1392 */
1393 BOOL
1394 WINAPI
1395 GetConsoleScreenBufferInfo(HANDLE hConsoleOutput,
1396 PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)
1397 {
1398 CONSOLE_API_MESSAGE ApiMessage;
1399 PCONSOLE_GETSCREENBUFFERINFO ScreenBufferInfoRequest = &ApiMessage.Data.ScreenBufferInfoRequest;
1400
1401 if (lpConsoleScreenBufferInfo == NULL)
1402 {
1403 SetLastError(ERROR_INVALID_PARAMETER);
1404 return FALSE;
1405 }
1406
1407 ScreenBufferInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1408 ScreenBufferInfoRequest->OutputHandle = hConsoleOutput;
1409
1410 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1411 NULL,
1412 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetScreenBufferInfo),
1413 sizeof(*ScreenBufferInfoRequest));
1414 if (!NT_SUCCESS(ApiMessage.Status))
1415 {
1416 BaseSetLastNTError(ApiMessage.Status);
1417 return FALSE;
1418 }
1419
1420 lpConsoleScreenBufferInfo->dwSize = ScreenBufferInfoRequest->ScreenBufferSize;
1421 lpConsoleScreenBufferInfo->dwCursorPosition = ScreenBufferInfoRequest->CursorPosition;
1422 lpConsoleScreenBufferInfo->wAttributes = ScreenBufferInfoRequest->Attributes;
1423 lpConsoleScreenBufferInfo->srWindow.Left = ScreenBufferInfoRequest->ViewOrigin.X;
1424 lpConsoleScreenBufferInfo->srWindow.Top = ScreenBufferInfoRequest->ViewOrigin.Y;
1425 lpConsoleScreenBufferInfo->srWindow.Right = ScreenBufferInfoRequest->ViewOrigin.X + ScreenBufferInfoRequest->ViewSize.X - 1;
1426 lpConsoleScreenBufferInfo->srWindow.Bottom = ScreenBufferInfoRequest->ViewOrigin.Y + ScreenBufferInfoRequest->ViewSize.Y - 1;
1427 lpConsoleScreenBufferInfo->dwMaximumWindowSize = ScreenBufferInfoRequest->MaximumViewSize;
1428
1429 return TRUE;
1430 }
1431
1432
1433 /*
1434 * @implemented
1435 */
1436 BOOL
1437 WINAPI
1438 DECLSPEC_HOTPATCH
1439 SetConsoleCursorPosition(HANDLE hConsoleOutput,
1440 COORD dwCursorPosition)
1441 {
1442 CONSOLE_API_MESSAGE ApiMessage;
1443 PCONSOLE_SETCURSORPOSITION SetCursorPositionRequest = &ApiMessage.Data.SetCursorPositionRequest;
1444
1445 SetCursorPositionRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1446 SetCursorPositionRequest->OutputHandle = hConsoleOutput;
1447 SetCursorPositionRequest->Position = dwCursorPosition;
1448
1449 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1450 NULL,
1451 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCursorPosition),
1452 sizeof(*SetCursorPositionRequest));
1453 if (!NT_SUCCESS(ApiMessage.Status))
1454 {
1455 BaseSetLastNTError(ApiMessage.Status);
1456 return FALSE;
1457 }
1458
1459 return TRUE;
1460 }
1461
1462
1463 /*
1464 * @implemented
1465 */
1466 BOOL
1467 WINAPI
1468 GetConsoleMode(HANDLE hConsoleHandle,
1469 LPDWORD lpMode)
1470 {
1471 CONSOLE_API_MESSAGE ApiMessage;
1472 PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &ApiMessage.Data.ConsoleModeRequest;
1473
1474 if (lpMode == NULL)
1475 {
1476 SetLastError(ERROR_INVALID_PARAMETER);
1477 return FALSE;
1478 }
1479
1480 ConsoleModeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1481 ConsoleModeRequest->Handle = hConsoleHandle;
1482
1483 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1484 NULL,
1485 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetMode),
1486 sizeof(*ConsoleModeRequest));
1487 if (!NT_SUCCESS(ApiMessage.Status))
1488 {
1489 BaseSetLastNTError(ApiMessage.Status);
1490 return FALSE;
1491 }
1492
1493 *lpMode = ConsoleModeRequest->Mode;
1494
1495 return TRUE;
1496 }
1497
1498
1499 /*
1500 * @implemented
1501 */
1502 BOOL
1503 WINAPI
1504 DECLSPEC_HOTPATCH
1505 SetConsoleMode(HANDLE hConsoleHandle,
1506 DWORD dwMode)
1507 {
1508 CONSOLE_API_MESSAGE ApiMessage;
1509 PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &ApiMessage.Data.ConsoleModeRequest;
1510
1511 ConsoleModeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1512 ConsoleModeRequest->Handle = hConsoleHandle;
1513 ConsoleModeRequest->Mode = dwMode;
1514
1515 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1516 NULL,
1517 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetMode),
1518 sizeof(*ConsoleModeRequest));
1519 if (!NT_SUCCESS(ApiMessage.Status))
1520 {
1521 BaseSetLastNTError(ApiMessage.Status);
1522 return FALSE;
1523 }
1524
1525 return TRUE;
1526 }
1527
1528
1529 /*
1530 * @implemented
1531 */
1532 BOOL
1533 WINAPI
1534 GetNumberOfConsoleInputEvents(HANDLE hConsoleInput,
1535 LPDWORD lpNumberOfEvents)
1536 {
1537 CONSOLE_API_MESSAGE ApiMessage;
1538 PCONSOLE_GETNUMINPUTEVENTS GetNumInputEventsRequest = &ApiMessage.Data.GetNumInputEventsRequest;
1539
1540 GetNumInputEventsRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1541 GetNumInputEventsRequest->InputHandle = hConsoleInput;
1542 GetNumInputEventsRequest->NumberOfEvents = 0;
1543
1544 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1545 NULL,
1546 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetNumberOfInputEvents),
1547 sizeof(*GetNumInputEventsRequest));
1548 if (!NT_SUCCESS(ApiMessage.Status))
1549 {
1550 BaseSetLastNTError(ApiMessage.Status);
1551 return FALSE;
1552 }
1553
1554 if (lpNumberOfEvents == NULL)
1555 {
1556 SetLastError(ERROR_INVALID_ACCESS);
1557 return FALSE;
1558 }
1559
1560 *lpNumberOfEvents = GetNumInputEventsRequest->NumberOfEvents;
1561
1562 return TRUE;
1563 }
1564
1565
1566 /*
1567 * @implemented
1568 */
1569 COORD
1570 WINAPI
1571 DECLSPEC_HOTPATCH
1572 GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
1573 {
1574 CONSOLE_API_MESSAGE ApiMessage;
1575 PCONSOLE_GETLARGESTWINDOWSIZE GetLargestWindowSizeRequest = &ApiMessage.Data.GetLargestWindowSizeRequest;
1576
1577 GetLargestWindowSizeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1578 GetLargestWindowSizeRequest->OutputHandle = hConsoleOutput;
1579 GetLargestWindowSizeRequest->Size.X = 0;
1580 GetLargestWindowSizeRequest->Size.Y = 0;
1581
1582 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1583 NULL,
1584 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetLargestWindowSize),
1585 sizeof(*GetLargestWindowSizeRequest));
1586 if (!NT_SUCCESS(ApiMessage.Status))
1587 {
1588 BaseSetLastNTError(ApiMessage.Status);
1589 }
1590
1591 DPRINT("GetLargestConsoleWindowSize, X = %d, Y = %d\n", GetLargestWindowSizeRequest->Size.X, GetLargestWindowSizeRequest->Size.Y);
1592 return GetLargestWindowSizeRequest->Size;
1593 }
1594
1595
1596 /*
1597 * @implemented
1598 */
1599 BOOL
1600 WINAPI
1601 GetConsoleCursorInfo(HANDLE hConsoleOutput,
1602 PCONSOLE_CURSOR_INFO lpConsoleCursorInfo)
1603 {
1604 CONSOLE_API_MESSAGE ApiMessage;
1605 PCONSOLE_GETSETCURSORINFO CursorInfoRequest = &ApiMessage.Data.CursorInfoRequest;
1606
1607 if (!lpConsoleCursorInfo)
1608 {
1609 if (!hConsoleOutput)
1610 SetLastError(ERROR_INVALID_HANDLE);
1611 else
1612 SetLastError(ERROR_INVALID_ACCESS);
1613
1614 return FALSE;
1615 }
1616
1617 CursorInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1618 CursorInfoRequest->OutputHandle = hConsoleOutput;
1619
1620 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1621 NULL,
1622 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCursorInfo),
1623 sizeof(*CursorInfoRequest));
1624 if (!NT_SUCCESS(ApiMessage.Status))
1625 {
1626 BaseSetLastNTError(ApiMessage.Status);
1627 return FALSE;
1628 }
1629
1630 *lpConsoleCursorInfo = CursorInfoRequest->Info;
1631
1632 return TRUE;
1633 }
1634
1635
1636 /*
1637 * @implemented
1638 */
1639 BOOL
1640 WINAPI
1641 SetConsoleCursorInfo(HANDLE hConsoleOutput,
1642 CONST CONSOLE_CURSOR_INFO *lpConsoleCursorInfo)
1643 {
1644 CONSOLE_API_MESSAGE ApiMessage;
1645 PCONSOLE_GETSETCURSORINFO CursorInfoRequest = &ApiMessage.Data.CursorInfoRequest;
1646
1647 CursorInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1648 CursorInfoRequest->OutputHandle = hConsoleOutput;
1649 CursorInfoRequest->Info = *lpConsoleCursorInfo;
1650
1651 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1652 NULL,
1653 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCursorInfo),
1654 sizeof(*CursorInfoRequest));
1655 if (!NT_SUCCESS(ApiMessage.Status))
1656 {
1657 BaseSetLastNTError(ApiMessage.Status);
1658 return FALSE;
1659 }
1660
1661 return TRUE;
1662 }
1663
1664
1665 /*
1666 * @implemented
1667 */
1668 BOOL
1669 WINAPI
1670 GetNumberOfConsoleMouseButtons(LPDWORD lpNumberOfMouseButtons)
1671 {
1672 CONSOLE_API_MESSAGE ApiMessage;
1673 PCONSOLE_GETMOUSEINFO GetMouseInfoRequest = &ApiMessage.Data.GetMouseInfoRequest;
1674
1675 GetMouseInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1676
1677 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1678 NULL,
1679 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetMouseInfo),
1680 sizeof(*GetMouseInfoRequest));
1681 if (!NT_SUCCESS(ApiMessage.Status))
1682 {
1683 BaseSetLastNTError(ApiMessage.Status);
1684 return FALSE;
1685 }
1686
1687 *lpNumberOfMouseButtons = GetMouseInfoRequest->NumButtons;
1688 return TRUE;
1689 }
1690
1691
1692 /*
1693 * @implemented
1694 */
1695 BOOL
1696 WINAPI
1697 DECLSPEC_HOTPATCH
1698 SetConsoleActiveScreenBuffer(HANDLE hConsoleOutput)
1699 {
1700 CONSOLE_API_MESSAGE ApiMessage;
1701 PCONSOLE_SETACTIVESCREENBUFFER SetScreenBufferRequest = &ApiMessage.Data.SetScreenBufferRequest;
1702
1703 SetScreenBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1704 SetScreenBufferRequest->OutputHandle = hConsoleOutput;
1705
1706 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1707 NULL,
1708 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetActiveScreenBuffer),
1709 sizeof(*SetScreenBufferRequest));
1710 if (!NT_SUCCESS(ApiMessage.Status))
1711 {
1712 BaseSetLastNTError(ApiMessage.Status);
1713 return FALSE;
1714 }
1715
1716 return TRUE;
1717 }
1718
1719
1720 /*
1721 * @implemented
1722 */
1723 BOOL
1724 WINAPI
1725 DECLSPEC_HOTPATCH
1726 FlushConsoleInputBuffer(HANDLE hConsoleInput)
1727 {
1728 CONSOLE_API_MESSAGE ApiMessage;
1729 PCONSOLE_FLUSHINPUTBUFFER FlushInputBufferRequest = &ApiMessage.Data.FlushInputBufferRequest;
1730
1731 FlushInputBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1732 FlushInputBufferRequest->InputHandle = hConsoleInput;
1733
1734 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1735 NULL,
1736 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFlushInputBuffer),
1737 sizeof(*FlushInputBufferRequest));
1738 if (!NT_SUCCESS(ApiMessage.Status))
1739 {
1740 BaseSetLastNTError(ApiMessage.Status);
1741 return FALSE;
1742 }
1743
1744 return TRUE;
1745 }
1746
1747
1748 /*
1749 * @implemented
1750 */
1751 BOOL
1752 WINAPI
1753 DECLSPEC_HOTPATCH
1754 SetConsoleScreenBufferSize(HANDLE hConsoleOutput,
1755 COORD dwSize)
1756 {
1757 CONSOLE_API_MESSAGE ApiMessage;
1758 PCONSOLE_SETSCREENBUFFERSIZE SetScreenBufferSizeRequest = &ApiMessage.Data.SetScreenBufferSizeRequest;
1759
1760 SetScreenBufferSizeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1761 SetScreenBufferSizeRequest->OutputHandle = hConsoleOutput;
1762 SetScreenBufferSizeRequest->Size = dwSize;
1763
1764 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1765 NULL,
1766 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetScreenBufferSize),
1767 sizeof(*SetScreenBufferSizeRequest));
1768 if (!NT_SUCCESS(ApiMessage.Status))
1769 {
1770 BaseSetLastNTError(ApiMessage.Status);
1771 return FALSE;
1772 }
1773
1774 return TRUE;
1775 }
1776
1777
1778 static
1779 BOOL
1780 IntScrollConsoleScreenBuffer(HANDLE hConsoleOutput,
1781 CONST SMALL_RECT* lpScrollRectangle,
1782 CONST SMALL_RECT* lpClipRectangle,
1783 COORD dwDestinationOrigin,
1784 CONST CHAR_INFO* lpFill,
1785 BOOL bUnicode)
1786 {
1787 CONSOLE_API_MESSAGE ApiMessage;
1788 PCONSOLE_SCROLLSCREENBUFFER ScrollScreenBufferRequest = &ApiMessage.Data.ScrollScreenBufferRequest;
1789
1790 ScrollScreenBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1791 ScrollScreenBufferRequest->OutputHandle = hConsoleOutput;
1792 ScrollScreenBufferRequest->ScrollRectangle = *lpScrollRectangle;
1793
1794 if (lpClipRectangle != NULL)
1795 {
1796 ScrollScreenBufferRequest->UseClipRectangle = TRUE;
1797 ScrollScreenBufferRequest->ClipRectangle = *lpClipRectangle;
1798 }
1799 else
1800 {
1801 ScrollScreenBufferRequest->UseClipRectangle = FALSE;
1802 }
1803
1804 ScrollScreenBufferRequest->DestinationOrigin = dwDestinationOrigin;
1805 ScrollScreenBufferRequest->Fill = *lpFill;
1806 ScrollScreenBufferRequest->Unicode = bUnicode;
1807
1808 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1809 NULL,
1810 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepScrollScreenBuffer),
1811 sizeof(*ScrollScreenBufferRequest));
1812 if (!NT_SUCCESS(ApiMessage.Status))
1813 {
1814 BaseSetLastNTError(ApiMessage.Status);
1815 return FALSE;
1816 }
1817
1818 return TRUE;
1819 }
1820
1821
1822 /*
1823 * @implemented
1824 */
1825 BOOL
1826 WINAPI
1827 DECLSPEC_HOTPATCH
1828 ScrollConsoleScreenBufferA(HANDLE hConsoleOutput,
1829 CONST SMALL_RECT* lpScrollRectangle,
1830 CONST SMALL_RECT* lpClipRectangle,
1831 COORD dwDestinationOrigin,
1832 CONST CHAR_INFO* lpFill)
1833 {
1834 return IntScrollConsoleScreenBuffer(hConsoleOutput,
1835 lpScrollRectangle,
1836 lpClipRectangle,
1837 dwDestinationOrigin,
1838 lpFill,
1839 FALSE);
1840 }
1841
1842
1843 /*
1844 * @implemented
1845 */
1846 BOOL
1847 WINAPI
1848 DECLSPEC_HOTPATCH
1849 ScrollConsoleScreenBufferW(HANDLE hConsoleOutput,
1850 CONST SMALL_RECT *lpScrollRectangle,
1851 CONST SMALL_RECT *lpClipRectangle,
1852 COORD dwDestinationOrigin,
1853 CONST CHAR_INFO *lpFill)
1854 {
1855 return IntScrollConsoleScreenBuffer(hConsoleOutput,
1856 lpScrollRectangle,
1857 lpClipRectangle,
1858 dwDestinationOrigin,
1859 lpFill,
1860 TRUE);
1861 }
1862
1863
1864 /*
1865 * @implemented
1866 */
1867 BOOL
1868 WINAPI
1869 SetConsoleWindowInfo(HANDLE hConsoleOutput,
1870 BOOL bAbsolute,
1871 CONST SMALL_RECT *lpConsoleWindow)
1872 {
1873 CONSOLE_API_MESSAGE ApiMessage;
1874 PCONSOLE_SETWINDOWINFO SetWindowInfoRequest = &ApiMessage.Data.SetWindowInfoRequest;
1875
1876 if (lpConsoleWindow == NULL)
1877 {
1878 SetLastError(ERROR_INVALID_PARAMETER);
1879 return FALSE;
1880 }
1881
1882 SetWindowInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1883 SetWindowInfoRequest->OutputHandle = hConsoleOutput;
1884 SetWindowInfoRequest->Absolute = bAbsolute;
1885 SetWindowInfoRequest->WindowRect = *lpConsoleWindow;
1886
1887 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1888 NULL,
1889 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetWindowInfo),
1890 sizeof(*SetWindowInfoRequest));
1891 if (!NT_SUCCESS(ApiMessage.Status))
1892 {
1893 BaseSetLastNTError(ApiMessage.Status);
1894 return FALSE;
1895 }
1896
1897 return TRUE;
1898 }
1899
1900
1901 /*
1902 * @implemented
1903 */
1904 BOOL
1905 WINAPI
1906 DECLSPEC_HOTPATCH
1907 SetConsoleTextAttribute(HANDLE hConsoleOutput,
1908 WORD wAttributes)
1909 {
1910 CONSOLE_API_MESSAGE ApiMessage;
1911 PCONSOLE_SETTEXTATTRIB SetTextAttribRequest = &ApiMessage.Data.SetTextAttribRequest;
1912
1913 SetTextAttribRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1914 SetTextAttribRequest->OutputHandle = hConsoleOutput;
1915 SetTextAttribRequest->Attributes = wAttributes;
1916
1917 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1918 NULL,
1919 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetTextAttribute),
1920 sizeof(*SetTextAttribRequest));
1921 if (!NT_SUCCESS(ApiMessage.Status))
1922 {
1923 BaseSetLastNTError(ApiMessage.Status);
1924 return FALSE;
1925 }
1926
1927 return TRUE;
1928 }
1929
1930
1931 static
1932 BOOL
1933 AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
1934 {
1935 PHANDLER_ROUTINE* NewCtrlHandlers = NULL;
1936
1937 if (HandlerRoutine == NULL)
1938 {
1939 NtCurrentPeb()->ProcessParameters->ConsoleFlags = TRUE;
1940 return TRUE;
1941 }
1942
1943 if (NrCtrlHandlers == NrAllocatedHandlers)
1944 {
1945 NewCtrlHandlers = RtlAllocateHeap(RtlGetProcessHeap(),
1946 0,
1947 (NrCtrlHandlers + 4) * sizeof(PHANDLER_ROUTINE));
1948 if (NewCtrlHandlers == NULL)
1949 {
1950 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1951 return FALSE;
1952 }
1953
1954 memmove(NewCtrlHandlers, CtrlHandlers, sizeof(PHANDLER_ROUTINE) * NrCtrlHandlers);
1955
1956 if (NrAllocatedHandlers > 1) RtlFreeHeap(RtlGetProcessHeap(), 0, CtrlHandlers);
1957
1958 CtrlHandlers = NewCtrlHandlers;
1959 NrAllocatedHandlers += 4;
1960 }
1961
1962 ASSERT(NrCtrlHandlers < NrAllocatedHandlers);
1963
1964 CtrlHandlers[NrCtrlHandlers++] = HandlerRoutine;
1965 return TRUE;
1966 }
1967
1968
1969 static
1970 BOOL
1971 RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
1972 {
1973 ULONG i;
1974
1975 if (HandlerRoutine == NULL)
1976 {
1977 NtCurrentPeb()->ProcessParameters->ConsoleFlags = FALSE;
1978 return TRUE;
1979 }
1980
1981 for (i = 0; i < NrCtrlHandlers; i++)
1982 {
1983 if (CtrlHandlers[i] == HandlerRoutine)
1984 {
1985 if (i < (NrCtrlHandlers - 1))
1986 {
1987 memmove(&CtrlHandlers[i],
1988 &CtrlHandlers[i+1],
1989 (NrCtrlHandlers - i + 1) * sizeof(PHANDLER_ROUTINE));
1990 }
1991
1992 NrCtrlHandlers--;
1993 return TRUE;
1994 }
1995 }
1996
1997 SetLastError(ERROR_INVALID_PARAMETER);
1998 return FALSE;
1999 }
2000
2001
2002 /*
2003 * @implemented
2004 */
2005 BOOL
2006 WINAPI
2007 DECLSPEC_HOTPATCH
2008 SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine,
2009 BOOL Add)
2010 {
2011 BOOL Ret;
2012
2013 RtlEnterCriticalSection(&BaseDllDirectoryLock);
2014 if (Add)
2015 {
2016 Ret = AddConsoleCtrlHandler(HandlerRoutine);
2017 }
2018 else
2019 {
2020 Ret = RemoveConsoleCtrlHandler(HandlerRoutine);
2021 }
2022
2023 RtlLeaveCriticalSection(&BaseDllDirectoryLock);
2024 return(Ret);
2025 }
2026
2027
2028 /*
2029 * @implemented
2030 */
2031 BOOL
2032 WINAPI
2033 DECLSPEC_HOTPATCH
2034 GenerateConsoleCtrlEvent(DWORD dwCtrlEvent,
2035 DWORD dwProcessGroupId)
2036 {
2037 CONSOLE_API_MESSAGE ApiMessage;
2038 PCONSOLE_GENERATECTRLEVENT GenerateCtrlEventRequest = &ApiMessage.Data.GenerateCtrlEventRequest;
2039
2040 if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT)
2041 {
2042 SetLastError(ERROR_INVALID_PARAMETER);
2043 return FALSE;
2044 }
2045
2046 GenerateCtrlEventRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2047 GenerateCtrlEventRequest->CtrlEvent = dwCtrlEvent;
2048 GenerateCtrlEventRequest->ProcessGroupId = dwProcessGroupId;
2049
2050 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2051 NULL,
2052 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGenerateCtrlEvent),
2053 sizeof(*GenerateCtrlEventRequest));
2054 if (!NT_SUCCESS(ApiMessage.Status))
2055 {
2056 BaseSetLastNTError(ApiMessage.Status);
2057 return FALSE;
2058 }
2059
2060 return TRUE;
2061 }
2062
2063
2064 static DWORD
2065 IntGetConsoleTitle(LPVOID lpConsoleTitle, DWORD dwNumChars, BOOLEAN bUnicode)
2066 {
2067 CONSOLE_API_MESSAGE ApiMessage;
2068 PCONSOLE_GETSETCONSOLETITLE TitleRequest = &ApiMessage.Data.TitleRequest;
2069 PCSR_CAPTURE_BUFFER CaptureBuffer;
2070
2071 if (dwNumChars == 0) return 0;
2072
2073 TitleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2074 TitleRequest->Length = dwNumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
2075 TitleRequest->Unicode = bUnicode;
2076
2077 CaptureBuffer = CsrAllocateCaptureBuffer(1, TitleRequest->Length);
2078 if (CaptureBuffer == NULL)
2079 {
2080 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
2081 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2082 return 0;
2083 }
2084
2085 CsrAllocateMessagePointer(CaptureBuffer,
2086 TitleRequest->Length,
2087 (PVOID*)&TitleRequest->Title);
2088
2089 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2090 CaptureBuffer,
2091 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetTitle),
2092 sizeof(*TitleRequest));
2093 if (!NT_SUCCESS(ApiMessage.Status))
2094 {
2095 CsrFreeCaptureBuffer(CaptureBuffer);
2096 BaseSetLastNTError(ApiMessage.Status);
2097 return 0;
2098 }
2099
2100 dwNumChars = TitleRequest->Length / (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
2101
2102 if (dwNumChars > 0)
2103 {
2104 memcpy(lpConsoleTitle, TitleRequest->Title, TitleRequest->Length);
2105
2106 if (bUnicode)
2107 ((LPWSTR)lpConsoleTitle)[dwNumChars] = UNICODE_NULL;
2108 else
2109 ((LPSTR)lpConsoleTitle)[dwNumChars] = ANSI_NULL;
2110 }
2111
2112 CsrFreeCaptureBuffer(CaptureBuffer);
2113
2114 return dwNumChars;
2115 }
2116
2117
2118 /*
2119 * @implemented
2120 */
2121 DWORD
2122 WINAPI
2123 DECLSPEC_HOTPATCH
2124 GetConsoleTitleW(LPWSTR lpConsoleTitle,
2125 DWORD nSize)
2126 {
2127 return IntGetConsoleTitle(lpConsoleTitle, nSize, TRUE);
2128 }
2129
2130
2131 /*
2132 * @implemented
2133 */
2134 DWORD
2135 WINAPI
2136 DECLSPEC_HOTPATCH
2137 GetConsoleTitleA(LPSTR lpConsoleTitle,
2138 DWORD nSize)
2139 {
2140 return IntGetConsoleTitle(lpConsoleTitle, nSize, FALSE);
2141 }
2142
2143
2144 static BOOL
2145 IntSetConsoleTitle(CONST VOID *lpConsoleTitle, BOOLEAN bUnicode)
2146 {
2147 CONSOLE_API_MESSAGE ApiMessage;
2148 PCONSOLE_GETSETCONSOLETITLE TitleRequest = &ApiMessage.Data.TitleRequest;
2149 PCSR_CAPTURE_BUFFER CaptureBuffer;
2150
2151 ULONG NumChars = (ULONG)(lpConsoleTitle ? (bUnicode ? wcslen(lpConsoleTitle) : strlen(lpConsoleTitle)) : 0);
2152
2153 TitleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2154 TitleRequest->Length = NumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
2155 TitleRequest->Unicode = bUnicode;
2156
2157 CaptureBuffer = CsrAllocateCaptureBuffer(1, TitleRequest->Length);
2158 if (CaptureBuffer == NULL)
2159 {
2160 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
2161 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2162 return FALSE;
2163 }
2164
2165 CsrCaptureMessageBuffer(CaptureBuffer,
2166 (PVOID)lpConsoleTitle,
2167 TitleRequest->Length,
2168 (PVOID*)&TitleRequest->Title);
2169
2170 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2171 CaptureBuffer,
2172 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetTitle),
2173 sizeof(*TitleRequest));
2174
2175 CsrFreeCaptureBuffer(CaptureBuffer);
2176
2177 if (!NT_SUCCESS(ApiMessage.Status))
2178 {
2179 BaseSetLastNTError(ApiMessage.Status);
2180 return FALSE;
2181 }
2182
2183 return TRUE;
2184 }
2185
2186 /*
2187 * @implemented
2188 */
2189 BOOL
2190 WINAPI
2191 DECLSPEC_HOTPATCH
2192 SetConsoleTitleW(LPCWSTR lpConsoleTitle)
2193 {
2194 return IntSetConsoleTitle(lpConsoleTitle, TRUE);
2195 }
2196
2197
2198 /*
2199 * @implemented
2200 */
2201 BOOL
2202 WINAPI
2203 DECLSPEC_HOTPATCH
2204 SetConsoleTitleA(LPCSTR lpConsoleTitle)
2205 {
2206 return IntSetConsoleTitle(lpConsoleTitle, FALSE);
2207 }
2208
2209
2210 /*
2211 * @implemented
2212 */
2213 HANDLE
2214 WINAPI
2215 CreateConsoleScreenBuffer(DWORD dwDesiredAccess,
2216 DWORD dwShareMode,
2217 CONST SECURITY_ATTRIBUTES *lpSecurityAttributes,
2218 DWORD dwFlags,
2219 LPVOID lpScreenBufferData)
2220 {
2221 CONSOLE_API_MESSAGE ApiMessage;
2222 PCONSOLE_CREATESCREENBUFFER CreateScreenBufferRequest = &ApiMessage.Data.CreateScreenBufferRequest;
2223 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
2224 PCONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo = lpScreenBufferData;
2225
2226 if ( (dwDesiredAccess & ~(GENERIC_READ | GENERIC_WRITE)) ||
2227 (dwShareMode & ~(FILE_SHARE_READ | FILE_SHARE_WRITE)) ||
2228 (dwFlags != CONSOLE_TEXTMODE_BUFFER && dwFlags != CONSOLE_GRAPHICS_BUFFER) )
2229 {
2230 SetLastError(ERROR_INVALID_PARAMETER);
2231 return INVALID_HANDLE_VALUE;
2232 }
2233
2234 CreateScreenBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2235 CreateScreenBufferRequest->DesiredAccess = dwDesiredAccess;
2236 CreateScreenBufferRequest->InheritHandle =
2237 (lpSecurityAttributes ? lpSecurityAttributes->bInheritHandle : FALSE);
2238 CreateScreenBufferRequest->ShareMode = dwShareMode;
2239 CreateScreenBufferRequest->ScreenBufferType = dwFlags;
2240
2241 if (dwFlags == CONSOLE_GRAPHICS_BUFFER)
2242 {
2243 if (CreateScreenBufferRequest->InheritHandle || GraphicsBufferInfo == NULL)
2244 {
2245 SetLastError(ERROR_INVALID_PARAMETER);
2246 return INVALID_HANDLE_VALUE;
2247 }
2248
2249 CreateScreenBufferRequest->GraphicsBufferInfo = *GraphicsBufferInfo;
2250
2251 CaptureBuffer = CsrAllocateCaptureBuffer(1, GraphicsBufferInfo->dwBitMapInfoLength);
2252 if (CaptureBuffer == NULL)
2253 {
2254 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2255 return INVALID_HANDLE_VALUE;
2256 }
2257
2258 CsrCaptureMessageBuffer(CaptureBuffer,
2259 (PVOID)GraphicsBufferInfo->lpBitMapInfo,
2260 GraphicsBufferInfo->dwBitMapInfoLength,
2261 (PVOID*)&CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMapInfo);
2262 }
2263
2264 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2265 CaptureBuffer,
2266 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepCreateScreenBuffer),
2267 sizeof(*CreateScreenBufferRequest));
2268
2269 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
2270
2271 if (!NT_SUCCESS(ApiMessage.Status))
2272 {
2273 BaseSetLastNTError(ApiMessage.Status);
2274 return INVALID_HANDLE_VALUE;
2275 }
2276
2277 if (dwFlags == CONSOLE_GRAPHICS_BUFFER && GraphicsBufferInfo)
2278 {
2279 GraphicsBufferInfo->hMutex = CreateScreenBufferRequest->hMutex ; // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex ;
2280 GraphicsBufferInfo->lpBitMap = CreateScreenBufferRequest->lpBitMap; // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap;
2281 }
2282
2283 return CreateScreenBufferRequest->OutputHandle;
2284 }
2285
2286
2287 /*
2288 * @implemented
2289 */
2290 UINT
2291 WINAPI
2292 DECLSPEC_HOTPATCH
2293 GetConsoleCP(VOID)
2294 {
2295 CONSOLE_API_MESSAGE ApiMessage;
2296 PCONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest = &ApiMessage.Data.GetConsoleCPRequest;
2297
2298 /* Get the Input Code Page */
2299 GetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2300 GetConsoleCPRequest->OutputCP = FALSE;
2301
2302 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2303 NULL,
2304 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCP),
2305 sizeof(*GetConsoleCPRequest));
2306 if (!NT_SUCCESS(ApiMessage.Status))
2307 {
2308 BaseSetLastNTError(ApiMessage.Status);
2309 return 0;
2310 }
2311
2312 return GetConsoleCPRequest->CodePage;
2313 }
2314
2315
2316 /*
2317 * @implemented
2318 */
2319 BOOL
2320 WINAPI
2321 DECLSPEC_HOTPATCH
2322 SetConsoleCP(UINT wCodePageID)
2323 {
2324 CONSOLE_API_MESSAGE ApiMessage;
2325 PCONSOLE_SETINPUTOUTPUTCP SetConsoleCPRequest = &ApiMessage.Data.SetConsoleCPRequest;
2326
2327 /* Set the Input Code Page */
2328 SetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2329 SetConsoleCPRequest->CodePage = wCodePageID;
2330 SetConsoleCPRequest->OutputCP = FALSE;
2331 /* SetConsoleCPRequest->EventHandle; */
2332
2333 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2334 NULL,
2335 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCP),
2336 sizeof(*SetConsoleCPRequest));
2337 if (!NT_SUCCESS(ApiMessage.Status))
2338 {
2339 BaseSetLastNTError(ApiMessage.Status);
2340 return FALSE;
2341 }
2342
2343 return TRUE;
2344 }
2345
2346
2347 /*
2348 * @implemented
2349 */
2350 UINT
2351 WINAPI
2352 DECLSPEC_HOTPATCH
2353 GetConsoleOutputCP(VOID)
2354 {
2355 CONSOLE_API_MESSAGE ApiMessage;
2356 PCONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest = &ApiMessage.Data.GetConsoleCPRequest;
2357
2358 /* Get the Output Code Page */
2359 GetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2360 GetConsoleCPRequest->OutputCP = TRUE;
2361
2362 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2363 NULL,
2364 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCP),
2365 sizeof(*GetConsoleCPRequest));
2366 if (!NT_SUCCESS(ApiMessage.Status))
2367 {
2368 BaseSetLastNTError(ApiMessage.Status);
2369 return 0;
2370 }
2371
2372 return GetConsoleCPRequest->CodePage;
2373 }
2374
2375
2376 /*
2377 * @implemented
2378 */
2379 BOOL
2380 WINAPI
2381 DECLSPEC_HOTPATCH
2382 SetConsoleOutputCP(UINT wCodePageID)
2383 {
2384 CONSOLE_API_MESSAGE ApiMessage;
2385 PCONSOLE_SETINPUTOUTPUTCP SetConsoleCPRequest = &ApiMessage.Data.SetConsoleCPRequest;
2386
2387 /* Set the Output Code Page */
2388 SetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2389 SetConsoleCPRequest->CodePage = wCodePageID;
2390 SetConsoleCPRequest->OutputCP = TRUE;
2391 /* SetConsoleCPRequest->EventHandle; */
2392
2393 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2394 NULL,
2395 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCP),
2396 sizeof(*SetConsoleCPRequest));
2397 if (!NT_SUCCESS(ApiMessage.Status))
2398 {
2399 BaseSetLastNTError(ApiMessage.Status);
2400 return FALSE;
2401 }
2402
2403 return TRUE;
2404 }
2405
2406
2407 /*
2408 * @implemented
2409 */
2410 DWORD
2411 WINAPI
2412 GetConsoleProcessList(LPDWORD lpdwProcessList,
2413 DWORD dwProcessCount)
2414 {
2415 CONSOLE_API_MESSAGE ApiMessage;
2416 PCONSOLE_GETPROCESSLIST GetProcessListRequest = &ApiMessage.Data.GetProcessListRequest;
2417 PCSR_CAPTURE_BUFFER CaptureBuffer;
2418 ULONG nProcesses = 0;
2419
2420 if (lpdwProcessList == NULL || dwProcessCount == 0)
2421 {
2422 SetLastError(ERROR_INVALID_PARAMETER);
2423 return 0;
2424 }
2425
2426 CaptureBuffer = CsrAllocateCaptureBuffer(1, dwProcessCount * sizeof(DWORD));
2427 if (CaptureBuffer == NULL)
2428 {
2429 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
2430 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2431 return 0;
2432 }
2433
2434 GetProcessListRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2435 GetProcessListRequest->ProcessCount = dwProcessCount;
2436
2437 CsrAllocateMessagePointer(CaptureBuffer,
2438 dwProcessCount * sizeof(DWORD),
2439 (PVOID*)&GetProcessListRequest->ProcessIdsList);
2440
2441 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2442 CaptureBuffer,
2443 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetProcessList),
2444 sizeof(*GetProcessListRequest));
2445 if (!NT_SUCCESS(ApiMessage.Status))
2446 {
2447 BaseSetLastNTError(ApiMessage.Status);
2448 }
2449 else
2450 {
2451 nProcesses = GetProcessListRequest->ProcessCount;
2452 if (dwProcessCount >= nProcesses)
2453 {
2454 memcpy(lpdwProcessList, GetProcessListRequest->ProcessIdsList, nProcesses * sizeof(DWORD));
2455 }
2456 }
2457
2458 CsrFreeCaptureBuffer(CaptureBuffer);
2459 return nProcesses;
2460 }
2461
2462
2463 /*
2464 * @implemented
2465 */
2466 BOOL
2467 WINAPI
2468 GetConsoleSelectionInfo(PCONSOLE_SELECTION_INFO lpConsoleSelectionInfo)
2469 {
2470 CONSOLE_API_MESSAGE ApiMessage;
2471 PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest = &ApiMessage.Data.GetSelectionInfoRequest;
2472
2473 if (lpConsoleSelectionInfo == NULL)
2474 {
2475 SetLastError(ERROR_INVALID_PARAMETER);
2476 return FALSE;
2477 }
2478
2479 GetSelectionInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2480
2481 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2482 NULL,
2483 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetSelectionInfo),
2484 sizeof(*GetSelectionInfoRequest));
2485 if (!NT_SUCCESS(ApiMessage.Status))
2486 {
2487 BaseSetLastNTError(ApiMessage.Status);
2488 return FALSE;
2489 }
2490
2491 *lpConsoleSelectionInfo = GetSelectionInfoRequest->Info;
2492
2493 return TRUE;
2494 }
2495
2496
2497 /*
2498 * @implemented
2499 * @note Strongly inspired by AllocConsole.
2500 */
2501 static BOOL
2502 IntAttachConsole(DWORD ProcessId,
2503 LPTHREAD_START_ROUTINE CtrlRoutine,
2504 LPTHREAD_START_ROUTINE PropRoutine,
2505 PCONSOLE_START_INFO ConsoleStartInfo)
2506 {
2507 BOOL Success = TRUE;
2508 #ifdef USE_CONSOLE_INIT_HANDLES
2509 NTSTATUS Status;
2510 #endif
2511
2512 CONSOLE_API_MESSAGE ApiMessage;
2513 PCONSOLE_ATTACHCONSOLE AttachConsoleRequest = &ApiMessage.Data.AttachConsoleRequest;
2514 PCSR_CAPTURE_BUFFER CaptureBuffer;
2515
2516 AttachConsoleRequest->ProcessId = ProcessId;
2517 AttachConsoleRequest->CtrlRoutine = CtrlRoutine;
2518 AttachConsoleRequest->PropRoutine = PropRoutine;
2519
2520 CaptureBuffer = CsrAllocateCaptureBuffer(1, sizeof(CONSOLE_START_INFO));
2521 if (CaptureBuffer == NULL)
2522 {
2523 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2524 Success = FALSE;
2525 goto Quit;
2526 }
2527
2528 CsrCaptureMessageBuffer(CaptureBuffer,
2529 ConsoleStartInfo,
2530 sizeof(CONSOLE_START_INFO),
2531 (PVOID*)&AttachConsoleRequest->ConsoleStartInfo);
2532
2533 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2534 CaptureBuffer,
2535 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAttach),
2536 sizeof(*AttachConsoleRequest));
2537 if (!NT_SUCCESS(ApiMessage.Status))
2538 {
2539 BaseSetLastNTError(ApiMessage.Status);
2540 Success = FALSE;
2541 goto Quit;
2542 }
2543
2544 #ifdef USE_CONSOLE_INIT_HANDLES
2545 // Is AttachConsoleRequest->ConsoleStartInfo->Events aligned on handle boundary ????
2546 Status = NtWaitForMultipleObjects(2, AttachConsoleRequest->ConsoleStartInfo->Events,
2547 WaitAny, FALSE, NULL);
2548 if (!NT_SUCCESS(Status))
2549 {
2550 BaseSetLastNTError(Status);
2551 Success = FALSE;
2552 goto Quit;
2553 }
2554
2555 NtClose(AttachConsoleRequest->ConsoleStartInfo->Events[0]);
2556 NtClose(AttachConsoleRequest->ConsoleStartInfo->Events[1]);
2557 if (Status != STATUS_SUCCESS)
2558 {
2559 NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
2560 Success = FALSE;
2561 }
2562 else
2563 #endif
2564 {
2565 RtlCopyMemory(ConsoleStartInfo,
2566 AttachConsoleRequest->ConsoleStartInfo,
2567 sizeof(CONSOLE_START_INFO));
2568 Success = TRUE;
2569 }
2570
2571 Quit:
2572 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
2573 return Success;
2574 }
2575
2576 BOOL
2577 WINAPI
2578 AttachConsole(DWORD dwProcessId)
2579 {
2580 BOOL Success;
2581 CONSOLE_START_INFO ConsoleStartInfo;
2582
2583 DWORD dummy;
2584 LCID lcid;
2585
2586 RtlEnterCriticalSection(&ConsoleLock);
2587
2588 if (NtCurrentPeb()->ProcessParameters->ConsoleHandle)
2589 {
2590 DPRINT1("AttachConsole: Attaching a console to a process already having one\n");
2591 SetLastError(ERROR_ACCESS_DENIED);
2592 Success = FALSE;
2593 goto Quit;
2594 }
2595
2596 /* Set up the console properties */
2597 SetUpConsoleInfo(FALSE,
2598 &dummy,
2599 NULL,
2600 &dummy,
2601 NULL,
2602 &ConsoleStartInfo);
2603
2604 Success = IntAttachConsole(dwProcessId,
2605 ConsoleControlDispatcher,
2606 PropDialogHandler,
2607 &ConsoleStartInfo);
2608 if (Success)
2609 {
2610 /* Set up the handles */
2611 SetUpHandles(&ConsoleStartInfo);
2612 InputWaitHandle = ConsoleStartInfo.InputWaitHandle;
2613
2614 /* Initialize Console Ctrl Handling */
2615 InitializeCtrlHandling();
2616
2617 /* Sets the current console locale for this thread */
2618 SetTEBLangID(lcid);
2619 }
2620
2621 Quit:
2622 RtlLeaveCriticalSection(&ConsoleLock);
2623 return Success;
2624 }
2625
2626
2627 /*
2628 * @implemented
2629 */
2630 HWND
2631 WINAPI
2632 DECLSPEC_HOTPATCH
2633 GetConsoleWindow(VOID)
2634 {
2635 CONSOLE_API_MESSAGE ApiMessage;
2636 PCONSOLE_GETWINDOW GetWindowRequest = &ApiMessage.Data.GetWindowRequest;
2637
2638 GetWindowRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2639
2640 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2641 NULL,
2642 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetConsoleWindow),
2643 sizeof(*GetWindowRequest));
2644 if (!NT_SUCCESS(ApiMessage.Status))
2645 {
2646 BaseSetLastNTError(ApiMessage.Status);
2647 return (HWND)NULL;
2648 }
2649
2650 return GetWindowRequest->WindowHandle;
2651 }
2652
2653
2654 /*
2655 * @implemented
2656 */
2657 BOOL
2658 WINAPI
2659 DECLSPEC_HOTPATCH
2660 SetConsoleIcon(HICON hIcon)
2661 {
2662 CONSOLE_API_MESSAGE ApiMessage;
2663 PCONSOLE_SETICON SetIconRequest = &ApiMessage.Data.SetIconRequest;
2664
2665 SetIconRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2666 SetIconRequest->IconHandle = hIcon;
2667
2668 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2669 NULL,
2670 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetIcon),
2671 sizeof(*SetIconRequest));
2672 if (!NT_SUCCESS(ApiMessage.Status))
2673 {
2674 BaseSetLastNTError(ApiMessage.Status);
2675 return FALSE;
2676 }
2677
2678 return TRUE;
2679 }
2680
2681
2682 /******************************************************************************
2683 * \name SetConsoleInputExeNameW
2684 * \brief Sets the console input file name from a unicode string.
2685 * \param lpExeName Pointer to a unicode string with the name.
2686 * \return TRUE if successful, FALSE if unsuccsedful.
2687 * \remarks If lpExeName is 0 or the string length is 0 or greater than 255,
2688 * the function fails and sets last error to ERROR_INVALID_PARAMETER.
2689 */
2690 BOOL
2691 WINAPI
2692 DECLSPEC_HOTPATCH
2693 SetConsoleInputExeNameW(IN LPWSTR lpExeName)
2694 {
2695 DWORD ExeLength;
2696
2697 ExeLength = lstrlenW(lpExeName);
2698 if ((ExeLength == 0) || (ExeLength >= EXENAME_LENGTH))
2699 {
2700 /* Fail if string is empty or too long */
2701 SetLastError(ERROR_INVALID_PARAMETER);
2702 return FALSE;
2703 }
2704
2705 RtlEnterCriticalSection(&ExeNameLock);
2706 _SEH2_TRY
2707 {
2708 /* Set the input EXE name, not NULL terminated */
2709 RtlCopyMemory(ExeNameBuffer, lpExeName, ExeLength * sizeof(WCHAR));
2710 ExeNameLength = (USHORT)ExeLength;
2711 }
2712 _SEH2_FINALLY
2713 {
2714 RtlLeaveCriticalSection(&ExeNameLock);
2715 }
2716 _SEH2_END;
2717
2718 return TRUE;
2719 }
2720
2721
2722 /******************************************************************************
2723 * \name SetConsoleInputExeNameA
2724 * \brief Sets the console input file name from an ansi string.
2725 * \param lpExeName Pointer to an ansi string with the name.
2726 * \return TRUE if successful, FALSE if unsuccsedful.
2727 * \remarks If lpExeName is 0 or the string length is 0 or greater than 255,
2728 * the function fails and sets last error to ERROR_INVALID_PARAMETER.
2729 */
2730 BOOL
2731 WINAPI
2732 DECLSPEC_HOTPATCH
2733 SetConsoleInputExeNameA(IN LPSTR lpExeName)
2734 {
2735 NTSTATUS Status;
2736 #ifdef USE_TEB_STATIC_USTR
2737 PUNICODE_STRING ExeNameU;
2738 #else
2739 UNICODE_STRING ExeNameU;
2740 #endif
2741 ANSI_STRING ExeNameA;
2742 #ifndef USE_TEB_STATIC_USTR
2743 WCHAR Buffer[EXENAME_LENGTH];
2744 #endif
2745
2746 #ifdef USE_TEB_STATIC_USTR
2747 /*
2748 * Use the TEB static UNICODE string for storage. It is already
2749 * initialized at process creation time by the Memory Manager.
2750 */
2751 ExeNameU = &NtCurrentTeb()->StaticUnicodeString;
2752 #endif
2753
2754 /* Initialize string for conversion */
2755 RtlInitAnsiString(&ExeNameA, lpExeName);
2756
2757 #if 1
2758 if ((ExeNameA.Length == 0) || (ExeNameA.Length >= EXENAME_LENGTH))
2759 {
2760 /* Fail if string is empty or too long */
2761 SetLastError(ERROR_INVALID_PARAMETER);
2762 return FALSE;
2763 }
2764 #endif
2765 #ifndef USE_TEB_STATIC_USTR
2766 ExeNameU.Length = 0;
2767 ExeNameU.MaximumLength = (USHORT)sizeof(Buffer);
2768 ExeNameU.Buffer = Buffer;
2769 #endif
2770
2771 #ifdef USE_TEB_STATIC_USTR
2772 Status = RtlAnsiStringToUnicodeString(ExeNameU, &ExeNameA, FALSE);
2773 #else
2774 Status = RtlAnsiStringToUnicodeString(&ExeNameU, &ExeNameA, FALSE);
2775 #endif
2776 if (!NT_SUCCESS(Status))
2777 {
2778 /* Fail if string is empty or too long */
2779 if (Status == STATUS_BUFFER_OVERFLOW)
2780 SetLastError(ERROR_FILENAME_EXCED_RANGE);
2781 else
2782 SetLastError(ERROR_INVALID_PARAMETER);
2783
2784 return FALSE;
2785 }
2786
2787 #ifdef USE_TEB_STATIC_USTR
2788 return SetConsoleInputExeNameW(ExeNameU->Buffer);
2789 #else
2790 return SetConsoleInputExeNameW(ExeNameU.Buffer);
2791 #endif
2792 }
2793
2794
2795 /******************************************************************************
2796 * \name GetConsoleInputExeNameW
2797 * \brief Retrieves the console input file name as unicode string.
2798 * \param nBufferLength Length of the buffer in WCHARs.
2799 * Specify 0 to receive the needed buffer length.
2800 * \param lpBuffer Pointer to a buffer that receives the string.
2801 * \return Needed buffer size if \p nBufferLength is 0.
2802 * Otherwise 1 if successful, 2 if buffer is too small.
2803 * \remarks Sets last error value to ERROR_BUFFER_OVERFLOW if the buffer
2804 * is not big enough.
2805 */
2806 DWORD
2807 WINAPI
2808 DECLSPEC_HOTPATCH
2809 GetConsoleInputExeNameW(IN DWORD nBufferLength,
2810 OUT LPWSTR lpExeName)
2811 {
2812 if (nBufferLength <= ExeNameLength)
2813 {
2814 /* Buffer is not large enough! Return the correct size. */
2815 SetLastError(ERROR_BUFFER_OVERFLOW);
2816 return ExeNameLength + 1;
2817 }
2818
2819 RtlEnterCriticalSection(&ExeNameLock);
2820 _SEH2_TRY
2821 {
2822 /* Copy the input EXE name and NULL-terminate it */
2823 RtlCopyMemory(lpExeName, ExeNameBuffer, ExeNameLength * sizeof(WCHAR));
2824 lpExeName[ExeNameLength] = UNICODE_NULL;
2825 }
2826 _SEH2_FINALLY
2827 {
2828 RtlLeaveCriticalSection(&ExeNameLock);
2829 }
2830 _SEH2_END;
2831
2832 return TRUE;
2833 }
2834
2835
2836 /******************************************************************************
2837 * \name GetConsoleInputExeNameA
2838 * \brief Retrieves the console input file name as ansi string.
2839 * \param nBufferLength Length of the buffer in CHARs.
2840 * \param lpBuffer Pointer to a buffer that receives the string.
2841 * \return 1 if successful, 2 if buffer is too small.
2842 * \remarks Sets last error value to ERROR_BUFFER_OVERFLOW if the buffer
2843 * is not big enough. The buffer receives as much characters as fit.
2844 */
2845 DWORD
2846 WINAPI
2847 DECLSPEC_HOTPATCH
2848 GetConsoleInputExeNameA(IN DWORD nBufferLength,
2849 OUT LPSTR lpExeName)
2850 {
2851 NTSTATUS Status;
2852 DWORD ExeLength;
2853 UNICODE_STRING BufferU;
2854 ANSI_STRING BufferA;
2855 WCHAR Buffer[EXENAME_LENGTH];
2856
2857 /* Get the UNICODE name */
2858 ExeLength = GetConsoleInputExeNameW(EXENAME_LENGTH, Buffer);
2859
2860 if ((ExeLength == 0) || (ExeLength >= EXENAME_LENGTH))
2861 return ExeLength;
2862
2863 /* Initialize the strings for conversion */
2864 RtlInitUnicodeString(&BufferU, Buffer);
2865 BufferA.Length = 0;
2866 BufferA.MaximumLength = (USHORT)nBufferLength;
2867 BufferA.Buffer = lpExeName;
2868
2869 /* Convert UNICODE name to ANSI, copying as much chars as it can fit */
2870 Status = RtlUnicodeStringToAnsiString(&BufferA, &BufferU, FALSE);
2871 if (!NT_SUCCESS(Status))
2872 {
2873 if (Status == STATUS_BUFFER_OVERFLOW)
2874 {
2875 SetLastError(ERROR_BUFFER_OVERFLOW);
2876 return ExeLength + 1;
2877 }
2878 SetLastError(ERROR_INVALID_PARAMETER);
2879 }
2880
2881 return ExeLength;
2882 }
2883
2884 BOOL
2885 WINAPI
2886 GetConsoleCharType(HANDLE hConsole, COORD Coord, PDWORD Type)
2887 {
2888 STUB;
2889 return FALSE;
2890 }
2891
2892 BOOL
2893 WINAPI
2894 DECLSPEC_HOTPATCH
2895 GetConsoleCursorMode(HANDLE hConsole, PBOOL pUnknown1, PBOOL pUnknown2)
2896 {
2897 STUB;
2898 return FALSE;
2899 }
2900
2901 BOOL
2902 WINAPI
2903 DECLSPEC_HOTPATCH
2904 SetConsoleCursorMode(HANDLE hConsole, BOOL Unknown1, BOOL Unknown2)
2905 {
2906 STUB;
2907 return FALSE;
2908 }
2909
2910 BOOL
2911 WINAPI
2912 DECLSPEC_HOTPATCH
2913 GetConsoleNlsMode(HANDLE hConsole, LPDWORD lpMode)
2914 {
2915 STUB;
2916 return FALSE;
2917 }
2918
2919 BOOL
2920 WINAPI
2921 DECLSPEC_HOTPATCH
2922 SetConsoleNlsMode(HANDLE hConsole, DWORD dwMode)
2923 {
2924 STUB;
2925 return FALSE;
2926 }
2927
2928 BOOL
2929 WINAPI
2930 DECLSPEC_HOTPATCH
2931 SetConsoleLocalEUDC(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4)
2932 {
2933 STUB;
2934 return FALSE;
2935 }
2936
2937 BOOL
2938 WINAPI
2939 DECLSPEC_HOTPATCH
2940 RegisterConsoleIME(HWND hWnd, LPDWORD ThreadId)
2941 {
2942 STUB;
2943 return FALSE;
2944 }
2945
2946 BOOL
2947 WINAPI
2948 DECLSPEC_HOTPATCH
2949 RegisterConsoleOS2(BOOL bUnknown)
2950 {
2951 STUB;
2952 return FALSE;
2953 }
2954
2955 BOOL
2956 WINAPI
2957 DECLSPEC_HOTPATCH
2958 SetConsoleOS2OemFormat(BOOL bUnknown)
2959 {
2960 STUB;
2961 return FALSE;
2962 }
2963
2964 BOOL
2965 WINAPI
2966 DECLSPEC_HOTPATCH
2967 UnregisterConsoleIME(VOID)
2968 {
2969 STUB;
2970 return FALSE;
2971 }
2972
2973
2974 static
2975 BOOL
2976 IntGetConsoleKeyboardLayoutName(OUT PVOID pszLayoutName,
2977 IN BOOL bAnsi)
2978 {
2979 CONSOLE_API_MESSAGE ApiMessage;
2980 PCONSOLE_GETKBDLAYOUTNAME GetKbdLayoutNameRequest = &ApiMessage.Data.GetKbdLayoutNameRequest;
2981
2982 /* Set up the data to send to the Console Server */
2983 GetKbdLayoutNameRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
2984 GetKbdLayoutNameRequest->Ansi = bAnsi;
2985
2986 /* Call the server */
2987 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
2988 NULL,
2989 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetKeyboardLayoutName),
2990 sizeof(*GetKbdLayoutNameRequest));
2991
2992 /* Check for success */
2993 if (!NT_SUCCESS(ApiMessage.Status))
2994 {
2995 BaseSetLastNTError(ApiMessage.Status);
2996 return FALSE;
2997 }
2998
2999 /* Retrieve the results */
3000 _SEH2_TRY
3001 {
3002 /* Copy only KL_NAMELENGTH == 9 characters, ANSI or UNICODE */
3003 if (bAnsi)
3004 strncpy(pszLayoutName, (PCHAR)GetKbdLayoutNameRequest->LayoutBuffer, KL_NAMELENGTH);
3005 else
3006 wcsncpy(pszLayoutName, (PWCHAR)GetKbdLayoutNameRequest->LayoutBuffer, KL_NAMELENGTH);
3007 }
3008 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3009 {
3010 SetLastError(ERROR_INVALID_ACCESS);
3011 _SEH2_YIELD(return FALSE);
3012 }
3013 _SEH2_END;
3014
3015 return TRUE;
3016 }
3017
3018 /*
3019 * @implemented (undocumented)
3020 */
3021 BOOL
3022 WINAPI
3023 DECLSPEC_HOTPATCH
3024 GetConsoleKeyboardLayoutNameA(OUT LPSTR pszLayoutName)
3025 {
3026 return IntGetConsoleKeyboardLayoutName(pszLayoutName, TRUE);
3027 }
3028
3029 /*
3030 * @implemented (undocumented)
3031 */
3032 BOOL
3033 WINAPI
3034 DECLSPEC_HOTPATCH
3035 GetConsoleKeyboardLayoutNameW(OUT LPWSTR pszLayoutName)
3036 {
3037 return IntGetConsoleKeyboardLayoutName(pszLayoutName, FALSE);
3038 }
3039
3040 /*
3041 * @implemented
3042 */
3043 DWORD
3044 WINAPI
3045 SetLastConsoleEventActive(VOID)
3046 {
3047 CONSOLE_API_MESSAGE ApiMessage;
3048 PCONSOLE_NOTIFYLASTCLOSE NotifyLastCloseRequest = &ApiMessage.Data.NotifyLastCloseRequest;
3049
3050 /* Set the flag used by the console control dispatcher */
3051 LastCloseNotify = TRUE;
3052
3053 /* Set up the input arguments */
3054 NotifyLastCloseRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
3055
3056 /* Call CSRSS; just return the NTSTATUS cast to DWORD */
3057 return CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
3058 NULL,
3059 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepNotifyLastClose),
3060 sizeof(*NotifyLastCloseRequest));
3061 }
3062
3063 /* EOF */