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"
18 /* FUNCTIONS *****************************************************************/
21 DtbgIsDesktopVisible(VOID
)
23 HWND VisibleDesktopWindow
= GetDesktopWindow(); // DESKTOPWNDPROC
25 if (VisibleDesktopWindow
!= NULL
&&
26 !IsWindowVisible(VisibleDesktopWindow
))
28 VisibleDesktopWindow
= NULL
;
31 return VisibleDesktopWindow
!= NULL
;
35 ConioConsoleCtrlEventTimeout(DWORD Event
,
36 PCONSOLE_PROCESS_DATA ProcessData
,
41 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData
->Process
->ClientId
.UniqueProcess
);
43 if (ProcessData
->CtrlDispatcher
)
45 Thread
= CreateRemoteThread(ProcessData
->Process
->ProcessHandle
, NULL
, 0,
46 ProcessData
->CtrlDispatcher
,
47 UlongToPtr(Event
), 0, NULL
);
50 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
54 DPRINT1("We succeeded at creating ProcessData->CtrlDispatcher remote thread, ProcessId = %x, Process = 0x%p\n", ProcessData
->Process
->ClientId
.UniqueProcess
, ProcessData
->Process
);
55 WaitForSingleObject(Thread
, Timeout
);
61 ConioConsoleCtrlEvent(DWORD Event
, PCONSOLE_PROCESS_DATA ProcessData
)
63 ConioConsoleCtrlEventTimeout(Event
, ProcessData
, 0);
67 CsrInitConsole(PCONSOLE
* NewConsole
, int ShowCmd
, PCSR_PROCESS ConsoleLeaderProcess
)
70 SECURITY_ATTRIBUTES SecurityAttributes
;
72 PCONSOLE_SCREEN_BUFFER NewBuffer
;
76 if (NewConsole
== NULL
) return STATUS_INVALID_PARAMETER
;
80 /* Allocate a console structure */
81 Console
= RtlAllocateHeap(ConSrvHeap
, HEAP_ZERO_MEMORY
, sizeof(CONSOLE
));
84 DPRINT1("Not enough memory for console creation.\n");
85 return STATUS_NO_MEMORY
;
88 /* Initialize the console */
89 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
90 Console
->Title
.Buffer
= NULL
;
92 if (LoadStringW(ConSrvDllInstance
, IDS_COMMAND_PROMPT
, Title
, sizeof(Title
) / sizeof(Title
[0])))
94 RtlCreateUnicodeString(&Console
->Title
, Title
);
98 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
101 InitializeCriticalSection(&Console
->Lock
);
102 Console
->ReferenceCount
= 0;
103 Console
->LineBuffer
= NULL
;
104 Console
->ConsoleLeaderCID
= ConsoleLeaderProcess
->ClientId
;
105 InitializeListHead(&Console
->ProcessList
);
106 InitializeListHead(&Console
->BufferList
);
107 Console
->ActiveBuffer
= NULL
;
109 /* Initialize the input buffer */
110 Console
->InputBuffer
.Header
.Type
= CONIO_INPUT_BUFFER_MAGIC
;
111 Console
->InputBuffer
.Header
.Console
= Console
;
112 Console
->InputBuffer
.Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
113 InitializeListHead(&Console
->InputBuffer
.ReadWaitQueue
);
114 InitializeListHead(&Console
->InputBuffer
.InputEvents
);
116 InitializeListHead(&Console
->WriteWaitQueue
);
117 InitializeListHead(&Console
->HistoryBuffers
);
118 Console
->CodePage
= GetOEMCP();
119 Console
->OutputCodePage
= GetOEMCP();
120 Console
->GuiData
= NULL
;
122 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
123 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
124 SecurityAttributes
.bInheritHandle
= TRUE
;
126 Console
->InputBuffer
.ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
127 if (NULL
== Console
->InputBuffer
.ActiveEvent
)
129 RtlFreeUnicodeString(&Console
->Title
);
130 DeleteCriticalSection(&Console
->Lock
);
131 RtlFreeHeap(ConSrvHeap
, 0, Console
);
132 return STATUS_UNSUCCESSFUL
;
135 GuiMode
= DtbgIsDesktopVisible();
137 /* allocate console screen buffer */
138 NewBuffer
= RtlAllocateHeap(ConSrvHeap
, HEAP_ZERO_MEMORY
, sizeof(CONSOLE_SCREEN_BUFFER
));
139 if (NULL
== NewBuffer
)
141 RtlFreeUnicodeString(&Console
->Title
);
142 DeleteCriticalSection(&Console
->Lock
);
143 CloseHandle(Console
->InputBuffer
.ActiveEvent
);
144 RtlFreeHeap(ConSrvHeap
, 0, Console
);
145 return STATUS_INSUFFICIENT_RESOURCES
;
147 /* init screen buffer with defaults */
148 NewBuffer
->CursorInfo
.bVisible
= TRUE
;
149 NewBuffer
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
150 /* make console active, and insert into console list */
151 Console
->ActiveBuffer
= (PCONSOLE_SCREEN_BUFFER
)NewBuffer
;
154 * If we are not in GUI-mode, start the text-mode console. If we fail,
155 * try to start the GUI-mode console (win32k will automatically switch
156 * to graphical mode, therefore no additional code is needed).
160 DPRINT1("CONSRV: Opening text-mode console\n");
161 Status
= TuiInitConsole(Console
);
162 if (!NT_SUCCESS(Status
))
164 DPRINT1("Failed to open text-mode console, switching to gui-mode, Status = 0x%08lx\n", Status
);
170 * Try to open the GUI-mode console. Two cases are possible:
171 * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
172 * failed and we start GUI-mode console.
173 * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
174 * succeeded BUT we failed at starting text-mode console. Then GuiMode
175 * was switched to TRUE in order to try to open the console in GUI-mode.
179 DPRINT1("CONSRV: Opening GUI-mode console\n");
180 Status
= GuiInitConsole(Console
, ShowCmd
);
181 if (!NT_SUCCESS(Status
))
183 RtlFreeHeap(ConSrvHeap
,0, NewBuffer
);
184 RtlFreeUnicodeString(&Console
->Title
);
185 DeleteCriticalSection(&Console
->Lock
);
186 CloseHandle(Console
->InputBuffer
.ActiveEvent
);
187 DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status
);
188 RtlFreeHeap(ConSrvHeap
, 0, Console
);
193 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
194 if (!NT_SUCCESS(Status
))
196 ConioCleanupConsole(Console
);
197 RtlFreeUnicodeString(&Console
->Title
);
198 DeleteCriticalSection(&Console
->Lock
);
199 CloseHandle(Console
->InputBuffer
.ActiveEvent
);
200 RtlFreeHeap(ConSrvHeap
, 0, NewBuffer
);
201 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
202 RtlFreeHeap(ConSrvHeap
, 0, Console
);
206 /* Copy buffer contents to screen */
207 ConioDrawConsole(Console
);
209 *NewConsole
= Console
;
211 return STATUS_SUCCESS
;
214 CSR_API(SrvOpenConsole
)
216 NTSTATUS Status
= STATUS_SUCCESS
;
217 PCONSOLE_OPENCONSOLE OpenConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.OpenConsoleRequest
;
218 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
220 DPRINT("SrvOpenConsole\n");
222 OpenConsoleRequest
->ConsoleHandle
= INVALID_HANDLE_VALUE
;
224 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
226 DPRINT1("SrvOpenConsole - Checkpoint 1\n");
227 DPRINT1("ProcessData = 0x%p ; ProcessData->Console = 0x%p\n", ProcessData
, ProcessData
->Console
);
229 if (ProcessData
->Console
)
231 DWORD DesiredAccess
= OpenConsoleRequest
->Access
;
232 DWORD ShareMode
= OpenConsoleRequest
->ShareMode
;
234 PCONSOLE Console
= ProcessData
->Console
;
237 DPRINT1("SrvOpenConsole - Checkpoint 2\n");
238 EnterCriticalSection(&Console
->Lock
);
239 DPRINT1("SrvOpenConsole - Checkpoint 3\n");
241 if (OpenConsoleRequest
->HandleType
== HANDLE_OUTPUT
)
243 Object
= &Console
->ActiveBuffer
->Header
;
247 Object
= &Console
->InputBuffer
.Header
;
250 if (((DesiredAccess
& GENERIC_READ
) && Object
->ExclusiveRead
!= 0) ||
251 ((DesiredAccess
& GENERIC_WRITE
) && Object
->ExclusiveWrite
!= 0) ||
252 (!(ShareMode
& FILE_SHARE_READ
) && Object
->AccessRead
!= 0) ||
253 (!(ShareMode
& FILE_SHARE_WRITE
) && Object
->AccessWrite
!= 0))
255 DPRINT1("Sharing violation\n");
256 Status
= STATUS_SHARING_VIOLATION
;
260 Status
= Win32CsrInsertObject(ProcessData
,
261 &OpenConsoleRequest
->ConsoleHandle
,
264 OpenConsoleRequest
->Inheritable
,
268 LeaveCriticalSection(&Console
->Lock
);
271 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
276 CSR_API(SrvAllocConsole
)
278 NTSTATUS Status
= STATUS_SUCCESS
;
279 PCONSOLE_ALLOCCONSOLE AllocConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.AllocConsoleRequest
;
280 PCSR_PROCESS ConsoleLeader
= CsrGetClientThread()->Process
;
281 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(ConsoleLeader
);
283 DPRINT("SrvAllocConsole\n");
285 if (ProcessData
->Console
!= NULL
)
287 DPRINT1("Process already has a console\n");
288 return STATUS_ACCESS_DENIED
;
291 /******************************************************************************/
292 /** This comes from ConsoleConnect!! **/
293 DPRINT1("SrvAllocConsole - Checkpoint 1\n");
296 * We are about to create a new console. However when ConsoleNewProcess
297 * was called, we didn't know that we wanted to create a new console and
298 * therefore, we by default inherited the handles table from our parent
299 * process. It's only now that we notice that in fact we do not need
300 * them, because we've created a new console and thus we must use it.
302 * Therefore, free the console we can have and our handles table,
303 * and recreate a new one later on.
305 Win32CsrReleaseConsole(ProcessData
);
306 // Win32CsrFreeHandlesTable(ProcessData);
308 /* Initialize a new Console owned by the Console Leader Process */
309 Status
= Win32CsrAllocateConsole(ProcessData
,
310 &AllocConsoleRequest
->InputHandle
,
311 &AllocConsoleRequest
->OutputHandle
,
312 &AllocConsoleRequest
->ErrorHandle
,
313 AllocConsoleRequest
->ShowCmd
,
315 if (!NT_SUCCESS(Status
))
317 DPRINT1("Console allocation failed\n");
321 /* Add a reference count because the process is tied to the console */
322 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
324 /* Insert the process into the processes list of the console */
325 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
327 /* Duplicate the Event */
328 Status
= NtDuplicateObject(NtCurrentProcess(),
329 ProcessData
->Console
->InputBuffer
.ActiveEvent
,
330 ProcessData
->Process
->ProcessHandle
,
331 &ProcessData
->ConsoleEvent
,
332 EVENT_ALL_ACCESS
, 0, 0);
333 if (!NT_SUCCESS(Status
))
335 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
336 Win32CsrReleaseConsole(ProcessData
);
340 /* Return it to the caller */
341 AllocConsoleRequest
->Console
= ProcessData
->Console
;
343 /* Input Wait Handle */
344 AllocConsoleRequest
->InputWaitHandle
= ProcessData
->ConsoleEvent
;
346 /* Set the Ctrl Dispatcher */
347 ProcessData
->CtrlDispatcher
= AllocConsoleRequest
->CtrlDispatcher
;
348 DPRINT("CONSRV: CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
349 /******************************************************************************/
351 return STATUS_SUCCESS
;
354 CSR_API(SrvAttachConsole
)
356 NTSTATUS Status
= STATUS_SUCCESS
;
357 PCONSOLE_ATTACHCONSOLE AttachConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.AttachConsoleRequest
;
358 PCSR_PROCESS SourceProcess
= NULL
; // The parent process.
359 PCSR_PROCESS TargetProcess
= CsrGetClientThread()->Process
; // Ourselves.
360 HANDLE ProcessId
= ULongToHandle(AttachConsoleRequest
->ProcessId
);
361 PCONSOLE_PROCESS_DATA SourceProcessData
, TargetProcessData
;
363 DPRINT("SrvAttachConsole\n");
365 TargetProcessData
= ConsoleGetPerProcessData(TargetProcess
);
367 if (TargetProcessData
->Console
!= NULL
)
369 DPRINT1("Process already has a console\n");
370 return STATUS_ACCESS_DENIED
;
373 if (ProcessId
== ULongToHandle(ATTACH_PARENT_PROCESS
))
375 PROCESS_BASIC_INFORMATION ProcessInfo
;
376 ULONG Length
= sizeof(ProcessInfo
);
378 /* Get the real parent's ID */
380 Status
= NtQueryInformationProcess(TargetProcess
->ProcessHandle
,
381 ProcessBasicInformation
,
384 if (!NT_SUCCESS(Status
))
386 DPRINT1("SrvAttachConsole - Cannot retrieve basic process info, Status = %lu\n", Status
);
390 DPRINT("We, process (ID) %lu;%lu\n", TargetProcess
->ClientId
.UniqueProcess
, TargetProcess
->ClientId
.UniqueThread
);
391 ProcessId
= ULongToHandle(ProcessInfo
.InheritedFromUniqueProcessId
);
392 DPRINT("Parent process ID = %lu\n", ProcessId
);
395 /* Lock the target process via its PID */
396 DPRINT1("Lock process Id %lu\n", ProcessId
);
397 Status
= CsrLockProcessByClientId(ProcessId
, &SourceProcess
);
398 DPRINT1("Lock process Status %lu\n", Status
);
399 if (!NT_SUCCESS(Status
)) return Status
;
400 DPRINT1("AttachConsole OK\n");
402 /******************************************************************************/
403 /** This comes from ConsoleNewProcess!! **/
404 SourceProcessData
= ConsoleGetPerProcessData(SourceProcess
);
407 * We are about to create a new console. However when ConsoleNewProcess
408 * was called, we didn't know that we wanted to create a new console and
409 * therefore, we by default inherited the handles table from our parent
410 * process. It's only now that we notice that in fact we do not need
411 * them, because we've created a new console and thus we must use it.
413 * Therefore, free the console we can have and our handles table,
414 * and recreate a new one later on.
416 Win32CsrReleaseConsole(TargetProcessData
);
417 // Win32CsrFreeHandlesTable(TargetProcessData);
420 * Inherit the console from the parent,
421 * if any, otherwise return an error.
423 DPRINT1("SourceProcessData->Console = 0x%p\n", SourceProcessData
->Console
);
424 if (SourceProcessData
->Console
== NULL
)
426 Status
= STATUS_INVALID_HANDLE
;
429 TargetProcessData
->Console
= SourceProcessData
->Console
;
431 /// REMARK: This code comes from Win32CsrAllocateConsole.
432 /* Initialize the handles table */
433 Status
= Win32CsrInitHandlesTable(TargetProcessData
,
434 &AttachConsoleRequest
->InputHandle
,
435 &AttachConsoleRequest
->OutputHandle
,
436 &AttachConsoleRequest
->ErrorHandle
);
437 if (!NT_SUCCESS(Status
))
439 DPRINT1("Failed to initialize the handles table\n");
441 // Win32CsrReleaseConsole(TargetProcessData);
442 TargetProcessData
->Console
= NULL
;
446 /******************************************************************************/
448 /******************************************************************************/
449 /** This comes from ConsoleConnect / SrvAllocConsole!! **/
450 /* Add a reference count because the process is tied to the console */
451 _InterlockedIncrement(&TargetProcessData
->Console
->ReferenceCount
);
453 /* Insert the process into the processes list of the console */
454 InsertHeadList(&TargetProcessData
->Console
->ProcessList
, &TargetProcessData
->ConsoleLink
);
456 /** Here, we inherited the console handles from the "source" process,
457 ** so no need to reinitialize the handles table. **/
459 DPRINT1("SrvAttachConsole - Checkpoint\n");
461 /* Duplicate the Event */
462 Status
= NtDuplicateObject(NtCurrentProcess(),
463 TargetProcessData
->Console
->InputBuffer
.ActiveEvent
,
464 TargetProcessData
->Process
->ProcessHandle
,
465 &TargetProcessData
->ConsoleEvent
,
466 EVENT_ALL_ACCESS
, 0, 0);
467 if (!NT_SUCCESS(Status
))
469 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
470 Win32CsrReleaseConsole(TargetProcessData
);
474 /* Return it to the caller */
475 AttachConsoleRequest
->Console
= TargetProcessData
->Console
;
477 /* Input Wait Handle */
478 AttachConsoleRequest
->InputWaitHandle
= TargetProcessData
->ConsoleEvent
;
480 /* Set the Ctrl Dispatcher */
481 TargetProcessData
->CtrlDispatcher
= AttachConsoleRequest
->CtrlDispatcher
;
482 DPRINT("CONSRV: CtrlDispatcher address: %x\n", TargetProcessData
->CtrlDispatcher
);
484 Status
= STATUS_SUCCESS
;
485 /******************************************************************************/
488 DPRINT1("SrvAttachConsole - exiting 1\n");
489 /* Unlock the "source" process */
490 CsrUnlockProcess(SourceProcess
);
491 DPRINT1("SrvAttachConsole - exiting 2\n");
496 CSR_API(SrvFreeConsole
)
498 DPRINT1("SrvFreeConsole\n");
499 Win32CsrReleaseConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
));
500 return STATUS_SUCCESS
;
504 ConioDeleteConsole(PCONSOLE Console
)
508 DPRINT("ConioDeleteConsole\n");
510 /* Drain input event queue */
511 while (Console
->InputBuffer
.InputEvents
.Flink
!= &Console
->InputBuffer
.InputEvents
)
513 Event
= (ConsoleInput
*) Console
->InputBuffer
.InputEvents
.Flink
;
514 Console
->InputBuffer
.InputEvents
.Flink
= Console
->InputBuffer
.InputEvents
.Flink
->Flink
;
515 Console
->InputBuffer
.InputEvents
.Flink
->Flink
->Blink
= &Console
->InputBuffer
.InputEvents
;
516 RtlFreeHeap(ConSrvHeap
, 0, Event
);
519 ConioCleanupConsole(Console
);
520 if (Console
->LineBuffer
)
521 RtlFreeHeap(ConSrvHeap
, 0, Console
->LineBuffer
);
522 while (!IsListEmpty(&Console
->HistoryBuffers
))
523 HistoryDeleteBuffer((struct _HISTORY_BUFFER
*)Console
->HistoryBuffers
.Flink
);
525 ConioDeleteScreenBuffer(Console
->ActiveBuffer
);
526 if (!IsListEmpty(&Console
->BufferList
))
528 DPRINT1("BUG: screen buffer list not empty\n");
531 CloseHandle(Console
->InputBuffer
.ActiveEvent
);
532 if (Console
->UnpauseEvent
) CloseHandle(Console
->UnpauseEvent
);
533 DeleteCriticalSection(&Console
->Lock
);
534 RtlFreeUnicodeString(&Console
->Title
);
535 IntDeleteAllAliases(Console
->Aliases
);
536 RtlFreeHeap(ConSrvHeap
, 0, Console
);
540 CsrInitConsoleSupport(VOID
)
542 DPRINT("CSR: CsrInitConsoleSupport()\n");
544 /* Should call LoadKeyboardLayout */
548 ConioPause(PCONSOLE Console
, UINT Flags
)
550 Console
->PauseFlags
|= Flags
;
551 if (!Console
->UnpauseEvent
)
552 Console
->UnpauseEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
556 ConioUnpause(PCONSOLE Console
, UINT Flags
)
558 Console
->PauseFlags
&= ~Flags
;
560 // if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0)
561 if (Console
->PauseFlags
== 0 && Console
->UnpauseEvent
)
563 SetEvent(Console
->UnpauseEvent
);
564 CloseHandle(Console
->UnpauseEvent
);
565 Console
->UnpauseEvent
= NULL
;
567 CsrNotifyWait(&Console
->WriteWaitQueue
,
574 CSR_API(SrvSetConsoleMode
)
577 PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleModeRequest
;
578 Object_t
* Object
= NULL
;
580 DPRINT("SrvSetConsoleMode\n");
582 Status
= Win32CsrLockObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
583 ConsoleModeRequest
->ConsoleHandle
,
584 &Object
, GENERIC_WRITE
, TRUE
, 0);
585 if (!NT_SUCCESS(Status
)) return Status
;
587 Status
= STATUS_SUCCESS
;
589 if (CONIO_INPUT_BUFFER_MAGIC
== Object
->Type
)
591 PCONSOLE Console
= (PCONSOLE
)Object
;
592 Console
->InputBuffer
.Mode
= ConsoleModeRequest
->ConsoleMode
& CONSOLE_INPUT_MODE_VALID
;
594 else if (CONIO_SCREEN_BUFFER_MAGIC
== Object
->Type
)
596 PCONSOLE_SCREEN_BUFFER Buff
= (PCONSOLE_SCREEN_BUFFER
)Object
;
597 Buff
->Mode
= ConsoleModeRequest
->ConsoleMode
& CONSOLE_OUTPUT_MODE_VALID
;
601 Status
= STATUS_INVALID_HANDLE
;
604 Win32CsrUnlockObject(Object
, TRUE
);
609 CSR_API(SrvGetConsoleMode
)
612 PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleModeRequest
;
613 Object_t
* Object
= NULL
;
615 DPRINT("SrvGetConsoleMode\n");
617 Status
= Win32CsrLockObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
618 ConsoleModeRequest
->ConsoleHandle
,
619 &Object
, GENERIC_READ
, TRUE
, 0);
620 if (!NT_SUCCESS(Status
)) return Status
;
622 Status
= STATUS_SUCCESS
;
624 if (CONIO_INPUT_BUFFER_MAGIC
== Object
->Type
)
626 PCONSOLE Console
= (PCONSOLE
)Object
;
627 ConsoleModeRequest
->ConsoleMode
= Console
->InputBuffer
.Mode
;
629 else if (CONIO_SCREEN_BUFFER_MAGIC
== Object
->Type
)
631 PCONSOLE_SCREEN_BUFFER Buff
= (PCONSOLE_SCREEN_BUFFER
)Object
;
632 ConsoleModeRequest
->ConsoleMode
= Buff
->Mode
;
636 Status
= STATUS_INVALID_HANDLE
;
639 Win32CsrUnlockObject(Object
, TRUE
);
644 CSR_API(SrvSetConsoleTitle
)
647 PCONSOLE_GETSETCONSOLETITLE TitleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.TitleRequest
;
648 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
652 DPRINT("SrvSetConsoleTitle\n");
654 if (!CsrValidateMessageBuffer(ApiMessage
,
655 (PVOID
)&TitleRequest
->Title
,
656 TitleRequest
->Length
,
659 return STATUS_INVALID_PARAMETER
;
662 Status
= ConioGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
663 if(NT_SUCCESS(Status
))
665 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, TitleRequest
->Length
);
668 /* Copy title to console */
669 RtlFreeUnicodeString(&Console
->Title
);
670 Console
->Title
.Buffer
= Buffer
;
671 Console
->Title
.Length
= Console
->Title
.MaximumLength
= TitleRequest
->Length
;
672 memcpy(Console
->Title
.Buffer
, TitleRequest
->Title
, Console
->Title
.Length
);
674 if (!ConioChangeTitle(Console
))
676 Status
= STATUS_UNSUCCESSFUL
;
680 Status
= STATUS_SUCCESS
;
685 Status
= STATUS_NO_MEMORY
;
688 ConioReleaseConsole(Console
, TRUE
);
694 CSR_API(SrvGetConsoleTitle
)
697 PCONSOLE_GETSETCONSOLETITLE TitleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.TitleRequest
;
698 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
702 DPRINT("SrvGetConsoleTitle\n");
704 if (!CsrValidateMessageBuffer(ApiMessage
,
705 (PVOID
)&TitleRequest
->Title
,
706 TitleRequest
->Length
,
709 return STATUS_INVALID_PARAMETER
;
712 Status
= ConioGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
713 if (!NT_SUCCESS(Status
))
715 DPRINT1("Can't get console\n");
719 /* Copy title of the console to the user title buffer */
720 if (TitleRequest
->Length
>= sizeof(WCHAR
))
722 Length
= min(TitleRequest
->Length
- sizeof(WCHAR
), Console
->Title
.Length
);
723 memcpy(TitleRequest
->Title
, Console
->Title
.Buffer
, Length
);
724 TitleRequest
->Title
[Length
/ sizeof(WCHAR
)] = L
'\0';
727 TitleRequest
->Length
= Console
->Title
.Length
;
729 ConioReleaseConsole(Console
, TRUE
);
730 return STATUS_SUCCESS
;
733 /**********************************************************************
734 * HardwareStateProperty
737 * Set/Get the value of the HardwareState and switch
738 * between direct video buffer ouput and GDI windowed
741 * Client hands us a CONSOLE_GETSETHWSTATE object.
742 * We use the same object to Request.
744 * ConsoleHwState has the correct size to be compatible
745 * with NT's, but values are not.
747 static NTSTATUS FASTCALL
748 SetConsoleHardwareState(PCONSOLE Console
, DWORD ConsoleHwState
)
750 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
752 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
753 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
755 if (Console
->HardwareState
!= ConsoleHwState
)
757 /* TODO: implement switching from full screen to windowed mode */
758 /* TODO: or back; now simply store the hardware state */
759 Console
->HardwareState
= ConsoleHwState
;
762 return STATUS_SUCCESS
;
765 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
768 CSR_API(SrvGetConsoleHardwareState
)
771 PCONSOLE_GETSETHWSTATE HardwareStateRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.HardwareStateRequest
;
772 PCONSOLE_SCREEN_BUFFER Buff
;
775 DPRINT("SrvGetConsoleHardwareState\n");
777 Status
= ConioGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
778 HardwareStateRequest
->OutputHandle
,
782 if (!NT_SUCCESS(Status
))
784 DPRINT1("Failed to get console handle in SrvGetConsoleHardwareState\n");
788 Console
= Buff
->Header
.Console
;
789 HardwareStateRequest
->State
= Console
->HardwareState
;
791 ConioReleaseScreenBuffer(Buff
, TRUE
);
796 CSR_API(SrvSetConsoleHardwareState
)
799 PCONSOLE_GETSETHWSTATE HardwareStateRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.HardwareStateRequest
;
800 PCONSOLE_SCREEN_BUFFER Buff
;
803 DPRINT("SrvSetConsoleHardwareState\n");
805 Status
= ConioGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
806 HardwareStateRequest
->OutputHandle
,
810 if (!NT_SUCCESS(Status
))
812 DPRINT1("Failed to get console handle in SrvSetConsoleHardwareState\n");
816 DPRINT("Setting console hardware state.\n");
817 Console
= Buff
->Header
.Console
;
818 Status
= SetConsoleHardwareState(Console
, HardwareStateRequest
->State
);
820 ConioReleaseScreenBuffer(Buff
, TRUE
);
825 CSR_API(SrvGetConsoleWindow
)
828 PCONSOLE_GETWINDOW GetWindowRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetWindowRequest
;
831 DPRINT("SrvGetConsoleWindow\n");
833 Status
= ConioGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
834 if (!NT_SUCCESS(Status
)) return Status
;
836 GetWindowRequest
->WindowHandle
= Console
->hWindow
;
837 ConioReleaseConsole(Console
, TRUE
);
839 return STATUS_SUCCESS
;
842 CSR_API(SrvSetConsoleIcon
)
845 PCONSOLE_SETICON SetIconRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetIconRequest
;
848 DPRINT("SrvSetConsoleIcon\n");
850 Status
= ConioGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
851 if (!NT_SUCCESS(Status
)) return Status
;
853 Status
= (ConioChangeIcon(Console
, SetIconRequest
->WindowIcon
)
855 : STATUS_UNSUCCESSFUL
);
857 ConioReleaseConsole(Console
, TRUE
);
862 CSR_API(SrvGetConsoleCP
)
865 PCONSOLE_GETSETINPUTOUTPUTCP ConsoleCPRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleCPRequest
;
868 DPRINT("SrvGetConsoleCP, getting %s Code Page\n",
869 ConsoleCPRequest
->InputCP
? "Input" : "Output");
871 Status
= ConioGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
872 if (!NT_SUCCESS(Status
)) return Status
;
874 ConsoleCPRequest
->CodePage
= (ConsoleCPRequest
->InputCP
? Console
->CodePage
875 : Console
->OutputCodePage
);
876 ConioReleaseConsole(Console
, TRUE
);
877 return STATUS_SUCCESS
;
880 CSR_API(SrvSetConsoleCP
)
883 PCONSOLE_GETSETINPUTOUTPUTCP ConsoleCPRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleCPRequest
;
886 DPRINT("SrvSetConsoleCP, setting %s Code Page\n",
887 ConsoleCPRequest
->InputCP
? "Input" : "Output");
889 Status
= ConioGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
890 if (!NT_SUCCESS(Status
)) return Status
;
892 if (IsValidCodePage(ConsoleCPRequest
->CodePage
))
894 if (ConsoleCPRequest
->InputCP
)
895 Console
->CodePage
= ConsoleCPRequest
->CodePage
;
897 Console
->OutputCodePage
= ConsoleCPRequest
->CodePage
;
899 ConioReleaseConsole(Console
, TRUE
);
900 return STATUS_SUCCESS
;
903 ConioReleaseConsole(Console
, TRUE
);
904 return STATUS_INVALID_PARAMETER
;
907 CSR_API(SrvGetConsoleProcessList
)
910 PCONSOLE_GETPROCESSLIST GetProcessListRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetProcessListRequest
;
912 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
914 PCONSOLE_PROCESS_DATA current
;
915 PLIST_ENTRY current_entry
;
918 DPRINT("SrvGetConsoleProcessList\n");
920 if (!CsrValidateMessageBuffer(ApiMessage
,
921 (PVOID
)&GetProcessListRequest
->pProcessIds
,
922 GetProcessListRequest
->nMaxIds
,
925 return STATUS_INVALID_PARAMETER
;
928 Buffer
= GetProcessListRequest
->pProcessIds
;
930 Status
= ConioGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
931 if (!NT_SUCCESS(Status
)) return Status
;
933 for (current_entry
= Console
->ProcessList
.Flink
;
934 current_entry
!= &Console
->ProcessList
;
935 current_entry
= current_entry
->Flink
)
937 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
938 if (++nItems
<= GetProcessListRequest
->nMaxIds
)
940 *Buffer
++ = HandleToUlong(current
->Process
->ClientId
.UniqueProcess
);
944 ConioReleaseConsole(Console
, TRUE
);
946 GetProcessListRequest
->nProcessIdsTotal
= nItems
;
947 return STATUS_SUCCESS
;
950 CSR_API(SrvGenerateConsoleCtrlEvent
)
953 PCONSOLE_GENERATECTRLEVENT GenerateCtrlEventRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GenerateCtrlEventRequest
;
955 PCONSOLE_PROCESS_DATA current
;
956 PLIST_ENTRY current_entry
;
959 Status
= ConioGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
960 if (!NT_SUCCESS(Status
)) return Status
;
962 Group
= GenerateCtrlEventRequest
->ProcessGroup
;
963 Status
= STATUS_INVALID_PARAMETER
;
964 for (current_entry
= Console
->ProcessList
.Flink
;
965 current_entry
!= &Console
->ProcessList
;
966 current_entry
= current_entry
->Flink
)
968 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
969 if (Group
== 0 || current
->Process
->ProcessGroupId
== Group
)
971 ConioConsoleCtrlEvent(GenerateCtrlEventRequest
->Event
, current
);
972 Status
= STATUS_SUCCESS
;
976 ConioReleaseConsole(Console
, TRUE
);
981 CSR_API(SrvGetConsoleSelectionInfo
)
984 PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetSelectionInfoRequest
;
987 Status
= ConioGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
988 if (NT_SUCCESS(Status
))
990 memset(&GetSelectionInfoRequest
->Info
, 0, sizeof(CONSOLE_SELECTION_INFO
));
991 if (Console
->Selection
.dwFlags
!= 0)
992 GetSelectionInfoRequest
->Info
= Console
->Selection
;
993 ConioReleaseConsole(Console
, TRUE
);