ReactOS 0.4.15-dev-7958-gcd0bb1a
console.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/winsrv/consrv/console.c
5 * PURPOSE: Console Management Functions
6 * PROGRAMMERS: Gé van Geldorp
7 * Jeffrey Morlan
8 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
9 */
10
11/* INCLUDES *******************************************************************/
12
13#include "consrv.h"
14
15/* This is for COM usage */
16#define COBJMACROS
17#include <shlobj.h>
18
19#include "../concfg/font.h"
20#include <alias.h>
21#include <history.h>
22#include "procinit.h"
23
24#define NDEBUG
25#include <debug.h>
26
27
28/* GLOBALS ********************************************************************/
29
30// static ULONG CurrentConsoleID = 0;
31
32/* The list of the ConSrv consoles */
35// static LIST_ENTRY ConDrvConsoleList;
37
38#define ConSrvLockConsoleListExclusive() \
39 RtlAcquireResourceExclusive(&ListLock, TRUE)
40
41#define ConSrvLockConsoleListShared() \
42 RtlAcquireResourceShared(&ListLock, TRUE)
43
44#define ConSrvUnlockConsoleList() \
45 RtlReleaseResource(&ListLock)
46
47#if 0
48static NTSTATUS
49ConDrvInsertConsole(
51{
53
54 /* All went right, so add the console to the list */
56
57 DPRINT("Insert in the list\n");
58 InsertTailList(&ConDrvConsoleList, &Console->ListEntry);
59
60 // FIXME: Move this code to the caller function!!
61 /* Get a new console ID */
62 _InterlockedExchange((PLONG)&Console->ConsoleID, CurrentConsoleID);
63 _InterlockedIncrement((PLONG)&CurrentConsoleID);
64
65 /* Unlock the console list and return success */
67 return STATUS_SUCCESS;
68}
69#endif
70
71static NTSTATUS
75{
76#define CONSOLE_HANDLES_INCREMENT 2 * 3
77
79 ULONG i = 0;
80 PCONSRV_CONSOLE* Block;
81
82 ASSERT( (ConsoleList == NULL && ConsoleListSize == 0) ||
83 (ConsoleList != NULL && ConsoleListSize != 0) );
84
85 /* All went right, so add the console to the list */
87 DPRINT("Insert in the list\n");
88
89 if (ConsoleList)
90 {
91 for (i = 0; i < ConsoleListSize; i++)
92 {
93 if (ConsoleList[i] == NULL) break;
94 }
95 }
96
97 if (i >= ConsoleListSize)
98 {
99 DPRINT("Creation of a new handles table\n");
100 /* Allocate a new handles table */
104 if (Block == NULL)
105 {
107 goto Quit;
108 }
109
110 /* If we previously had a handles table, free it and use the new one */
111 if (ConsoleList)
112 {
113 /* Copy the handles from the old table to the new one */
114 RtlCopyMemory(Block,
118 }
119 ConsoleList = Block;
121 }
122
124 *Handle = ULongToHandle((i << 2) | 0x3);
125
126Quit:
127 /* Unlock the console list and return status */
129 return Status;
130}
131
132/* Unused */
133#if 0
134static NTSTATUS
135RemoveConsoleByHandle(IN HANDLE Handle)
136{
139
140 BOOLEAN ValidHandle = ((HandleToULong(Handle) & 0x3) == 0x3);
142
143 if (!ValidHandle) return STATUS_INVALID_HANDLE;
144
145 ASSERT( (ConsoleList == NULL && ConsoleListSize == 0) ||
146 (ConsoleList != NULL && ConsoleListSize != 0) );
147
148 /* Remove the console from the list */
150
151 if (Index >= ConsoleListSize ||
153 {
155 goto Quit;
156 }
157
159
160Quit:
161 /* Unlock the console list and return status */
163 return Status;
164}
165#endif
166
167static NTSTATUS
169{
170 ULONG i = 0;
171
173
174 ASSERT( (ConsoleList == NULL && ConsoleListSize == 0) ||
175 (ConsoleList != NULL && ConsoleListSize != 0) );
176
177 /* Remove the console from the list */
179
180 if (ConsoleList)
181 {
182 for (i = 0; i < ConsoleListSize; i++)
183 {
185 }
186 }
187
188 /* Unlock the console list and return */
190 return STATUS_SUCCESS;
191}
192
193#if 0
194static NTSTATUS
196{
197 // ASSERT(Console);
199
200 /* Remove the console from the list */
202
203 RemoveEntryList(&Console->ListEntry);
204
205 /* Unlock the console list and return success */
207 return STATUS_SUCCESS;
208}
209#endif
210
211
212/* PRIVATE FUNCTIONS **********************************************************/
213
214// Adapted from reactos/lib/rtl/unicode.c, RtlCreateUnicodeString line 2180
215static BOOLEAN
218{
219 SIZE_T Size = (wcslen(Source) + 1) * sizeof(WCHAR);
220 if (Size > MAXUSHORT) return FALSE;
221
222 UniDest->Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Size);
223 if (UniDest->Buffer == NULL) return FALSE;
224
225 RtlCopyMemory(UniDest->Buffer, Source, Size);
226 UniDest->MaximumLength = (USHORT)Size;
227 UniDest->Length = (USHORT)Size - sizeof(WCHAR);
228
229 return TRUE;
230}
231
232// Adapted from reactos/lib/rtl/unicode.c, RtlFreeUnicodeString line 431
233static VOID
235{
236 if (UnicodeString->Buffer)
237 {
240 }
241}
242
243
244/* CONSOLE VALIDATION FUNCTIONS ***********************************************/
245
248 IN HANDLE ConsoleHandle,
249 IN CONSOLE_STATE ExpectedState,
250 IN BOOLEAN LockConsole)
251{
252 BOOLEAN RetVal = FALSE;
253 PCONSRV_CONSOLE ValidatedConsole;
254
255 BOOLEAN ValidHandle = ((HandleToULong(ConsoleHandle) & 0x3) == 0x3);
256 ULONG Index = HandleToULong(ConsoleHandle) >> 2;
257
258 if (!ValidHandle) return FALSE;
259
260 if (!Console) return FALSE;
261 *Console = NULL;
262
263 /*
264 * Forbid creation or deletion of consoles when
265 * checking for the existence of a console.
266 */
268
269 if (Index >= ConsoleListSize ||
270 (ValidatedConsole = ConsoleList[Index]) == NULL)
271 {
272 /* Unlock the console list and return */
274 return FALSE;
275 }
276
277 ValidatedConsole = ConsoleList[Index];
278
279 /* Unlock the console list */
281
282 RetVal = ConDrvValidateConsoleUnsafe((PCONSOLE)ValidatedConsole,
283 ExpectedState,
284 LockConsole);
285 if (RetVal) *Console = ValidatedConsole;
286
287 return RetVal;
288}
289
293 IN BOOLEAN LockConsole)
294{
296 PCONSRV_CONSOLE GrabConsole;
297
298 // if (Console == NULL) return STATUS_INVALID_PARAMETER;
300 *Console = NULL;
301
302 if (ConSrvValidateConsole(&GrabConsole,
303 ProcessData->ConsoleHandle,
305 LockConsole))
306 {
307 _InterlockedIncrement(&GrabConsole->ReferenceCount);
308 *Console = GrabConsole;
310 }
311
312 return Status;
313}
314
315VOID
317 IN BOOLEAN IsConsoleLocked)
318{
319 LONG RefCount = 0;
320
321 if (!Console) return;
322 // if (Console->ReferenceCount == 0) return; // This shouldn't happen
323 ASSERT(Console->ReferenceCount > 0);
324
325 /* The console must be locked */
326 // ASSERT(Console_locked);
327
328 /*
329 * Decrement the reference count. Save the new value too,
330 * because Console->ReferenceCount might be modified after
331 * the console gets unlocked but before we check whether we
332 * can destroy it.
333 */
334 RefCount = _InterlockedDecrement(&Console->ReferenceCount);
335
336 /* Unlock the console if needed */
337 if (IsConsoleLocked) LeaveCriticalSection(&Console->Lock);
338
339 /* Delete the console if needed */
340 if (RefCount <= 0) ConSrvDeleteConsole(Console);
341}
342
343
344/* CONSOLE INITIALIZATION FUNCTIONS *******************************************/
345
348{
349 DPRINT("CONSRV: ConSrvInitConsoleSupport()\n");
350
351 /* Initialize the console list and its lock */
352 ConsoleListSize = 0;
354 // InitializeListHead(&ConDrvConsoleList);
356
357 /* Should call LoadKeyboardLayout */
358}
359
363 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
364 IN HANDLE ConsoleLeaderProcessHandle);
367
368
369static BOOL
371 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo)
372{
373#define PATH_SEPARATOR L'\\'
374
375 BOOL RetVal = FALSE;
376 HRESULT hRes = S_OK;
377 SIZE_T Length = 0;
378 LPWSTR LinkName = NULL;
380 WCHAR Buffer[MAX_PATH + 1];
381
382 ConsoleInitInfo->ConsoleStartInfo->IconIndex = 0;
383
384 if ((ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
385 {
386 // return FALSE; // FIXME!! (for icon loading)
387 RetVal = TRUE;
388 goto Finish;
389 }
390
391 /* 1- Find the last path separator if any */
392 LinkName = wcsrchr(ConsoleInfo->ConsoleTitle, PATH_SEPARATOR);
393 if (LinkName == NULL)
394 LinkName = ConsoleInfo->ConsoleTitle;
395 else
396 ++LinkName; // Skip the path separator
397
398 /* 2- Check for the link extension. The name ".lnk" is considered invalid. */
399 Length = wcslen(LinkName);
400 if ( (Length <= 4) || (wcsicmp(LinkName + (Length - 4), L".lnk") != 0) )
401 return FALSE;
402
403 /* 3- It may be a link. Try to retrieve some properties */
404 hRes = CoInitialize(NULL);
405 if (SUCCEEDED(hRes))
406 {
407 /* Get a pointer to the IShellLink interface */
408 IShellLinkW* pshl = NULL;
409 hRes = CoCreateInstance(&CLSID_ShellLink,
410 NULL,
411 CLSCTX_INPROC_SERVER,
412 &IID_IShellLinkW,
413 (LPVOID*)&pshl);
414 if (SUCCEEDED(hRes))
415 {
416 /* Get a pointer to the IPersistFile interface */
417 IPersistFile* ppf = NULL;
418 hRes = IPersistFile_QueryInterface(pshl, &IID_IPersistFile, (LPVOID*)&ppf);
419 if (SUCCEEDED(hRes))
420 {
421 /* Load the shortcut */
422 hRes = IPersistFile_Load(ppf, ConsoleInfo->ConsoleTitle, STGM_READ);
423 if (SUCCEEDED(hRes))
424 {
425 /*
426 * Finally we can get the properties !
427 * Update the old ones if needed.
428 */
429 INT ShowCmd = 0;
430 // WORD HotKey = 0;
431
432 /* Reset the name of the console with the name of the shortcut */
433 Length = min(/*Length*/ Length - 4, // 4 == len(".lnk")
434 (ConsoleInfo->cbSize - FIELD_OFFSET(CONSOLE_STATE_INFO, ConsoleTitle) - sizeof(UNICODE_NULL)) / sizeof(WCHAR));
435 wcsncpy(ConsoleInfo->ConsoleTitle, LinkName, Length);
436 ConsoleInfo->ConsoleTitle[Length] = UNICODE_NULL;
437
438 /* Get the window showing command */
439 hRes = IShellLinkW_GetShowCmd(pshl, &ShowCmd);
440 if (SUCCEEDED(hRes)) ConsoleInitInfo->ConsoleStartInfo->wShowWindow = (WORD)ShowCmd;
441
442 /* Get the hotkey */
443 // hRes = pshl->GetHotkey(&ShowCmd);
444 // if (SUCCEEDED(hRes)) ConsoleInitInfo->ConsoleStartInfo->HotKey = HotKey;
445
446 /* Get the icon location, if any */
447 hRes = IShellLinkW_GetIconLocation(pshl,
448 Buffer,
449 sizeof(Buffer)/sizeof(Buffer[0]) - 1, // == MAX_PATH
450 &ConsoleInitInfo->ConsoleStartInfo->IconIndex);
451 if (!SUCCEEDED(hRes))
452 {
453 ConsoleInitInfo->ConsoleStartInfo->IconIndex = 0;
454 }
455 else
456 {
458 }
459
460 // FIXME: Since we still don't load console properties from the shortcut,
461 // return false. When this will be done, we will return true instead.
462 RetVal = TRUE; // FALSE;
463 }
464 IPersistFile_Release(ppf);
465 }
466 IShellLinkW_Release(pshl);
467 }
469 }
470
471Finish:
472
473 if (RetVal)
474 {
475 /* Get the associated icon, if any */
476 if (IconPath == NULL)
477 {
478 // Question: How to retrieve the full path name
479 // of the app we are going to run??
480 Length = RtlDosSearchPath_U(ConsoleInitInfo->CurDir,
481 ConsoleInitInfo->AppName,
482 NULL,
483 sizeof(Buffer),
484 Buffer,
485 NULL);
486 if (Length > 0 && Length < sizeof(Buffer))
488 else
489 IconPath = ConsoleInitInfo->AppName;
490
491 // ConsoleInitInfo->ConsoleStartInfo->IconIndex = 0;
492 }
493 DPRINT("IconPath = '%S' ; IconIndex = %lu\n",
494 IconPath, ConsoleInitInfo->ConsoleStartInfo->IconIndex);
495 if (IconPath && *IconPath)
496 {
498 /*
499 * FIXME!! Because of a strange bug we have in PrivateExtractIconExW
500 * (see r65683 for more details), we cannot use this API to extract
501 * at the same time the large and small icons from the app.
502 * Instead we just use PrivateExtractIconsW.
503 *
504 PrivateExtractIconExW(IconPath,
505 ConsoleInitInfo->ConsoleStartInfo->IconIndex,
506 &hIcon,
507 &hIconSm,
508 1);
509 */
511 ConsoleInitInfo->ConsoleStartInfo->IconIndex,
512 32, 32,
515 ConsoleInitInfo->ConsoleStartInfo->IconIndex,
516 16, 16,
518
519 DPRINT("hIcon = 0x%p ; hIconSm = 0x%p\n", hIcon, hIconSm);
520 if (hIcon != NULL) ConsoleInitInfo->ConsoleStartInfo->hIcon = hIcon;
521 if (hIconSm != NULL) ConsoleInitInfo->ConsoleStartInfo->hIconSm = hIconSm;
522 }
523 }
524
525 // FIXME: See the previous FIXME above.
526 RetVal = FALSE;
527
528 return RetVal;
529}
530
533 OUT PCONSRV_CONSOLE* NewConsole,
534 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
535 IN PCSR_PROCESS ConsoleLeaderProcess)
536{
538 HANDLE ConsoleHandle;
540
541 BYTE ConsoleInfoBuffer[sizeof(CONSOLE_STATE_INFO) + MAX_PATH * sizeof(WCHAR)]; // CONSRV console information
543 CONSOLE_INFO DrvConsoleInfo; // Console information for CONDRV
544
545 SIZE_T Length = 0;
546
547 TERMINAL Terminal; /* The ConSrv terminal for this console */
548
549 if (NewConsole == NULL || ConsoleInitInfo == NULL)
551
552 *NewConsole = NULL;
553
554 DPRINT("Initialization of console '%S' for process '%S' on desktop '%S'\n",
555 ConsoleInitInfo->ConsoleTitle ? ConsoleInitInfo->ConsoleTitle : L"n/a",
556 ConsoleInitInfo->AppName ? ConsoleInitInfo->AppName : L"n/a",
557 ConsoleInitInfo->Desktop ? ConsoleInitInfo->Desktop : L"n/a");
558
559 /*
560 * Load the console settings
561 */
562 RtlZeroMemory(ConsoleInfo, sizeof(ConsoleInfoBuffer));
563 ConsoleInfo->cbSize = sizeof(ConsoleInfoBuffer);
564
565 /* 1. Get the title of the console (initialize ConsoleInfo->ConsoleTitle) */
566 Length = min(ConsoleInitInfo->TitleLength,
567 (ConsoleInfo->cbSize - FIELD_OFFSET(CONSOLE_STATE_INFO, ConsoleTitle) - sizeof(UNICODE_NULL)) / sizeof(WCHAR));
568 wcsncpy(ConsoleInfo->ConsoleTitle, ConsoleInitInfo->ConsoleTitle, Length);
569 ConsoleInfo->ConsoleTitle[Length] = UNICODE_NULL; // NULL-terminate it.
570
571 /* 2. Impersonate the caller in order to retrieve settings in its context */
574
575 /* 3. Load the default settings */
577
578 /*
579 * 4. Load per-application terminal settings.
580 *
581 * Check whether the process creating the console was launched via
582 * a shell-link. ConsoleInfo->ConsoleTitle may be updated with the
583 * name of the shortcut, and ConsoleStartInfo->Icon[Path|Index] too.
584 */
585 // if (ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) // FIXME!! (for icon loading)
586 {
587 if (!LoadShellLinkConsoleInfo(ConsoleInfo, ConsoleInitInfo))
588 {
589 ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags &= ~STARTF_TITLEISLINKNAME;
590 }
591 }
592
593 /*
594 * 5. Load the remaining console settings via the registry.
595 */
596 if ((ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
597 {
598 /*
599 * Either we weren't created by an app launched via a shell-link,
600 * or we failed to load shell-link console properties.
601 * Therefore, load the console infos for the application from the registry.
602 */
604
605 /*
606 * Now, update them with the properties the user might gave to us
607 * via the STARTUPINFO structure before calling CreateProcess
608 * (and which was transmitted via the ConsoleStartInfo structure).
609 * We therefore overwrite the values read in the registry.
610 */
611 if (ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_USEFILLATTRIBUTE)
612 {
613 ConsoleInfo->ScreenAttributes = (USHORT)ConsoleInitInfo->ConsoleStartInfo->wFillAttribute;
614 }
615 if (ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_USECOUNTCHARS)
616 {
617 ConsoleInfo->ScreenBufferSize = ConsoleInitInfo->ConsoleStartInfo->dwScreenBufferSize;
618 }
619 if (ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_USESIZE)
620 {
621 ConsoleInfo->WindowSize = ConsoleInitInfo->ConsoleStartInfo->dwWindowSize;
622 }
623
624#if 0
625 /*
626 * Now, update them with the properties the user might gave to us
627 * via the STARTUPINFO structure before calling CreateProcess
628 * (and which was transmitted via the ConsoleStartInfo structure).
629 * We therefore overwrite the values read in the registry.
630 */
631 if (ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_USEPOSITION)
632 {
633 ConsoleInfo->AutoPosition = FALSE;
634 ConsoleInfo->WindowPosition.x = ConsoleInitInfo->ConsoleStartInfo->dwWindowOrigin.X;
635 ConsoleInfo->WindowPosition.y = ConsoleInitInfo->ConsoleStartInfo->dwWindowOrigin.Y;
636 }
637 if (ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN)
638 {
639 ConsoleInfo->FullScreen = TRUE;
640 }
641#endif
642 }
643
644 /* 6. Revert impersonation */
646
647 /* Set-up the code page */
648 ConsoleInfo->CodePage = GetOEMCP();
649
650 /*
651 * Initialize the ConSrv terminal and give it a chance to load
652 * its own settings and override the console settings.
653 */
654 Status = ConSrvInitTerminal(&Terminal,
656 ConsoleInitInfo,
657 ConsoleLeaderProcess->ProcessHandle);
658 if (!NT_SUCCESS(Status))
659 {
660 DPRINT1("CONSRV: Failed to initialize a terminal, Status = 0x%08lx\n", Status);
661 return Status;
662 }
663 DPRINT("CONSRV: Terminal initialized\n");
664
665 /* Initialize a new console via the driver */
666 // DrvConsoleInfo.InputBufferSize = 0;
667 DrvConsoleInfo.ScreenBufferSize = ConsoleInfo->ScreenBufferSize;
668 DrvConsoleInfo.ConsoleSize = ConsoleInfo->WindowSize;
669 DrvConsoleInfo.CursorSize = ConsoleInfo->CursorSize;
670 // DrvConsoleInfo.CursorBlinkOn = ConsoleInfo->CursorBlinkOn;
671 DrvConsoleInfo.ScreenAttrib = ConsoleInfo->ScreenAttributes;
672 DrvConsoleInfo.PopupAttrib = ConsoleInfo->PopupAttributes;
673 DrvConsoleInfo.CodePage = ConsoleInfo->CodePage;
674
675 /*
676 * Allocate a new console
677 */
679 if (Console == NULL)
680 {
681 DPRINT1("Not enough memory for console creation.\n");
682 ConSrvDeinitTerminal(&Terminal);
683 return STATUS_NO_MEMORY;
684 }
685
686 Status = ConDrvInitConsole((PCONSOLE)Console, &DrvConsoleInfo);
687 if (!NT_SUCCESS(Status))
688 {
689 DPRINT1("Creating a new console failed, Status = 0x%08lx\n", Status);
691 ConSrvDeinitTerminal(&Terminal);
692 return Status;
693 }
694
695 DPRINT("Console initialized\n");
696
697 /*** Register ConSrv features ***/
698
699 /* Initialize the console title */
700#if 0
701 WCHAR DefaultTitle[128];
702#endif
703 ConsoleCreateUnicodeString(&Console->OriginalTitle, ConsoleInfo->ConsoleTitle);
704#if 0
705 if (ConsoleInfo->ConsoleTitle[0] == UNICODE_NULL)
706 {
707 if (LoadStringW(ConSrvDllInstance, IDS_CONSOLE_TITLE, DefaultTitle, sizeof(DefaultTitle) / sizeof(DefaultTitle[0])))
708 {
709 ConsoleCreateUnicodeString(&Console->Title, DefaultTitle);
710 }
711 else
712 {
713 ConsoleCreateUnicodeString(&Console->Title, L"ReactOS Console");
714 }
715 }
716 else
717 {
718#endif
719 ConsoleCreateUnicodeString(&Console->Title, ConsoleInfo->ConsoleTitle);
720#if 0
721 }
722#endif
723
724 /* Initialize process support */
725 // InitProcessSupport(Console);
726 InitializeListHead(&Console->ProcessList);
727 Console->NotifiedLastCloseProcess = NULL;
728 Console->NotifyLastClose = FALSE;
729 Console->HasFocus = FALSE;
730
731 /* Initialize pausing support */
732 Console->PauseFlags = 0;
733 InitializeListHead(&Console->ReadWaitQueue);
734 InitializeListHead(&Console->WriteWaitQueue);
735
736 /* Initialize the alias and history buffers */
737 // InitAliasesHistory(Console);
738 Console->Aliases = NULL;
739 InitializeListHead(&Console->HistoryBuffers);
740 Console->NumberOfHistoryBuffers = 0;
741 Console->MaxNumberOfHistoryBuffers = ConsoleInfo->NumberOfHistoryBuffers;
742 Console->HistoryBufferSize = ConsoleInfo->HistoryBufferSize;
743 Console->HistoryNoDup = ConsoleInfo->HistoryNoDup;
744
745 /* Initialize the Input Line Discipline */
746 // InitLineInput(Console);
747 Console->LineBuffer = NULL;
748 Console->LinePos = Console->LineMaxSize = Console->LineSize = 0;
749 Console->LineComplete = Console->LineUpPressed = FALSE;
750 // LineWakeupMask
751 Console->LineInsertToggle =
752 Console->InsertMode = ConsoleInfo->InsertMode;
753 Console->QuickEdit = ConsoleInfo->QuickEdit;
754
755 /* Popup windows */
756 InitializeListHead(&Console->PopupWindows);
757
758 /* Colour table */
759 RtlCopyMemory(Console->Colors, ConsoleInfo->ColorTable,
760 sizeof(ConsoleInfo->ColorTable));
761
762 /* Create the Initialization Events */
765 if (!NT_SUCCESS(Status))
766 {
767 DPRINT1("NtCreateEvent(InitEvents[INIT_SUCCESS]) failed: %lu\n", Status);
769 ConSrvDeinitTerminal(&Terminal);
770 return Status;
771 }
774 if (!NT_SUCCESS(Status))
775 {
776 DPRINT1("NtCreateEvent(InitEvents[INIT_FAILURE]) failed: %lu\n", Status);
777 NtClose(Console->InitEvents[INIT_SUCCESS]);
779 ConSrvDeinitTerminal(&Terminal);
780 return Status;
781 }
782
783 /*
784 * Attach the ConSrv terminal to the console.
785 * This call makes a copy of our local Terminal variable.
786 */
788 if (!NT_SUCCESS(Status))
789 {
790 DPRINT1("Failed to register terminal to the given console, Status = 0x%08lx\n", Status);
791 NtClose(Console->InitEvents[INIT_FAILURE]);
792 NtClose(Console->InitEvents[INIT_SUCCESS]);
794 ConSrvDeinitTerminal(&Terminal);
795 return Status;
796 }
797 DPRINT("Terminal attached\n");
798
799 /* All went right, so add the console to the list */
800#if 0
801 Status = ConDrvInsertConsole((PCONSOLE)Console);
802 if (!NT_SUCCESS(Status))
803 {
804 /* Fail */
806 return Status;
807 }
808#endif
809 Status = InsertConsole(&ConsoleHandle, Console);
810
811 // FIXME! We do not support at all asynchronous console creation!
812 NtSetEvent(Console->InitEvents[INIT_SUCCESS], NULL);
813 // NtSetEvent(Console->InitEvents[INIT_FAILURE], NULL);
814
815 /* Return the newly created console to the caller and a success code too */
816 *NewConsoleHandle = ConsoleHandle;
817 *NewConsole = Console;
818 return STATUS_SUCCESS;
819}
820
823{
824 DPRINT("ConSrvDeleteConsole\n");
825
826 // FIXME: Send a terminate message to all the processes owning this console.
827 // NOTE: In principle there should be none, because such processes would
828 // have a reference to the console and thus this function would not have
829 // been called in the first place.
830
831 /* Remove the console from the list */
833
834 /* Destroy the Initialization Events */
835 NtClose(Console->InitEvents[INIT_FAILURE]);
836 NtClose(Console->InitEvents[INIT_SUCCESS]);
837
838 /* Clean the Input Line Discipline */
839 if (Console->LineBuffer) ConsoleFreeHeap(Console->LineBuffer);
840
841 /* Clean aliases and history */
844
845 /* Free the console title */
846 ConsoleFreeUnicodeString(&Console->OriginalTitle);
848
849 /* Now, call the driver. ConDrvDetachTerminal is called on-demand. */
851
852 /* Deinit the ConSrv terminal */
853 // FIXME!!
854 // ConSrvDeinitTerminal(&Terminal);
855}
856
857
858VOID
860{
861 Console->PauseFlags |= Flags;
863}
864
865VOID
867{
868 Console->PauseFlags &= ~Flags;
869
870 // if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0)
871 if (Console->PauseFlags == 0)
872 {
874
875 CsrNotifyWait(&Console->WriteWaitQueue,
876 TRUE,
877 NULL,
878 NULL);
879 if (!IsListEmpty(&Console->WriteWaitQueue))
880 {
881 CsrDereferenceWait(&Console->WriteWaitQueue);
882 }
883 }
884}
885
886
887/* CONSOLE PROCESS INITIALIZATION FUNCTIONS ***********************************/
888
889static NTSTATUS
891 IN OUT PCONSOLE_PROCESS_DATA ProcessData,
893 OUT PHANDLE pInputHandle,
894 OUT PHANDLE pOutputHandle,
895 OUT PHANDLE pErrorHandle)
896{
900 ErrorHandle = INVALID_HANDLE_VALUE;
901
902 /*
903 * Initialize the process handles. Use temporary variables to store
904 * the handles values in such a way that, if we fail, we don't
905 * return to the caller invalid handle values.
906 *
907 * Insert the IO handles.
908 */
909
910 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
911
912 /* Insert the Input handle */
913 Status = ConSrvInsertObject(ProcessData,
915 &Console->InputBuffer.Header,
917 TRUE,
919 if (!NT_SUCCESS(Status))
920 {
921 DPRINT1("Failed to insert the input handle\n");
922 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
923 ConSrvFreeHandlesTable(ProcessData);
924 return Status;
925 }
926
927 /* Insert the Output handle */
928 Status = ConSrvInsertObject(ProcessData,
930 &Console->ActiveBuffer->Header,
932 TRUE,
934 if (!NT_SUCCESS(Status))
935 {
936 DPRINT1("Failed to insert the output handle\n");
937 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
938 ConSrvFreeHandlesTable(ProcessData);
939 return Status;
940 }
941
942 /* Insert the Error handle */
943 Status = ConSrvInsertObject(ProcessData,
944 &ErrorHandle,
945 &Console->ActiveBuffer->Header,
947 TRUE,
949 if (!NT_SUCCESS(Status))
950 {
951 DPRINT1("Failed to insert the error handle\n");
952 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
953 ConSrvFreeHandlesTable(ProcessData);
954 return Status;
955 }
956
957 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
958
959 /* Return the newly created handles */
960 *pInputHandle = InputHandle;
961 *pOutputHandle = OutputHandle;
962 *pErrorHandle = ErrorHandle;
963
964 return STATUS_SUCCESS;
965}
966
969 IN OUT PCONSOLE_PROCESS_DATA ProcessData,
970 OUT PHANDLE pInputHandle,
971 OUT PHANDLE pOutputHandle,
972 OUT PHANDLE pErrorHandle,
973 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo)
974{
976 HANDLE ConsoleHandle;
978
979 /*
980 * We are about to create a new console. However when ConSrvNewProcess()
981 * was called, we didn't know that we wanted to create a new console and
982 * therefore, we by default inherited the handle table from our parent
983 * process. It's only now that we notice that in fact we do not need
984 * them, because we've created a new console and thus we must use it.
985 *
986 * Therefore, free the handle table so that we can recreate
987 * a new one later on.
988 */
989 ConSrvFreeHandlesTable(ProcessData);
990
991 /* Initialize a new Console owned by this process */
992 Status = ConSrvInitConsole(&ConsoleHandle,
993 &Console,
994 ConsoleInitInfo,
995 ProcessData->Process);
996 if (!NT_SUCCESS(Status))
997 {
998 DPRINT1("Console initialization failed\n");
999 return Status;
1000 }
1001
1002 /* Assign the new console handle */
1003 ProcessData->ConsoleHandle = ConsoleHandle;
1004
1005 /* Initialize the process handles */
1006 Status = ConSrvInitProcessHandles(ProcessData,
1007 Console,
1008 pInputHandle,
1009 pOutputHandle,
1010 pErrorHandle);
1011 if (!NT_SUCCESS(Status))
1012 {
1013 DPRINT1("Failed to initialize the process handles\n");
1015 ProcessData->ConsoleHandle = NULL;
1016 return Status;
1017 }
1018
1019 /* Duplicate the Initialization Events */
1021 Console->InitEvents[INIT_SUCCESS],
1022 ProcessData->Process->ProcessHandle,
1023 &ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_SUCCESS],
1024 EVENT_ALL_ACCESS, 0, 0);
1025 if (!NT_SUCCESS(Status))
1026 {
1027 DPRINT1("NtDuplicateObject(InitEvents[INIT_SUCCESS]) failed: %lu\n", Status);
1028 ConSrvFreeHandlesTable(ProcessData);
1030 ProcessData->ConsoleHandle = NULL;
1031 return Status;
1032 }
1033
1035 Console->InitEvents[INIT_FAILURE],
1036 ProcessData->Process->ProcessHandle,
1037 &ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_FAILURE],
1038 EVENT_ALL_ACCESS, 0, 0);
1039 if (!NT_SUCCESS(Status))
1040 {
1041 DPRINT1("NtDuplicateObject(InitEvents[INIT_FAILURE]) failed: %lu\n", Status);
1042 NtDuplicateObject(ProcessData->Process->ProcessHandle,
1043 ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_SUCCESS],
1045 ConSrvFreeHandlesTable(ProcessData);
1047 ProcessData->ConsoleHandle = NULL;
1048 return Status;
1049 }
1050
1051 /* Duplicate the Input Event */
1053 Console->InputBuffer.ActiveEvent,
1054 ProcessData->Process->ProcessHandle,
1055 &ConsoleInitInfo->ConsoleStartInfo->InputWaitHandle,
1056 EVENT_ALL_ACCESS, 0, 0);
1057 if (!NT_SUCCESS(Status))
1058 {
1059 DPRINT1("NtDuplicateObject(InputWaitHandle) failed: %lu\n", Status);
1060 NtDuplicateObject(ProcessData->Process->ProcessHandle,
1061 ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_FAILURE],
1063 NtDuplicateObject(ProcessData->Process->ProcessHandle,
1064 ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_SUCCESS],
1066 ConSrvFreeHandlesTable(ProcessData);
1068 ProcessData->ConsoleHandle = NULL;
1069 return Status;
1070 }
1071
1072 /* Mark the process as having a console */
1073 ProcessData->ConsoleApp = TRUE;
1074 ProcessData->Process->Flags |= CsrProcessIsConsoleApp;
1075
1076 /* Return the console handle to the caller */
1077 ConsoleInitInfo->ConsoleStartInfo->ConsoleHandle = ProcessData->ConsoleHandle;
1078
1079 /*
1080 * Insert the process into the processes list of the console,
1081 * and set its foreground priority.
1082 */
1083 InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
1084 ConSrvSetProcessFocus(ProcessData->Process, Console->HasFocus);
1085
1086 /* Add a reference count because the process is tied to the console */
1087 _InterlockedIncrement(&Console->ReferenceCount);
1088
1089 /* Update the internal info of the terminal */
1091
1092 return STATUS_SUCCESS;
1093}
1094
1097 IN OUT PCONSOLE_PROCESS_DATA ProcessData,
1098 IN HANDLE ConsoleHandle,
1099 IN BOOLEAN CreateNewHandleTable,
1100 OUT PHANDLE pInputHandle,
1101 OUT PHANDLE pOutputHandle,
1102 OUT PHANDLE pErrorHandle,
1103 IN OUT PCONSOLE_START_INFO ConsoleStartInfo)
1104{
1107
1108 /* Validate and lock the console */
1110 ConsoleHandle,
1112 {
1113 // FIXME: Find another status code
1114 return STATUS_UNSUCCESSFUL;
1115 }
1116
1117 /* Inherit the console */
1118 ProcessData->ConsoleHandle = ConsoleHandle;
1119
1120 if (CreateNewHandleTable)
1121 {
1122 /*
1123 * We are about to create a new console. However when ConSrvNewProcess()
1124 * was called, we didn't know that we wanted to create a new console and
1125 * therefore, we by default inherited the handle table from our parent
1126 * process. It's only now that we notice that in fact we do not need
1127 * them, because we've created a new console and thus we must use it.
1128 *
1129 * Therefore, free the handle table so that we can recreate
1130 * a new one later on.
1131 */
1132 ConSrvFreeHandlesTable(ProcessData);
1133
1134 /* Initialize the process handles */
1135 Status = ConSrvInitProcessHandles(ProcessData,
1136 Console,
1137 pInputHandle,
1138 pOutputHandle,
1139 pErrorHandle);
1140 if (!NT_SUCCESS(Status))
1141 {
1142 DPRINT1("Failed to initialize the process handles\n");
1143 ProcessData->ConsoleHandle = NULL;
1144 goto Quit;
1145 }
1146 }
1147
1148 /* Duplicate the Initialization Events */
1150 Console->InitEvents[INIT_SUCCESS],
1151 ProcessData->Process->ProcessHandle,
1152 &ConsoleStartInfo->InitEvents[INIT_SUCCESS],
1153 EVENT_ALL_ACCESS, 0, 0);
1154 if (!NT_SUCCESS(Status))
1155 {
1156 DPRINT1("NtDuplicateObject(InitEvents[INIT_SUCCESS]) failed: %lu\n", Status);
1157 ConSrvFreeHandlesTable(ProcessData);
1158 ProcessData->ConsoleHandle = NULL;
1159 goto Quit;
1160 }
1161
1163 Console->InitEvents[INIT_FAILURE],
1164 ProcessData->Process->ProcessHandle,
1165 &ConsoleStartInfo->InitEvents[INIT_FAILURE],
1166 EVENT_ALL_ACCESS, 0, 0);
1167 if (!NT_SUCCESS(Status))
1168 {
1169 DPRINT1("NtDuplicateObject(InitEvents[INIT_FAILURE]) failed: %lu\n", Status);
1170 NtDuplicateObject(ProcessData->Process->ProcessHandle,
1171 ConsoleStartInfo->InitEvents[INIT_SUCCESS],
1173 ConSrvFreeHandlesTable(ProcessData);
1174 ProcessData->ConsoleHandle = NULL;
1175 goto Quit;
1176 }
1177
1178 /* Duplicate the Input Event */
1180 Console->InputBuffer.ActiveEvent,
1181 ProcessData->Process->ProcessHandle,
1182 &ConsoleStartInfo->InputWaitHandle,
1183 EVENT_ALL_ACCESS, 0, 0);
1184 if (!NT_SUCCESS(Status))
1185 {
1186 DPRINT1("NtDuplicateObject(InputWaitHandle) failed: %lu\n", Status);
1187 NtDuplicateObject(ProcessData->Process->ProcessHandle,
1188 ConsoleStartInfo->InitEvents[INIT_FAILURE],
1190 NtDuplicateObject(ProcessData->Process->ProcessHandle,
1191 ConsoleStartInfo->InitEvents[INIT_SUCCESS],
1193 ConSrvFreeHandlesTable(ProcessData); // NOTE: Always free the handle table.
1194 ProcessData->ConsoleHandle = NULL;
1195 goto Quit;
1196 }
1197
1198 /* Mark the process as having a console */
1199 ProcessData->ConsoleApp = TRUE;
1200 ProcessData->Process->Flags |= CsrProcessIsConsoleApp;
1201
1202 /* Return the console handle to the caller */
1203 ConsoleStartInfo->ConsoleHandle = ProcessData->ConsoleHandle;
1204
1205 /*
1206 * Insert the process into the processes list of the console,
1207 * and set its foreground priority.
1208 */
1209 InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
1210 ConSrvSetProcessFocus(ProcessData->Process, Console->HasFocus);
1211
1212 /* Add a reference count because the process is tied to the console */
1213 _InterlockedIncrement(&Console->ReferenceCount);
1214
1215 /* Update the internal info of the terminal */
1217
1219
1220Quit:
1221 /* Unlock the console and return */
1223 return Status;
1224}
1225
1228 IN OUT PCONSOLE_PROCESS_DATA ProcessData)
1229{
1231 PCONSOLE_PROCESS_DATA ConsoleLeaderProcess;
1232
1233 DPRINT("ConSrvRemoveConsole\n");
1234
1235 /* Mark the process as not having a console anymore */
1236 ProcessData->ConsoleApp = FALSE;
1237 ProcessData->Process->Flags &= ~CsrProcessIsConsoleApp;
1238
1239 /* Validate and lock the console */
1241 ProcessData->ConsoleHandle,
1243 {
1244 // FIXME: Find another status code
1245 return STATUS_UNSUCCESSFUL;
1246 }
1247
1248 DPRINT("ConSrvRemoveConsole - Locking OK\n");
1249
1250 /* Retrieve the console leader process */
1251 ConsoleLeaderProcess = ConSrvGetConsoleLeaderProcess(Console);
1252
1253 /* Close all console handles and free the handle table */
1254 ConSrvFreeHandlesTable(ProcessData);
1255
1256 /* Detach the process from the console */
1257 ProcessData->ConsoleHandle = NULL;
1258
1259 /* Remove the process from the console's list of processes */
1260 RemoveEntryList(&ProcessData->ConsoleLink);
1261
1262 /* Check whether the console should send a last close notification */
1263 if (Console->NotifyLastClose)
1264 {
1265 /* If we are removing the process which wants the last close notification... */
1266 if (ProcessData == Console->NotifiedLastCloseProcess)
1267 {
1268 /* ... just reset the flag and the pointer... */
1269 Console->NotifyLastClose = FALSE;
1270 Console->NotifiedLastCloseProcess = NULL;
1271 }
1272 /*
1273 * ... otherwise, if we are removing the console leader process
1274 * (that cannot be the process wanting the notification, because
1275 * the previous case already dealt with it)...
1276 */
1277 else if (ProcessData == ConsoleLeaderProcess)
1278 {
1279 /*
1280 * ... reset the flag first (so that we avoid multiple notifications)
1281 * and then send the last close notification.
1282 */
1283 Console->NotifyLastClose = FALSE;
1284 ConSrvConsoleCtrlEvent(CTRL_LAST_CLOSE_EVENT, Console->NotifiedLastCloseProcess);
1285
1286 /* Only now, reset the pointer */
1287 Console->NotifiedLastCloseProcess = NULL;
1288 }
1289 }
1290
1291 /* Update the internal info of the terminal */
1293
1294 /* Release the console */
1295 DPRINT("ConSrvRemoveConsole - Decrement Console->ReferenceCount = %lu\n", Console->ReferenceCount);
1297
1298 return STATUS_SUCCESS;
1299}
1300
1301
1302/* CONSOLE PROCESS MANAGEMENT FUNCTIONS ***************************************/
1303
1306 IN PCONSOLE_PROCESS_DATA ProcessData,
1308{
1310
1311 DPRINT("ConSrvConsoleCtrlEventTimeout Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess);
1312
1313 /*
1314 * Be sure we effectively have a control routine. It resides in kernel32.dll (client).
1315 */
1316 if (ProcessData->CtrlRoutine == NULL) return Status;
1317
1318 _SEH2_TRY
1319 {
1320 HANDLE Thread = NULL;
1321
1322 _SEH2_TRY
1323 {
1324 Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
1325 ProcessData->CtrlRoutine,
1326 UlongToPtr(CtrlEvent), 0, NULL);
1327 if (NULL == Thread)
1328 {
1330 DPRINT1("Failed thread creation, Status = 0x%08lx\n", Status);
1331 }
1332 else
1333 {
1334 DPRINT("ProcessData->CtrlRoutine remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n",
1335 ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
1337 }
1338 }
1340 {
1342 }
1343 _SEH2_END;
1344 }
1346 {
1348 DPRINT1("ConSrvConsoleCtrlEventTimeout - Caught an exception, Status = 0x%08lx\n", Status);
1349 }
1350 _SEH2_END;
1351
1352 return Status;
1353}
1354
1357 IN PCONSOLE_PROCESS_DATA ProcessData)
1358{
1359 return ConSrvConsoleCtrlEventTimeout(CtrlEvent, ProcessData, 0);
1360}
1361
1364{
1365 if (Console == NULL) return NULL;
1366
1367 return CONTAINING_RECORD(Console->ProcessList.Blink,
1369 ConsoleLink);
1370}
1371
1374 IN OUT PULONG ProcessIdsList,
1375 IN ULONG MaxIdListItems,
1376 OUT PULONG ProcessIdsTotal)
1377{
1379 PLIST_ENTRY current_entry;
1380
1381 if (Console == NULL || ProcessIdsList == NULL || ProcessIdsTotal == NULL)
1383
1384 *ProcessIdsTotal = 0;
1385
1386 for (current_entry = Console->ProcessList.Flink;
1387 current_entry != &Console->ProcessList;
1388 current_entry = current_entry->Flink)
1389 {
1390 current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
1391 if (++(*ProcessIdsTotal) <= MaxIdListItems)
1392 {
1393 *ProcessIdsList++ = HandleToUlong(current->Process->ClientId.UniqueProcess);
1394 }
1395 }
1396
1397 return STATUS_SUCCESS;
1398}
1399
1400// ConSrvGenerateConsoleCtrlEvent
1403 IN ULONG ProcessGroupId,
1404 IN ULONG CtrlEvent)
1405{
1407 PLIST_ENTRY current_entry;
1409
1410 /* If the console is already being destroyed, just return */
1412 return STATUS_UNSUCCESSFUL;
1413
1414 /*
1415 * Loop through the process list, from the most recent process
1416 * (the active one) to the oldest one (the first created, i.e.
1417 * the console leader process), and for each, send an event
1418 * (new processes are inserted at the head of the console process list).
1419 */
1420 current_entry = Console->ProcessList.Flink;
1421 while (current_entry != &Console->ProcessList)
1422 {
1423 current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
1424 current_entry = current_entry->Flink;
1425
1426 /*
1427 * Only processes belonging to the same process group are signaled.
1428 * If the process group ID is zero, then all the processes are signaled.
1429 */
1430 if (ProcessGroupId == 0 || current->Process->ProcessGroupId == ProcessGroupId)
1431 {
1433 }
1434 }
1435
1436 return Status;
1437}
1438
1439VOID
1441 IN BOOLEAN SetForeground)
1442{
1443 // FIXME: Call NtUserSetInformationProcess (currently unimplemented!)
1444 // for setting Win32 foreground/background flags.
1445
1446 if (SetForeground)
1448 else
1450}
1451
1454 IN BOOLEAN SetForeground)
1455{
1456 PLIST_ENTRY current_entry;
1458
1459 /* If the console is already being destroyed, just return */
1461 return STATUS_UNSUCCESSFUL;
1462
1463 /*
1464 * Loop through the process list, from the most recent process
1465 * to the oldest one, and for each, set its foreground priority.
1466 */
1467 current_entry = Console->ProcessList.Flink;
1468 while (current_entry != &Console->ProcessList)
1469 {
1470 current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
1471 current_entry = current_entry->Flink;
1472
1473 ConSrvSetProcessFocus(current->Process, SetForeground);
1474 }
1475
1476 return STATUS_SUCCESS;
1477}
1478
1479
1480/* PUBLIC SERVER APIS *********************************************************/
1481
1482/* API_NUMBER: ConsolepAlloc */
1483CON_API_NOCONSOLE(SrvAllocConsole,
1484 CONSOLE_ALLOCCONSOLE, AllocConsoleRequest)
1485{
1487 CONSOLE_INIT_INFO ConsoleInitInfo;
1488
1489 if (ProcessData->ConsoleHandle != NULL)
1490 {
1491 DPRINT1("Process already has a console\n");
1492 return STATUS_ACCESS_DENIED;
1493 }
1494
1495 if ( !CsrValidateMessageBuffer(ApiMessage,
1496 (PVOID*)&AllocConsoleRequest->ConsoleStartInfo,
1497 1,
1498 sizeof(CONSOLE_START_INFO)) ||
1499 !CsrValidateMessageBuffer(ApiMessage,
1500 (PVOID*)&AllocConsoleRequest->ConsoleTitle,
1501 AllocConsoleRequest->TitleLength,
1502 sizeof(BYTE)) ||
1503 !CsrValidateMessageBuffer(ApiMessage,
1504 (PVOID*)&AllocConsoleRequest->Desktop,
1505 AllocConsoleRequest->DesktopLength,
1506 sizeof(BYTE)) ||
1507 !CsrValidateMessageBuffer(ApiMessage,
1508 (PVOID*)&AllocConsoleRequest->CurDir,
1509 AllocConsoleRequest->CurDirLength,
1510 sizeof(BYTE)) ||
1511 !CsrValidateMessageBuffer(ApiMessage,
1512 (PVOID*)&AllocConsoleRequest->AppName,
1513 AllocConsoleRequest->AppNameLength,
1514 sizeof(BYTE)) )
1515 {
1517 }
1518
1519 /* Initialize the console initialization info structure */
1520 ConsoleInitInfo.ConsoleStartInfo = AllocConsoleRequest->ConsoleStartInfo;
1521 ConsoleInitInfo.IsWindowVisible = TRUE; // The console window is always visible.
1522 ConsoleInitInfo.TitleLength = AllocConsoleRequest->TitleLength;
1523 ConsoleInitInfo.ConsoleTitle = AllocConsoleRequest->ConsoleTitle;
1524 ConsoleInitInfo.DesktopLength = AllocConsoleRequest->DesktopLength;
1525 ConsoleInitInfo.Desktop = AllocConsoleRequest->Desktop;
1526 ConsoleInitInfo.AppNameLength = AllocConsoleRequest->AppNameLength;
1527 ConsoleInitInfo.AppName = AllocConsoleRequest->AppName;
1528 ConsoleInitInfo.CurDirLength = AllocConsoleRequest->CurDirLength;
1529 ConsoleInitInfo.CurDir = AllocConsoleRequest->CurDir;
1530
1531 /* Initialize a new Console owned by the Console Leader Process */
1532 Status = ConSrvAllocateConsole(ProcessData,
1533 &AllocConsoleRequest->ConsoleStartInfo->InputHandle,
1534 &AllocConsoleRequest->ConsoleStartInfo->OutputHandle,
1535 &AllocConsoleRequest->ConsoleStartInfo->ErrorHandle,
1536 &ConsoleInitInfo);
1537 if (!NT_SUCCESS(Status))
1538 {
1539 DPRINT1("Console allocation failed\n");
1540 return Status;
1541 }
1542
1543 /* Set the Property-Dialog and Control-Dispatcher handlers */
1544 ProcessData->PropRoutine = AllocConsoleRequest->PropRoutine;
1545 ProcessData->CtrlRoutine = AllocConsoleRequest->CtrlRoutine;
1546
1547 return STATUS_SUCCESS;
1548}
1549
1550/* API_NUMBER: ConsolepAttach */
1551CON_API_NOCONSOLE(SrvAttachConsole,
1552 CONSOLE_ATTACHCONSOLE, AttachConsoleRequest)
1553{
1555 PCSR_PROCESS SourceProcess = NULL; // The parent process.
1556 PCSR_PROCESS TargetProcess = CsrGetClientThread()->Process; // Ourselves.
1557 HANDLE ProcessId = ULongToHandle(AttachConsoleRequest->ProcessId);
1558 PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
1559
1560 TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
1561
1562 if (TargetProcessData->ConsoleHandle != NULL)
1563 {
1564 DPRINT1("Process already has a console\n");
1565 return STATUS_ACCESS_DENIED;
1566 }
1567
1568 if (!CsrValidateMessageBuffer(ApiMessage,
1569 (PVOID*)&AttachConsoleRequest->ConsoleStartInfo,
1570 1,
1571 sizeof(CONSOLE_START_INFO)))
1572 {
1574 }
1575
1576 /* Check whether we try to attach to the parent's console */
1578 {
1579 PROCESS_BASIC_INFORMATION ProcessInfo;
1580 ULONG Length = sizeof(ProcessInfo);
1581
1582 /* Get the real parent's PID */
1583
1586 &ProcessInfo,
1587 Length, &Length);
1588 if (!NT_SUCCESS(Status))
1589 {
1590 DPRINT1("SrvAttachConsole - Cannot retrieve basic process info, Status = 0x%08lx\n", Status);
1591 return Status;
1592 }
1593
1595 }
1596
1597 /* Lock the source process via its PID */
1598 Status = CsrLockProcessByClientId(ProcessId, &SourceProcess);
1599 if (!NT_SUCCESS(Status)) return Status;
1600
1601 SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
1602
1603 if (SourceProcessData->ConsoleHandle == NULL)
1604 {
1606 goto Quit;
1607 }
1608
1609 /*
1610 * Inherit the console from the parent,
1611 * if any, otherwise return an error.
1612 */
1613 Status = ConSrvInheritConsole(TargetProcessData,
1614 SourceProcessData->ConsoleHandle,
1615 TRUE,
1616 &AttachConsoleRequest->ConsoleStartInfo->InputHandle,
1617 &AttachConsoleRequest->ConsoleStartInfo->OutputHandle,
1618 &AttachConsoleRequest->ConsoleStartInfo->ErrorHandle,
1619 AttachConsoleRequest->ConsoleStartInfo);
1620 if (!NT_SUCCESS(Status))
1621 {
1622 DPRINT1("Console inheritance failed\n");
1623 goto Quit;
1624 }
1625
1626 /* Set the Property-Dialog and Control-Dispatcher handlers */
1627 TargetProcessData->PropRoutine = AttachConsoleRequest->PropRoutine;
1628 TargetProcessData->CtrlRoutine = AttachConsoleRequest->CtrlRoutine;
1629
1631
1632Quit:
1633 /* Unlock the "source" process and exit */
1634 CsrUnlockProcess(SourceProcess);
1635 return Status;
1636}
1637
1638/* API_NUMBER: ConsolepFree */
1639CON_API_NOCONSOLE(SrvFreeConsole,
1640 CONSOLE_FREECONSOLE, FreeConsoleRequest)
1641{
1642 /*
1643 * If this process doesn't have a console handle, bail out immediately.
1644 * Also the passed console handle should be the same as the process' one.
1645 */
1646 if ((FreeConsoleRequest->ConsoleHandle == NULL) ||
1647 (FreeConsoleRequest->ConsoleHandle != ProcessData->ConsoleHandle))
1648 {
1649 return STATUS_INVALID_HANDLE; // STATUS_ACCESS_DENIED;
1650 }
1651
1652 return ConSrvRemoveConsole(ProcessData);
1653}
1654
1658 OUT PULONG ConsoleMode);
1659/* API_NUMBER: ConsolepGetMode */
1660CON_API(SrvGetConsoleMode,
1661 CONSOLE_GETSETCONSOLEMODE, ConsoleModeRequest)
1662{
1665 PULONG ConsoleMode = &ConsoleModeRequest->Mode;
1666
1667 Status = ConSrvGetObject(ProcessData,
1668 ConsoleModeRequest->Handle,
1669 &Object, NULL, GENERIC_READ, TRUE, 0);
1670 if (!NT_SUCCESS(Status))
1671 return Status;
1672
1673 ASSERT((PCONSOLE)Console == Object->Console);
1674
1675 /* Get the standard console modes */
1677 if (NT_SUCCESS(Status))
1678 {
1679 /*
1680 * If getting the console modes succeeds, then retrieve
1681 * the extended CONSRV-specific input modes.
1682 */
1683 if (INPUT_BUFFER == Object->Type)
1684 {
1685 if (Console->InsertMode || Console->QuickEdit)
1686 {
1687 /* Windows also adds ENABLE_EXTENDED_FLAGS, even if it's not documented on MSDN */
1688 *ConsoleMode |= ENABLE_EXTENDED_FLAGS;
1689
1690 if (Console->InsertMode) *ConsoleMode |= ENABLE_INSERT_MODE;
1691 if (Console->QuickEdit ) *ConsoleMode |= ENABLE_QUICK_EDIT_MODE;
1692 }
1693 }
1694 }
1695
1697 return Status;
1698}
1699
1703 IN ULONG ConsoleMode);
1704/* API_NUMBER: ConsolepSetMode */
1705CON_API(SrvSetConsoleMode,
1706 CONSOLE_GETSETCONSOLEMODE, ConsoleModeRequest)
1707{
1708#define CONSOLE_VALID_CONTROL_MODES ( ENABLE_EXTENDED_FLAGS | \
1709 ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE )
1710// NOTE: Vista+ ENABLE_AUTO_POSITION is also a control mode.
1711
1714 ULONG ConsoleMode = ConsoleModeRequest->Mode;
1715
1716 Status = ConSrvGetObject(ProcessData,
1717 ConsoleModeRequest->Handle,
1718 &Object, NULL, GENERIC_WRITE, TRUE, 0);
1719 if (!NT_SUCCESS(Status))
1720 return Status;
1721
1722 ASSERT((PCONSOLE)Console == Object->Console);
1723
1724 /* Set the standard console modes (without the CONSRV-specific input modes) */
1725 ConsoleMode &= ~CONSOLE_VALID_CONTROL_MODES; // Remove CONSRV-specific input modes.
1727 if (NT_SUCCESS(Status))
1728 {
1729 /*
1730 * If setting the console modes succeeds, then set
1731 * the extended CONSRV-specific input modes.
1732 */
1733 if (INPUT_BUFFER == Object->Type)
1734 {
1735 ConsoleMode = ConsoleModeRequest->Mode;
1736
1737 if (ConsoleMode & CONSOLE_VALID_CONTROL_MODES)
1738 {
1739 /*
1740 * If we use control mode flags without ENABLE_EXTENDED_FLAGS,
1741 * then consider the flags invalid.
1742 */
1743 if ((ConsoleMode & ENABLE_EXTENDED_FLAGS) == 0)
1744 {
1746 }
1747 else
1748 {
1749 Console->InsertMode = !!(ConsoleMode & ENABLE_INSERT_MODE);
1750 Console->QuickEdit = !!(ConsoleMode & ENABLE_QUICK_EDIT_MODE);
1751 }
1752 }
1753 }
1754 }
1755
1757 return Status;
1758}
1759
1760/* API_NUMBER: ConsolepGetTitle */
1761CON_API(SrvGetConsoleTitle,
1762 CONSOLE_GETSETCONSOLETITLE, TitleRequest)
1763{
1764 ULONG Length;
1765
1766 if (!CsrValidateMessageBuffer(ApiMessage,
1767 (PVOID)&TitleRequest->Title,
1768 TitleRequest->Length,
1769 sizeof(BYTE)))
1770 {
1772 }
1773
1774 /* Copy title of the console to the user title buffer */
1775 if (TitleRequest->Unicode)
1776 {
1777 if (TitleRequest->Length >= sizeof(WCHAR))
1778 {
1779 Length = min(TitleRequest->Length - sizeof(WCHAR), Console->Title.Length);
1780 RtlCopyMemory(TitleRequest->Title, Console->Title.Buffer, Length);
1781 ((PWCHAR)TitleRequest->Title)[Length / sizeof(WCHAR)] = UNICODE_NULL;
1782 TitleRequest->Length = Length;
1783 }
1784 else
1785 {
1786 TitleRequest->Length = Console->Title.Length;
1787 }
1788 }
1789 else
1790 {
1791 if (TitleRequest->Length >= sizeof(CHAR))
1792 {
1793 Length = min(TitleRequest->Length - sizeof(CHAR), Console->Title.Length / sizeof(WCHAR));
1794 Length = WideCharToMultiByte(Console->InputCodePage, 0,
1795 Console->Title.Buffer, Length,
1796 TitleRequest->Title, Length,
1797 NULL, NULL);
1798 ((PCHAR)TitleRequest->Title)[Length] = ANSI_NULL;
1799 TitleRequest->Length = Length;
1800 }
1801 else
1802 {
1803 TitleRequest->Length = Console->Title.Length / sizeof(WCHAR);
1804 }
1805 }
1806
1807 return STATUS_SUCCESS;
1808}
1809
1810/* API_NUMBER: ConsolepSetTitle */
1811CON_API(SrvSetConsoleTitle,
1812 CONSOLE_GETSETCONSOLETITLE, TitleRequest)
1813{
1814 PWCHAR Buffer;
1815 ULONG Length;
1816
1817 if (!CsrValidateMessageBuffer(ApiMessage,
1818 (PVOID)&TitleRequest->Title,
1819 TitleRequest->Length,
1820 sizeof(BYTE)))
1821 {
1823 }
1824
1825 if (TitleRequest->Unicode)
1826 {
1827 /* Length is in bytes */
1828 Length = TitleRequest->Length;
1829 }
1830 else
1831 {
1832 /* Use the console input CP for the conversion */
1833 Length = MultiByteToWideChar(Console->InputCodePage, 0,
1834 TitleRequest->Title, TitleRequest->Length,
1835 NULL, 0);
1836 /* The returned Length was in number of wchars, convert it in bytes */
1837 Length *= sizeof(WCHAR);
1838 }
1839
1840 /* Allocate a new buffer to hold the new title (NULL-terminated) */
1842 if (!Buffer)
1843 return STATUS_NO_MEMORY;
1844
1845 /* Free the old title */
1847
1848 /* Copy title to console */
1849 Console->Title.Buffer = Buffer;
1850 Console->Title.Length = Length;
1851 Console->Title.MaximumLength = Console->Title.Length + sizeof(WCHAR);
1852
1853 if (TitleRequest->Unicode)
1854 {
1855 RtlCopyMemory(Console->Title.Buffer, TitleRequest->Title, Console->Title.Length);
1856 }
1857 else
1858 {
1859 MultiByteToWideChar(Console->InputCodePage, 0,
1860 TitleRequest->Title, TitleRequest->Length,
1861 Console->Title.Buffer,
1862 Console->Title.Length / sizeof(WCHAR));
1863 }
1864
1865 /* NULL-terminate */
1866 Console->Title.Buffer[Console->Title.Length / sizeof(WCHAR)] = UNICODE_NULL;
1867
1869
1870 return STATUS_SUCCESS;
1871}
1872
1875 OUT PUINT CodePage,
1876 IN BOOLEAN OutputCP);
1877/* API_NUMBER: ConsolepGetCP */
1878CON_API(SrvGetConsoleCP,
1879 CONSOLE_GETINPUTOUTPUTCP, GetConsoleCPRequest)
1880{
1881 DPRINT("SrvGetConsoleCP, getting %s Code Page\n",
1882 GetConsoleCPRequest->OutputCP ? "Output" : "Input");
1883
1885 &GetConsoleCPRequest->CodePage,
1886 GetConsoleCPRequest->OutputCP);
1887}
1888
1891 IN UINT CodePage,
1892 IN BOOLEAN OutputCP);
1893/* API_NUMBER: ConsolepSetCP */
1894CON_API(SrvSetConsoleCP,
1895 CONSOLE_SETINPUTOUTPUTCP, SetConsoleCPRequest)
1896{
1897 DPRINT("SrvSetConsoleCP, setting %s Code Page\n",
1898 SetConsoleCPRequest->OutputCP ? "Output" : "Input");
1899
1901 SetConsoleCPRequest->CodePage,
1902 SetConsoleCPRequest->OutputCP);
1903}
1904
1905/* API_NUMBER: ConsolepGetProcessList */
1906CON_API(SrvGetConsoleProcessList,
1907 CONSOLE_GETPROCESSLIST, GetProcessListRequest)
1908{
1909 if (!CsrValidateMessageBuffer(ApiMessage,
1910 (PVOID)&GetProcessListRequest->ProcessIdsList,
1911 GetProcessListRequest->ProcessCount,
1912 sizeof(DWORD)))
1913 {
1915 }
1916
1918 GetProcessListRequest->ProcessIdsList,
1919 GetProcessListRequest->ProcessCount,
1920 &GetProcessListRequest->ProcessCount);
1921}
1922
1923/* API_NUMBER: ConsolepGenerateCtrlEvent */
1924CON_API(SrvGenerateConsoleCtrlEvent,
1925 CONSOLE_GENERATECTRLEVENT, GenerateCtrlEventRequest)
1926{
1928 GenerateCtrlEventRequest->ProcessGroupId,
1929 GenerateCtrlEventRequest->CtrlEvent);
1930}
1931
1932/* API_NUMBER: ConsolepNotifyLastClose */
1933CON_API(SrvConsoleNotifyLastClose,
1934 CONSOLE_NOTIFYLASTCLOSE, NotifyLastCloseRequest)
1935{
1936 /* Only one process is allowed to be registered for last close notification */
1937 if (Console->NotifyLastClose)
1938 return STATUS_ACCESS_DENIED;
1939
1940 Console->NotifyLastClose = TRUE;
1941 Console->NotifiedLastCloseProcess = ProcessData;
1942 return STATUS_SUCCESS;
1943}
1944
1945/* API_NUMBER: ConsolepGetMouseInfo */
1946CON_API(SrvGetConsoleMouseInfo,
1947 CONSOLE_GETMOUSEINFO, GetMouseInfoRequest)
1948{
1949 /* Just retrieve the number of buttons of the mouse attached to this console */
1950 GetMouseInfoRequest->NumButtons = GetSystemMetrics(SM_CMOUSEBUTTONS);
1951 return STATUS_SUCCESS;
1952}
1953
1954/* API_NUMBER: ConsolepSetKeyShortcuts */
1955CSR_API(SrvSetConsoleKeyShortcuts)
1956{
1957 DPRINT1("%s not yet implemented\n", __FUNCTION__);
1959}
1960
1961/* API_NUMBER: ConsolepGetKeyboardLayoutName */
1962CON_API(SrvGetConsoleKeyboardLayoutName,
1963 CONSOLE_GETKBDLAYOUTNAME, GetKbdLayoutNameRequest)
1964{
1965 /* Retrieve the keyboard layout name of the system */
1966 if (GetKbdLayoutNameRequest->Ansi)
1967 GetKeyboardLayoutNameA((PCHAR)GetKbdLayoutNameRequest->LayoutBuffer);
1968 else
1969 GetKeyboardLayoutNameW((PWCHAR)GetKbdLayoutNameRequest->LayoutBuffer);
1970
1971 return STATUS_SUCCESS;
1972}
1973
1974/* API_NUMBER: ConsolepCharType */
1975CSR_API(SrvGetConsoleCharType)
1976{
1977 DPRINT1("%s not yet implemented\n", __FUNCTION__);
1979}
1980
1981/* API_NUMBER: ConsolepSetLocalEUDC */
1982CSR_API(SrvSetConsoleLocalEUDC)
1983{
1984 DPRINT1("%s not yet implemented\n", __FUNCTION__);
1986}
1987
1988/* API_NUMBER: ConsolepSetCursorMode */
1989CSR_API(SrvSetConsoleCursorMode)
1990{
1991 DPRINT1("%s not yet implemented\n", __FUNCTION__);
1993}
1994
1995/* API_NUMBER: ConsolepGetCursorMode */
1996CSR_API(SrvGetConsoleCursorMode)
1997{
1998 DPRINT1("%s not yet implemented\n", __FUNCTION__);
2000}
2001
2002/* API_NUMBER: ConsolepGetNlsMode */
2003CSR_API(SrvGetConsoleNlsMode)
2004{
2005 DPRINT1("%s not yet implemented\n", __FUNCTION__);
2007}
2008
2009/* API_NUMBER: ConsolepSetNlsMode */
2010CSR_API(SrvSetConsoleNlsMode)
2011{
2012 DPRINT1("%s not yet implemented\n", __FUNCTION__);
2014}
2015
2016/* API_NUMBER: ConsolepGetLangId */
2017CON_API(SrvGetConsoleLangId,
2018 CONSOLE_GETLANGID, LangIdRequest)
2019{
2020 /*
2021 * Quoting MS Terminal, see function GetConsoleLangId() at
2022 * https://github.com/microsoft/terminal/blob/main/src/host/srvinit.cpp#L655
2023 * "Only attempt to return the Lang ID if the Windows ACP on console
2024 * launch was an East Asian Code Page."
2025 *
2026 * The underlying logic is as follows:
2027 *
2028 * - When the current user's UI language is *not* CJK, the user expects
2029 * to not see any CJK output to the console by default, even if its
2030 * output has been set to a CJK code page (this is possible when CJK
2031 * fonts are installed on the system). That is, of course, unless if
2032 * the attached console program chooses to actually output CJK text.
2033 * Whatever current language of the running program's thread should
2034 * be kept: STATUS_NOT_SUPPORTED is returned.
2035 *
2036 * - When the current user's UI language *is* CJK, the user expects to
2037 * see CJK output to the console by default when its code page is CJK.
2038 * A valid LangId is returned in this case to ensure this.
2039 * However, if the console code page is not CJK, then it is evident
2040 * that CJK text will not be able to be correctly shown, and therefore
2041 * we should fall back to a standard language that can be shown, namely
2042 * en-US english, instead of keeping the current language.
2043 */
2044
2045 BYTE UserCharSet = CodePageToCharSet(GetACP());
2046 if (!IsCJKCharSet(UserCharSet))
2047 return STATUS_NOT_SUPPORTED;
2048
2049 /* Return a "best-suited" language ID corresponding
2050 * to the active console output code page. */
2051 switch (Console->OutputCodePage)
2052 {
2055 case CP_UTF8:
2056 return STATUS_NOT_SUPPORTED;
2058 case CP_JAPANESE:
2059 LangIdRequest->LangId = MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT);
2060 break;
2061 case CP_KOREAN:
2062 LangIdRequest->LangId = MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN);
2063 break;
2065 LangIdRequest->LangId = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED);
2066 break;
2068 LangIdRequest->LangId = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL);
2069 break;
2070 default:
2071 /* Default to en-US english otherwise */
2072 LangIdRequest->LangId = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
2073 break;
2074 }
2075
2076 return STATUS_SUCCESS;
2077}
2078
2079/* EOF */
unsigned char BOOLEAN
CConsole Console
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define HandleToUlong(h)
Definition: basetsd.h:79
#define ULongToHandle(h)
Definition: basetsd.h:81
#define HandleToULong(h)
Definition: basetsd.h:95
#define IsCJKCharSet(CharSet)
Definition: cjkcode.h:44
#define CP_CHINESE_SIMPLIFIED
Definition: cjkcode.h:23
#define CP_JAPANESE
Definition: cjkcode.h:21
#define CP_CHINESE_TRADITIONAL
Definition: cjkcode.h:24
#define CP_KOREAN
Definition: cjkcode.h:22
Definition: bufpool.h:45
@ INIT_SUCCESS
Definition: conmsg.h:163
@ INIT_FAILURE
Definition: conmsg.h:164
#define ConsoleGetPerProcessData(Process)
Definition: consrv.h:37
HINSTANCE ConSrvDllInstance
Definition: init.c:21
NTSTATUS NTAPI CsrUnlockProcess(IN PCSR_PROCESS CsrProcess)
Definition: procsup.c:1410
BOOLEAN NTAPI CsrValidateMessageBuffer(IN PCSR_API_MESSAGE ApiMessage, IN PVOID *Buffer, IN ULONG ElementCount, IN ULONG ElementSize)
Definition: api.c:1430
#define CsrGetClientThread()
Definition: csrsrv.h:77
BOOLEAN NTAPI CsrImpersonateClient(IN PCSR_THREAD CsrThread)
Definition: procsup.c:932
#define CSR_API(n)
Definition: csrsrv.h:176
BOOLEAN NTAPI CsrRevertToSelf(VOID)
Definition: procsup.c:1057
VOID NTAPI CsrDereferenceWait(IN PLIST_ENTRY WaitList)
Definition: wait.c:266
VOID NTAPI CsrSetForegroundPriority(IN PCSR_PROCESS CsrProcess)
Definition: procsup.c:1138
@ CsrProcessIsConsoleApp
Definition: csrsrv.h:94
NTSTATUS NTAPI CsrLockProcessByClientId(IN HANDLE Pid, OUT PCSR_PROCESS *CsrProcess OPTIONAL)
VOID NTAPI CsrSetBackgroundPriority(IN PCSR_PROCESS CsrProcess)
Definition: procsup.c:1107
BOOLEAN NTAPI CsrNotifyWait(IN PLIST_ENTRY WaitList, IN BOOLEAN NotifyAll, IN PVOID WaitArgument1, IN PVOID WaitArgument2)
Definition: wait.c:388
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define CloseHandle
Definition: compat.h:739
#define wcsrchr
Definition: compat.h:16
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
#define FILE_SHARE_READ
Definition: compat.h:136
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define wcsicmp
Definition: compat.h:15
HANDLE WINAPI CreateRemoteThread(IN HANDLE hProcess, IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:159
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1964
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
static const WCHAR IconPath[]
Definition: install.c:51
#define __FUNCTION__
Definition: types.h:116
#define UlongToPtr(u)
Definition: config.h:106
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ProcessId
Definition: fatprocs.h:2711
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
@ ProcessBasicInformation
Definition: winternl.h:394
NTSYSAPI NTSTATUS WINAPI RtlGetLastNtStatus(void)
Definition: error.c:114
long __cdecl _InterlockedIncrement(_Interlocked_operand_ long volatile *_Addend)
long __cdecl _InterlockedExchange(_Interlocked_operand_ long volatile *_Target, long _Value)
long __cdecl _InterlockedDecrement(_Interlocked_operand_ long volatile *_Addend)
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
#define PCHAR
Definition: match.c:90
#define ASSERT(a)
Definition: mode.c:44
struct task_struct * current
Definition: linux.c:32
HANDLE InputHandle
Definition: apc.c:9
HANDLE OutputHandle
Definition: apc.c:8
static HICON
Definition: imagelist.c:84
#define min(a, b)
Definition: monoChain.cc:55
HICON hIcon
Definition: msconfig.c:44
HICON hIconSm
Definition: msconfig.c:44
void RemoveConsole(void)
unsigned int * PUINT
Definition: ndis.h:50
unsigned int UINT
Definition: ndis.h:50
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3169
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI ULONG NTAPI RtlDosSearchPath_U(_In_ PCWSTR Path, _In_ PCWSTR FileName, _In_ PCWSTR Extension, _In_ ULONG BufferSize, _Out_ PWSTR Buffer, _Out_ PWSTR *PartName)
NTSYSAPI VOID NTAPI RtlInitializeResource(_In_ PRTL_RESOURCE Resource)
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define NtCurrentProcess()
Definition: nt_native.h:1657
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define GENERIC_WRITE
Definition: nt_native.h:90
#define UNICODE_NULL
#define ANSI_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ NotificationEvent
NTSTATUS NTAPI NtSetEvent(IN HANDLE EventHandle, OUT PLONG PreviousState OPTIONAL)
Definition: event.c:455
NTSTATUS NTAPI NtCreateEvent(OUT PHANDLE EventHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN EVENT_TYPE EventType, IN BOOLEAN InitialState)
Definition: event.c:96
NTSTATUS NTAPI NtQueryInformationProcess(_In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _Out_ PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength)
Definition: query.c:59
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:245
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_BAD_IMPERSONATION_LEVEL
Definition: ntstatus.h:401
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI NtDuplicateObject(IN HANDLE SourceProcessHandle, IN HANDLE SourceHandle, IN HANDLE TargetProcessHandle OPTIONAL, OUT PHANDLE TargetHandle OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG HandleAttributes, IN ULONG Options)
Definition: obhandle.c:3410
#define STGM_READ
Definition: objbase.h:917
const GUID IID_IPersistFile
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
static ULONG Timeout
Definition: ping.c:61
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
_CRTIMP wchar_t *__cdecl wcsncpy(wchar_t *_Dest, const wchar_t *_Source, size_t _Count)
#define MAKELANGID(p, s)
Definition: nls.h:15
#define LANG_ENGLISH
Definition: nls.h:52
#define SUBLANG_CHINESE_TRADITIONAL
Definition: nls.h:208
#define SUBLANG_CHINESE_SIMPLIFIED
Definition: nls.h:209
#define SUBLANG_DEFAULT
Definition: nls.h:168
#define LANG_CHINESE
Definition: nls.h:42
#define CP_UTF8
Definition: nls.h:20
#define LANG_JAPANESE
Definition: nls.h:76
#define LANG_KOREAN
Definition: nls.h:84
#define SUBLANG_ENGLISH_US
Definition: nls.h:222
#define SUBLANG_KOREAN
Definition: nls.h:280
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
USHORT ScreenAttrib
Definition: conio.h:189
ULONG CodePage
Definition: conio.h:192
COORD ScreenBufferSize
Definition: conio.h:182
USHORT PopupAttrib
Definition: conio.h:190
ULONG CursorSize
Definition: conio.h:185
COORD ConsoleSize
Definition: conio.h:183
ULONG CurDirLength
Definition: console.h:22
ULONG DesktopLength
Definition: console.h:18
ULONG TitleLength
Definition: console.h:16
PCONSOLE_START_INFO ConsoleStartInfo
Definition: console.h:13
BOOLEAN IsWindowVisible
Definition: console.h:14
PWCHAR ConsoleTitle
Definition: console.h:17
ULONG AppNameLength
Definition: console.h:20
PWCHAR Desktop
Definition: console.h:19
PWCHAR AppName
Definition: console.h:21
HANDLE ConsoleHandle
Definition: consrv.h:45
LPTHREAD_START_ROUTINE CtrlRoutine
Definition: consrv.h:52
LPTHREAD_START_ROUTINE PropRoutine
Definition: consrv.h:53
HANDLE ProcessHandle
Definition: csrsrv.h:46
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
ULONG_PTR InheritedFromUniqueProcessId
Definition: pstypes.h:340
static CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo
Definition: video.c:47
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define TermChangeTitle(Console)
Definition: term.h:48
#define TermRefreshInternalInfo(Console)
Definition: term.h:46
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define MAXUSHORT
Definition: typedefs.h:83
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
uint16_t * PWCHAR
Definition: typedefs.h:56
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
PKPROCESS CsrProcess
Definition: videoprt.c:39
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
BYTE CodePageToCharSet(_In_ UINT CodePage)
Retrieves the character set associated with a given code page.
Definition: font.c:51
VOID ConCfgGetDefaultSettings(IN OUT PCONSOLE_STATE_INFO ConsoleInfo)
Definition: settings.c:491
BOOLEAN ConCfgReadUserSettings(IN OUT PCONSOLE_STATE_INFO ConsoleInfo, IN BOOLEAN DefaultSettings)
Definition: settings.c:167
struct _CONSOLE_STATE_INFO * PCONSOLE_STATE_INFO
struct _CONSOLE_STATE_INFO CONSOLE_STATE_INFO
VOID IntDeleteAllAliases(PCONSRV_CONSOLE Console)
Definition: alias.c:428
#define CON_API(Name, TYPE, RequestName)
Definition: api.h:80
#define CON_API_NOCONSOLE(Name, TYPE, RequestName)
Definition: api.h:39
BOOLEAN NTAPI ConDrvValidateConsoleState(IN PCONSOLE Console, IN CONSOLE_STATE ExpectedState)
Definition: console.c:24
VOID NTAPI ConDrvUnpause(PCONSOLE Console)
Definition: console.c:314
BOOLEAN NTAPI ConDrvValidateConsoleUnsafe(IN PCONSOLE Console, IN CONSOLE_STATE ExpectedState, IN BOOLEAN LockConsole)
Definition: console.c:36
VOID NTAPI ConDrvDeleteConsole(IN PCONSOLE Console)
Definition: console.c:218
NTSTATUS NTAPI ConDrvGetConsoleCP(IN PCONSOLE Console, OUT PUINT CodePage, IN BOOLEAN OutputCP)
Definition: console.c:411
NTSTATUS NTAPI ConDrvSetConsoleMode(IN PCONSOLE Console, IN PCONSOLE_IO_OBJECT Object, IN ULONG ConsoleMode)
Definition: console.c:357
NTSTATUS NTAPI ConDrvAttachTerminal(IN PCONSOLE Console, IN PTERMINAL Terminal)
Definition: console.c:160
NTSTATUS NTAPI ConDrvSetConsoleCP(IN PCONSOLE Console, IN UINT CodePage, IN BOOLEAN OutputCP)
Definition: console.c:424
NTSTATUS NTAPI ConDrvGetConsoleMode(IN PCONSOLE Console, IN PCONSOLE_IO_OBJECT Object, OUT PULONG ConsoleMode)
Definition: console.c:324
NTSTATUS NTAPI ConDrvInitConsole(IN OUT PCONSOLE Console, IN PCONSOLE_INFO ConsoleInfo)
Definition: console.c:69
VOID NTAPI ConDrvPause(PCONSOLE Console)
Definition: console.c:304
static VOID ConsoleFreeUnicodeString(IN PUNICODE_STRING UnicodeString)
Definition: console.c:234
VOID ConioUnpause(PCONSRV_CONSOLE Console, UCHAR Flags)
Definition: console.c:866
NTSTATUS NTAPI ConSrvSetConsoleProcessFocus(IN PCONSRV_CONSOLE Console, IN BOOLEAN SetForeground)
Definition: console.c:1453
VOID ConSrvSetProcessFocus(IN PCSR_PROCESS CsrProcess, IN BOOLEAN SetForeground)
Definition: console.c:1440
static BOOL LoadShellLinkConsoleInfo(IN OUT PCONSOLE_STATE_INFO ConsoleInfo, IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo)
Definition: console.c:370
BOOLEAN NTAPI ConSrvValidateConsole(OUT PCONSRV_CONSOLE *Console, IN HANDLE ConsoleHandle, IN CONSOLE_STATE ExpectedState, IN BOOLEAN LockConsole)
Definition: console.c:247
static NTSTATUS RemoveConsoleByPointer(IN PCONSRV_CONSOLE Console)
Definition: console.c:168
#define PATH_SEPARATOR
VOID NTAPI ConSrvInitConsoleSupport(VOID)
Definition: console.c:347
PCONSOLE_PROCESS_DATA NTAPI ConSrvGetConsoleLeaderProcess(IN PCONSRV_CONSOLE Console)
Definition: console.c:1363
NTSTATUS ConSrvConsoleCtrlEventTimeout(IN ULONG CtrlEvent, IN PCONSOLE_PROCESS_DATA ProcessData, IN ULONG Timeout)
Definition: console.c:1305
NTSTATUS NTAPI ConSrvConsoleProcessCtrlEvent(IN PCONSRV_CONSOLE Console, IN ULONG ProcessGroupId, IN ULONG CtrlEvent)
Definition: console.c:1402
NTSTATUS NTAPI ConSrvInitConsole(OUT PHANDLE NewConsoleHandle, OUT PCONSRV_CONSOLE *NewConsole, IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo, IN PCSR_PROCESS ConsoleLeaderProcess)
Definition: console.c:532
NTSTATUS ConSrvAllocateConsole(IN OUT PCONSOLE_PROCESS_DATA ProcessData, OUT PHANDLE pInputHandle, OUT PHANDLE pOutputHandle, OUT PHANDLE pErrorHandle, IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo)
Definition: console.c:968
static PCONSRV_CONSOLE * ConsoleList
Definition: console.c:34
VOID ConioPause(PCONSRV_CONSOLE Console, UCHAR Flags)
Definition: console.c:859
static NTSTATUS ConSrvInitProcessHandles(IN OUT PCONSOLE_PROCESS_DATA ProcessData, IN PCONSRV_CONSOLE Console, OUT PHANDLE pInputHandle, OUT PHANDLE pOutputHandle, OUT PHANDLE pErrorHandle)
Definition: console.c:890
NTSTATUS NTAPI ConSrvGetConsoleProcessList(IN PCONSRV_CONSOLE Console, IN OUT PULONG ProcessIdsList, IN ULONG MaxIdListItems, OUT PULONG ProcessIdsTotal)
Definition: console.c:1373
VOID ConSrvReleaseConsole(IN PCONSRV_CONSOLE Console, IN BOOLEAN IsConsoleLocked)
Definition: console.c:316
static RTL_RESOURCE ListLock
Definition: console.c:36
#define CONSOLE_VALID_CONTROL_MODES
NTSTATUS ConSrvRemoveConsole(IN OUT PCONSOLE_PROCESS_DATA ProcessData)
Definition: console.c:1227
#define ConSrvLockConsoleListExclusive()
Definition: console.c:38
NTSTATUS ConSrvConsoleCtrlEvent(IN ULONG CtrlEvent, IN PCONSOLE_PROCESS_DATA ProcessData)
Definition: console.c:1356
#define ConSrvUnlockConsoleList()
Definition: console.c:44
#define ConSrvLockConsoleListShared()
Definition: console.c:41
NTSTATUS ConSrvInheritConsole(IN OUT PCONSOLE_PROCESS_DATA ProcessData, IN HANDLE ConsoleHandle, IN BOOLEAN CreateNewHandleTable, OUT PHANDLE pInputHandle, OUT PHANDLE pOutputHandle, OUT PHANDLE pErrorHandle, IN OUT PCONSOLE_START_INFO ConsoleStartInfo)
Definition: console.c:1096
static ULONG ConsoleListSize
Definition: console.c:33
#define CONSOLE_HANDLES_INCREMENT
NTSTATUS NTAPI ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal)
Definition: terminal.c:237
NTSTATUS NTAPI ConSrvInitTerminal(IN OUT PTERMINAL Terminal, IN OUT PCONSOLE_STATE_INFO ConsoleInfo, IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo, IN HANDLE ConsoleLeaderProcessHandle)
Definition: terminal.c:204
static BOOLEAN ConsoleCreateUnicodeString(IN OUT PUNICODE_STRING UniDest, IN PCWSTR Source)
Definition: console.c:216
static NTSTATUS InsertConsole(OUT PHANDLE Handle, IN PCONSRV_CONSOLE Console)
Definition: console.c:72
NTSTATUS ConSrvGetConsole(IN PCONSOLE_PROCESS_DATA ProcessData, OUT PCONSRV_CONSOLE *Console, IN BOOLEAN LockConsole)
Definition: console.c:291
VOID NTAPI ConSrvDeleteConsole(PCONSRV_CONSOLE Console)
Definition: console.c:822
NTSTATUS ConSrvGetObject(IN PCONSOLE_PROCESS_DATA ProcessData, IN HANDLE Handle, OUT PCONSOLE_IO_OBJECT *Object, OUT PVOID *Entry OPTIONAL, IN ULONG Access, IN BOOLEAN LockConsole, IN CONSOLE_IO_OBJECT_TYPE Type)
Definition: handle.c:318
NTSTATUS ConSrvInsertObject(IN PCONSOLE_PROCESS_DATA ProcessData, OUT PHANDLE Handle, IN PCONSOLE_IO_OBJECT Object, IN ULONG Access, IN BOOLEAN Inheritable, IN ULONG ShareMode)
Definition: handle.c:227
VOID ConSrvFreeHandlesTable(IN PCONSOLE_PROCESS_DATA ProcessData)
Definition: handle.c:172
VOID ConSrvReleaseObject(IN PCONSOLE_IO_OBJECT Object, IN BOOLEAN IsConsoleLocked)
Definition: handle.c:382
#define ConsoleAllocHeap(Flags, Size)
Definition: heap.h:14
#define ConsoleFreeHeap(HeapBase)
Definition: heap.h:15
VOID HistoryDeleteBuffers(PCONSRV_CONSOLE Console)
Definition: history.c:357
@ INPUT_BUFFER
Definition: conio.h:28
@ CONSOLE_RUNNING
Definition: conio.h:283
#define IDS_CONSOLE_TITLE
Definition: resource.h:10
#define STARTF_USEPOSITION
Definition: winbase.h:493
#define STARTF_USECOUNTCHARS
Definition: winbase.h:494
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define STARTF_USEFILLATTRIBUTE
Definition: winbase.h:495
#define STARTF_RUNFULLSCREEN
Definition: winbase.h:496
#define STARTF_USESIZE
Definition: winbase.h:492
#define ATTACH_PARENT_PROCESS
Definition: wincon.h:21
#define ENABLE_QUICK_EDIT_MODE
Definition: wincon.h:84
#define ENABLE_EXTENDED_FLAGS
Definition: wincon.h:85
#define ENABLE_INSERT_MODE
Definition: wincon.h:83
#define CTRL_LAST_CLOSE_EVENT
Definition: wincon.h:71
UINT WINAPI GetACP(void)
Definition: nls.c:2307
UINT WINAPI GetOEMCP(void)
Definition: nls.c:2322
BOOL WINAPI GetKeyboardLayoutNameW(_Out_writes_(KL_NAMELENGTH) LPWSTR)
BOOL WINAPI GetKeyboardLayoutNameA(_Out_writes_(KL_NAMELENGTH) LPSTR)
#define SM_CMOUSEBUTTONS
Definition: winuser.h:1006
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
UINT WINAPI PrivateExtractIconsW(_In_reads_(MAX_PATH) LPCWSTR szFileName, _In_ int nIconIndex, _In_ int cxIcon, _In_ int cyIcon, _Out_writes_opt_(nIcons) HICON *phicon, _Out_writes_opt_(nIcons) UINT *piconid, _In_ UINT nIcons, _In_ UINT flags)
#define LR_COPYFROMRESOURCE
Definition: winuser.h:1099
int WINAPI GetSystemMetrics(_In_ int)
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define DUPLICATE_CLOSE_SOURCE
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193