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 Console
->ReferenceCount
= 0;
102 Console
->LineBuffer
= NULL
;
103 Console
->ConsoleLeaderCID
= ConsoleLeaderProcess
->ClientId
;
104 InitializeListHead(&Console
->ProcessList
);
105 InitializeListHead(&Console
->BufferList
);
106 Console
->ActiveBuffer
= NULL
;
108 /* Initialize the input buffer */
109 Console
->InputBuffer
.Header
.Type
= CONIO_INPUT_BUFFER_MAGIC
;
110 Console
->InputBuffer
.Header
.Console
= Console
;
111 Console
->InputBuffer
.Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
112 InitializeListHead(&Console
->InputBuffer
.ReadWaitQueue
);
113 InitializeListHead(&Console
->InputBuffer
.InputEvents
);
115 InitializeListHead(&Console
->WriteWaitQueue
);
116 InitializeListHead(&Console
->HistoryBuffers
);
117 Console
->CodePage
= GetOEMCP();
118 Console
->OutputCodePage
= GetOEMCP();
120 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
121 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
122 SecurityAttributes
.bInheritHandle
= TRUE
;
124 Console
->InputBuffer
.ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
125 if (NULL
== Console
->InputBuffer
.ActiveEvent
)
127 RtlFreeUnicodeString(&Console
->Title
);
128 RtlFreeHeap(ConSrvHeap
, 0, Console
);
129 return STATUS_UNSUCCESSFUL
;
131 Console
->PrivateData
= NULL
;
132 InitializeCriticalSection(&Console
->Lock
);
134 GuiMode
= DtbgIsDesktopVisible();
136 /* allocate console screen buffer */
137 NewBuffer
= RtlAllocateHeap(ConSrvHeap
, HEAP_ZERO_MEMORY
, sizeof(CONSOLE_SCREEN_BUFFER
));
138 if (NULL
== NewBuffer
)
140 RtlFreeUnicodeString(&Console
->Title
);
141 DeleteCriticalSection(&Console
->Lock
);
142 CloseHandle(Console
->InputBuffer
.ActiveEvent
);
143 RtlFreeHeap(ConSrvHeap
, 0, Console
);
144 return STATUS_INSUFFICIENT_RESOURCES
;
146 /* init screen buffer with defaults */
147 NewBuffer
->CursorInfo
.bVisible
= TRUE
;
148 NewBuffer
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
149 /* make console active, and insert into console list */
150 Console
->ActiveBuffer
= (PCONSOLE_SCREEN_BUFFER
)NewBuffer
;
153 * If we are not in GUI-mode, start the text-mode console. If we fail,
154 * try to start the GUI-mode console (win32k will automatically switch
155 * to graphical mode, therefore no additional code is needed).
159 DPRINT1("CONSRV: Opening text-mode console\n");
160 Status
= TuiInitConsole(Console
);
161 if (!NT_SUCCESS(Status
))
163 DPRINT1("Failed to open text-mode console, switching to gui-mode, Status = 0x%08lx\n", Status
);
169 * Try to open the GUI-mode console. Two cases are possible:
170 * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
171 * failed and we start GUI-mode console.
172 * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
173 * succeeded BUT we failed at starting text-mode console. Then GuiMode
174 * was switched to TRUE in order to try to open the console in GUI-mode.
178 DPRINT1("CONSRV: Opening GUI-mode console\n");
179 Status
= GuiInitConsole(Console
, ShowCmd
);
180 if (!NT_SUCCESS(Status
))
182 RtlFreeHeap(ConSrvHeap
,0, NewBuffer
);
183 RtlFreeUnicodeString(&Console
->Title
);
184 DeleteCriticalSection(&Console
->Lock
);
185 CloseHandle(Console
->InputBuffer
.ActiveEvent
);
186 DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status
);
187 RtlFreeHeap(ConSrvHeap
, 0, Console
);
192 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
193 if (!NT_SUCCESS(Status
))
195 ConioCleanupConsole(Console
);
196 RtlFreeUnicodeString(&Console
->Title
);
197 DeleteCriticalSection(&Console
->Lock
);
198 CloseHandle(Console
->InputBuffer
.ActiveEvent
);
199 RtlFreeHeap(ConSrvHeap
, 0, NewBuffer
);
200 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
201 RtlFreeHeap(ConSrvHeap
, 0, Console
);
205 /* Copy buffer contents to screen */
206 ConioDrawConsole(Console
);
208 *NewConsole
= Console
;
210 return STATUS_SUCCESS
;
213 CSR_API(SrvOpenConsole
)
215 NTSTATUS Status
= STATUS_SUCCESS
;
216 PCONSOLE_OPENCONSOLE OpenConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.OpenConsoleRequest
;
217 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
219 DPRINT("SrvOpenConsole\n");
221 OpenConsoleRequest
->ConsoleHandle
= INVALID_HANDLE_VALUE
;
223 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
225 DPRINT1("SrvOpenConsole - Checkpoint 1\n");
226 DPRINT1("ProcessData = 0x%p ; ProcessData->Console = 0x%p\n", ProcessData
, ProcessData
->Console
);
228 if (ProcessData
->Console
)
230 DWORD DesiredAccess
= OpenConsoleRequest
->Access
;
231 DWORD ShareMode
= OpenConsoleRequest
->ShareMode
;
233 PCONSOLE Console
= ProcessData
->Console
;
236 DPRINT1("SrvOpenConsole - Checkpoint 2\n");
237 EnterCriticalSection(&Console
->Lock
);
238 DPRINT1("SrvOpenConsole - Checkpoint 3\n");
240 if (OpenConsoleRequest
->HandleType
== HANDLE_OUTPUT
)
242 Object
= &Console
->ActiveBuffer
->Header
;
246 Object
= &Console
->InputBuffer
.Header
;
249 if (((DesiredAccess
& GENERIC_READ
) && Object
->ExclusiveRead
!= 0) ||
250 ((DesiredAccess
& GENERIC_WRITE
) && Object
->ExclusiveWrite
!= 0) ||
251 (!(ShareMode
& FILE_SHARE_READ
) && Object
->AccessRead
!= 0) ||
252 (!(ShareMode
& FILE_SHARE_WRITE
) && Object
->AccessWrite
!= 0))
254 DPRINT1("Sharing violation\n");
255 Status
= STATUS_SHARING_VIOLATION
;
259 Status
= Win32CsrInsertObject(ProcessData
,
260 &OpenConsoleRequest
->ConsoleHandle
,
263 OpenConsoleRequest
->Inheritable
,
267 LeaveCriticalSection(&Console
->Lock
);
270 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
275 CSR_API(SrvAllocConsole
)
277 NTSTATUS Status
= STATUS_SUCCESS
;
278 PCONSOLE_ALLOCCONSOLE AllocConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.AllocConsoleRequest
;
279 PCSR_PROCESS ConsoleLeader
= CsrGetClientThread()->Process
;
280 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(ConsoleLeader
);
282 DPRINT("SrvAllocConsole\n");
284 if (ProcessData
->Console
!= NULL
)
286 DPRINT1("Process already has a console\n");
287 return STATUS_ACCESS_DENIED
;
290 /******************************************************************************/
291 /** This comes from ConsoleConnect!! **/
292 DPRINT1("SrvAllocConsole - Checkpoint 1\n");
295 * We are about to create a new console. However when ConsoleNewProcess
296 * was called, we didn't know that we wanted to create a new console and
297 * therefore, we by default inherited the handles table from our parent
298 * process. It's only now that we notice that in fact we do not need
299 * them, because we've created a new console and thus we must use it.
301 * Therefore, free the console we can have and our handles table,
302 * and recreate a new one later on.
304 Win32CsrReleaseConsole(ProcessData
);
305 // Win32CsrFreeHandlesTable(ProcessData);
307 /* Initialize a new Console owned by the Console Leader Process */
308 Status
= Win32CsrAllocateConsole(ProcessData
,
309 &AllocConsoleRequest
->InputHandle
,
310 &AllocConsoleRequest
->OutputHandle
,
311 &AllocConsoleRequest
->ErrorHandle
,
312 AllocConsoleRequest
->ShowCmd
,
314 if (!NT_SUCCESS(Status
))
316 DPRINT1("Console allocation failed\n");
320 /* Add a reference count because the process is tied to the console */
321 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
323 /* Insert the process into the processes list of the console */
324 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
326 /* Duplicate the Event */
327 Status
= NtDuplicateObject(NtCurrentProcess(),
328 ProcessData
->Console
->InputBuffer
.ActiveEvent
,
329 ProcessData
->Process
->ProcessHandle
,
330 &ProcessData
->ConsoleEvent
,
331 EVENT_ALL_ACCESS
, 0, 0);
332 if (!NT_SUCCESS(Status
))
334 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
335 Win32CsrReleaseConsole(ProcessData
);
339 /* Return it to the caller */
340 AllocConsoleRequest
->Console
= ProcessData
->Console
;
342 /* Input Wait Handle */
343 AllocConsoleRequest
->InputWaitHandle
= ProcessData
->ConsoleEvent
;
345 /* Set the Ctrl Dispatcher */
346 ProcessData
->CtrlDispatcher
= AllocConsoleRequest
->CtrlDispatcher
;
347 DPRINT("CONSRV: CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
348 /******************************************************************************/
350 return STATUS_SUCCESS
;
353 CSR_API(SrvAttachConsole
)
355 NTSTATUS Status
= STATUS_SUCCESS
;
356 PCONSOLE_ATTACHCONSOLE AttachConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.AttachConsoleRequest
;
357 PCSR_PROCESS SourceProcess
= NULL
; // The parent process.
358 PCSR_PROCESS TargetProcess
= CsrGetClientThread()->Process
; // Ourselves.
359 HANDLE ProcessId
= ULongToHandle(AttachConsoleRequest
->ProcessId
);
360 PCONSOLE_PROCESS_DATA SourceProcessData
, TargetProcessData
;
362 DPRINT("SrvAttachConsole\n");
364 TargetProcessData
= ConsoleGetPerProcessData(TargetProcess
);
366 if (TargetProcessData
->Console
!= NULL
)
368 DPRINT1("Process already has a console\n");
369 return STATUS_ACCESS_DENIED
;
372 if (ProcessId
== ULongToHandle(ATTACH_PARENT_PROCESS
))
374 PROCESS_BASIC_INFORMATION ProcessInfo
;
375 ULONG Length
= sizeof(ProcessInfo
);
377 /* Get the real parent's ID */
379 Status
= NtQueryInformationProcess(TargetProcess
->ProcessHandle
,
380 ProcessBasicInformation
,
383 if (!NT_SUCCESS(Status
))
385 DPRINT1("SrvAttachConsole - Cannot retrieve basic process info, Status = %lu\n", Status
);
389 DPRINT("We, process (ID) %lu;%lu\n", TargetProcess
->ClientId
.UniqueProcess
, TargetProcess
->ClientId
.UniqueThread
);
390 ProcessId
= ULongToHandle(ProcessInfo
.InheritedFromUniqueProcessId
);
391 DPRINT("Parent process ID = %lu\n", ProcessId
);
394 /* Lock the target process via its PID */
395 DPRINT1("Lock process Id %lu\n", ProcessId
);
396 Status
= CsrLockProcessByClientId(ProcessId
, &SourceProcess
);
397 DPRINT1("Lock process Status %lu\n", Status
);
398 if (!NT_SUCCESS(Status
)) return Status
;
399 DPRINT1("AttachConsole OK\n");
401 /******************************************************************************/
402 /** This comes from ConsoleNewProcess!! **/
403 SourceProcessData
= ConsoleGetPerProcessData(SourceProcess
);
406 * We are about to create a new console. However when ConsoleNewProcess
407 * was called, we didn't know that we wanted to create a new console and
408 * therefore, we by default inherited the handles table from our parent
409 * process. It's only now that we notice that in fact we do not need
410 * them, because we've created a new console and thus we must use it.
412 * Therefore, free the console we can have and our handles table,
413 * and recreate a new one later on.
415 Win32CsrReleaseConsole(TargetProcessData
);
416 // Win32CsrFreeHandlesTable(TargetProcessData);
419 * Inherit the console from the parent,
420 * if any, otherwise return an error.
422 DPRINT1("SourceProcessData->Console = 0x%p\n", SourceProcessData
->Console
);
423 if (SourceProcessData
->Console
== NULL
)
425 Status
= STATUS_INVALID_HANDLE
;
428 TargetProcessData
->Console
= SourceProcessData
->Console
;
430 /// REMARK: This code comes from Win32CsrAllocateConsole.
431 /* Initialize the handles table */
432 Status
= Win32CsrInitHandlesTable(TargetProcessData
,
433 &AttachConsoleRequest
->InputHandle
,
434 &AttachConsoleRequest
->OutputHandle
,
435 &AttachConsoleRequest
->ErrorHandle
);
436 if (!NT_SUCCESS(Status
))
438 DPRINT1("Failed to initialize the handles table\n");
440 // Win32CsrReleaseConsole(TargetProcessData);
441 TargetProcessData
->Console
= NULL
;
445 /******************************************************************************/
447 /******************************************************************************/
448 /** This comes from ConsoleConnect / SrvAllocConsole!! **/
449 /* Add a reference count because the process is tied to the console */
450 _InterlockedIncrement(&TargetProcessData
->Console
->ReferenceCount
);
452 /* Insert the process into the processes list of the console */
453 InsertHeadList(&TargetProcessData
->Console
->ProcessList
, &TargetProcessData
->ConsoleLink
);
455 /** Here, we inherited the console handles from the "source" process,
456 ** so no need to reinitialize the handles table. **/
458 DPRINT1("SrvAttachConsole - Checkpoint\n");
460 /* Duplicate the Event */
461 Status
= NtDuplicateObject(NtCurrentProcess(),
462 TargetProcessData
->Console
->InputBuffer
.ActiveEvent
,
463 TargetProcessData
->Process
->ProcessHandle
,
464 &TargetProcessData
->ConsoleEvent
,
465 EVENT_ALL_ACCESS
, 0, 0);
466 if (!NT_SUCCESS(Status
))
468 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
469 Win32CsrReleaseConsole(TargetProcessData
);
473 /* Return it to the caller */
474 AttachConsoleRequest
->Console
= TargetProcessData
->Console
;
476 /* Input Wait Handle */
477 AttachConsoleRequest
->InputWaitHandle
= TargetProcessData
->ConsoleEvent
;
479 /* Set the Ctrl Dispatcher */
480 TargetProcessData
->CtrlDispatcher
= AttachConsoleRequest
->CtrlDispatcher
;
481 DPRINT("CONSRV: CtrlDispatcher address: %x\n", TargetProcessData
->CtrlDispatcher
);
483 Status
= STATUS_SUCCESS
;
484 /******************************************************************************/
487 DPRINT1("SrvAttachConsole - exiting 1\n");
488 /* Unlock the "source" process */
489 CsrUnlockProcess(SourceProcess
);
490 DPRINT1("SrvAttachConsole - exiting 2\n");
495 CSR_API(SrvFreeConsole
)
497 DPRINT1("SrvFreeConsole\n");
498 Win32CsrReleaseConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
));
499 return STATUS_SUCCESS
;
503 ConioDeleteConsole(PCONSOLE Console
)
507 DPRINT("ConioDeleteConsole\n");
509 /* Drain input event queue */
510 while (Console
->InputBuffer
.InputEvents
.Flink
!= &Console
->InputBuffer
.InputEvents
)
512 Event
= (ConsoleInput
*) Console
->InputBuffer
.InputEvents
.Flink
;
513 Console
->InputBuffer
.InputEvents
.Flink
= Console
->InputBuffer
.InputEvents
.Flink
->Flink
;
514 Console
->InputBuffer
.InputEvents
.Flink
->Flink
->Blink
= &Console
->InputBuffer
.InputEvents
;
515 RtlFreeHeap(ConSrvHeap
, 0, Event
);
518 ConioCleanupConsole(Console
);
519 if (Console
->LineBuffer
)
520 RtlFreeHeap(ConSrvHeap
, 0, Console
->LineBuffer
);
521 while (!IsListEmpty(&Console
->HistoryBuffers
))
522 HistoryDeleteBuffer((struct _HISTORY_BUFFER
*)Console
->HistoryBuffers
.Flink
);
524 ConioDeleteScreenBuffer(Console
->ActiveBuffer
);
525 if (!IsListEmpty(&Console
->BufferList
))
527 DPRINT1("BUG: screen buffer list not empty\n");
530 CloseHandle(Console
->InputBuffer
.ActiveEvent
);
531 if (Console
->UnpauseEvent
) CloseHandle(Console
->UnpauseEvent
);
532 DeleteCriticalSection(&Console
->Lock
);
533 RtlFreeUnicodeString(&Console
->Title
);
534 IntDeleteAllAliases(Console
->Aliases
);
535 RtlFreeHeap(ConSrvHeap
, 0, Console
);
539 CsrInitConsoleSupport(VOID
)
541 DPRINT("CSR: CsrInitConsoleSupport()\n");
543 /* Should call LoadKeyboardLayout */
547 ConioPause(PCONSOLE Console
, UINT Flags
)
549 Console
->PauseFlags
|= Flags
;
550 if (!Console
->UnpauseEvent
)
551 Console
->UnpauseEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
555 ConioUnpause(PCONSOLE Console
, UINT Flags
)
557 Console
->PauseFlags
&= ~Flags
;
559 // if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0)
560 if (Console
->PauseFlags
== 0 && Console
->UnpauseEvent
)
562 SetEvent(Console
->UnpauseEvent
);
563 CloseHandle(Console
->UnpauseEvent
);
564 Console
->UnpauseEvent
= NULL
;
566 CsrNotifyWait(&Console
->WriteWaitQueue
,
573 CSR_API(SrvSetConsoleMode
)
576 PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleModeRequest
;
577 Object_t
* Object
= NULL
;
579 DPRINT("SrvSetConsoleMode\n");
581 Status
= Win32CsrLockObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
582 ConsoleModeRequest
->ConsoleHandle
,
583 &Object
, GENERIC_WRITE
, 0);
584 if (!NT_SUCCESS(Status
)) return Status
;
586 Status
= STATUS_SUCCESS
;
588 if (CONIO_INPUT_BUFFER_MAGIC
== Object
->Type
)
590 PCONSOLE Console
= (PCONSOLE
)Object
;
591 Console
->InputBuffer
.Mode
= ConsoleModeRequest
->ConsoleMode
& CONSOLE_INPUT_MODE_VALID
;
593 else if (CONIO_SCREEN_BUFFER_MAGIC
== Object
->Type
)
595 PCONSOLE_SCREEN_BUFFER Buff
= (PCONSOLE_SCREEN_BUFFER
)Object
;
596 Buff
->Mode
= ConsoleModeRequest
->ConsoleMode
& CONSOLE_OUTPUT_MODE_VALID
;
600 Status
= STATUS_INVALID_HANDLE
;
603 Win32CsrUnlockObject(Object
);
608 CSR_API(SrvGetConsoleMode
)
611 PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleModeRequest
;
612 Object_t
* Object
= NULL
;
614 DPRINT("SrvGetConsoleMode\n");
616 Status
= Win32CsrLockObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
617 ConsoleModeRequest
->ConsoleHandle
,
618 &Object
, GENERIC_READ
, 0);
619 if (!NT_SUCCESS(Status
)) return Status
;
621 Status
= STATUS_SUCCESS
;
623 if (CONIO_INPUT_BUFFER_MAGIC
== Object
->Type
)
625 PCONSOLE Console
= (PCONSOLE
)Object
;
626 ConsoleModeRequest
->ConsoleMode
= Console
->InputBuffer
.Mode
;
628 else if (CONIO_SCREEN_BUFFER_MAGIC
== Object
->Type
)
630 PCONSOLE_SCREEN_BUFFER Buff
= (PCONSOLE_SCREEN_BUFFER
)Object
;
631 ConsoleModeRequest
->ConsoleMode
= Buff
->Mode
;
635 Status
= STATUS_INVALID_HANDLE
;
638 Win32CsrUnlockObject(Object
);
643 CSR_API(SrvSetConsoleTitle
)
646 PCONSOLE_GETSETCONSOLETITLE TitleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.TitleRequest
;
647 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
651 DPRINT("SrvSetConsoleTitle\n");
653 if (!CsrValidateMessageBuffer(ApiMessage
,
654 (PVOID
)&TitleRequest
->Title
,
655 TitleRequest
->Length
,
658 return STATUS_INVALID_PARAMETER
;
661 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
662 if(NT_SUCCESS(Status
))
664 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, TitleRequest
->Length
);
667 /* Copy title to console */
668 RtlFreeUnicodeString(&Console
->Title
);
669 Console
->Title
.Buffer
= Buffer
;
670 Console
->Title
.Length
= Console
->Title
.MaximumLength
= TitleRequest
->Length
;
671 memcpy(Console
->Title
.Buffer
, TitleRequest
->Title
, Console
->Title
.Length
);
673 if (!ConioChangeTitle(Console
))
675 Status
= STATUS_UNSUCCESSFUL
;
679 Status
= STATUS_SUCCESS
;
684 Status
= STATUS_NO_MEMORY
;
687 ConioUnlockConsole(Console
);
693 CSR_API(SrvGetConsoleTitle
)
696 PCONSOLE_GETSETCONSOLETITLE TitleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.TitleRequest
;
697 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
701 DPRINT("SrvGetConsoleTitle\n");
703 if (!CsrValidateMessageBuffer(ApiMessage
,
704 (PVOID
)&TitleRequest
->Title
,
705 TitleRequest
->Length
,
708 return STATUS_INVALID_PARAMETER
;
711 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
712 if (!NT_SUCCESS(Status
))
714 DPRINT1("Can't get console\n");
718 /* Copy title of the console to the user title buffer */
719 if (TitleRequest
->Length
>= sizeof(WCHAR
))
721 Length
= min(TitleRequest
->Length
- sizeof(WCHAR
), Console
->Title
.Length
);
722 memcpy(TitleRequest
->Title
, Console
->Title
.Buffer
, Length
);
723 TitleRequest
->Title
[Length
/ sizeof(WCHAR
)] = L
'\0';
726 TitleRequest
->Length
= Console
->Title
.Length
;
728 ConioUnlockConsole(Console
);
729 return STATUS_SUCCESS
;
732 /**********************************************************************
733 * HardwareStateProperty
736 * Set/Get the value of the HardwareState and switch
737 * between direct video buffer ouput and GDI windowed
740 * Client hands us a CONSOLE_GETSETHWSTATE object.
741 * We use the same object to Request.
743 * ConsoleHwState has the correct size to be compatible
744 * with NT's, but values are not.
746 static NTSTATUS FASTCALL
747 SetConsoleHardwareState(PCONSOLE Console
, DWORD ConsoleHwState
)
749 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
751 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
752 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
754 if (Console
->HardwareState
!= ConsoleHwState
)
756 /* TODO: implement switching from full screen to windowed mode */
757 /* TODO: or back; now simply store the hardware state */
758 Console
->HardwareState
= ConsoleHwState
;
761 return STATUS_SUCCESS
;
764 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
767 CSR_API(SrvGetConsoleHardwareState
)
770 PCONSOLE_GETSETHWSTATE HardwareStateRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.HardwareStateRequest
;
771 PCONSOLE_SCREEN_BUFFER Buff
;
774 DPRINT("SrvGetConsoleHardwareState\n");
776 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
777 HardwareStateRequest
->OutputHandle
,
780 if (!NT_SUCCESS(Status
))
782 DPRINT1("Failed to get console handle in SrvGetConsoleHardwareState\n");
786 Console
= Buff
->Header
.Console
;
787 HardwareStateRequest
->State
= Console
->HardwareState
;
789 ConioUnlockScreenBuffer(Buff
);
794 CSR_API(SrvSetConsoleHardwareState
)
797 PCONSOLE_GETSETHWSTATE HardwareStateRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.HardwareStateRequest
;
798 PCONSOLE_SCREEN_BUFFER Buff
;
801 DPRINT("SrvSetConsoleHardwareState\n");
803 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
804 HardwareStateRequest
->OutputHandle
,
807 if (!NT_SUCCESS(Status
))
809 DPRINT1("Failed to get console handle in SrvSetConsoleHardwareState\n");
813 DPRINT("Setting console hardware state.\n");
814 Console
= Buff
->Header
.Console
;
815 Status
= SetConsoleHardwareState(Console
, HardwareStateRequest
->State
);
817 ConioUnlockScreenBuffer(Buff
);
822 CSR_API(SrvGetConsoleWindow
)
825 PCONSOLE_GETWINDOW GetWindowRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetWindowRequest
;
828 DPRINT("SrvGetConsoleWindow\n");
830 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
831 if (!NT_SUCCESS(Status
)) return Status
;
833 GetWindowRequest
->WindowHandle
= Console
->hWindow
;
834 ConioUnlockConsole(Console
);
836 return STATUS_SUCCESS
;
839 CSR_API(SrvSetConsoleIcon
)
842 PCONSOLE_SETICON SetIconRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetIconRequest
;
845 DPRINT("SrvSetConsoleIcon\n");
847 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
848 if (!NT_SUCCESS(Status
)) return Status
;
850 Status
= (ConioChangeIcon(Console
, SetIconRequest
->WindowIcon
)
852 : STATUS_UNSUCCESSFUL
);
854 ConioUnlockConsole(Console
);
859 CSR_API(SrvGetConsoleCP
)
862 PCONSOLE_GETSETINPUTOUTPUTCP ConsoleCPRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleCPRequest
;
865 DPRINT("SrvGetConsoleCP, getting %s Code Page\n",
866 ConsoleCPRequest
->InputCP
? "Input" : "Output");
868 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
869 if (!NT_SUCCESS(Status
)) return Status
;
871 ConsoleCPRequest
->CodePage
= (ConsoleCPRequest
->InputCP
? Console
->CodePage
872 : Console
->OutputCodePage
);
873 ConioUnlockConsole(Console
);
874 return STATUS_SUCCESS
;
877 CSR_API(SrvSetConsoleCP
)
880 PCONSOLE_GETSETINPUTOUTPUTCP ConsoleCPRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleCPRequest
;
883 DPRINT("SrvSetConsoleCP, setting %s Code Page\n",
884 ConsoleCPRequest
->InputCP
? "Input" : "Output");
886 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
887 if (!NT_SUCCESS(Status
)) return Status
;
889 if (IsValidCodePage(ConsoleCPRequest
->CodePage
))
891 if (ConsoleCPRequest
->InputCP
)
892 Console
->CodePage
= ConsoleCPRequest
->CodePage
;
894 Console
->OutputCodePage
= ConsoleCPRequest
->CodePage
;
896 ConioUnlockConsole(Console
);
897 return STATUS_SUCCESS
;
900 ConioUnlockConsole(Console
);
901 return STATUS_INVALID_PARAMETER
;
904 CSR_API(SrvGetConsoleProcessList
)
907 PCONSOLE_GETPROCESSLIST GetProcessListRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetProcessListRequest
;
909 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
911 PCONSOLE_PROCESS_DATA current
;
912 PLIST_ENTRY current_entry
;
915 DPRINT("SrvGetConsoleProcessList\n");
917 if (!CsrValidateMessageBuffer(ApiMessage
,
918 (PVOID
)&GetProcessListRequest
->pProcessIds
,
919 GetProcessListRequest
->nMaxIds
,
922 return STATUS_INVALID_PARAMETER
;
925 Buffer
= GetProcessListRequest
->pProcessIds
;
927 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
928 if (!NT_SUCCESS(Status
)) return Status
;
930 for (current_entry
= Console
->ProcessList
.Flink
;
931 current_entry
!= &Console
->ProcessList
;
932 current_entry
= current_entry
->Flink
)
934 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
935 if (++nItems
<= GetProcessListRequest
->nMaxIds
)
937 *Buffer
++ = HandleToUlong(current
->Process
->ClientId
.UniqueProcess
);
941 ConioUnlockConsole(Console
);
943 GetProcessListRequest
->nProcessIdsTotal
= nItems
;
944 return STATUS_SUCCESS
;
947 CSR_API(SrvGenerateConsoleCtrlEvent
)
950 PCONSOLE_GENERATECTRLEVENT GenerateCtrlEventRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GenerateCtrlEventRequest
;
952 PCONSOLE_PROCESS_DATA current
;
953 PLIST_ENTRY current_entry
;
956 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
957 if (!NT_SUCCESS(Status
)) return Status
;
959 Group
= GenerateCtrlEventRequest
->ProcessGroup
;
960 Status
= STATUS_INVALID_PARAMETER
;
961 for (current_entry
= Console
->ProcessList
.Flink
;
962 current_entry
!= &Console
->ProcessList
;
963 current_entry
= current_entry
->Flink
)
965 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
966 if (Group
== 0 || current
->Process
->ProcessGroupId
== Group
)
968 ConioConsoleCtrlEvent(GenerateCtrlEventRequest
->Event
, current
);
969 Status
= STATUS_SUCCESS
;
973 ConioUnlockConsole(Console
);
978 CSR_API(SrvGetConsoleSelectionInfo
)
981 PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetSelectionInfoRequest
;
984 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
985 if (NT_SUCCESS(Status
))
987 memset(&GetSelectionInfoRequest
->Info
, 0, sizeof(CONSOLE_SELECTION_INFO
));
988 if (Console
->Selection
.dwFlags
!= 0)
989 GetSelectionInfoRequest
->Info
= Console
->Selection
;
990 ConioUnlockConsole(Console
);