2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: consrv/console.c
5 * PURPOSE: Console Management Functions
6 * PROGRAMMERS: Gé van Geldorp
8 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
11 /* INCLUDES *******************************************************************/
15 /* This is for COM usage */
27 // FIXME: Add this prototype to winternl.h / rtlfuncs.h / ...
28 NTSTATUS NTAPI
RtlGetLastNtStatus(VOID
);
30 /* GLOBALS ********************************************************************/
32 /* The list of the ConSrv consoles */
33 static ULONG ConsoleListSize
;
34 static PCONSRV_CONSOLE
* ConsoleList
;
35 static RTL_RESOURCE ListLock
;
37 #define ConSrvLockConsoleListExclusive() \
38 RtlAcquireResourceExclusive(&ListLock, TRUE)
40 #define ConSrvLockConsoleListShared() \
41 RtlAcquireResourceShared(&ListLock, TRUE)
43 #define ConSrvUnlockConsoleList() \
44 RtlReleaseResource(&ListLock)
48 InsertConsole(OUT PHANDLE Handle
,
49 IN PCONSRV_CONSOLE Console
)
51 #define CONSOLE_HANDLES_INCREMENT 2 * 3
53 NTSTATUS Status
= STATUS_SUCCESS
;
55 PCONSRV_CONSOLE
* Block
;
57 ASSERT( (ConsoleList
== NULL
&& ConsoleListSize
== 0) ||
58 (ConsoleList
!= NULL
&& ConsoleListSize
!= 0) );
60 /* All went right, so add the console to the list */
61 ConSrvLockConsoleListExclusive();
62 DPRINT("Insert in the list\n");
66 for (i
= 0; i
< ConsoleListSize
; i
++)
68 if (ConsoleList
[i
] == NULL
) break;
72 if (i
>= ConsoleListSize
)
74 DPRINT("Creation of a new handles table\n");
75 /* Allocate a new handles table */
76 Block
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
,
78 CONSOLE_HANDLES_INCREMENT
) * sizeof(PCONSRV_CONSOLE
));
81 Status
= STATUS_UNSUCCESSFUL
;
85 /* If we previously had a handles table, free it and use the new one */
88 /* Copy the handles from the old table to the new one */
91 ConsoleListSize
* sizeof(PCONSRV_CONSOLE
));
92 ConsoleFreeHeap(ConsoleList
);
95 ConsoleListSize
+= CONSOLE_HANDLES_INCREMENT
;
98 ConsoleList
[i
] = Console
;
99 *Handle
= ULongToHandle((i
<< 2) | 0x3);
102 /* Unlock the console list and return status */
103 ConSrvUnlockConsoleList();
110 RemoveConsoleByHandle(IN HANDLE Handle
)
112 NTSTATUS Status
= STATUS_SUCCESS
;
113 PCONSRV_CONSOLE Console
;
115 BOOLEAN ValidHandle
= ((HandleToULong(Handle
) & 0x3) == 0x3);
116 ULONG Index
= HandleToULong(Handle
) >> 2;
118 if (!ValidHandle
) return STATUS_INVALID_HANDLE
;
120 ASSERT( (ConsoleList
== NULL
&& ConsoleListSize
== 0) ||
121 (ConsoleList
!= NULL
&& ConsoleListSize
!= 0) );
123 /* Remove the console from the list */
124 ConSrvLockConsoleListExclusive();
126 if (Index
>= ConsoleListSize
||
127 (Console
= ConsoleList
[Index
]) == NULL
)
129 Status
= STATUS_INVALID_HANDLE
;
133 ConsoleList
[Index
] = NULL
;
136 /* Unlock the console list and return status */
137 ConSrvUnlockConsoleList();
143 RemoveConsoleByPointer(IN PCONSRV_CONSOLE Console
)
147 if (!Console
) return STATUS_INVALID_PARAMETER
;
149 ASSERT( (ConsoleList
== NULL
&& ConsoleListSize
== 0) ||
150 (ConsoleList
!= NULL
&& ConsoleListSize
!= 0) );
152 /* Remove the console from the list */
153 ConSrvLockConsoleListExclusive();
157 for (i
= 0; i
< ConsoleListSize
; i
++)
159 if (ConsoleList
[i
] == Console
) ConsoleList
[i
] = NULL
;
163 /* Unlock the console list and return */
164 ConSrvUnlockConsoleList();
165 return STATUS_SUCCESS
;
169 ConSrvValidateConsole(OUT PCONSRV_CONSOLE
* Console
,
170 IN HANDLE ConsoleHandle
,
171 IN CONSOLE_STATE ExpectedState
,
172 IN BOOLEAN LockConsole
)
174 BOOLEAN RetVal
= FALSE
;
175 PCONSRV_CONSOLE ValidatedConsole
;
177 BOOLEAN ValidHandle
= ((HandleToULong(ConsoleHandle
) & 0x3) == 0x3);
178 ULONG Index
= HandleToULong(ConsoleHandle
) >> 2;
180 if (!ValidHandle
) return FALSE
;
182 if (!Console
) return FALSE
;
186 * Forbid creation or deletion of consoles when
187 * checking for the existence of a console.
189 ConSrvLockConsoleListShared();
191 if (Index
>= ConsoleListSize
||
192 (ValidatedConsole
= ConsoleList
[Index
]) == NULL
)
194 /* Unlock the console list and return */
195 ConSrvUnlockConsoleList();
199 ValidatedConsole
= ConsoleList
[Index
];
201 /* Unlock the console list and return */
202 ConSrvUnlockConsoleList();
204 RetVal
= ConDrvValidateConsoleUnsafe((PCONSOLE
)ValidatedConsole
,
207 if (RetVal
) *Console
= ValidatedConsole
;
213 /* PRIVATE FUNCTIONS **********************************************************/
215 // Adapted from reactos/lib/rtl/unicode.c, RtlCreateUnicodeString line 2180
217 ConsoleCreateUnicodeString(IN OUT PUNICODE_STRING UniDest
,
220 SIZE_T Size
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
221 if (Size
> MAXUSHORT
) return FALSE
;
223 UniDest
->Buffer
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, Size
);
224 if (UniDest
->Buffer
== NULL
) return FALSE
;
226 RtlCopyMemory(UniDest
->Buffer
, Source
, Size
);
227 UniDest
->MaximumLength
= (USHORT
)Size
;
228 UniDest
->Length
= (USHORT
)Size
- sizeof(WCHAR
);
233 // Adapted from reactos/lib/rtl/unicode.c, RtlFreeUnicodeString line 431
235 ConsoleFreeUnicodeString(IN PUNICODE_STRING UnicodeString
)
237 if (UnicodeString
->Buffer
)
239 ConsoleFreeHeap(UnicodeString
->Buffer
);
240 RtlZeroMemory(UnicodeString
, sizeof(UNICODE_STRING
));
245 ConioPause(PCONSRV_CONSOLE Console
, UINT Flags
)
247 Console
->PauseFlags
|= Flags
;
248 ConDrvPause((PCONSOLE
)Console
);
252 ConioUnpause(PCONSRV_CONSOLE Console
, UINT Flags
)
254 Console
->PauseFlags
&= ~Flags
;
256 // if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0)
257 if (Console
->PauseFlags
== 0)
259 ConDrvUnpause((PCONSOLE
)Console
);
261 CsrNotifyWait(&Console
->WriteWaitQueue
,
265 if (!IsListEmpty(&Console
->WriteWaitQueue
))
267 CsrDereferenceWait(&Console
->WriteWaitQueue
);
273 ConSrvGetConsole(IN PCONSOLE_PROCESS_DATA ProcessData
,
274 OUT PCONSRV_CONSOLE
* Console
,
275 IN BOOLEAN LockConsole
)
277 NTSTATUS Status
= STATUS_INVALID_HANDLE
;
278 PCONSRV_CONSOLE GrabConsole
;
280 // if (Console == NULL) return STATUS_INVALID_PARAMETER;
284 if (ConSrvValidateConsole(&GrabConsole
,
285 ProcessData
->ConsoleHandle
,
289 InterlockedIncrement(&GrabConsole
->ReferenceCount
);
290 *Console
= GrabConsole
;
291 Status
= STATUS_SUCCESS
;
298 ConSrvReleaseConsole(IN PCONSRV_CONSOLE Console
,
299 IN BOOLEAN WasConsoleLocked
)
303 if (!Console
) return;
304 // if (Console->ReferenceCount == 0) return; // This shouldn't happen
305 ASSERT(Console
->ReferenceCount
> 0);
307 /* The console must be locked */
308 // ASSERT(Console_locked);
311 * Decrement the reference count. Save the new value too,
312 * because Console->ReferenceCount might be modified after
313 * the console gets unlocked but before we check whether we
316 RefCount
= _InterlockedDecrement(&Console
->ReferenceCount
);
318 /* Unlock the console if needed */
319 if (WasConsoleLocked
) LeaveCriticalSection(&Console
->Lock
);
321 /* Delete the console if needed */
322 if (RefCount
<= 0) ConSrvDeleteConsole(Console
);
326 /* CONSOLE INITIALIZATION FUNCTIONS *******************************************/
329 ConSrvInitConsoleSupport(VOID
)
331 DPRINT("CONSRV: ConSrvInitConsoleSupport()\n");
333 /* Initialize the console list and its lock */
336 RtlInitializeResource(&ListLock
);
338 /* Should call LoadKeyboardLayout */
342 ConSrvInitTerminal(IN OUT PTERMINAL Terminal
,
343 IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
344 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo
,
345 IN HANDLE ConsoleLeaderProcessHandle
);
347 ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal
);
351 LoadShellLinkConsoleInfo(IN OUT PCONSOLE_STATE_INFO ConsoleInfo
,
352 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo
)
354 #define PATH_SEPARATOR L'\\'
359 LPWSTR LinkName
= NULL
;
360 LPWSTR IconPath
= NULL
;
361 WCHAR Buffer
[MAX_PATH
+ 1];
363 ConsoleInitInfo
->ConsoleStartInfo
->IconIndex
= 0;
365 if ((ConsoleInitInfo
->ConsoleStartInfo
->dwStartupFlags
& STARTF_TITLEISLINKNAME
) == 0)
367 // return FALSE; // FIXME!! (for icon loading)
372 /* 1- Find the last path separator if any */
373 LinkName
= wcsrchr(ConsoleInfo
->ConsoleTitle
, PATH_SEPARATOR
);
374 if (LinkName
== NULL
)
375 LinkName
= ConsoleInfo
->ConsoleTitle
;
377 ++LinkName
; // Skip the path separator
379 /* 2- Check for the link extension. The name ".lnk" is considered invalid. */
380 Length
= wcslen(LinkName
);
381 if ( (Length
<= 4) || (wcsicmp(LinkName
+ (Length
- 4), L
".lnk") != 0) )
384 /* 3- It may be a link. Try to retrieve some properties */
385 hRes
= CoInitialize(NULL
);
388 /* Get a pointer to the IShellLink interface */
389 IShellLinkW
* pshl
= NULL
;
390 hRes
= CoCreateInstance(&CLSID_ShellLink
,
392 CLSCTX_INPROC_SERVER
,
397 /* Get a pointer to the IPersistFile interface */
398 IPersistFile
* ppf
= NULL
;
399 hRes
= IPersistFile_QueryInterface(pshl
, &IID_IPersistFile
, (LPVOID
*)&ppf
);
402 /* Load the shortcut */
403 hRes
= IPersistFile_Load(ppf
, ConsoleInfo
->ConsoleTitle
, STGM_READ
);
407 * Finally we can get the properties !
408 * Update the old ones if needed.
413 /* Reset the name of the console with the name of the shortcut */
414 Length
= min(/*Length*/ Length
- 4, // 4 == len(".lnk")
415 (ConsoleInfo
->cbSize
- FIELD_OFFSET(CONSOLE_STATE_INFO
, ConsoleTitle
) - sizeof(UNICODE_NULL
)) / sizeof(WCHAR
));
416 wcsncpy(ConsoleInfo
->ConsoleTitle
, LinkName
, Length
);
417 ConsoleInfo
->ConsoleTitle
[Length
] = UNICODE_NULL
;
419 /* Get the window showing command */
420 hRes
= IShellLinkW_GetShowCmd(pshl
, &ShowCmd
);
421 if (SUCCEEDED(hRes
)) ConsoleInitInfo
->ConsoleStartInfo
->wShowWindow
= (WORD
)ShowCmd
;
424 // hRes = pshl->GetHotkey(&ShowCmd);
425 // if (SUCCEEDED(hRes)) ConsoleInitInfo->ConsoleStartInfo->HotKey = HotKey;
427 /* Get the icon location, if any */
428 hRes
= IShellLinkW_GetIconLocation(pshl
,
430 sizeof(Buffer
)/sizeof(Buffer
[0]) - 1, // == MAX_PATH
431 &ConsoleInitInfo
->ConsoleStartInfo
->IconIndex
);
432 if (!SUCCEEDED(hRes
))
434 ConsoleInitInfo
->ConsoleStartInfo
->IconIndex
= 0;
441 // FIXME: Since we still don't load console properties from the shortcut,
442 // return false. When this will be done, we will return true instead.
443 RetVal
= TRUE
; // FALSE;
445 IPersistFile_Release(ppf
);
447 IShellLinkW_Release(pshl
);
456 /* Get the associated icon, if any */
457 if (IconPath
== NULL
)
459 // Question: How to retrieve the full path name
460 // of the app we are going to run??
461 Length
= RtlDosSearchPath_U(ConsoleInitInfo
->CurDir
,
462 ConsoleInitInfo
->AppName
,
467 if (Length
> 0 && Length
< sizeof(Buffer
))
470 IconPath
= ConsoleInitInfo
->AppName
;
472 // ConsoleInitInfo->ConsoleStartInfo->IconIndex = 0;
474 DPRINT("IconPath = '%S' ; IconIndex = %lu\n",
475 IconPath
, ConsoleInitInfo
->ConsoleStartInfo
->IconIndex
);
476 if (IconPath
&& *IconPath
)
478 HICON hIcon
= NULL
, hIconSm
= NULL
;
480 * FIXME!! Because of a strange bug we have in PrivateExtractIconExW
481 * (see r65683 for more details), we cannot use this API to extract
482 * at the same time the large and small icons from the app.
483 * Instead we just use PrivateExtractIconsW.
485 PrivateExtractIconExW(IconPath,
486 ConsoleInitInfo->ConsoleStartInfo->IconIndex,
491 PrivateExtractIconsW(IconPath
,
492 ConsoleInitInfo
->ConsoleStartInfo
->IconIndex
,
494 &hIcon
, NULL
, 1, LR_COPYFROMRESOURCE
);
495 PrivateExtractIconsW(IconPath
,
496 ConsoleInitInfo
->ConsoleStartInfo
->IconIndex
,
498 &hIconSm
, NULL
, 1, LR_COPYFROMRESOURCE
);
500 DPRINT("hIcon = 0x%p ; hIconSm = 0x%p\n", hIcon
, hIconSm
);
501 if (hIcon
!= NULL
) ConsoleInitInfo
->ConsoleStartInfo
->hIcon
= hIcon
;
502 if (hIconSm
!= NULL
) ConsoleInitInfo
->ConsoleStartInfo
->hIconSm
= hIconSm
;
506 // FIXME: See the previous FIXME above.
513 ConSrvInitConsole(OUT PHANDLE NewConsoleHandle
,
514 OUT PCONSRV_CONSOLE
* NewConsole
,
515 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo
,
516 IN PCSR_PROCESS ConsoleLeaderProcess
)
519 HANDLE ConsoleHandle
;
520 PCONSRV_CONSOLE Console
;
522 BYTE ConsoleInfoBuffer
[sizeof(CONSOLE_STATE_INFO
) + MAX_PATH
* sizeof(WCHAR
)]; // CONSRV console information
523 PCONSOLE_STATE_INFO ConsoleInfo
= (PCONSOLE_STATE_INFO
)&ConsoleInfoBuffer
;
524 CONSOLE_INFO DrvConsoleInfo
; // Console information for CONDRV
528 TERMINAL Terminal
; /* The ConSrv terminal for this console */
530 if (NewConsole
== NULL
|| ConsoleInitInfo
== NULL
)
531 return STATUS_INVALID_PARAMETER
;
536 * Load the console settings
539 /* Impersonate the caller in order to retrieve settings in its context */
540 if (!CsrImpersonateClient(NULL
))
541 return STATUS_BAD_IMPERSONATION_LEVEL
;
543 /* 1. Load the default settings */
544 RtlZeroMemory(ConsoleInfo
, sizeof(ConsoleInfoBuffer
));
545 ConsoleInfo
->cbSize
= sizeof(ConsoleInfoBuffer
);
546 ConCfgGetDefaultSettings(ConsoleInfo
);
548 /* 2. Get the title of the console (initialize ConsoleInfo->ConsoleTitle) */
549 Length
= min(ConsoleInitInfo
->TitleLength
,
550 (ConsoleInfo
->cbSize
- FIELD_OFFSET(CONSOLE_STATE_INFO
, ConsoleTitle
) - sizeof(UNICODE_NULL
)) / sizeof(WCHAR
));
551 wcsncpy(ConsoleInfo
->ConsoleTitle
, ConsoleInitInfo
->ConsoleTitle
, Length
);
552 ConsoleInfo
->ConsoleTitle
[Length
] = UNICODE_NULL
; // NULL-terminate it.
555 * 3. Load per-application terminal settings.
557 * Check whether the process creating the console was launched via
558 * a shell-link. ConsoleInfo->ConsoleTitle may be updated with the
559 * name of the shortcut, and ConsoleStartInfo->Icon[Path|Index] too.
561 // if (ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) // FIXME!! (for icon loading)
563 if (!LoadShellLinkConsoleInfo(ConsoleInfo
, ConsoleInitInfo
))
565 ConsoleInitInfo
->ConsoleStartInfo
->dwStartupFlags
&= ~STARTF_TITLEISLINKNAME
;
570 * 4. Load the remaining console settings via the registry.
572 if ((ConsoleInitInfo
->ConsoleStartInfo
->dwStartupFlags
& STARTF_TITLEISLINKNAME
) == 0)
575 * Either we weren't created by an app launched via a shell-link,
576 * or we failed to load shell-link console properties.
577 * Therefore, load the console infos for the application from the registry.
579 ConCfgReadUserSettings(ConsoleInfo
);
582 * Now, update them with the properties the user might gave to us
583 * via the STARTUPINFO structure before calling CreateProcess
584 * (and which was transmitted via the ConsoleStartInfo structure).
585 * We therefore overwrite the values read in the registry.
587 if (ConsoleInitInfo
->ConsoleStartInfo
->dwStartupFlags
& STARTF_USEFILLATTRIBUTE
)
589 ConsoleInfo
->ScreenAttributes
= (USHORT
)ConsoleInitInfo
->ConsoleStartInfo
->wFillAttribute
;
591 if (ConsoleInitInfo
->ConsoleStartInfo
->dwStartupFlags
& STARTF_USECOUNTCHARS
)
593 ConsoleInfo
->ScreenBufferSize
= ConsoleInitInfo
->ConsoleStartInfo
->dwScreenBufferSize
;
595 if (ConsoleInitInfo
->ConsoleStartInfo
->dwStartupFlags
& STARTF_USESIZE
)
597 ConsoleInfo
->WindowSize
= ConsoleInitInfo
->ConsoleStartInfo
->dwWindowSize
;
602 * Now, update them with the properties the user might gave to us
603 * via the STARTUPINFO structure before calling CreateProcess
604 * (and which was transmitted via the ConsoleStartInfo structure).
605 * We therefore overwrite the values read in the registry.
607 if (ConsoleInitInfo
->ConsoleStartInfo
->dwStartupFlags
& STARTF_USEPOSITION
)
609 ConsoleInfo
->AutoPosition
= FALSE
;
610 ConsoleInfo
->WindowPosition
.x
= ConsoleInitInfo
->ConsoleStartInfo
->dwWindowOrigin
.X
;
611 ConsoleInfo
->WindowPosition
.y
= ConsoleInitInfo
->ConsoleStartInfo
->dwWindowOrigin
.Y
;
613 if (ConsoleInitInfo
->ConsoleStartInfo
->dwStartupFlags
& STARTF_RUNFULLSCREEN
)
615 ConsoleInfo
->FullScreen
= TRUE
;
620 /* Revert impersonation */
623 /* Set-up the code page */
624 ConsoleInfo
->CodePage
= GetOEMCP();
627 * Initialize the ConSrv terminal and give it a chance to load
628 * its own settings and override the console settings.
630 Status
= ConSrvInitTerminal(&Terminal
,
633 ConsoleLeaderProcess
->ProcessHandle
);
634 if (!NT_SUCCESS(Status
))
636 DPRINT1("CONSRV: Failed to initialize a terminal, Status = 0x%08lx\n", Status
);
639 DPRINT("CONSRV: Terminal initialized\n");
641 /* Initialize a new console via the driver */
642 // DrvConsoleInfo.InputBufferSize = 0;
643 DrvConsoleInfo
.ScreenBufferSize
= ConsoleInfo
->ScreenBufferSize
;
644 DrvConsoleInfo
.ConsoleSize
= ConsoleInfo
->WindowSize
;
645 DrvConsoleInfo
.CursorSize
= ConsoleInfo
->CursorSize
;
646 // DrvConsoleInfo.CursorBlinkOn = ConsoleInfo->CursorBlinkOn;
647 DrvConsoleInfo
.ScreenAttrib
= ConsoleInfo
->ScreenAttributes
;
648 DrvConsoleInfo
.PopupAttrib
= ConsoleInfo
->PopupAttributes
;
649 DrvConsoleInfo
.CodePage
= ConsoleInfo
->CodePage
;
650 Status
= ConDrvInitConsole(&Console
, &DrvConsoleInfo
);
651 if (!NT_SUCCESS(Status
))
653 DPRINT1("Creating a new console failed, Status = 0x%08lx\n", Status
);
654 ConSrvDeinitTerminal(&Terminal
);
659 DPRINT("Console initialized\n");
661 /*** Register ConSrv features ***/
663 /* Initialize the console title */
665 WCHAR DefaultTitle
[128];
667 ConsoleCreateUnicodeString(&Console
->OriginalTitle
, ConsoleInfo
->ConsoleTitle
);
669 if (ConsoleInfo
->ConsoleTitle
[0] == UNICODE_NULL
)
671 if (LoadStringW(ConSrvDllInstance
, IDS_CONSOLE_TITLE
, DefaultTitle
, sizeof(DefaultTitle
) / sizeof(DefaultTitle
[0])))
673 ConsoleCreateUnicodeString(&Console
->Title
, DefaultTitle
);
677 ConsoleCreateUnicodeString(&Console
->Title
, L
"ReactOS Console");
683 ConsoleCreateUnicodeString(&Console
->Title
, ConsoleInfo
->ConsoleTitle
);
688 /* Initialize process support */
689 InitializeListHead(&Console
->ProcessList
);
690 Console
->NotifiedLastCloseProcess
= NULL
;
691 Console
->NotifyLastClose
= FALSE
;
693 /* Initialize pausing support */
694 Console
->PauseFlags
= 0;
695 InitializeListHead(&Console
->ReadWaitQueue
);
696 InitializeListHead(&Console
->WriteWaitQueue
);
698 /* Initialize the alias and history buffers */
699 Console
->Aliases
= NULL
;
700 InitializeListHead(&Console
->HistoryBuffers
);
701 Console
->HistoryBufferSize
= ConsoleInfo
->HistoryBufferSize
;
702 Console
->NumberOfHistoryBuffers
= ConsoleInfo
->NumberOfHistoryBuffers
;
703 Console
->HistoryNoDup
= ConsoleInfo
->HistoryNoDup
;
705 /* Initialize the Input Line Discipline */
706 Console
->LineBuffer
= NULL
;
707 Console
->LinePos
= Console
->LineMaxSize
= Console
->LineSize
= 0;
708 Console
->LineComplete
= Console
->LineUpPressed
= FALSE
;
710 Console
->LineInsertToggle
=
711 Console
->InsertMode
= ConsoleInfo
->InsertMode
;
712 Console
->QuickEdit
= ConsoleInfo
->QuickEdit
;
715 InitializeListHead(&Console
->PopupWindows
);
718 RtlCopyMemory(Console
->Colors
, ConsoleInfo
->ColorTable
,
719 sizeof(ConsoleInfo
->ColorTable
));
721 /* Create the Initialization Events */
722 Status
= NtCreateEvent(&Console
->InitEvents
[INIT_SUCCESS
], EVENT_ALL_ACCESS
,
723 NULL
, NotificationEvent
, FALSE
);
724 if (!NT_SUCCESS(Status
))
726 DPRINT1("NtCreateEvent(InitEvents[INIT_SUCCESS]) failed: %lu\n", Status
);
727 ConDrvDeleteConsole(Console
);
728 ConSrvDeinitTerminal(&Terminal
);
731 Status
= NtCreateEvent(&Console
->InitEvents
[INIT_FAILURE
], EVENT_ALL_ACCESS
,
732 NULL
, NotificationEvent
, FALSE
);
733 if (!NT_SUCCESS(Status
))
735 DPRINT1("NtCreateEvent(InitEvents[INIT_FAILURE]) failed: %lu\n", Status
);
736 NtClose(Console
->InitEvents
[INIT_SUCCESS
]);
737 ConDrvDeleteConsole(Console
);
738 ConSrvDeinitTerminal(&Terminal
);
743 * Attach the ConSrv terminal to the console.
744 * This call makes a copy of our local Terminal variable.
746 Status
= ConDrvAttachTerminal(Console
, &Terminal
);
747 if (!NT_SUCCESS(Status
))
749 DPRINT1("Failed to register terminal to the given console, Status = 0x%08lx\n", Status
);
750 NtClose(Console
->InitEvents
[INIT_FAILURE
]);
751 NtClose(Console
->InitEvents
[INIT_SUCCESS
]);
752 ConDrvDeleteConsole(Console
);
753 ConSrvDeinitTerminal(&Terminal
);
756 DPRINT("Terminal attached\n");
758 /* All went right, so add the console to the list */
759 Status
= InsertConsole(&ConsoleHandle
, Console
);
761 // FIXME! We do not support at all asynchronous console creation!
762 NtSetEvent(Console
->InitEvents
[INIT_SUCCESS
], NULL
);
763 // NtSetEvent(Console->InitEvents[INIT_FAILURE], NULL);
765 /* Return the newly created console to the caller and a success code too */
766 *NewConsoleHandle
= ConsoleHandle
;
767 *NewConsole
= Console
;
768 return STATUS_SUCCESS
;
772 ConSrvDeleteConsole(PCONSRV_CONSOLE Console
)
774 DPRINT("ConSrvDeleteConsole\n");
776 // FIXME: Send a terminate message to all the processes owning this console
778 /* Remove the console from the list */
779 RemoveConsoleByPointer(Console
);
781 /* Destroy the Initialization Events */
782 NtClose(Console
->InitEvents
[INIT_FAILURE
]);
783 NtClose(Console
->InitEvents
[INIT_SUCCESS
]);
785 /* Clean the Input Line Discipline */
786 if (Console
->LineBuffer
) ConsoleFreeHeap(Console
->LineBuffer
);
788 /* Clean aliases and history */
789 IntDeleteAllAliases(Console
);
790 HistoryDeleteBuffers(Console
);
792 /* Free the console title */
793 ConsoleFreeUnicodeString(&Console
->OriginalTitle
);
794 ConsoleFreeUnicodeString(&Console
->Title
);
796 /* Now, call the driver. ConDrvDetachTerminal is called on-demand. */
797 ConDrvDeleteConsole((PCONSOLE
)Console
);
799 /* Deinit the ConSrv terminal */
801 // ConSrvDeinitTerminal(&Terminal);
810 ConSrvConsoleCtrlEventTimeout(IN ULONG CtrlEvent
,
811 IN PCONSOLE_PROCESS_DATA ProcessData
,
814 NTSTATUS Status
= STATUS_SUCCESS
;
816 DPRINT("ConSrvConsoleCtrlEventTimeout Parent ProcessId = %x\n", ProcessData
->Process
->ClientId
.UniqueProcess
);
819 * Be sure we effectively have a control routine. It resides in kernel32.dll (client).
821 if (ProcessData
->CtrlRoutine
== NULL
) return Status
;
825 HANDLE Thread
= NULL
;
829 Thread
= CreateRemoteThread(ProcessData
->Process
->ProcessHandle
, NULL
, 0,
830 ProcessData
->CtrlRoutine
,
831 UlongToPtr(CtrlEvent
), 0, NULL
);
834 Status
= RtlGetLastNtStatus();
835 DPRINT1("Failed thread creation, Status = 0x%08lx\n", Status
);
839 DPRINT("ProcessData->CtrlRoutine remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n",
840 ProcessData
->Process
->ClientId
.UniqueProcess
, ProcessData
->Process
);
841 WaitForSingleObject(Thread
, Timeout
);
850 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
852 Status
= _SEH2_GetExceptionCode();
853 DPRINT1("ConSrvConsoleCtrlEventTimeout - Caught an exception, Status = 0x%08lx\n", Status
);
861 ConSrvConsoleCtrlEvent(IN ULONG CtrlEvent
,
862 IN PCONSOLE_PROCESS_DATA ProcessData
)
864 return ConSrvConsoleCtrlEventTimeout(CtrlEvent
, ProcessData
, 0);
867 PCONSOLE_PROCESS_DATA NTAPI
868 ConSrvGetConsoleLeaderProcess(IN PCONSRV_CONSOLE Console
)
870 if (Console
== NULL
) return NULL
;
872 return CONTAINING_RECORD(Console
->ProcessList
.Blink
,
873 CONSOLE_PROCESS_DATA
,
878 ConSrvGetConsoleProcessList(IN PCONSRV_CONSOLE Console
,
879 IN OUT PULONG ProcessIdsList
,
880 IN ULONG MaxIdListItems
,
881 OUT PULONG ProcessIdsTotal
)
883 PCONSOLE_PROCESS_DATA current
;
884 PLIST_ENTRY current_entry
;
886 if (Console
== NULL
|| ProcessIdsList
== NULL
|| ProcessIdsTotal
== NULL
)
887 return STATUS_INVALID_PARAMETER
;
889 *ProcessIdsTotal
= 0;
891 for (current_entry
= Console
->ProcessList
.Flink
;
892 current_entry
!= &Console
->ProcessList
;
893 current_entry
= current_entry
->Flink
)
895 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
896 if (++(*ProcessIdsTotal
) <= MaxIdListItems
)
898 *ProcessIdsList
++ = HandleToUlong(current
->Process
->ClientId
.UniqueProcess
);
902 return STATUS_SUCCESS
;
905 // ConSrvGenerateConsoleCtrlEvent
907 ConSrvConsoleProcessCtrlEvent(IN PCONSRV_CONSOLE Console
,
908 IN ULONG ProcessGroupId
,
911 NTSTATUS Status
= STATUS_SUCCESS
;
912 PLIST_ENTRY current_entry
;
913 PCONSOLE_PROCESS_DATA current
;
915 /* If the console is already being destroyed, just return */
916 if (!ConDrvValidateConsoleState((PCONSOLE
)Console
, CONSOLE_RUNNING
))
917 return STATUS_UNSUCCESSFUL
;
920 * Loop through the process list, from the most recent process
921 * (the active one) to the oldest one (the first created, i.e.
922 * the console leader process), and for each, send an event
923 * (new processes are inserted at the head of the console process list).
925 current_entry
= Console
->ProcessList
.Flink
;
926 while (current_entry
!= &Console
->ProcessList
)
928 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
929 current_entry
= current_entry
->Flink
;
932 * Only processes belonging to the same process group are signaled.
933 * If the process group ID is zero, then all the processes are signaled.
935 if (ProcessGroupId
== 0 || current
->Process
->ProcessGroupId
== ProcessGroupId
)
937 Status
= ConSrvConsoleCtrlEvent(CtrlEvent
, current
);
945 /* PUBLIC SERVER APIS *********************************************************/
947 CSR_API(SrvAllocConsole
)
949 NTSTATUS Status
= STATUS_SUCCESS
;
950 PCONSOLE_ALLOCCONSOLE AllocConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.AllocConsoleRequest
;
951 PCSR_PROCESS CsrProcess
= CsrGetClientThread()->Process
;
952 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrProcess
);
953 CONSOLE_INIT_INFO ConsoleInitInfo
;
955 if (ProcessData
->ConsoleHandle
!= NULL
)
957 DPRINT1("Process already has a console\n");
958 return STATUS_ACCESS_DENIED
;
961 if ( !CsrValidateMessageBuffer(ApiMessage
,
962 (PVOID
*)&AllocConsoleRequest
->ConsoleStartInfo
,
964 sizeof(CONSOLE_START_INFO
)) ||
965 !CsrValidateMessageBuffer(ApiMessage
,
966 (PVOID
*)&AllocConsoleRequest
->ConsoleTitle
,
967 AllocConsoleRequest
->TitleLength
,
969 !CsrValidateMessageBuffer(ApiMessage
,
970 (PVOID
*)&AllocConsoleRequest
->Desktop
,
971 AllocConsoleRequest
->DesktopLength
,
973 !CsrValidateMessageBuffer(ApiMessage
,
974 (PVOID
*)&AllocConsoleRequest
->CurDir
,
975 AllocConsoleRequest
->CurDirLength
,
977 !CsrValidateMessageBuffer(ApiMessage
,
978 (PVOID
*)&AllocConsoleRequest
->AppName
,
979 AllocConsoleRequest
->AppNameLength
,
982 return STATUS_INVALID_PARAMETER
;
985 /* Initialize the console initialization info structure */
986 ConsoleInitInfo
.ConsoleStartInfo
= AllocConsoleRequest
->ConsoleStartInfo
;
987 ConsoleInitInfo
.IsWindowVisible
= TRUE
; // The console window is always visible.
988 ConsoleInitInfo
.TitleLength
= AllocConsoleRequest
->TitleLength
;
989 ConsoleInitInfo
.ConsoleTitle
= AllocConsoleRequest
->ConsoleTitle
;
990 ConsoleInitInfo
.DesktopLength
= AllocConsoleRequest
->DesktopLength
;
991 ConsoleInitInfo
.Desktop
= AllocConsoleRequest
->Desktop
;
992 ConsoleInitInfo
.AppNameLength
= AllocConsoleRequest
->AppNameLength
;
993 ConsoleInitInfo
.AppName
= AllocConsoleRequest
->AppName
;
994 ConsoleInitInfo
.CurDirLength
= AllocConsoleRequest
->CurDirLength
;
995 ConsoleInitInfo
.CurDir
= AllocConsoleRequest
->CurDir
;
997 /* Initialize a new Console owned by the Console Leader Process */
998 Status
= ConSrvAllocateConsole(ProcessData
,
999 &AllocConsoleRequest
->ConsoleStartInfo
->InputHandle
,
1000 &AllocConsoleRequest
->ConsoleStartInfo
->OutputHandle
,
1001 &AllocConsoleRequest
->ConsoleStartInfo
->ErrorHandle
,
1003 if (!NT_SUCCESS(Status
))
1005 DPRINT1("Console allocation failed\n");
1009 /* Set the Property-Dialog and Control-Dispatcher handlers */
1010 ProcessData
->PropRoutine
= AllocConsoleRequest
->PropRoutine
;
1011 ProcessData
->CtrlRoutine
= AllocConsoleRequest
->CtrlRoutine
;
1013 return STATUS_SUCCESS
;
1016 CSR_API(SrvAttachConsole
)
1018 NTSTATUS Status
= STATUS_SUCCESS
;
1019 PCONSOLE_ATTACHCONSOLE AttachConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.AttachConsoleRequest
;
1020 PCSR_PROCESS SourceProcess
= NULL
; // The parent process.
1021 PCSR_PROCESS TargetProcess
= CsrGetClientThread()->Process
; // Ourselves.
1022 HANDLE ProcessId
= ULongToHandle(AttachConsoleRequest
->ProcessId
);
1023 PCONSOLE_PROCESS_DATA SourceProcessData
, TargetProcessData
;
1025 TargetProcessData
= ConsoleGetPerProcessData(TargetProcess
);
1027 if (TargetProcessData
->ConsoleHandle
!= NULL
)
1029 DPRINT1("Process already has a console\n");
1030 return STATUS_ACCESS_DENIED
;
1033 if (!CsrValidateMessageBuffer(ApiMessage
,
1034 (PVOID
*)&AttachConsoleRequest
->ConsoleStartInfo
,
1036 sizeof(CONSOLE_START_INFO
)))
1038 return STATUS_INVALID_PARAMETER
;
1041 /* Check whether we try to attach to the parent's console */
1042 if (ProcessId
== ULongToHandle(ATTACH_PARENT_PROCESS
))
1044 PROCESS_BASIC_INFORMATION ProcessInfo
;
1045 ULONG Length
= sizeof(ProcessInfo
);
1047 /* Get the real parent's ID */
1049 Status
= NtQueryInformationProcess(TargetProcess
->ProcessHandle
,
1050 ProcessBasicInformation
,
1053 if (!NT_SUCCESS(Status
))
1055 DPRINT1("SrvAttachConsole - Cannot retrieve basic process info, Status = 0x%08lx\n", Status
);
1059 ProcessId
= ULongToHandle(ProcessInfo
.InheritedFromUniqueProcessId
);
1062 /* Lock the source process via its PID */
1063 Status
= CsrLockProcessByClientId(ProcessId
, &SourceProcess
);
1064 if (!NT_SUCCESS(Status
)) return Status
;
1066 SourceProcessData
= ConsoleGetPerProcessData(SourceProcess
);
1068 if (SourceProcessData
->ConsoleHandle
== NULL
)
1070 Status
= STATUS_INVALID_HANDLE
;
1075 * Inherit the console from the parent,
1076 * if any, otherwise return an error.
1078 Status
= ConSrvInheritConsole(TargetProcessData
,
1079 SourceProcessData
->ConsoleHandle
,
1081 &AttachConsoleRequest
->ConsoleStartInfo
->InputHandle
,
1082 &AttachConsoleRequest
->ConsoleStartInfo
->OutputHandle
,
1083 &AttachConsoleRequest
->ConsoleStartInfo
->ErrorHandle
,
1084 AttachConsoleRequest
->ConsoleStartInfo
);
1085 if (!NT_SUCCESS(Status
))
1087 DPRINT1("Console inheritance failed\n");
1091 /* Set the Property-Dialog and Control-Dispatcher handlers */
1092 TargetProcessData
->PropRoutine
= AttachConsoleRequest
->PropRoutine
;
1093 TargetProcessData
->CtrlRoutine
= AttachConsoleRequest
->CtrlRoutine
;
1095 Status
= STATUS_SUCCESS
;
1098 /* Unlock the "source" process and exit */
1099 CsrUnlockProcess(SourceProcess
);
1103 CSR_API(SrvFreeConsole
)
1105 return ConSrvRemoveConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
));
1109 ConDrvGetConsoleMode(IN PCONSOLE Console
,
1110 IN PCONSOLE_IO_OBJECT Object
,
1111 OUT PULONG ConsoleMode
);
1112 CSR_API(SrvGetConsoleMode
)
1115 PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleModeRequest
;
1116 PCONSOLE_IO_OBJECT Object
;
1118 PULONG ConsoleMode
= &ConsoleModeRequest
->Mode
;
1120 Status
= ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
1121 ConsoleModeRequest
->Handle
,
1122 &Object
, NULL
, GENERIC_READ
, TRUE
, 0);
1123 if (!NT_SUCCESS(Status
)) return Status
;
1125 /* Get the standard console modes */
1126 Status
= ConDrvGetConsoleMode(Object
->Console
, Object
,
1128 if (NT_SUCCESS(Status
))
1131 * If getting the console modes succeeds, then retrieve
1132 * the extended CONSRV-specific input modes.
1134 if (INPUT_BUFFER
== Object
->Type
)
1136 if (Object
->Console
->InsertMode
|| Object
->Console
->QuickEdit
)
1138 /* Windows also adds ENABLE_EXTENDED_FLAGS, even if it's not documented on MSDN */
1139 *ConsoleMode
|= ENABLE_EXTENDED_FLAGS
;
1141 if (Object
->Console
->InsertMode
) *ConsoleMode
|= ENABLE_INSERT_MODE
;
1142 if (Object
->Console
->QuickEdit
) *ConsoleMode
|= ENABLE_QUICK_EDIT_MODE
;
1147 ConSrvReleaseObject(Object
, TRUE
);
1152 ConDrvSetConsoleMode(IN PCONSOLE Console
,
1153 IN PCONSOLE_IO_OBJECT Object
,
1154 IN ULONG ConsoleMode
);
1155 CSR_API(SrvSetConsoleMode
)
1157 #define CONSOLE_VALID_CONTROL_MODES ( ENABLE_EXTENDED_FLAGS | \
1158 ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE )
1161 PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleModeRequest
;
1162 PCONSOLE_IO_OBJECT Object
;
1164 ULONG ConsoleMode
= ConsoleModeRequest
->Mode
;
1166 Status
= ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
1167 ConsoleModeRequest
->Handle
,
1168 &Object
, NULL
, GENERIC_WRITE
, TRUE
, 0);
1169 if (!NT_SUCCESS(Status
)) return Status
;
1171 /* Set the standard console modes (without the CONSRV-specific input modes) */
1172 ConsoleMode
&= ~CONSOLE_VALID_CONTROL_MODES
; // Remove CONSRV-specific input modes.
1173 Status
= ConDrvSetConsoleMode(Object
->Console
, Object
,
1175 if (NT_SUCCESS(Status
))
1178 * If setting the console modes succeeds, then set
1179 * the extended CONSRV-specific input modes.
1181 if (INPUT_BUFFER
== Object
->Type
)
1183 ConsoleMode
= ConsoleModeRequest
->Mode
;
1185 if (ConsoleMode
& CONSOLE_VALID_CONTROL_MODES
)
1188 * If we use control mode flags without ENABLE_EXTENDED_FLAGS,
1189 * then consider the flags invalid.
1191 if ((ConsoleMode
& ENABLE_EXTENDED_FLAGS
) == 0)
1193 Status
= STATUS_INVALID_PARAMETER
;
1197 Object
->Console
->InsertMode
= !!(ConsoleMode
& ENABLE_INSERT_MODE
);
1198 Object
->Console
->QuickEdit
= !!(ConsoleMode
& ENABLE_QUICK_EDIT_MODE
);
1204 ConSrvReleaseObject(Object
, TRUE
);
1208 CSR_API(SrvGetConsoleTitle
)
1211 PCONSOLE_GETSETCONSOLETITLE TitleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.TitleRequest
;
1212 PCONSRV_CONSOLE Console
;
1215 if (!CsrValidateMessageBuffer(ApiMessage
,
1216 (PVOID
)&TitleRequest
->Title
,
1217 TitleRequest
->Length
,
1220 return STATUS_INVALID_PARAMETER
;
1223 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
1224 if (!NT_SUCCESS(Status
))
1226 DPRINT1("Can't get console\n");
1230 /* Copy title of the console to the user title buffer */
1231 if (TitleRequest
->Unicode
)
1233 if (TitleRequest
->Length
>= sizeof(WCHAR
))
1235 Length
= min(TitleRequest
->Length
- sizeof(WCHAR
), Console
->Title
.Length
);
1236 RtlCopyMemory(TitleRequest
->Title
, Console
->Title
.Buffer
, Length
);
1237 ((PWCHAR
)TitleRequest
->Title
)[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1238 TitleRequest
->Length
= Length
;
1242 TitleRequest
->Length
= Console
->Title
.Length
;
1247 if (TitleRequest
->Length
>= sizeof(CHAR
))
1249 Length
= min(TitleRequest
->Length
- sizeof(CHAR
), Console
->Title
.Length
/ sizeof(WCHAR
));
1250 Length
= WideCharToMultiByte(Console
->InputCodePage
, 0,
1251 Console
->Title
.Buffer
, Length
,
1252 TitleRequest
->Title
, Length
,
1254 ((PCHAR
)TitleRequest
->Title
)[Length
] = ANSI_NULL
;
1255 TitleRequest
->Length
= Length
;
1259 TitleRequest
->Length
= Console
->Title
.Length
/ sizeof(WCHAR
);
1263 ConSrvReleaseConsole(Console
, TRUE
);
1267 CSR_API(SrvSetConsoleTitle
)
1270 PCONSOLE_GETSETCONSOLETITLE TitleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.TitleRequest
;
1271 PCONSRV_CONSOLE Console
;
1276 if (!CsrValidateMessageBuffer(ApiMessage
,
1277 (PVOID
)&TitleRequest
->Title
,
1278 TitleRequest
->Length
,
1281 return STATUS_INVALID_PARAMETER
;
1284 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
1285 if (!NT_SUCCESS(Status
))
1287 DPRINT1("Can't get console\n");
1291 if (TitleRequest
->Unicode
)
1293 /* Length is in bytes */
1294 Length
= TitleRequest
->Length
;
1298 /* Use the console input CP for the conversion */
1299 Length
= MultiByteToWideChar(Console
->InputCodePage
, 0,
1300 TitleRequest
->Title
, TitleRequest
->Length
,
1302 /* The returned Length was in number of wchars, convert it in bytes */
1303 Length
*= sizeof(WCHAR
);
1306 /* Allocate a new buffer to hold the new title (NULL-terminated) */
1307 Buffer
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, Length
+ sizeof(WCHAR
));
1310 Status
= STATUS_NO_MEMORY
;
1314 /* Free the old title */
1315 ConsoleFreeUnicodeString(&Console
->Title
);
1317 /* Copy title to console */
1318 Console
->Title
.Buffer
= Buffer
;
1319 Console
->Title
.Length
= Length
;
1320 Console
->Title
.MaximumLength
= Console
->Title
.Length
+ sizeof(WCHAR
);
1322 if (TitleRequest
->Unicode
)
1324 RtlCopyMemory(Console
->Title
.Buffer
, TitleRequest
->Title
, Console
->Title
.Length
);
1328 MultiByteToWideChar(Console
->InputCodePage
, 0,
1329 TitleRequest
->Title
, TitleRequest
->Length
,
1330 Console
->Title
.Buffer
,
1331 Console
->Title
.Length
/ sizeof(WCHAR
));
1334 /* NULL-terminate */
1335 Console
->Title
.Buffer
[Console
->Title
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1337 TermChangeTitle(Console
);
1338 Status
= STATUS_SUCCESS
;
1341 ConSrvReleaseConsole(Console
, TRUE
);
1346 ConDrvGetConsoleCP(IN PCONSOLE Console
,
1348 IN BOOLEAN OutputCP
);
1349 CSR_API(SrvGetConsoleCP
)
1352 PCONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetConsoleCPRequest
;
1353 PCONSRV_CONSOLE Console
;
1355 DPRINT("SrvGetConsoleCP, getting %s Code Page\n",
1356 GetConsoleCPRequest
->OutputCP
? "Output" : "Input");
1358 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
1359 if (!NT_SUCCESS(Status
)) return Status
;
1361 Status
= ConDrvGetConsoleCP(Console
,
1362 &GetConsoleCPRequest
->CodePage
,
1363 GetConsoleCPRequest
->OutputCP
);
1365 ConSrvReleaseConsole(Console
, TRUE
);
1370 ConDrvSetConsoleCP(IN PCONSOLE Console
,
1372 IN BOOLEAN OutputCP
);
1373 CSR_API(SrvSetConsoleCP
)
1375 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
1376 PCONSOLE_SETINPUTOUTPUTCP SetConsoleCPRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetConsoleCPRequest
;
1377 PCONSRV_CONSOLE Console
;
1379 DPRINT("SrvSetConsoleCP, setting %s Code Page\n",
1380 SetConsoleCPRequest
->OutputCP
? "Output" : "Input");
1382 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
1383 if (!NT_SUCCESS(Status
)) return Status
;
1385 Status
= ConDrvSetConsoleCP(Console
,
1386 SetConsoleCPRequest
->CodePage
,
1387 SetConsoleCPRequest
->OutputCP
);
1389 ConSrvReleaseConsole(Console
, TRUE
);
1393 CSR_API(SrvGetConsoleProcessList
)
1396 PCONSOLE_GETPROCESSLIST GetProcessListRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetProcessListRequest
;
1397 PCONSRV_CONSOLE Console
;
1399 if (!CsrValidateMessageBuffer(ApiMessage
,
1400 (PVOID
)&GetProcessListRequest
->ProcessIdsList
,
1401 GetProcessListRequest
->ProcessCount
,
1404 return STATUS_INVALID_PARAMETER
;
1407 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
1408 if (!NT_SUCCESS(Status
)) return Status
;
1410 Status
= ConSrvGetConsoleProcessList(Console
,
1411 GetProcessListRequest
->ProcessIdsList
,
1412 GetProcessListRequest
->ProcessCount
,
1413 &GetProcessListRequest
->ProcessCount
);
1415 ConSrvReleaseConsole(Console
, TRUE
);
1419 CSR_API(SrvGenerateConsoleCtrlEvent
)
1422 PCONSOLE_GENERATECTRLEVENT GenerateCtrlEventRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GenerateCtrlEventRequest
;
1423 PCONSRV_CONSOLE Console
;
1425 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
1426 if (!NT_SUCCESS(Status
)) return Status
;
1428 Status
= ConSrvConsoleProcessCtrlEvent(Console
,
1429 GenerateCtrlEventRequest
->ProcessGroupId
,
1430 GenerateCtrlEventRequest
->CtrlEvent
);
1432 ConSrvReleaseConsole(Console
, TRUE
);
1436 CSR_API(SrvConsoleNotifyLastClose
)
1439 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
1440 PCONSRV_CONSOLE Console
;
1442 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
1443 if (!NT_SUCCESS(Status
)) return Status
;
1445 /* Only one process is allowed to be registered for last close notification */
1446 if (!Console
->NotifyLastClose
)
1448 Console
->NotifyLastClose
= TRUE
;
1449 Console
->NotifiedLastCloseProcess
= ProcessData
;
1450 Status
= STATUS_SUCCESS
;
1454 Status
= STATUS_ACCESS_DENIED
;
1457 ConSrvReleaseConsole(Console
, TRUE
);
1463 CSR_API(SrvGetConsoleMouseInfo
)
1466 PCONSOLE_GETMOUSEINFO GetMouseInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetMouseInfoRequest
;
1467 PCONSRV_CONSOLE Console
;
1469 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
1470 if (!NT_SUCCESS(Status
)) return Status
;
1472 /* Just retrieve the number of buttons of the mouse attached to this console */
1473 GetMouseInfoRequest
->NumButtons
= GetSystemMetrics(SM_CMOUSEBUTTONS
);
1475 ConSrvReleaseConsole(Console
, TRUE
);
1476 return STATUS_SUCCESS
;
1479 CSR_API(SrvSetConsoleKeyShortcuts
)
1481 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1482 return STATUS_NOT_IMPLEMENTED
;
1485 CSR_API(SrvGetConsoleKeyboardLayoutName
)
1488 PCONSOLE_GETKBDLAYOUTNAME GetKbdLayoutNameRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetKbdLayoutNameRequest
;
1489 PCONSRV_CONSOLE Console
;
1491 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
1492 if (!NT_SUCCESS(Status
)) return Status
;
1494 /* Retrieve the keyboard layout name of the system */
1495 if (GetKbdLayoutNameRequest
->Ansi
)
1496 GetKeyboardLayoutNameA((PCHAR
)GetKbdLayoutNameRequest
->LayoutBuffer
);
1498 GetKeyboardLayoutNameW((PWCHAR
)GetKbdLayoutNameRequest
->LayoutBuffer
);
1500 ConSrvReleaseConsole(Console
, TRUE
);
1501 return STATUS_SUCCESS
;
1504 CSR_API(SrvGetConsoleCharType
)
1506 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1507 return STATUS_NOT_IMPLEMENTED
;
1510 CSR_API(SrvSetConsoleLocalEUDC
)
1512 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1513 return STATUS_NOT_IMPLEMENTED
;
1516 CSR_API(SrvSetConsoleCursorMode
)
1518 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1519 return STATUS_NOT_IMPLEMENTED
;
1522 CSR_API(SrvGetConsoleCursorMode
)
1524 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1525 return STATUS_NOT_IMPLEMENTED
;
1528 CSR_API(SrvGetConsoleNlsMode
)
1530 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1531 return STATUS_NOT_IMPLEMENTED
;
1534 CSR_API(SrvSetConsoleNlsMode
)
1536 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1537 return STATUS_NOT_IMPLEMENTED
;
1540 CSR_API(SrvGetConsoleLangId
)
1542 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1543 return STATUS_NOT_IMPLEMENTED
;