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);
90 /* static */ NTSTATUS WINAPI
91 CsrInitConsole(PCSRSS_CONSOLE
* NewConsole
, int ShowCmd
)
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 InitializeListHead(&Console
->ProcessList
);
131 InitializeListHead(&Console
->BufferList
);
132 Console
->ActiveBuffer
= NULL
;
133 InitializeListHead(&Console
->ReadWaitQueue
);
134 InitializeListHead(&Console
->WriteWaitQueue
);
135 InitializeListHead(&Console
->InputEvents
);
136 InitializeListHead(&Console
->HistoryBuffers
);
137 Console
->CodePage
= GetOEMCP();
138 Console
->OutputCodePage
= GetOEMCP();
140 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
141 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
142 SecurityAttributes
.bInheritHandle
= TRUE
;
144 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
145 if (NULL
== Console
->ActiveEvent
)
147 RtlFreeUnicodeString(&Console
->Title
);
148 HeapFree(ConSrvHeap
, 0, Console
);
149 return STATUS_UNSUCCESSFUL
;
151 Console
->PrivateData
= NULL
;
152 InitializeCriticalSection(&Console
->Lock
);
154 GuiMode
= DtbgIsDesktopVisible();
156 /* allocate console screen buffer */
157 NewBuffer
= HeapAlloc(ConSrvHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
158 if (NULL
== NewBuffer
)
160 RtlFreeUnicodeString(&Console
->Title
);
161 DeleteCriticalSection(&Console
->Lock
);
162 CloseHandle(Console
->ActiveEvent
);
163 HeapFree(ConSrvHeap
, 0, Console
);
164 return STATUS_INSUFFICIENT_RESOURCES
;
166 /* init screen buffer with defaults */
167 NewBuffer
->CursorInfo
.bVisible
= TRUE
;
168 NewBuffer
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
169 /* make console active, and insert into console list */
170 Console
->ActiveBuffer
= (PCSRSS_SCREEN_BUFFER
) NewBuffer
;
173 * If we are not in GUI-mode, start the text-mode console. If we fail,
174 * try to start the GUI-mode console (win32k will automatically switch
175 * to graphical mode, therefore no additional code is needed).
179 DPRINT1("CONSRV: Opening text-mode console\n");
180 Status
= TuiInitConsole(Console
);
181 if (!NT_SUCCESS(Status
))
183 DPRINT1("Failed to open text-mode console, switching to gui-mode, Status = 0x%08lx\n", Status
);
189 * Try to open the GUI-mode console. Two cases are possible:
190 * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
191 * failed and we start GUI-mode console.
192 * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
193 * succeeded BUT we failed at starting text-mode console. Then GuiMode
194 * was switched to TRUE in order to try to open the console in GUI-mode.
198 DPRINT1("CONSRV: Opening GUI-mode console\n");
199 Status
= GuiInitConsole(Console
, ShowCmd
);
200 if (!NT_SUCCESS(Status
))
202 HeapFree(ConSrvHeap
,0, NewBuffer
);
203 RtlFreeUnicodeString(&Console
->Title
);
204 DeleteCriticalSection(&Console
->Lock
);
205 CloseHandle(Console
->ActiveEvent
);
206 DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status
);
207 HeapFree(ConSrvHeap
, 0, Console
);
212 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
213 if (!NT_SUCCESS(Status
))
215 ConioCleanupConsole(Console
);
216 RtlFreeUnicodeString(&Console
->Title
);
217 DeleteCriticalSection(&Console
->Lock
);
218 CloseHandle(Console
->ActiveEvent
);
219 HeapFree(ConSrvHeap
, 0, NewBuffer
);
220 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
221 HeapFree(ConSrvHeap
, 0, Console
);
225 /* Copy buffer contents to screen */
226 ConioDrawConsole(Console
);
228 *NewConsole
= Console
;
230 return STATUS_SUCCESS
;
233 CSR_API(SrvOpenConsole
)
235 NTSTATUS Status
= STATUS_SUCCESS
;
236 PCSRSS_OPEN_CONSOLE OpenConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.OpenConsoleRequest
;
237 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
239 DPRINT("SrvOpenConsole\n");
241 OpenConsoleRequest
->Handle
= INVALID_HANDLE_VALUE
;
243 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
245 DPRINT1("SrvOpenConsole - Checkpoint 1\n");
246 DPRINT1("ProcessData = 0x%p ; ProcessData->Console = 0x%p\n", ProcessData
, ProcessData
->Console
);
248 if (ProcessData
->Console
)
250 DWORD DesiredAccess
= OpenConsoleRequest
->Access
;
251 DWORD ShareMode
= OpenConsoleRequest
->ShareMode
;
253 PCSRSS_CONSOLE Console
= ProcessData
->Console
;
256 DPRINT1("SrvOpenConsole - Checkpoint 2\n");
257 EnterCriticalSection(&Console
->Lock
);
258 DPRINT1("SrvOpenConsole - Checkpoint 3\n");
260 if (OpenConsoleRequest
->HandleType
== HANDLE_OUTPUT
)
261 Object
= &Console
->ActiveBuffer
->Header
;
263 Object
= &Console
->Header
;
265 if (((DesiredAccess
& GENERIC_READ
) && Object
->ExclusiveRead
!= 0) ||
266 ((DesiredAccess
& GENERIC_WRITE
) && Object
->ExclusiveWrite
!= 0) ||
267 (!(ShareMode
& FILE_SHARE_READ
) && Object
->AccessRead
!= 0) ||
268 (!(ShareMode
& FILE_SHARE_WRITE
) && Object
->AccessWrite
!= 0))
270 DPRINT1("Sharing violation\n");
271 Status
= STATUS_SHARING_VIOLATION
;
275 Status
= Win32CsrInsertObject(ProcessData
,
276 &OpenConsoleRequest
->Handle
,
279 OpenConsoleRequest
->Inheritable
,
283 LeaveCriticalSection(&Console
->Lock
);
286 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
291 CSR_API(SrvAllocConsole
)
293 NTSTATUS Status
= STATUS_SUCCESS
;
294 PCSRSS_ALLOC_CONSOLE AllocConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.AllocConsoleRequest
;
295 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
297 DPRINT("SrvAllocConsole\n");
299 if (ProcessData
->Console
!= NULL
)
301 DPRINT1("Process already has a console\n");
302 return STATUS_INVALID_PARAMETER
;
305 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
307 DPRINT1("SrvAllocConsole - Checkpoint 1\n");
309 /* Initialize a new Console */
310 Status
= CsrInitConsole(&ProcessData
->Console
, AllocConsoleRequest
->ShowCmd
);
311 if (!NT_SUCCESS(Status
))
313 DPRINT1("Console initialization failed\n");
314 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
318 /* Insert the process into the processes list of the console */
319 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
321 /* Return it to the caller */
322 AllocConsoleRequest
->Console
= ProcessData
->Console
;
324 /* Add a reference count because the process is tied to the console */
325 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
329 * We've just created a new console. However when ConsoleNewProcess was
330 * called, we didn't know that we wanted to create a new console and
331 * therefore, we by default inherited the handles table from our parent
332 * process. It's only now that we notice that in fact we do not need
333 * them, because we've created a new console and thus we must use it.
335 * Therefore, free our handles table and recreate a new one.
340 /* Close all console handles and free the handle table memory */
341 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
343 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
345 ProcessData
->HandleTableSize
= 0;
346 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
347 ProcessData
->HandleTable
= NULL
;
351 * Create a new handle table - Insert the IO handles
354 /* Insert the Input handle */
355 Status
= Win32CsrInsertObject(ProcessData
,
356 &AllocConsoleRequest
->InputHandle
,
357 &ProcessData
->Console
->Header
,
358 GENERIC_READ
| GENERIC_WRITE
,
360 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
361 if (!NT_SUCCESS(Status
))
363 DPRINT1("Failed to insert the input handle\n");
364 ConioDeleteConsole(ProcessData
->Console
);
365 ProcessData
->Console
= NULL
;
366 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
370 /* Insert the Output handle */
371 Status
= Win32CsrInsertObject(ProcessData
,
372 &AllocConsoleRequest
->OutputHandle
,
373 &ProcessData
->Console
->ActiveBuffer
->Header
,
374 GENERIC_READ
| GENERIC_WRITE
,
376 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
377 if (!NT_SUCCESS(Status
))
379 DPRINT1("Failed to insert the output handle\n");
380 ConioDeleteConsole(ProcessData
->Console
);
381 Win32CsrReleaseObject(ProcessData
,
382 AllocConsoleRequest
->InputHandle
);
383 ProcessData
->Console
= NULL
;
384 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
388 /* Insert the Error handle */
389 Status
= Win32CsrInsertObject(ProcessData
,
390 &AllocConsoleRequest
->ErrorHandle
,
391 &ProcessData
->Console
->ActiveBuffer
->Header
,
392 GENERIC_READ
| GENERIC_WRITE
,
394 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
395 if (!NT_SUCCESS(Status
))
397 DPRINT1("Failed to insert the error handle\n");
398 ConioDeleteConsole(ProcessData
->Console
);
399 Win32CsrReleaseObject(ProcessData
,
400 AllocConsoleRequest
->OutputHandle
);
401 Win32CsrReleaseObject(ProcessData
,
402 AllocConsoleRequest
->InputHandle
);
403 ProcessData
->Console
= NULL
;
404 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
408 /* Duplicate the Event */
409 Status
= NtDuplicateObject(NtCurrentProcess(),
410 ProcessData
->Console
->ActiveEvent
,
411 ProcessData
->Process
->ProcessHandle
,
412 &ProcessData
->ConsoleEvent
,
413 EVENT_ALL_ACCESS
, 0, 0);
414 if (!NT_SUCCESS(Status
))
416 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
417 ConioDeleteConsole(ProcessData
->Console
);
418 // if (NewConsole /* || !ProcessData->bInheritHandles */)
420 Win32CsrReleaseObject(ProcessData
,
421 AllocConsoleRequest
->ErrorHandle
);
422 Win32CsrReleaseObject(ProcessData
,
423 AllocConsoleRequest
->OutputHandle
);
424 Win32CsrReleaseObject(ProcessData
,
425 AllocConsoleRequest
->InputHandle
);
427 ProcessData
->Console
= NULL
;
428 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
431 /* Input Wait Handle */
432 AllocConsoleRequest
->InputWaitHandle
= ProcessData
->ConsoleEvent
;
434 /* Set the Ctrl Dispatcher */
435 ProcessData
->CtrlDispatcher
= AllocConsoleRequest
->CtrlDispatcher
;
436 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
438 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
439 return STATUS_SUCCESS
;
442 CSR_API(SrvFreeConsole
)
444 DPRINT1("SrvFreeConsole\n");
445 Win32CsrReleaseConsole(CsrGetClientThread()->Process
);
446 return STATUS_SUCCESS
;
450 ConioDeleteConsole(PCSRSS_CONSOLE Console
)
454 DPRINT("ConioDeleteConsole\n");
456 /* Drain input event queue */
457 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
459 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
460 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
461 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
462 HeapFree(ConSrvHeap
, 0, Event
);
465 ConioCleanupConsole(Console
);
466 if (Console
->LineBuffer
)
467 RtlFreeHeap(ConSrvHeap
, 0, Console
->LineBuffer
);
468 while (!IsListEmpty(&Console
->HistoryBuffers
))
469 HistoryDeleteBuffer((struct tagHISTORY_BUFFER
*)Console
->HistoryBuffers
.Flink
);
471 ConioDeleteScreenBuffer(Console
->ActiveBuffer
);
472 if (!IsListEmpty(&Console
->BufferList
))
474 DPRINT1("BUG: screen buffer list not empty\n");
477 CloseHandle(Console
->ActiveEvent
);
478 if (Console
->UnpauseEvent
) CloseHandle(Console
->UnpauseEvent
);
479 DeleteCriticalSection(&Console
->Lock
);
480 RtlFreeUnicodeString(&Console
->Title
);
481 IntDeleteAllAliases(Console
->Aliases
);
482 HeapFree(ConSrvHeap
, 0, Console
);
486 CsrInitConsoleSupport(VOID
)
488 DPRINT("CSR: CsrInitConsoleSupport()\n");
490 /* Should call LoadKeyboardLayout */
494 ConioPause(PCSRSS_CONSOLE Console
, UINT Flags
)
496 Console
->PauseFlags
|= Flags
;
497 if (!Console
->UnpauseEvent
)
498 Console
->UnpauseEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
502 ConioUnpause(PCSRSS_CONSOLE Console
, UINT Flags
)
504 Console
->PauseFlags
&= ~Flags
;
506 // if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0)
507 if (Console
->PauseFlags
== 0 && Console
->UnpauseEvent
)
509 SetEvent(Console
->UnpauseEvent
);
510 CloseHandle(Console
->UnpauseEvent
);
511 Console
->UnpauseEvent
= NULL
;
513 CsrNotifyWait(&Console
->WriteWaitQueue
,
520 CSR_API(SrvSetConsoleMode
)
523 PCSRSS_CONSOLE_MODE ConsoleModeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleModeRequest
;
524 PCSRSS_CONSOLE Console
;
525 PCSRSS_SCREEN_BUFFER Buff
;
527 DPRINT("SrvSetConsoleMode\n");
529 Status
= Win32CsrLockObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
530 ConsoleModeRequest
->ConsoleHandle
,
531 (Object_t
**) &Console
, GENERIC_WRITE
, 0);
532 if (!NT_SUCCESS(Status
)) return Status
;
534 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
536 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
538 Console
->Mode
= ConsoleModeRequest
->ConsoleMode
& CONSOLE_INPUT_MODE_VALID
;
540 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
542 Buff
->Mode
= ConsoleModeRequest
->ConsoleMode
& CONSOLE_OUTPUT_MODE_VALID
;
546 Status
= STATUS_INVALID_HANDLE
;
549 Win32CsrUnlockObject((Object_t
*)Console
);
554 CSR_API(SrvGetConsoleMode
)
557 PCSRSS_CONSOLE_MODE ConsoleModeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleModeRequest
;
558 PCSRSS_CONSOLE Console
;
559 PCSRSS_SCREEN_BUFFER Buff
;
561 DPRINT("SrvGetConsoleMode\n");
563 Status
= Win32CsrLockObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
564 ConsoleModeRequest
->ConsoleHandle
,
565 (Object_t
**) &Console
, GENERIC_READ
, 0);
566 if (!NT_SUCCESS(Status
)) return Status
;
568 Status
= STATUS_SUCCESS
;
569 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
571 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
573 ConsoleModeRequest
->ConsoleMode
= Console
->Mode
;
575 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
577 ConsoleModeRequest
->ConsoleMode
= Buff
->Mode
;
581 Status
= STATUS_INVALID_HANDLE
;
584 Win32CsrUnlockObject((Object_t
*)Console
);
588 CSR_API(SrvSetConsoleTitle
)
591 PCSRSS_CONSOLE_TITLE TitleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.TitleRequest
;
592 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
593 PCSRSS_CONSOLE Console
;
596 DPRINT("SrvSetConsoleTitle\n");
598 if (!CsrValidateMessageBuffer(ApiMessage
,
599 (PVOID
)&TitleRequest
->Title
,
600 TitleRequest
->Length
,
603 return STATUS_INVALID_PARAMETER
;
606 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
607 if(NT_SUCCESS(Status
))
609 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, TitleRequest
->Length
);
612 /* Copy title to console */
613 RtlFreeUnicodeString(&Console
->Title
);
614 Console
->Title
.Buffer
= Buffer
;
615 Console
->Title
.Length
= Console
->Title
.MaximumLength
= TitleRequest
->Length
;
616 memcpy(Console
->Title
.Buffer
, TitleRequest
->Title
, Console
->Title
.Length
);
618 if (!ConioChangeTitle(Console
))
620 Status
= STATUS_UNSUCCESSFUL
;
624 Status
= STATUS_SUCCESS
;
629 Status
= STATUS_NO_MEMORY
;
632 ConioUnlockConsole(Console
);
638 CSR_API(SrvGetConsoleTitle
)
641 PCSRSS_CONSOLE_TITLE TitleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.TitleRequest
;
642 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
643 PCSRSS_CONSOLE Console
;
646 DPRINT("SrvGetConsoleTitle\n");
648 if (!CsrValidateMessageBuffer(ApiMessage
,
649 (PVOID
)&TitleRequest
->Title
,
650 TitleRequest
->Length
,
653 return STATUS_INVALID_PARAMETER
;
656 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
657 if (!NT_SUCCESS(Status
))
659 DPRINT1("Can't get console\n");
663 /* Copy title of the console to the user title buffer */
664 if (TitleRequest
->Length
>= sizeof(WCHAR
))
666 Length
= min(TitleRequest
->Length
- sizeof(WCHAR
), Console
->Title
.Length
);
667 memcpy(TitleRequest
->Title
, Console
->Title
.Buffer
, Length
);
668 TitleRequest
->Title
[Length
/ sizeof(WCHAR
)] = L
'\0';
671 TitleRequest
->Length
= Console
->Title
.Length
;
673 ConioUnlockConsole(Console
);
674 return STATUS_SUCCESS
;
677 /**********************************************************************
678 * HardwareStateProperty
681 * Set/Get the value of the HardwareState and switch
682 * between direct video buffer ouput and GDI windowed
685 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
686 * object. We use the same object to Request.
688 * ConsoleHwState has the correct size to be compatible
689 * with NT's, but values are not.
691 static NTSTATUS FASTCALL
692 SetConsoleHardwareState(PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
694 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
696 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
697 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
699 if (Console
->HardwareState
!= ConsoleHwState
)
701 /* TODO: implement switching from full screen to windowed mode */
702 /* TODO: or back; now simply store the hardware state */
703 Console
->HardwareState
= ConsoleHwState
;
706 return STATUS_SUCCESS
;
709 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
712 CSR_API(SrvGetConsoleHardwareState
)
715 PCSRSS_CONSOLE_HW_STATE ConsoleHardwareStateRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleHardwareStateRequest
;
716 PCSRSS_CONSOLE Console
;
718 DPRINT("SrvGetConsoleHardwareState\n");
720 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
721 ConsoleHardwareStateRequest
->ConsoleHandle
,
724 if (!NT_SUCCESS(Status
))
726 DPRINT1("Failed to get console handle in SrvGetConsoleHardwareState\n");
730 ConsoleHardwareStateRequest
->State
= Console
->HardwareState
;
732 ConioUnlockConsole(Console
);
737 CSR_API(SrvSetConsoleHardwareState
)
740 PCSRSS_CONSOLE_HW_STATE ConsoleHardwareStateRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleHardwareStateRequest
;
741 PCSRSS_CONSOLE Console
;
743 DPRINT("SrvSetConsoleHardwareState\n");
745 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
746 ConsoleHardwareStateRequest
->ConsoleHandle
,
749 if (!NT_SUCCESS(Status
))
751 DPRINT1("Failed to get console handle in SrvSetConsoleHardwareState\n");
755 DPRINT("Setting console hardware state.\n");
756 Status
= SetConsoleHardwareState(Console
, ConsoleHardwareStateRequest
->State
);
758 ConioUnlockConsole(Console
);
763 CSR_API(SrvGetConsoleWindow
)
766 PCSRSS_GET_CONSOLE_WINDOW GetConsoleWindowRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetConsoleWindowRequest
;
767 PCSRSS_CONSOLE Console
;
769 DPRINT("SrvGetConsoleWindow\n");
771 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
772 if (!NT_SUCCESS(Status
)) return Status
;
774 GetConsoleWindowRequest
->WindowHandle
= Console
->hWindow
;
775 ConioUnlockConsole(Console
);
777 return STATUS_SUCCESS
;
780 CSR_API(SrvSetConsoleIcon
)
783 PCSRSS_SET_CONSOLE_ICON SetConsoleIconRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetConsoleIconRequest
;
784 PCSRSS_CONSOLE Console
;
786 DPRINT("SrvSetConsoleIcon\n");
788 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
789 if (!NT_SUCCESS(Status
)) return Status
;
791 Status
= (ConioChangeIcon(Console
, SetConsoleIconRequest
->WindowIcon
)
793 : STATUS_UNSUCCESSFUL
);
795 ConioUnlockConsole(Console
);
800 CSR_API(SrvGetConsoleCP
)
803 PCSRSS_CONSOLE_CP ConsoleCPRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleCPRequest
;
804 PCSRSS_CONSOLE Console
;
806 DPRINT("SrvGetConsoleCP, getting %s Code Page\n",
807 ConsoleCPRequest
->InputCP
? "Input" : "Output");
809 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
810 if (!NT_SUCCESS(Status
)) return Status
;
812 ConsoleCPRequest
->CodePage
= (ConsoleCPRequest
->InputCP
? Console
->CodePage
813 : Console
->OutputCodePage
);
814 ConioUnlockConsole(Console
);
815 return STATUS_SUCCESS
;
818 CSR_API(SrvSetConsoleCP
)
821 PCSRSS_CONSOLE_CP ConsoleCPRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleCPRequest
;
822 PCSRSS_CONSOLE Console
;
824 DPRINT("SrvSetConsoleCP, setting %s Code Page\n",
825 ConsoleCPRequest
->InputCP
? "Input" : "Output");
827 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
828 if (!NT_SUCCESS(Status
)) return Status
;
830 if (IsValidCodePage(ConsoleCPRequest
->CodePage
))
832 if (ConsoleCPRequest
->InputCP
)
833 Console
->CodePage
= ConsoleCPRequest
->CodePage
;
835 Console
->OutputCodePage
= ConsoleCPRequest
->CodePage
;
837 ConioUnlockConsole(Console
);
838 return STATUS_SUCCESS
;
841 ConioUnlockConsole(Console
);
842 return STATUS_INVALID_PARAMETER
;
845 CSR_API(SrvGetConsoleProcessList
)
848 PCSRSS_GET_PROCESS_LIST GetProcessListRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetProcessListRequest
;
850 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
851 PCSRSS_CONSOLE Console
;
852 PCONSOLE_PROCESS_DATA current
;
853 PLIST_ENTRY current_entry
;
856 DPRINT("SrvGetConsoleProcessList\n");
858 if (!CsrValidateMessageBuffer(ApiMessage
,
859 (PVOID
)&GetProcessListRequest
->pProcessIds
,
860 GetProcessListRequest
->nMaxIds
,
863 return STATUS_INVALID_PARAMETER
;
866 Buffer
= GetProcessListRequest
->pProcessIds
;
868 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
869 if (!NT_SUCCESS(Status
)) return Status
;
871 for (current_entry
= Console
->ProcessList
.Flink
;
872 current_entry
!= &Console
->ProcessList
;
873 current_entry
= current_entry
->Flink
)
875 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
876 if (++nItems
<= GetProcessListRequest
->nMaxIds
)
878 *Buffer
++ = HandleToUlong(current
->Process
->ClientId
.UniqueProcess
);
882 ConioUnlockConsole(Console
);
884 GetProcessListRequest
->nProcessIdsTotal
= nItems
;
885 return STATUS_SUCCESS
;
888 CSR_API(SrvGenerateConsoleCtrlEvent
)
891 PCSRSS_GENERATE_CTRL_EVENT GenerateCtrlEvent
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GenerateCtrlEvent
;
892 PCSRSS_CONSOLE Console
;
893 PCONSOLE_PROCESS_DATA current
;
894 PLIST_ENTRY current_entry
;
897 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
898 if (!NT_SUCCESS(Status
)) return Status
;
900 Group
= GenerateCtrlEvent
->ProcessGroup
;
901 Status
= STATUS_INVALID_PARAMETER
;
902 for (current_entry
= Console
->ProcessList
.Flink
;
903 current_entry
!= &Console
->ProcessList
;
904 current_entry
= current_entry
->Flink
)
906 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
907 if (Group
== 0 || current
->Process
->ProcessGroupId
== Group
)
909 ConioConsoleCtrlEvent(GenerateCtrlEvent
->Event
, current
);
910 Status
= STATUS_SUCCESS
;
914 ConioUnlockConsole(Console
);
919 CSR_API(SrvGetConsoleSelectionInfo
)
922 PCSRSS_GET_CONSOLE_SELECTION_INFO GetConsoleSelectionInfo
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetConsoleSelectionInfo
;
923 PCSRSS_CONSOLE Console
;
925 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
926 if (NT_SUCCESS(Status
))
928 memset(&GetConsoleSelectionInfo
->Info
, 0, sizeof(CONSOLE_SELECTION_INFO
));
929 if (Console
->Selection
.dwFlags
!= 0)
930 GetConsoleSelectionInfo
->Info
= Console
->Selection
;
931 ConioUnlockConsole(Console
);