2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/consrv/console.c
5 * PURPOSE: Console I/O functions
9 /* INCLUDES ******************************************************************/
12 #include "guiconsole.h"
13 #include "tuiconsole.h"
19 /* FUNCTIONS *****************************************************************/
22 DtbgIsDesktopVisible(VOID
)
24 HWND VisibleDesktopWindow
= GetDesktopWindow(); // DESKTOPWNDPROC
26 if (VisibleDesktopWindow
!= NULL
&&
27 !IsWindowVisible(VisibleDesktopWindow
))
29 VisibleDesktopWindow
= NULL
;
32 return VisibleDesktopWindow
!= NULL
;
36 ConSrvConsoleCtrlEventTimeout(DWORD Event
,
37 PCONSOLE_PROCESS_DATA ProcessData
,
42 DPRINT("ConSrvConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData
->Process
->ClientId
.UniqueProcess
);
44 if (ProcessData
->CtrlDispatcher
)
46 Thread
= CreateRemoteThread(ProcessData
->Process
->ProcessHandle
, NULL
, 0,
47 ProcessData
->CtrlDispatcher
,
48 UlongToPtr(Event
), 0, NULL
);
51 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
55 DPRINT1("We succeeded at creating ProcessData->CtrlDispatcher remote thread, ProcessId = %x, Process = 0x%p\n", ProcessData
->Process
->ClientId
.UniqueProcess
, ProcessData
->Process
);
56 WaitForSingleObject(Thread
, Timeout
);
62 ConSrvConsoleCtrlEvent(DWORD Event
, PCONSOLE_PROCESS_DATA ProcessData
)
64 ConSrvConsoleCtrlEventTimeout(Event
, ProcessData
, 0);
68 ConioPause(PCONSOLE Console
, UINT Flags
)
70 Console
->PauseFlags
|= Flags
;
71 if (!Console
->UnpauseEvent
)
72 Console
->UnpauseEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
76 ConioUnpause(PCONSOLE Console
, UINT Flags
)
78 Console
->PauseFlags
&= ~Flags
;
80 // if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0)
81 if (Console
->PauseFlags
== 0 && Console
->UnpauseEvent
)
83 SetEvent(Console
->UnpauseEvent
);
84 CloseHandle(Console
->UnpauseEvent
);
85 Console
->UnpauseEvent
= NULL
;
87 CsrNotifyWait(&Console
->WriteWaitQueue
,
91 if (!IsListEmpty(&Console
->WriteWaitQueue
))
93 CsrDereferenceWait(&Console
->WriteWaitQueue
);
99 ConSrvInitConsole(PCONSOLE
* NewConsole
, int ShowCmd
, PCSR_PROCESS ConsoleLeaderProcess
)
102 SECURITY_ATTRIBUTES SecurityAttributes
;
104 PCONSOLE_SCREEN_BUFFER NewBuffer
;
108 if (NewConsole
== NULL
) return STATUS_INVALID_PARAMETER
;
112 /* Allocate a console structure */
113 Console
= RtlAllocateHeap(ConSrvHeap
, HEAP_ZERO_MEMORY
, sizeof(CONSOLE
));
116 DPRINT1("Not enough memory for console creation.\n");
117 return STATUS_NO_MEMORY
;
120 /* Initialize the console */
121 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
122 Console
->Title
.Buffer
= NULL
;
124 if (LoadStringW(ConSrvDllInstance
, IDS_COMMAND_PROMPT
, Title
, sizeof(Title
) / sizeof(Title
[0])))
126 RtlCreateUnicodeString(&Console
->Title
, Title
);
130 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
133 InitializeCriticalSection(&Console
->Lock
);
134 Console
->ReferenceCount
= 0;
135 Console
->LineBuffer
= NULL
;
136 Console
->ConsoleLeaderCID
= ConsoleLeaderProcess
->ClientId
;
137 InitializeListHead(&Console
->ProcessList
);
138 InitializeListHead(&Console
->BufferList
);
139 Console
->ActiveBuffer
= NULL
;
141 /* Initialize the input buffer */
142 Console
->InputBuffer
.Header
.Type
= CONIO_INPUT_BUFFER_MAGIC
;
143 Console
->InputBuffer
.Header
.Console
= Console
;
144 Console
->InputBuffer
.Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
145 InitializeListHead(&Console
->InputBuffer
.ReadWaitQueue
);
146 InitializeListHead(&Console
->InputBuffer
.InputEvents
);
148 InitializeListHead(&Console
->WriteWaitQueue
);
149 InitializeListHead(&Console
->HistoryBuffers
);
150 Console
->CodePage
= GetOEMCP();
151 Console
->OutputCodePage
= GetOEMCP();
152 Console
->GuiData
= NULL
;
154 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
155 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
156 SecurityAttributes
.bInheritHandle
= TRUE
;
158 Console
->InputBuffer
.ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
159 if (NULL
== Console
->InputBuffer
.ActiveEvent
)
161 RtlFreeUnicodeString(&Console
->Title
);
162 DeleteCriticalSection(&Console
->Lock
);
163 RtlFreeHeap(ConSrvHeap
, 0, Console
);
164 return STATUS_UNSUCCESSFUL
;
167 GuiMode
= DtbgIsDesktopVisible();
169 /* allocate console screen buffer */
170 NewBuffer
= RtlAllocateHeap(ConSrvHeap
, HEAP_ZERO_MEMORY
, sizeof(CONSOLE_SCREEN_BUFFER
));
171 if (NULL
== NewBuffer
)
173 RtlFreeUnicodeString(&Console
->Title
);
174 DeleteCriticalSection(&Console
->Lock
);
175 CloseHandle(Console
->InputBuffer
.ActiveEvent
);
176 RtlFreeHeap(ConSrvHeap
, 0, Console
);
177 return STATUS_INSUFFICIENT_RESOURCES
;
179 /* init screen buffer with defaults */
180 NewBuffer
->CursorInfo
.bVisible
= TRUE
;
181 NewBuffer
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
182 /* make console active, and insert into console list */
183 Console
->ActiveBuffer
= (PCONSOLE_SCREEN_BUFFER
)NewBuffer
;
186 * If we are not in GUI-mode, start the text-mode console. If we fail,
187 * try to start the GUI-mode console (win32k will automatically switch
188 * to graphical mode, therefore no additional code is needed).
192 DPRINT1("CONSRV: Opening text-mode console\n");
193 Status
= TuiInitConsole(Console
);
194 if (!NT_SUCCESS(Status
))
196 DPRINT1("Failed to open text-mode console, switching to gui-mode, Status = 0x%08lx\n", Status
);
202 * Try to open the GUI-mode console. Two cases are possible:
203 * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
204 * failed and we start GUI-mode console.
205 * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
206 * succeeded BUT we failed at starting text-mode console. Then GuiMode
207 * was switched to TRUE in order to try to open the console in GUI-mode.
211 DPRINT1("CONSRV: Opening GUI-mode console\n");
212 Status
= GuiInitConsole(Console
, ShowCmd
);
213 if (!NT_SUCCESS(Status
))
215 RtlFreeHeap(ConSrvHeap
,0, NewBuffer
);
216 RtlFreeUnicodeString(&Console
->Title
);
217 DeleteCriticalSection(&Console
->Lock
);
218 CloseHandle(Console
->InputBuffer
.ActiveEvent
);
219 DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status
);
220 RtlFreeHeap(ConSrvHeap
, 0, Console
);
225 Status
= ConSrvInitConsoleScreenBuffer(Console
, NewBuffer
);
226 if (!NT_SUCCESS(Status
))
228 ConioCleanupConsole(Console
);
229 RtlFreeUnicodeString(&Console
->Title
);
230 DeleteCriticalSection(&Console
->Lock
);
231 CloseHandle(Console
->InputBuffer
.ActiveEvent
);
232 RtlFreeHeap(ConSrvHeap
, 0, NewBuffer
);
233 DPRINT1("ConSrvInitConsoleScreenBuffer: failed\n");
234 RtlFreeHeap(ConSrvHeap
, 0, Console
);
238 /* Copy buffer contents to screen */
239 ConioDrawConsole(Console
);
241 *NewConsole
= Console
;
243 return STATUS_SUCCESS
;
247 ConSrvInitConsoleSupport(VOID
)
249 DPRINT("CONSRV: ConSrvInitConsoleSupport()\n");
251 /* Should call LoadKeyboardLayout */
255 ConSrvDeleteConsole(PCONSOLE Console
)
259 DPRINT("ConSrvDeleteConsole\n");
261 /* Drain input event queue */
262 while (Console
->InputBuffer
.InputEvents
.Flink
!= &Console
->InputBuffer
.InputEvents
)
264 Event
= (ConsoleInput
*) Console
->InputBuffer
.InputEvents
.Flink
;
265 Console
->InputBuffer
.InputEvents
.Flink
= Console
->InputBuffer
.InputEvents
.Flink
->Flink
;
266 Console
->InputBuffer
.InputEvents
.Flink
->Flink
->Blink
= &Console
->InputBuffer
.InputEvents
;
267 RtlFreeHeap(ConSrvHeap
, 0, Event
);
270 ConioCleanupConsole(Console
);
271 if (Console
->LineBuffer
)
272 RtlFreeHeap(ConSrvHeap
, 0, Console
->LineBuffer
);
273 while (!IsListEmpty(&Console
->HistoryBuffers
))
274 HistoryDeleteBuffer((struct _HISTORY_BUFFER
*)Console
->HistoryBuffers
.Flink
);
276 ConioDeleteScreenBuffer(Console
->ActiveBuffer
);
277 if (!IsListEmpty(&Console
->BufferList
))
279 DPRINT1("BUG: screen buffer list not empty\n");
282 CloseHandle(Console
->InputBuffer
.ActiveEvent
);
283 if (Console
->UnpauseEvent
) CloseHandle(Console
->UnpauseEvent
);
284 DeleteCriticalSection(&Console
->Lock
);
285 RtlFreeUnicodeString(&Console
->Title
);
286 IntDeleteAllAliases(Console
->Aliases
);
287 RtlFreeHeap(ConSrvHeap
, 0, Console
);
290 CSR_API(SrvOpenConsole
)
292 NTSTATUS Status
= STATUS_SUCCESS
;
293 PCONSOLE_OPENCONSOLE OpenConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.OpenConsoleRequest
;
294 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
296 DPRINT("SrvOpenConsole\n");
298 OpenConsoleRequest
->ConsoleHandle
= INVALID_HANDLE_VALUE
;
300 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
302 DPRINT1("SrvOpenConsole - Checkpoint 1\n");
303 DPRINT1("ProcessData = 0x%p ; ProcessData->Console = 0x%p\n", ProcessData
, ProcessData
->Console
);
305 if (ProcessData
->Console
)
307 DWORD DesiredAccess
= OpenConsoleRequest
->Access
;
308 DWORD ShareMode
= OpenConsoleRequest
->ShareMode
;
310 PCONSOLE Console
= ProcessData
->Console
;
313 DPRINT1("SrvOpenConsole - Checkpoint 2\n");
314 EnterCriticalSection(&Console
->Lock
);
315 DPRINT1("SrvOpenConsole - Checkpoint 3\n");
317 if (OpenConsoleRequest
->HandleType
== HANDLE_OUTPUT
)
319 Object
= &Console
->ActiveBuffer
->Header
;
323 Object
= &Console
->InputBuffer
.Header
;
326 if (((DesiredAccess
& GENERIC_READ
) && Object
->ExclusiveRead
!= 0) ||
327 ((DesiredAccess
& GENERIC_WRITE
) && Object
->ExclusiveWrite
!= 0) ||
328 (!(ShareMode
& FILE_SHARE_READ
) && Object
->AccessRead
!= 0) ||
329 (!(ShareMode
& FILE_SHARE_WRITE
) && Object
->AccessWrite
!= 0))
331 DPRINT1("Sharing violation\n");
332 Status
= STATUS_SHARING_VIOLATION
;
336 Status
= ConSrvInsertObject(ProcessData
,
337 &OpenConsoleRequest
->ConsoleHandle
,
340 OpenConsoleRequest
->Inheritable
,
344 LeaveCriticalSection(&Console
->Lock
);
347 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
352 CSR_API(SrvAllocConsole
)
354 NTSTATUS Status
= STATUS_SUCCESS
;
355 PCONSOLE_ALLOCCONSOLE AllocConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.AllocConsoleRequest
;
356 PCSR_PROCESS ConsoleLeader
= CsrGetClientThread()->Process
;
357 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(ConsoleLeader
);
359 DPRINT("SrvAllocConsole\n");
361 if (ProcessData
->Console
!= NULL
)
363 DPRINT1("Process already has a console\n");
364 return STATUS_ACCESS_DENIED
;
367 /******************************************************************************/
368 /** This comes from ConSrvConnect!! **/
369 DPRINT1("SrvAllocConsole - Checkpoint 1\n");
372 * We are about to create a new console. However when ConSrvNewProcess
373 * was called, we didn't know that we wanted to create a new console and
374 * therefore, we by default inherited the handles table from our parent
375 * process. It's only now that we notice that in fact we do not need
376 * them, because we've created a new console and thus we must use it.
378 * Therefore, free the console we can have and our handles table,
379 * and recreate a new one later on.
381 ConSrvRemoveConsole(ProcessData
);
382 // ConSrvFreeHandlesTable(ProcessData);
384 /* Initialize a new Console owned by the Console Leader Process */
385 Status
= ConSrvAllocateConsole(ProcessData
,
386 &AllocConsoleRequest
->InputHandle
,
387 &AllocConsoleRequest
->OutputHandle
,
388 &AllocConsoleRequest
->ErrorHandle
,
389 AllocConsoleRequest
->ShowCmd
,
391 if (!NT_SUCCESS(Status
))
393 DPRINT1("Console allocation failed\n");
397 /* Add a reference count because the process is tied to the console */
398 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
400 /* Insert the process into the processes list of the console */
401 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
403 /* Duplicate the Event */
404 Status
= NtDuplicateObject(NtCurrentProcess(),
405 ProcessData
->Console
->InputBuffer
.ActiveEvent
,
406 ProcessData
->Process
->ProcessHandle
,
407 &ProcessData
->ConsoleEvent
,
408 EVENT_ALL_ACCESS
, 0, 0);
409 if (!NT_SUCCESS(Status
))
411 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
412 ConSrvRemoveConsole(ProcessData
);
416 /* Return it to the caller */
417 AllocConsoleRequest
->Console
= ProcessData
->Console
;
419 /* Input Wait Handle */
420 AllocConsoleRequest
->InputWaitHandle
= ProcessData
->ConsoleEvent
;
422 /* Set the Ctrl Dispatcher */
423 ProcessData
->CtrlDispatcher
= AllocConsoleRequest
->CtrlDispatcher
;
424 DPRINT("CONSRV: CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
425 /******************************************************************************/
427 return STATUS_SUCCESS
;
430 CSR_API(SrvAttachConsole
)
432 NTSTATUS Status
= STATUS_SUCCESS
;
433 PCONSOLE_ATTACHCONSOLE AttachConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.AttachConsoleRequest
;
434 PCSR_PROCESS SourceProcess
= NULL
; // The parent process.
435 PCSR_PROCESS TargetProcess
= CsrGetClientThread()->Process
; // Ourselves.
436 HANDLE ProcessId
= ULongToHandle(AttachConsoleRequest
->ProcessId
);
437 PCONSOLE_PROCESS_DATA SourceProcessData
, TargetProcessData
;
439 DPRINT("SrvAttachConsole\n");
441 TargetProcessData
= ConsoleGetPerProcessData(TargetProcess
);
443 if (TargetProcessData
->Console
!= NULL
)
445 DPRINT1("Process already has a console\n");
446 return STATUS_ACCESS_DENIED
;
449 if (ProcessId
== ULongToHandle(ATTACH_PARENT_PROCESS
))
451 PROCESS_BASIC_INFORMATION ProcessInfo
;
452 ULONG Length
= sizeof(ProcessInfo
);
454 /* Get the real parent's ID */
456 Status
= NtQueryInformationProcess(TargetProcess
->ProcessHandle
,
457 ProcessBasicInformation
,
460 if (!NT_SUCCESS(Status
))
462 DPRINT1("SrvAttachConsole - Cannot retrieve basic process info, Status = %lu\n", Status
);
466 DPRINT("We, process (ID) %lu;%lu\n", TargetProcess
->ClientId
.UniqueProcess
, TargetProcess
->ClientId
.UniqueThread
);
467 ProcessId
= ULongToHandle(ProcessInfo
.InheritedFromUniqueProcessId
);
468 DPRINT("Parent process ID = %lu\n", ProcessId
);
471 /* Lock the target process via its PID */
472 DPRINT1("Lock process Id %lu\n", ProcessId
);
473 Status
= CsrLockProcessByClientId(ProcessId
, &SourceProcess
);
474 DPRINT1("Lock process Status %lu\n", Status
);
475 if (!NT_SUCCESS(Status
)) return Status
;
476 DPRINT1("AttachConsole OK\n");
478 /******************************************************************************/
479 /** This comes from ConSrvNewProcess!! **/
480 SourceProcessData
= ConsoleGetPerProcessData(SourceProcess
);
483 * We are about to create a new console. However when ConSrvNewProcess
484 * was called, we didn't know that we wanted to create a new console and
485 * therefore, we by default inherited the handles table from our parent
486 * process. It's only now that we notice that in fact we do not need
487 * them, because we've created a new console and thus we must use it.
489 * Therefore, free the console we can have and our handles table,
490 * and recreate a new one later on.
492 ConSrvRemoveConsole(TargetProcessData
);
493 // ConSrvFreeHandlesTable(TargetProcessData);
496 * Inherit the console from the parent,
497 * if any, otherwise return an error.
499 DPRINT1("SourceProcessData->Console = 0x%p\n", SourceProcessData
->Console
);
500 if (SourceProcessData
->Console
== NULL
)
502 Status
= STATUS_INVALID_HANDLE
;
505 TargetProcessData
->Console
= SourceProcessData
->Console
;
507 /// REMARK: This code comes from ConSrvAllocateConsole.
508 /* Initialize the handles table */
509 Status
= ConSrvInitHandlesTable(TargetProcessData
,
510 &AttachConsoleRequest
->InputHandle
,
511 &AttachConsoleRequest
->OutputHandle
,
512 &AttachConsoleRequest
->ErrorHandle
);
513 if (!NT_SUCCESS(Status
))
515 DPRINT1("Failed to initialize the handles table\n");
517 // ConSrvRemoveConsole(TargetProcessData);
518 TargetProcessData
->Console
= NULL
;
522 /******************************************************************************/
524 /******************************************************************************/
525 /** This comes from ConSrvConnect / SrvAllocConsole!! **/
526 /* Add a reference count because the process is tied to the console */
527 _InterlockedIncrement(&TargetProcessData
->Console
->ReferenceCount
);
529 /* Insert the process into the processes list of the console */
530 InsertHeadList(&TargetProcessData
->Console
->ProcessList
, &TargetProcessData
->ConsoleLink
);
532 /** Here, we inherited the console handles from the "source" process,
533 ** so no need to reinitialize the handles table. **/
535 DPRINT1("SrvAttachConsole - Checkpoint\n");
537 /* Duplicate the Event */
538 Status
= NtDuplicateObject(NtCurrentProcess(),
539 TargetProcessData
->Console
->InputBuffer
.ActiveEvent
,
540 TargetProcessData
->Process
->ProcessHandle
,
541 &TargetProcessData
->ConsoleEvent
,
542 EVENT_ALL_ACCESS
, 0, 0);
543 if (!NT_SUCCESS(Status
))
545 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
546 ConSrvRemoveConsole(TargetProcessData
);
550 /* Return it to the caller */
551 AttachConsoleRequest
->Console
= TargetProcessData
->Console
;
553 /* Input Wait Handle */
554 AttachConsoleRequest
->InputWaitHandle
= TargetProcessData
->ConsoleEvent
;
556 /* Set the Ctrl Dispatcher */
557 TargetProcessData
->CtrlDispatcher
= AttachConsoleRequest
->CtrlDispatcher
;
558 DPRINT("CONSRV: CtrlDispatcher address: %x\n", TargetProcessData
->CtrlDispatcher
);
560 Status
= STATUS_SUCCESS
;
561 /******************************************************************************/
564 DPRINT1("SrvAttachConsole - exiting 1\n");
565 /* Unlock the "source" process */
566 CsrUnlockProcess(SourceProcess
);
567 DPRINT1("SrvAttachConsole - exiting 2\n");
572 CSR_API(SrvFreeConsole
)
574 DPRINT1("SrvFreeConsole\n");
575 ConSrvRemoveConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
));
576 return STATUS_SUCCESS
;
579 CSR_API(SrvSetConsoleMode
)
582 PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleModeRequest
;
583 Object_t
* Object
= NULL
;
585 DPRINT("SrvSetConsoleMode\n");
587 Status
= ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
588 ConsoleModeRequest
->ConsoleHandle
,
589 &Object
, NULL
, GENERIC_WRITE
, TRUE
, 0);
590 if (!NT_SUCCESS(Status
)) return Status
;
592 Status
= STATUS_SUCCESS
;
594 if (CONIO_INPUT_BUFFER_MAGIC
== Object
->Type
)
596 PCONSOLE_INPUT_BUFFER InputBuffer
= (PCONSOLE_INPUT_BUFFER
)Object
;
597 InputBuffer
->Mode
= ConsoleModeRequest
->ConsoleMode
& CONSOLE_INPUT_MODE_VALID
;
599 else if (CONIO_SCREEN_BUFFER_MAGIC
== Object
->Type
)
601 PCONSOLE_SCREEN_BUFFER Buffer
= (PCONSOLE_SCREEN_BUFFER
)Object
;
602 Buffer
->Mode
= ConsoleModeRequest
->ConsoleMode
& CONSOLE_OUTPUT_MODE_VALID
;
606 Status
= STATUS_INVALID_HANDLE
;
609 ConSrvReleaseObject(Object
, TRUE
);
614 CSR_API(SrvGetConsoleMode
)
617 PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleModeRequest
;
618 Object_t
* Object
= NULL
;
620 DPRINT("SrvGetConsoleMode\n");
622 Status
= ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
623 ConsoleModeRequest
->ConsoleHandle
,
624 &Object
, NULL
, GENERIC_READ
, TRUE
, 0);
625 if (!NT_SUCCESS(Status
)) return Status
;
627 Status
= STATUS_SUCCESS
;
629 if (CONIO_INPUT_BUFFER_MAGIC
== Object
->Type
)
631 PCONSOLE_INPUT_BUFFER InputBuffer
= (PCONSOLE_INPUT_BUFFER
)Object
;
632 ConsoleModeRequest
->ConsoleMode
= InputBuffer
->Mode
;
634 else if (CONIO_SCREEN_BUFFER_MAGIC
== Object
->Type
)
636 PCONSOLE_SCREEN_BUFFER Buffer
= (PCONSOLE_SCREEN_BUFFER
)Object
;
637 ConsoleModeRequest
->ConsoleMode
= Buffer
->Mode
;
641 Status
= STATUS_INVALID_HANDLE
;
644 ConSrvReleaseObject(Object
, TRUE
);
649 CSR_API(SrvSetConsoleTitle
)
652 PCONSOLE_GETSETCONSOLETITLE TitleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.TitleRequest
;
653 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
657 DPRINT("SrvSetConsoleTitle\n");
659 if (!CsrValidateMessageBuffer(ApiMessage
,
660 (PVOID
)&TitleRequest
->Title
,
661 TitleRequest
->Length
,
664 return STATUS_INVALID_PARAMETER
;
667 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
668 if(NT_SUCCESS(Status
))
670 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, TitleRequest
->Length
);
673 /* Copy title to console */
674 RtlFreeUnicodeString(&Console
->Title
);
675 Console
->Title
.Buffer
= Buffer
;
676 Console
->Title
.Length
= Console
->Title
.MaximumLength
= TitleRequest
->Length
;
677 memcpy(Console
->Title
.Buffer
, TitleRequest
->Title
, Console
->Title
.Length
);
679 if (!ConioChangeTitle(Console
))
681 Status
= STATUS_UNSUCCESSFUL
;
685 Status
= STATUS_SUCCESS
;
690 Status
= STATUS_NO_MEMORY
;
693 ConSrvReleaseConsole(Console
, TRUE
);
699 CSR_API(SrvGetConsoleTitle
)
702 PCONSOLE_GETSETCONSOLETITLE TitleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.TitleRequest
;
703 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
707 DPRINT("SrvGetConsoleTitle\n");
709 if (!CsrValidateMessageBuffer(ApiMessage
,
710 (PVOID
)&TitleRequest
->Title
,
711 TitleRequest
->Length
,
714 return STATUS_INVALID_PARAMETER
;
717 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
718 if (!NT_SUCCESS(Status
))
720 DPRINT1("Can't get console\n");
724 /* Copy title of the console to the user title buffer */
725 if (TitleRequest
->Length
>= sizeof(WCHAR
))
727 Length
= min(TitleRequest
->Length
- sizeof(WCHAR
), Console
->Title
.Length
);
728 memcpy(TitleRequest
->Title
, Console
->Title
.Buffer
, Length
);
729 TitleRequest
->Title
[Length
/ sizeof(WCHAR
)] = L
'\0';
732 TitleRequest
->Length
= Console
->Title
.Length
;
734 ConSrvReleaseConsole(Console
, TRUE
);
735 return STATUS_SUCCESS
;
738 /**********************************************************************
739 * HardwareStateProperty
742 * Set/Get the value of the HardwareState and switch
743 * between direct video buffer ouput and GDI windowed
746 * Client hands us a CONSOLE_GETSETHWSTATE object.
747 * We use the same object to Request.
749 * ConsoleHwState has the correct size to be compatible
750 * with NT's, but values are not.
752 static NTSTATUS FASTCALL
753 SetConsoleHardwareState(PCONSOLE Console
, DWORD ConsoleHwState
)
755 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
757 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
758 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
760 if (Console
->HardwareState
!= ConsoleHwState
)
762 /* TODO: implement switching from full screen to windowed mode */
763 /* TODO: or back; now simply store the hardware state */
764 Console
->HardwareState
= ConsoleHwState
;
767 return STATUS_SUCCESS
;
770 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
773 CSR_API(SrvGetConsoleHardwareState
)
776 PCONSOLE_GETSETHWSTATE HardwareStateRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.HardwareStateRequest
;
777 PCONSOLE_SCREEN_BUFFER Buff
;
780 DPRINT("SrvGetConsoleHardwareState\n");
782 Status
= ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
783 HardwareStateRequest
->OutputHandle
,
787 if (!NT_SUCCESS(Status
))
789 DPRINT1("Failed to get console handle in SrvGetConsoleHardwareState\n");
793 Console
= Buff
->Header
.Console
;
794 HardwareStateRequest
->State
= Console
->HardwareState
;
796 ConSrvReleaseScreenBuffer(Buff
, TRUE
);
801 CSR_API(SrvSetConsoleHardwareState
)
804 PCONSOLE_GETSETHWSTATE HardwareStateRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.HardwareStateRequest
;
805 PCONSOLE_SCREEN_BUFFER Buff
;
808 DPRINT("SrvSetConsoleHardwareState\n");
810 Status
= ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
811 HardwareStateRequest
->OutputHandle
,
815 if (!NT_SUCCESS(Status
))
817 DPRINT1("Failed to get console handle in SrvSetConsoleHardwareState\n");
821 DPRINT("Setting console hardware state.\n");
822 Console
= Buff
->Header
.Console
;
823 Status
= SetConsoleHardwareState(Console
, HardwareStateRequest
->State
);
825 ConSrvReleaseScreenBuffer(Buff
, TRUE
);
830 CSR_API(SrvGetConsoleWindow
)
833 PCONSOLE_GETWINDOW GetWindowRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetWindowRequest
;
836 DPRINT("SrvGetConsoleWindow\n");
838 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
839 if (!NT_SUCCESS(Status
)) return Status
;
841 GetWindowRequest
->WindowHandle
= Console
->hWindow
;
842 ConSrvReleaseConsole(Console
, TRUE
);
844 return STATUS_SUCCESS
;
847 CSR_API(SrvSetConsoleIcon
)
850 PCONSOLE_SETICON SetIconRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetIconRequest
;
853 DPRINT("SrvSetConsoleIcon\n");
855 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
856 if (!NT_SUCCESS(Status
)) return Status
;
858 Status
= (ConioChangeIcon(Console
, SetIconRequest
->WindowIcon
)
860 : STATUS_UNSUCCESSFUL
);
862 ConSrvReleaseConsole(Console
, TRUE
);
867 CSR_API(SrvGetConsoleCP
)
870 PCONSOLE_GETSETINPUTOUTPUTCP ConsoleCPRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleCPRequest
;
873 DPRINT("SrvGetConsoleCP, getting %s Code Page\n",
874 ConsoleCPRequest
->InputCP
? "Input" : "Output");
876 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
877 if (!NT_SUCCESS(Status
)) return Status
;
879 ConsoleCPRequest
->CodePage
= (ConsoleCPRequest
->InputCP
? Console
->CodePage
880 : Console
->OutputCodePage
);
881 ConSrvReleaseConsole(Console
, TRUE
);
882 return STATUS_SUCCESS
;
885 CSR_API(SrvSetConsoleCP
)
888 PCONSOLE_GETSETINPUTOUTPUTCP ConsoleCPRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleCPRequest
;
891 DPRINT("SrvSetConsoleCP, setting %s Code Page\n",
892 ConsoleCPRequest
->InputCP
? "Input" : "Output");
894 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
895 if (!NT_SUCCESS(Status
)) return Status
;
897 if (IsValidCodePage(ConsoleCPRequest
->CodePage
))
899 if (ConsoleCPRequest
->InputCP
)
900 Console
->CodePage
= ConsoleCPRequest
->CodePage
;
902 Console
->OutputCodePage
= ConsoleCPRequest
->CodePage
;
904 ConSrvReleaseConsole(Console
, TRUE
);
905 return STATUS_SUCCESS
;
908 ConSrvReleaseConsole(Console
, TRUE
);
909 return STATUS_INVALID_PARAMETER
;
912 CSR_API(SrvGetConsoleProcessList
)
915 PCONSOLE_GETPROCESSLIST GetProcessListRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetProcessListRequest
;
917 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
919 PCONSOLE_PROCESS_DATA current
;
920 PLIST_ENTRY current_entry
;
923 DPRINT("SrvGetConsoleProcessList\n");
925 if (!CsrValidateMessageBuffer(ApiMessage
,
926 (PVOID
)&GetProcessListRequest
->pProcessIds
,
927 GetProcessListRequest
->nMaxIds
,
930 return STATUS_INVALID_PARAMETER
;
933 Buffer
= GetProcessListRequest
->pProcessIds
;
935 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
936 if (!NT_SUCCESS(Status
)) return Status
;
938 for (current_entry
= Console
->ProcessList
.Flink
;
939 current_entry
!= &Console
->ProcessList
;
940 current_entry
= current_entry
->Flink
)
942 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
943 if (++nItems
<= GetProcessListRequest
->nMaxIds
)
945 *Buffer
++ = HandleToUlong(current
->Process
->ClientId
.UniqueProcess
);
949 ConSrvReleaseConsole(Console
, TRUE
);
951 GetProcessListRequest
->nProcessIdsTotal
= nItems
;
952 return STATUS_SUCCESS
;
955 CSR_API(SrvGenerateConsoleCtrlEvent
)
958 PCONSOLE_GENERATECTRLEVENT GenerateCtrlEventRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GenerateCtrlEventRequest
;
960 PCONSOLE_PROCESS_DATA current
;
961 PLIST_ENTRY current_entry
;
964 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
965 if (!NT_SUCCESS(Status
)) return Status
;
967 Group
= GenerateCtrlEventRequest
->ProcessGroup
;
968 Status
= STATUS_INVALID_PARAMETER
;
969 for (current_entry
= Console
->ProcessList
.Flink
;
970 current_entry
!= &Console
->ProcessList
;
971 current_entry
= current_entry
->Flink
)
973 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
974 if (Group
== 0 || current
->Process
->ProcessGroupId
== Group
)
976 ConSrvConsoleCtrlEvent(GenerateCtrlEventRequest
->Event
, current
);
977 Status
= STATUS_SUCCESS
;
981 ConSrvReleaseConsole(Console
, TRUE
);
986 CSR_API(SrvGetConsoleSelectionInfo
)
989 PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetSelectionInfoRequest
;
992 Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
993 if (NT_SUCCESS(Status
))
995 memset(&GetSelectionInfoRequest
->Info
, 0, sizeof(CONSOLE_SELECTION_INFO
));
996 if (Console
->Selection
.dwFlags
!= 0)
997 GetSelectionInfoRequest
->Info
= Console
->Selection
;
998 ConSrvReleaseConsole(Console
, TRUE
);