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 ConioConsoleFromProcessData(PCONSOLE_PROCESS_DATA ProcessData
,
36 PCSRSS_CONSOLE
*Console
)
38 PCSRSS_CONSOLE ProcessConsole
;
40 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
41 ProcessConsole
= ProcessData
->Console
;
46 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
47 return STATUS_INVALID_HANDLE
;
50 InterlockedIncrement(&ProcessConsole
->ReferenceCount
);
51 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
52 EnterCriticalSection(&(ProcessConsole
->Lock
));
53 *Console
= ProcessConsole
;
55 return STATUS_SUCCESS
;
59 ConioConsoleCtrlEventTimeout(DWORD Event
,
60 PCONSOLE_PROCESS_DATA ProcessData
,
65 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData
->Process
->ClientId
.UniqueProcess
);
67 if (ProcessData
->CtrlDispatcher
)
69 Thread
= CreateRemoteThread(ProcessData
->Process
->ProcessHandle
, NULL
, 0,
70 ProcessData
->CtrlDispatcher
,
71 UlongToPtr(Event
), 0, NULL
);
74 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
78 DPRINT1("We succeeded at creating ProcessData->CtrlDispatcher remote thread, ProcessId = %x, Process = 0x%p\n", ProcessData
->Process
->ClientId
.UniqueProcess
, ProcessData
->Process
);
79 WaitForSingleObject(Thread
, Timeout
);
85 ConioConsoleCtrlEvent(DWORD Event
, PCONSOLE_PROCESS_DATA ProcessData
)
87 ConioConsoleCtrlEventTimeout(Event
, ProcessData
, 0);
91 CsrInitConsole(PCSRSS_CONSOLE
* NewConsole
, int ShowCmd
, PCSR_PROCESS ConsoleLeaderProcess
)
94 SECURITY_ATTRIBUTES SecurityAttributes
;
95 PCSRSS_CONSOLE Console
;
96 PCSRSS_SCREEN_BUFFER NewBuffer
;
100 if (NewConsole
== NULL
) return STATUS_INVALID_PARAMETER
;
104 /* Allocate a console structure */
105 Console
= HeapAlloc(ConSrvHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_CONSOLE
));
108 DPRINT1("Not enough memory for console creation.\n");
109 return STATUS_NO_MEMORY
;
112 /* Initialize the console */
113 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
114 Console
->Title
.Buffer
= NULL
;
116 if (LoadStringW(ConSrvDllInstance
, IDS_COMMAND_PROMPT
, Title
, sizeof(Title
) / sizeof(Title
[0])))
118 RtlCreateUnicodeString(&Console
->Title
, Title
);
122 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
125 Console
->ReferenceCount
= 0;
126 Console
->LineBuffer
= NULL
;
127 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
128 Console
->Header
.Console
= Console
;
129 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
130 Console
->ConsoleLeaderCID
= ConsoleLeaderProcess
->ClientId
;
131 InitializeListHead(&Console
->ProcessList
);
132 InitializeListHead(&Console
->BufferList
);
133 Console
->ActiveBuffer
= NULL
;
134 InitializeListHead(&Console
->ReadWaitQueue
);
135 InitializeListHead(&Console
->WriteWaitQueue
);
136 InitializeListHead(&Console
->InputEvents
);
137 InitializeListHead(&Console
->HistoryBuffers
);
138 Console
->CodePage
= GetOEMCP();
139 Console
->OutputCodePage
= GetOEMCP();
141 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
142 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
143 SecurityAttributes
.bInheritHandle
= TRUE
;
145 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
146 if (NULL
== Console
->ActiveEvent
)
148 RtlFreeUnicodeString(&Console
->Title
);
149 HeapFree(ConSrvHeap
, 0, Console
);
150 return STATUS_UNSUCCESSFUL
;
152 Console
->PrivateData
= NULL
;
153 InitializeCriticalSection(&Console
->Lock
);
155 GuiMode
= DtbgIsDesktopVisible();
157 /* allocate console screen buffer */
158 NewBuffer
= HeapAlloc(ConSrvHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
159 if (NULL
== NewBuffer
)
161 RtlFreeUnicodeString(&Console
->Title
);
162 DeleteCriticalSection(&Console
->Lock
);
163 CloseHandle(Console
->ActiveEvent
);
164 HeapFree(ConSrvHeap
, 0, Console
);
165 return STATUS_INSUFFICIENT_RESOURCES
;
167 /* init screen buffer with defaults */
168 NewBuffer
->CursorInfo
.bVisible
= TRUE
;
169 NewBuffer
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
170 /* make console active, and insert into console list */
171 Console
->ActiveBuffer
= (PCSRSS_SCREEN_BUFFER
) NewBuffer
;
174 * If we are not in GUI-mode, start the text-mode console. If we fail,
175 * try to start the GUI-mode console (win32k will automatically switch
176 * to graphical mode, therefore no additional code is needed).
180 DPRINT1("CONSRV: Opening text-mode console\n");
181 Status
= TuiInitConsole(Console
);
182 if (!NT_SUCCESS(Status
))
184 DPRINT1("Failed to open text-mode console, switching to gui-mode, Status = 0x%08lx\n", Status
);
190 * Try to open the GUI-mode console. Two cases are possible:
191 * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
192 * failed and we start GUI-mode console.
193 * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
194 * succeeded BUT we failed at starting text-mode console. Then GuiMode
195 * was switched to TRUE in order to try to open the console in GUI-mode.
199 DPRINT1("CONSRV: Opening GUI-mode console\n");
200 Status
= GuiInitConsole(Console
, ShowCmd
);
201 if (!NT_SUCCESS(Status
))
203 HeapFree(ConSrvHeap
,0, NewBuffer
);
204 RtlFreeUnicodeString(&Console
->Title
);
205 DeleteCriticalSection(&Console
->Lock
);
206 CloseHandle(Console
->ActiveEvent
);
207 DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status
);
208 HeapFree(ConSrvHeap
, 0, Console
);
213 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
214 if (!NT_SUCCESS(Status
))
216 ConioCleanupConsole(Console
);
217 RtlFreeUnicodeString(&Console
->Title
);
218 DeleteCriticalSection(&Console
->Lock
);
219 CloseHandle(Console
->ActiveEvent
);
220 HeapFree(ConSrvHeap
, 0, NewBuffer
);
221 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
222 HeapFree(ConSrvHeap
, 0, Console
);
226 /* Copy buffer contents to screen */
227 ConioDrawConsole(Console
);
229 *NewConsole
= Console
;
231 return STATUS_SUCCESS
;
234 CSR_API(SrvOpenConsole
)
236 NTSTATUS Status
= STATUS_SUCCESS
;
237 PCSRSS_OPEN_CONSOLE OpenConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.OpenConsoleRequest
;
238 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
240 DPRINT("SrvOpenConsole\n");
242 OpenConsoleRequest
->Handle
= INVALID_HANDLE_VALUE
;
244 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
246 DPRINT1("SrvOpenConsole - Checkpoint 1\n");
247 DPRINT1("ProcessData = 0x%p ; ProcessData->Console = 0x%p\n", ProcessData
, ProcessData
->Console
);
249 if (ProcessData
->Console
)
251 DWORD DesiredAccess
= OpenConsoleRequest
->Access
;
252 DWORD ShareMode
= OpenConsoleRequest
->ShareMode
;
254 PCSRSS_CONSOLE Console
= ProcessData
->Console
;
257 DPRINT1("SrvOpenConsole - Checkpoint 2\n");
258 EnterCriticalSection(&Console
->Lock
);
259 DPRINT1("SrvOpenConsole - Checkpoint 3\n");
261 if (OpenConsoleRequest
->HandleType
== HANDLE_OUTPUT
)
262 Object
= &Console
->ActiveBuffer
->Header
;
264 Object
= &Console
->Header
;
266 if (((DesiredAccess
& GENERIC_READ
) && Object
->ExclusiveRead
!= 0) ||
267 ((DesiredAccess
& GENERIC_WRITE
) && Object
->ExclusiveWrite
!= 0) ||
268 (!(ShareMode
& FILE_SHARE_READ
) && Object
->AccessRead
!= 0) ||
269 (!(ShareMode
& FILE_SHARE_WRITE
) && Object
->AccessWrite
!= 0))
271 DPRINT1("Sharing violation\n");
272 Status
= STATUS_SHARING_VIOLATION
;
276 Status
= Win32CsrInsertObject(ProcessData
,
277 &OpenConsoleRequest
->Handle
,
280 OpenConsoleRequest
->Inheritable
,
284 LeaveCriticalSection(&Console
->Lock
);
287 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
292 CSR_API(SrvAllocConsole
)
294 NTSTATUS Status
= STATUS_SUCCESS
;
295 PCSRSS_ALLOC_CONSOLE AllocConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.AllocConsoleRequest
;
296 PCSR_PROCESS ConsoleLeader
= CsrGetClientThread()->Process
;
297 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(ConsoleLeader
);
299 DPRINT("SrvAllocConsole\n");
301 if (ProcessData
->Console
!= NULL
)
303 DPRINT1("Process already has a console\n");
304 return STATUS_INVALID_PARAMETER
;
307 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
309 DPRINT1("SrvAllocConsole - Checkpoint 1\n");
311 /* Initialize a new Console owned by the Console Leader Process */
312 Status
= CsrInitConsole(&ProcessData
->Console
, AllocConsoleRequest
->ShowCmd
, ConsoleLeader
);
313 if (!NT_SUCCESS(Status
))
315 DPRINT1("Console initialization failed\n");
316 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
320 /* Insert the process into the processes list of the console */
321 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
323 /* Return it to the caller */
324 AllocConsoleRequest
->Console
= ProcessData
->Console
;
326 /* Add a reference count because the process is tied to the console */
327 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
331 * We've just created a new console. However when ConsoleNewProcess was
332 * called, we didn't know that we wanted to create a new console and
333 * therefore, we by default inherited the handles table from our parent
334 * process. It's only now that we notice that in fact we do not need
335 * them, because we've created a new console and thus we must use it.
337 * Therefore, free our handles table and recreate a new one.
342 /* Close all console handles and free the handle table memory */
343 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
345 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
347 ProcessData
->HandleTableSize
= 0;
348 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
349 ProcessData
->HandleTable
= NULL
;
353 * Create a new handle table - Insert the IO handles
356 /* Insert the Input handle */
357 Status
= Win32CsrInsertObject(ProcessData
,
358 &AllocConsoleRequest
->InputHandle
,
359 &ProcessData
->Console
->Header
,
360 GENERIC_READ
| GENERIC_WRITE
,
362 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
363 if (!NT_SUCCESS(Status
))
365 DPRINT1("Failed to insert the input handle\n");
366 ConioDeleteConsole(ProcessData
->Console
);
367 ProcessData
->Console
= NULL
;
368 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
372 /* Insert the Output handle */
373 Status
= Win32CsrInsertObject(ProcessData
,
374 &AllocConsoleRequest
->OutputHandle
,
375 &ProcessData
->Console
->ActiveBuffer
->Header
,
376 GENERIC_READ
| GENERIC_WRITE
,
378 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
379 if (!NT_SUCCESS(Status
))
381 DPRINT1("Failed to insert the output handle\n");
382 ConioDeleteConsole(ProcessData
->Console
);
383 Win32CsrReleaseObject(ProcessData
,
384 AllocConsoleRequest
->InputHandle
);
385 ProcessData
->Console
= NULL
;
386 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
390 /* Insert the Error handle */
391 Status
= Win32CsrInsertObject(ProcessData
,
392 &AllocConsoleRequest
->ErrorHandle
,
393 &ProcessData
->Console
->ActiveBuffer
->Header
,
394 GENERIC_READ
| GENERIC_WRITE
,
396 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
397 if (!NT_SUCCESS(Status
))
399 DPRINT1("Failed to insert the error handle\n");
400 ConioDeleteConsole(ProcessData
->Console
);
401 Win32CsrReleaseObject(ProcessData
,
402 AllocConsoleRequest
->OutputHandle
);
403 Win32CsrReleaseObject(ProcessData
,
404 AllocConsoleRequest
->InputHandle
);
405 ProcessData
->Console
= NULL
;
406 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
410 /* Duplicate the Event */
411 Status
= NtDuplicateObject(NtCurrentProcess(),
412 ProcessData
->Console
->ActiveEvent
,
413 ProcessData
->Process
->ProcessHandle
,
414 &ProcessData
->ConsoleEvent
,
415 EVENT_ALL_ACCESS
, 0, 0);
416 if (!NT_SUCCESS(Status
))
418 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
419 ConioDeleteConsole(ProcessData
->Console
);
420 // if (NewConsole /* || !ProcessData->bInheritHandles */)
422 Win32CsrReleaseObject(ProcessData
,
423 AllocConsoleRequest
->ErrorHandle
);
424 Win32CsrReleaseObject(ProcessData
,
425 AllocConsoleRequest
->OutputHandle
);
426 Win32CsrReleaseObject(ProcessData
,
427 AllocConsoleRequest
->InputHandle
);
429 ProcessData
->Console
= NULL
;
430 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
433 /* Input Wait Handle */
434 AllocConsoleRequest
->InputWaitHandle
= ProcessData
->ConsoleEvent
;
436 /* Set the Ctrl Dispatcher */
437 ProcessData
->CtrlDispatcher
= AllocConsoleRequest
->CtrlDispatcher
;
438 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
440 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
441 return STATUS_SUCCESS
;
444 CSR_API(SrvFreeConsole
)
446 DPRINT1("SrvFreeConsole\n");
447 Win32CsrReleaseConsole(CsrGetClientThread()->Process
);
448 return STATUS_SUCCESS
;
452 ConioDeleteConsole(PCSRSS_CONSOLE Console
)
456 DPRINT("ConioDeleteConsole\n");
458 /* Drain input event queue */
459 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
461 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
462 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
463 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
464 HeapFree(ConSrvHeap
, 0, Event
);
467 ConioCleanupConsole(Console
);
468 if (Console
->LineBuffer
)
469 RtlFreeHeap(ConSrvHeap
, 0, Console
->LineBuffer
);
470 while (!IsListEmpty(&Console
->HistoryBuffers
))
471 HistoryDeleteBuffer((struct tagHISTORY_BUFFER
*)Console
->HistoryBuffers
.Flink
);
473 ConioDeleteScreenBuffer(Console
->ActiveBuffer
);
474 if (!IsListEmpty(&Console
->BufferList
))
476 DPRINT1("BUG: screen buffer list not empty\n");
479 CloseHandle(Console
->ActiveEvent
);
480 if (Console
->UnpauseEvent
) CloseHandle(Console
->UnpauseEvent
);
481 DeleteCriticalSection(&Console
->Lock
);
482 RtlFreeUnicodeString(&Console
->Title
);
483 IntDeleteAllAliases(Console
->Aliases
);
484 HeapFree(ConSrvHeap
, 0, Console
);
488 CsrInitConsoleSupport(VOID
)
490 DPRINT("CSR: CsrInitConsoleSupport()\n");
492 /* Should call LoadKeyboardLayout */
496 ConioPause(PCSRSS_CONSOLE Console
, UINT Flags
)
498 Console
->PauseFlags
|= Flags
;
499 if (!Console
->UnpauseEvent
)
500 Console
->UnpauseEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
504 ConioUnpause(PCSRSS_CONSOLE Console
, UINT Flags
)
506 Console
->PauseFlags
&= ~Flags
;
508 // if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0)
509 if (Console
->PauseFlags
== 0 && Console
->UnpauseEvent
)
511 SetEvent(Console
->UnpauseEvent
);
512 CloseHandle(Console
->UnpauseEvent
);
513 Console
->UnpauseEvent
= NULL
;
515 CsrNotifyWait(&Console
->WriteWaitQueue
,
522 CSR_API(SrvSetConsoleMode
)
525 PCSRSS_CONSOLE_MODE ConsoleModeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleModeRequest
;
526 PCSRSS_CONSOLE Console
;
527 PCSRSS_SCREEN_BUFFER Buff
;
529 DPRINT("SrvSetConsoleMode\n");
531 Status
= Win32CsrLockObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
532 ConsoleModeRequest
->ConsoleHandle
,
533 (Object_t
**) &Console
, GENERIC_WRITE
, 0);
534 if (!NT_SUCCESS(Status
)) return Status
;
536 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
538 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
540 Console
->Mode
= ConsoleModeRequest
->ConsoleMode
& CONSOLE_INPUT_MODE_VALID
;
542 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
544 Buff
->Mode
= ConsoleModeRequest
->ConsoleMode
& CONSOLE_OUTPUT_MODE_VALID
;
548 Status
= STATUS_INVALID_HANDLE
;
551 Win32CsrUnlockObject((Object_t
*)Console
);
556 CSR_API(SrvGetConsoleMode
)
559 PCSRSS_CONSOLE_MODE ConsoleModeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleModeRequest
;
560 PCSRSS_CONSOLE Console
;
561 PCSRSS_SCREEN_BUFFER Buff
;
563 DPRINT("SrvGetConsoleMode\n");
565 Status
= Win32CsrLockObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
566 ConsoleModeRequest
->ConsoleHandle
,
567 (Object_t
**) &Console
, GENERIC_READ
, 0);
568 if (!NT_SUCCESS(Status
)) return Status
;
570 Status
= STATUS_SUCCESS
;
571 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
573 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
575 ConsoleModeRequest
->ConsoleMode
= Console
->Mode
;
577 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
579 ConsoleModeRequest
->ConsoleMode
= Buff
->Mode
;
583 Status
= STATUS_INVALID_HANDLE
;
586 Win32CsrUnlockObject((Object_t
*)Console
);
590 CSR_API(SrvSetConsoleTitle
)
593 PCSRSS_CONSOLE_TITLE TitleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.TitleRequest
;
594 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
595 PCSRSS_CONSOLE Console
;
598 DPRINT("SrvSetConsoleTitle\n");
600 if (!CsrValidateMessageBuffer(ApiMessage
,
601 (PVOID
)&TitleRequest
->Title
,
602 TitleRequest
->Length
,
605 return STATUS_INVALID_PARAMETER
;
608 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
609 if(NT_SUCCESS(Status
))
611 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, TitleRequest
->Length
);
614 /* Copy title to console */
615 RtlFreeUnicodeString(&Console
->Title
);
616 Console
->Title
.Buffer
= Buffer
;
617 Console
->Title
.Length
= Console
->Title
.MaximumLength
= TitleRequest
->Length
;
618 memcpy(Console
->Title
.Buffer
, TitleRequest
->Title
, Console
->Title
.Length
);
620 if (!ConioChangeTitle(Console
))
622 Status
= STATUS_UNSUCCESSFUL
;
626 Status
= STATUS_SUCCESS
;
631 Status
= STATUS_NO_MEMORY
;
634 ConioUnlockConsole(Console
);
640 CSR_API(SrvGetConsoleTitle
)
643 PCSRSS_CONSOLE_TITLE TitleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.TitleRequest
;
644 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
645 PCSRSS_CONSOLE Console
;
648 DPRINT("SrvGetConsoleTitle\n");
650 if (!CsrValidateMessageBuffer(ApiMessage
,
651 (PVOID
)&TitleRequest
->Title
,
652 TitleRequest
->Length
,
655 return STATUS_INVALID_PARAMETER
;
658 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
659 if (!NT_SUCCESS(Status
))
661 DPRINT1("Can't get console\n");
665 /* Copy title of the console to the user title buffer */
666 if (TitleRequest
->Length
>= sizeof(WCHAR
))
668 Length
= min(TitleRequest
->Length
- sizeof(WCHAR
), Console
->Title
.Length
);
669 memcpy(TitleRequest
->Title
, Console
->Title
.Buffer
, Length
);
670 TitleRequest
->Title
[Length
/ sizeof(WCHAR
)] = L
'\0';
673 TitleRequest
->Length
= Console
->Title
.Length
;
675 ConioUnlockConsole(Console
);
676 return STATUS_SUCCESS
;
679 /**********************************************************************
680 * HardwareStateProperty
683 * Set/Get the value of the HardwareState and switch
684 * between direct video buffer ouput and GDI windowed
687 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
688 * object. We use the same object to Request.
690 * ConsoleHwState has the correct size to be compatible
691 * with NT's, but values are not.
693 static NTSTATUS FASTCALL
694 SetConsoleHardwareState(PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
696 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
698 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
699 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
701 if (Console
->HardwareState
!= ConsoleHwState
)
703 /* TODO: implement switching from full screen to windowed mode */
704 /* TODO: or back; now simply store the hardware state */
705 Console
->HardwareState
= ConsoleHwState
;
708 return STATUS_SUCCESS
;
711 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
714 CSR_API(SrvGetConsoleHardwareState
)
717 PCSRSS_CONSOLE_HW_STATE ConsoleHardwareStateRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleHardwareStateRequest
;
718 PCSRSS_CONSOLE Console
;
720 DPRINT("SrvGetConsoleHardwareState\n");
722 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
723 ConsoleHardwareStateRequest
->ConsoleHandle
,
726 if (!NT_SUCCESS(Status
))
728 DPRINT1("Failed to get console handle in SrvGetConsoleHardwareState\n");
732 ConsoleHardwareStateRequest
->State
= Console
->HardwareState
;
734 ConioUnlockConsole(Console
);
739 CSR_API(SrvSetConsoleHardwareState
)
742 PCSRSS_CONSOLE_HW_STATE ConsoleHardwareStateRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleHardwareStateRequest
;
743 PCSRSS_CONSOLE Console
;
745 DPRINT("SrvSetConsoleHardwareState\n");
747 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
748 ConsoleHardwareStateRequest
->ConsoleHandle
,
751 if (!NT_SUCCESS(Status
))
753 DPRINT1("Failed to get console handle in SrvSetConsoleHardwareState\n");
757 DPRINT("Setting console hardware state.\n");
758 Status
= SetConsoleHardwareState(Console
, ConsoleHardwareStateRequest
->State
);
760 ConioUnlockConsole(Console
);
765 CSR_API(SrvGetConsoleWindow
)
768 PCSRSS_GET_CONSOLE_WINDOW GetConsoleWindowRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetConsoleWindowRequest
;
769 PCSRSS_CONSOLE Console
;
771 DPRINT("SrvGetConsoleWindow\n");
773 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
774 if (!NT_SUCCESS(Status
)) return Status
;
776 GetConsoleWindowRequest
->WindowHandle
= Console
->hWindow
;
777 ConioUnlockConsole(Console
);
779 return STATUS_SUCCESS
;
782 CSR_API(SrvSetConsoleIcon
)
785 PCSRSS_SET_CONSOLE_ICON SetConsoleIconRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetConsoleIconRequest
;
786 PCSRSS_CONSOLE Console
;
788 DPRINT("SrvSetConsoleIcon\n");
790 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
791 if (!NT_SUCCESS(Status
)) return Status
;
793 Status
= (ConioChangeIcon(Console
, SetConsoleIconRequest
->WindowIcon
)
795 : STATUS_UNSUCCESSFUL
);
797 ConioUnlockConsole(Console
);
802 CSR_API(SrvGetConsoleCP
)
805 PCSRSS_CONSOLE_CP ConsoleCPRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleCPRequest
;
806 PCSRSS_CONSOLE Console
;
808 DPRINT("SrvGetConsoleCP, getting %s Code Page\n",
809 ConsoleCPRequest
->InputCP
? "Input" : "Output");
811 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
812 if (!NT_SUCCESS(Status
)) return Status
;
814 ConsoleCPRequest
->CodePage
= (ConsoleCPRequest
->InputCP
? Console
->CodePage
815 : Console
->OutputCodePage
);
816 ConioUnlockConsole(Console
);
817 return STATUS_SUCCESS
;
820 CSR_API(SrvSetConsoleCP
)
823 PCSRSS_CONSOLE_CP ConsoleCPRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleCPRequest
;
824 PCSRSS_CONSOLE Console
;
826 DPRINT("SrvSetConsoleCP, setting %s Code Page\n",
827 ConsoleCPRequest
->InputCP
? "Input" : "Output");
829 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
830 if (!NT_SUCCESS(Status
)) return Status
;
832 if (IsValidCodePage(ConsoleCPRequest
->CodePage
))
834 if (ConsoleCPRequest
->InputCP
)
835 Console
->CodePage
= ConsoleCPRequest
->CodePage
;
837 Console
->OutputCodePage
= ConsoleCPRequest
->CodePage
;
839 ConioUnlockConsole(Console
);
840 return STATUS_SUCCESS
;
843 ConioUnlockConsole(Console
);
844 return STATUS_INVALID_PARAMETER
;
847 CSR_API(SrvGetConsoleProcessList
)
850 PCSRSS_GET_PROCESS_LIST GetProcessListRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetProcessListRequest
;
852 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
853 PCSRSS_CONSOLE Console
;
854 PCONSOLE_PROCESS_DATA current
;
855 PLIST_ENTRY current_entry
;
858 DPRINT("SrvGetConsoleProcessList\n");
860 if (!CsrValidateMessageBuffer(ApiMessage
,
861 (PVOID
)&GetProcessListRequest
->pProcessIds
,
862 GetProcessListRequest
->nMaxIds
,
865 return STATUS_INVALID_PARAMETER
;
868 Buffer
= GetProcessListRequest
->pProcessIds
;
870 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
871 if (!NT_SUCCESS(Status
)) return Status
;
873 for (current_entry
= Console
->ProcessList
.Flink
;
874 current_entry
!= &Console
->ProcessList
;
875 current_entry
= current_entry
->Flink
)
877 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
878 if (++nItems
<= GetProcessListRequest
->nMaxIds
)
880 *Buffer
++ = HandleToUlong(current
->Process
->ClientId
.UniqueProcess
);
884 ConioUnlockConsole(Console
);
886 GetProcessListRequest
->nProcessIdsTotal
= nItems
;
887 return STATUS_SUCCESS
;
890 CSR_API(SrvGenerateConsoleCtrlEvent
)
893 PCSRSS_GENERATE_CTRL_EVENT GenerateCtrlEvent
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GenerateCtrlEvent
;
894 PCSRSS_CONSOLE Console
;
895 PCONSOLE_PROCESS_DATA current
;
896 PLIST_ENTRY current_entry
;
899 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
900 if (!NT_SUCCESS(Status
)) return Status
;
902 Group
= GenerateCtrlEvent
->ProcessGroup
;
903 Status
= STATUS_INVALID_PARAMETER
;
904 for (current_entry
= Console
->ProcessList
.Flink
;
905 current_entry
!= &Console
->ProcessList
;
906 current_entry
= current_entry
->Flink
)
908 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
909 if (Group
== 0 || current
->Process
->ProcessGroupId
== Group
)
911 ConioConsoleCtrlEvent(GenerateCtrlEvent
->Event
, current
);
912 Status
= STATUS_SUCCESS
;
916 ConioUnlockConsole(Console
);
921 CSR_API(SrvGetConsoleSelectionInfo
)
924 PCSRSS_GET_CONSOLE_SELECTION_INFO GetConsoleSelectionInfo
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetConsoleSelectionInfo
;
925 PCSRSS_CONSOLE Console
;
927 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
928 if (NT_SUCCESS(Status
))
930 memset(&GetConsoleSelectionInfo
->Info
, 0, sizeof(CONSOLE_SELECTION_INFO
));
931 if (Console
->Selection
.dwFlags
!= 0)
932 GetConsoleSelectionInfo
->Info
= Console
->Selection
;
933 ConioUnlockConsole(Console
);