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 /* Notify all the waits only if we see Ctrl-C or Ctrl-Break */
68 if (Event
== CTRL_C_EVENT
|| Event
== CTRL_BREAK_EVENT
)
70 DWORD Flag
= (1 << Event
); // Transform an integer value to a power of 2.
72 PCSRSS_CONSOLE Console
;
73 // LIST_ENTRY WaitQueue;
75 DPRINT1("ConioConsoleCtrlEvent - Ctrl-C captured\n");
76 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
77 if (NT_SUCCESS(Status
))
79 DPRINT1("ConioConsoleCtrlEvent - console captured, try to dereference waits...\n");
81 * Wake-up all of the writing waiters, dereference them
82 * and purge them all from the list.
84 if (CsrNotifyWait(&Console
->ReadWaitQueue
,
89 DPRINT1("ConioConsoleCtrlEvent - waits dereferenced...\n");
90 // InitializeListHead(&WaitQueue);
92 // CsrMoveSatisfiedWait(&WaitQueue, &Console->ReadWaitQueue);
93 if (!IsListEmpty(&Console
->ReadWaitQueue
/* &WaitQueue */))
95 CsrDereferenceWait(&Console
->ReadWaitQueue
/* &WaitQueue */);
98 ConioUnlockConsole(Console
); // NOTE_WAITS: <-- Here we have the possibility to free the console waits also.
102 /* Notify the process of the control event */
103 if (ProcessData
->CtrlDispatcher
)
105 Thread
= CreateRemoteThread(ProcessData
->Process
->ProcessHandle
, NULL
, 0,
106 ProcessData
->CtrlDispatcher
,
107 UlongToPtr(Event
), 0, NULL
);
110 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
114 DPRINT1("We succeeded at creating ProcessData->CtrlDispatcher remote thread, ProcessId = %x, Process = 0x%p\n", ProcessData
->Process
->ClientId
.UniqueProcess
, ProcessData
->Process
);
115 WaitForSingleObject(Thread
, Timeout
);
121 ConioConsoleCtrlEvent(DWORD Event
, PCONSOLE_PROCESS_DATA ProcessData
)
123 ConioConsoleCtrlEventTimeout(Event
, ProcessData
, 0);
126 /* static */ NTSTATUS WINAPI
127 CsrInitConsole(PCSRSS_CONSOLE
* NewConsole
, int ShowCmd
)
130 SECURITY_ATTRIBUTES SecurityAttributes
;
131 PCSRSS_CONSOLE Console
;
132 PCSRSS_SCREEN_BUFFER NewBuffer
;
136 if (NewConsole
== NULL
) return STATUS_INVALID_PARAMETER
;
140 /* Allocate a console structure */
141 Console
= HeapAlloc(ConSrvHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_CONSOLE
));
144 DPRINT1("Not enough memory for console creation.\n");
145 return STATUS_NO_MEMORY
;
148 /* Initialize the console */
149 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
150 Console
->Title
.Buffer
= NULL
;
152 if (LoadStringW(ConSrvDllInstance
, IDS_COMMAND_PROMPT
, Title
, sizeof(Title
) / sizeof(Title
[0])))
154 RtlCreateUnicodeString(&Console
->Title
, Title
);
158 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
161 Console
->ReferenceCount
= 0;
162 Console
->LineBuffer
= NULL
;
163 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
164 Console
->Header
.Console
= Console
;
165 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
166 InitializeListHead(&Console
->ProcessList
);
167 InitializeListHead(&Console
->BufferList
);
168 Console
->ActiveBuffer
= NULL
;
169 // Console->SatisfiedWaits = NULL;
170 InitializeListHead(&Console
->ReadWaitQueue
);
171 InitializeListHead(&Console
->WriteWaitQueue
);
172 InitializeListHead(&Console
->InputEvents
);
173 InitializeListHead(&Console
->HistoryBuffers
);
174 Console
->CodePage
= GetOEMCP();
175 Console
->OutputCodePage
= GetOEMCP();
177 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
178 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
179 SecurityAttributes
.bInheritHandle
= TRUE
;
181 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
182 if (NULL
== Console
->ActiveEvent
)
184 RtlFreeUnicodeString(&Console
->Title
);
185 HeapFree(ConSrvHeap
, 0, Console
);
186 return STATUS_UNSUCCESSFUL
;
188 Console
->PrivateData
= NULL
;
189 InitializeCriticalSection(&Console
->Lock
);
191 GuiMode
= DtbgIsDesktopVisible();
193 /* allocate console screen buffer */
194 NewBuffer
= HeapAlloc(ConSrvHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
195 if (NULL
== NewBuffer
)
197 RtlFreeUnicodeString(&Console
->Title
);
198 DeleteCriticalSection(&Console
->Lock
);
199 CloseHandle(Console
->ActiveEvent
);
200 HeapFree(ConSrvHeap
, 0, Console
);
201 return STATUS_INSUFFICIENT_RESOURCES
;
203 /* init screen buffer with defaults */
204 NewBuffer
->CursorInfo
.bVisible
= TRUE
;
205 NewBuffer
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
206 /* make console active, and insert into console list */
207 Console
->ActiveBuffer
= (PCSRSS_SCREEN_BUFFER
) NewBuffer
;
210 * If we are not in GUI-mode, start the text-mode console. If we fail,
211 * try to start the GUI-mode console (win32k will automatically switch
212 * to graphical mode, therefore no additional code is needed).
216 DPRINT1("CONSRV: Opening text-mode console\n");
217 Status
= TuiInitConsole(Console
);
218 if (!NT_SUCCESS(Status
))
220 DPRINT1("Failed to open text-mode console, switching to gui-mode, Status = 0x%08lx\n", Status
);
226 * Try to open the GUI-mode console. Two cases are possible:
227 * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
228 * failed and we start GUI-mode console.
229 * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
230 * succeeded BUT we failed at starting text-mode console. Then GuiMode
231 * was switched to TRUE in order to try to open the console in GUI-mode.
235 DPRINT1("CONSRV: Opening GUI-mode console\n");
236 Status
= GuiInitConsole(Console
, ShowCmd
);
237 if (!NT_SUCCESS(Status
))
239 HeapFree(ConSrvHeap
,0, NewBuffer
);
240 RtlFreeUnicodeString(&Console
->Title
);
241 DeleteCriticalSection(&Console
->Lock
);
242 CloseHandle(Console
->ActiveEvent
);
243 DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status
);
244 HeapFree(ConSrvHeap
, 0, Console
);
249 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
250 if (!NT_SUCCESS(Status
))
252 ConioCleanupConsole(Console
);
253 RtlFreeUnicodeString(&Console
->Title
);
254 DeleteCriticalSection(&Console
->Lock
);
255 CloseHandle(Console
->ActiveEvent
);
256 HeapFree(ConSrvHeap
, 0, NewBuffer
);
257 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
258 HeapFree(ConSrvHeap
, 0, Console
);
262 /* Copy buffer contents to screen */
263 ConioDrawConsole(Console
);
265 *NewConsole
= Console
;
267 return STATUS_SUCCESS
;
270 CSR_API(SrvOpenConsole
)
272 NTSTATUS Status
= STATUS_SUCCESS
;
273 PCSRSS_OPEN_CONSOLE OpenConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.OpenConsoleRequest
;
274 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
276 DPRINT("SrvOpenConsole\n");
278 OpenConsoleRequest
->Handle
= INVALID_HANDLE_VALUE
;
280 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
282 DPRINT1("SrvOpenConsole - Checkpoint 1\n");
283 DPRINT1("ProcessData = 0x%p ; ProcessData->Console = 0x%p\n", ProcessData
, ProcessData
->Console
);
285 if (ProcessData
->Console
)
287 DWORD DesiredAccess
= OpenConsoleRequest
->Access
;
288 DWORD ShareMode
= OpenConsoleRequest
->ShareMode
;
290 PCSRSS_CONSOLE Console
= ProcessData
->Console
;
293 DPRINT1("SrvOpenConsole - Checkpoint 2\n");
294 EnterCriticalSection(&Console
->Lock
);
295 DPRINT1("SrvOpenConsole - Checkpoint 3\n");
297 if (OpenConsoleRequest
->HandleType
== HANDLE_OUTPUT
)
298 Object
= &Console
->ActiveBuffer
->Header
;
300 Object
= &Console
->Header
;
302 if (((DesiredAccess
& GENERIC_READ
) && Object
->ExclusiveRead
!= 0) ||
303 ((DesiredAccess
& GENERIC_WRITE
) && Object
->ExclusiveWrite
!= 0) ||
304 (!(ShareMode
& FILE_SHARE_READ
) && Object
->AccessRead
!= 0) ||
305 (!(ShareMode
& FILE_SHARE_WRITE
) && Object
->AccessWrite
!= 0))
307 DPRINT1("Sharing violation\n");
308 Status
= STATUS_SHARING_VIOLATION
;
312 Status
= Win32CsrInsertObject(ProcessData
,
313 &OpenConsoleRequest
->Handle
,
316 OpenConsoleRequest
->Inheritable
,
320 LeaveCriticalSection(&Console
->Lock
);
323 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
328 CSR_API(SrvAllocConsole
)
330 NTSTATUS Status
= STATUS_SUCCESS
;
331 PCSRSS_ALLOC_CONSOLE AllocConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.AllocConsoleRequest
;
332 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
334 DPRINT("SrvAllocConsole\n");
336 if (ProcessData
->Console
!= NULL
)
338 DPRINT1("Process already has a console\n");
339 return STATUS_INVALID_PARAMETER
;
342 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
344 DPRINT1("SrvAllocConsole - Checkpoint 1\n");
346 /* Initialize a new Console */
347 Status
= CsrInitConsole(&ProcessData
->Console
, AllocConsoleRequest
->ShowCmd
);
348 if (!NT_SUCCESS(Status
))
350 DPRINT1("Console initialization failed\n");
351 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
355 /* Insert the process into the processes list of the console */
356 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
358 /* Return it to the caller */
359 AllocConsoleRequest
->Console
= ProcessData
->Console
;
361 /* Add a reference count because the process is tied to the console */
362 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
366 * We've just created a new console. However when ConsoleNewProcess was
367 * called, we didn't know that we wanted to create a new console and
368 * therefore, we by default inherited the handles table from our parent
369 * process. It's only now that we notice that in fact we do not need
370 * them, because we've created a new console and thus we must use it.
372 * Therefore, free our handles table and recreate a new one.
377 /* Close all console handles and free the handle table memory */
378 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
380 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
382 ProcessData
->HandleTableSize
= 0;
383 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
384 ProcessData
->HandleTable
= NULL
;
388 * Create a new handle table - Insert the IO handles
391 /* Insert the Input handle */
392 Status
= Win32CsrInsertObject(ProcessData
,
393 &AllocConsoleRequest
->InputHandle
,
394 &ProcessData
->Console
->Header
,
395 GENERIC_READ
| GENERIC_WRITE
,
397 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
398 if (!NT_SUCCESS(Status
))
400 DPRINT1("Failed to insert the input handle\n");
401 ConioDeleteConsole(ProcessData
->Console
);
402 ProcessData
->Console
= NULL
;
403 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
407 /* Insert the Output handle */
408 Status
= Win32CsrInsertObject(ProcessData
,
409 &AllocConsoleRequest
->OutputHandle
,
410 &ProcessData
->Console
->ActiveBuffer
->Header
,
411 GENERIC_READ
| GENERIC_WRITE
,
413 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
414 if (!NT_SUCCESS(Status
))
416 DPRINT1("Failed to insert the output handle\n");
417 ConioDeleteConsole(ProcessData
->Console
);
418 Win32CsrReleaseObject(ProcessData
,
419 AllocConsoleRequest
->InputHandle
);
420 ProcessData
->Console
= NULL
;
421 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
425 /* Insert the Error handle */
426 Status
= Win32CsrInsertObject(ProcessData
,
427 &AllocConsoleRequest
->ErrorHandle
,
428 &ProcessData
->Console
->ActiveBuffer
->Header
,
429 GENERIC_READ
| GENERIC_WRITE
,
431 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
432 if (!NT_SUCCESS(Status
))
434 DPRINT1("Failed to insert the error handle\n");
435 ConioDeleteConsole(ProcessData
->Console
);
436 Win32CsrReleaseObject(ProcessData
,
437 AllocConsoleRequest
->OutputHandle
);
438 Win32CsrReleaseObject(ProcessData
,
439 AllocConsoleRequest
->InputHandle
);
440 ProcessData
->Console
= NULL
;
441 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
445 /* Duplicate the Event */
446 Status
= NtDuplicateObject(NtCurrentProcess(),
447 ProcessData
->Console
->ActiveEvent
,
448 ProcessData
->Process
->ProcessHandle
,
449 &ProcessData
->ConsoleEvent
,
450 EVENT_ALL_ACCESS
, 0, 0);
451 if (!NT_SUCCESS(Status
))
453 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
454 ConioDeleteConsole(ProcessData
->Console
);
455 // if (NewConsole /* || !ProcessData->bInheritHandles */)
457 Win32CsrReleaseObject(ProcessData
,
458 AllocConsoleRequest
->ErrorHandle
);
459 Win32CsrReleaseObject(ProcessData
,
460 AllocConsoleRequest
->OutputHandle
);
461 Win32CsrReleaseObject(ProcessData
,
462 AllocConsoleRequest
->InputHandle
);
464 ProcessData
->Console
= NULL
;
465 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
468 /* Input Wait Handle */
469 AllocConsoleRequest
->InputWaitHandle
= ProcessData
->ConsoleEvent
;
471 /* Set the Ctrl Dispatcher */
472 ProcessData
->CtrlDispatcher
= AllocConsoleRequest
->CtrlDispatcher
;
473 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
475 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
476 return STATUS_SUCCESS
;
479 CSR_API(SrvFreeConsole
)
481 DPRINT1("SrvFreeConsole\n");
482 Win32CsrReleaseConsole(CsrGetClientThread()->Process
);
483 return STATUS_SUCCESS
;
487 ConioDeleteConsole(PCSRSS_CONSOLE Console
)
491 DPRINT("ConioDeleteConsole\n");
493 /* TODO: Dereference all the waits in Console->ReadWaitQueue */
494 /* TODO: Dereference all the waits in Console->WriteWaitQueue */
496 /* Drain input event queue */
497 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
499 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
500 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
501 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
502 HeapFree(ConSrvHeap
, 0, Event
);
505 ConioCleanupConsole(Console
);
506 if (Console
->LineBuffer
)
507 RtlFreeHeap(ConSrvHeap
, 0, Console
->LineBuffer
);
508 while (!IsListEmpty(&Console
->HistoryBuffers
))
509 HistoryDeleteBuffer((struct tagHISTORY_BUFFER
*)Console
->HistoryBuffers
.Flink
);
511 ConioDeleteScreenBuffer(Console
->ActiveBuffer
);
512 if (!IsListEmpty(&Console
->BufferList
))
514 DPRINT1("BUG: screen buffer list not empty\n");
517 CloseHandle(Console
->ActiveEvent
);
518 if (Console
->UnpauseEvent
) CloseHandle(Console
->UnpauseEvent
);
519 DeleteCriticalSection(&Console
->Lock
);
520 RtlFreeUnicodeString(&Console
->Title
);
521 IntDeleteAllAliases(Console
->Aliases
);
522 HeapFree(ConSrvHeap
, 0, Console
);
526 CsrInitConsoleSupport(VOID
)
528 DPRINT("CSR: CsrInitConsoleSupport()\n");
530 /* Should call LoadKeyboardLayout */
534 ConioPause(PCSRSS_CONSOLE Console
, UINT Flags
)
536 Console
->PauseFlags
|= Flags
;
537 if (!Console
->UnpauseEvent
)
538 Console
->UnpauseEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
542 ConioUnpause(PCSRSS_CONSOLE Console
, UINT Flags
)
544 // LIST_ENTRY WaitQueue;
546 Console
->PauseFlags
&= ~Flags
;
548 // if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0)
549 if (Console
->PauseFlags
== 0 && Console
->UnpauseEvent
)
551 SetEvent(Console
->UnpauseEvent
);
552 CloseHandle(Console
->UnpauseEvent
);
553 Console
->UnpauseEvent
= NULL
;
556 * Wake-up all of the writing waiters, dereference them
557 * and purge them all from the list.
559 if (CsrNotifyWait(&Console
->WriteWaitQueue
,
564 // InitializeListHead(&WaitQueue);
566 // CsrMoveSatisfiedWait(&WaitQueue, &Console->WriteWaitQueue);
567 if (!IsListEmpty(&Console
->WriteWaitQueue
/* &WaitQueue */))
569 CsrDereferenceWait(&Console
->WriteWaitQueue
/* &WaitQueue */);
575 CSR_API(SrvSetConsoleMode
)
578 PCSRSS_CONSOLE_MODE ConsoleModeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleModeRequest
;
579 PCSRSS_CONSOLE Console
;
580 PCSRSS_SCREEN_BUFFER Buff
;
582 DPRINT("SrvSetConsoleMode\n");
584 Status
= Win32CsrLockObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
585 ConsoleModeRequest
->ConsoleHandle
,
586 (Object_t
**) &Console
, GENERIC_WRITE
, 0);
587 if (!NT_SUCCESS(Status
)) return Status
;
589 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
591 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
593 Console
->Mode
= ConsoleModeRequest
->ConsoleMode
& CONSOLE_INPUT_MODE_VALID
;
595 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
597 Buff
->Mode
= ConsoleModeRequest
->ConsoleMode
& CONSOLE_OUTPUT_MODE_VALID
;
601 Status
= STATUS_INVALID_HANDLE
;
604 Win32CsrUnlockObject((Object_t
*)Console
);
609 CSR_API(SrvGetConsoleMode
)
612 PCSRSS_CONSOLE_MODE ConsoleModeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleModeRequest
;
613 PCSRSS_CONSOLE Console
;
614 PCSRSS_SCREEN_BUFFER Buff
;
616 DPRINT("SrvGetConsoleMode\n");
618 Status
= Win32CsrLockObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
619 ConsoleModeRequest
->ConsoleHandle
,
620 (Object_t
**) &Console
, GENERIC_READ
, 0);
621 if (!NT_SUCCESS(Status
)) return Status
;
623 Status
= STATUS_SUCCESS
;
624 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
626 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
628 ConsoleModeRequest
->ConsoleMode
= Console
->Mode
;
630 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
632 ConsoleModeRequest
->ConsoleMode
= Buff
->Mode
;
636 Status
= STATUS_INVALID_HANDLE
;
639 Win32CsrUnlockObject((Object_t
*)Console
);
643 CSR_API(SrvSetConsoleTitle
)
646 PCSRSS_CONSOLE_TITLE TitleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.TitleRequest
;
647 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
648 PCSRSS_CONSOLE Console
;
651 DPRINT("SrvSetConsoleTitle\n");
653 if (!CsrValidateMessageBuffer(ApiMessage
,
654 (PVOID
)&TitleRequest
->Title
,
655 TitleRequest
->Length
,
658 return STATUS_INVALID_PARAMETER
;
661 Status
= ConioConsoleFromProcessData(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 PCSRSS_CONSOLE_TITLE TitleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.TitleRequest
;
697 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
698 PCSRSS_CONSOLE Console
;
701 DPRINT("SrvGetConsoleTitle\n");
703 if (!CsrValidateMessageBuffer(ApiMessage
,
704 (PVOID
)&TitleRequest
->Title
,
705 TitleRequest
->Length
,
708 return STATUS_INVALID_PARAMETER
;
711 Status
= ConioConsoleFromProcessData(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 CSRSS_CONSOLE_HARDWARE_STATE
741 * object. 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(PCSRSS_CONSOLE 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 PCSRSS_CONSOLE_HW_STATE ConsoleHardwareStateRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleHardwareStateRequest
;
771 PCSRSS_CONSOLE Console
;
773 DPRINT("SrvGetConsoleHardwareState\n");
775 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
776 ConsoleHardwareStateRequest
->ConsoleHandle
,
779 if (!NT_SUCCESS(Status
))
781 DPRINT1("Failed to get console handle in SrvGetConsoleHardwareState\n");
785 ConsoleHardwareStateRequest
->State
= Console
->HardwareState
;
787 ConioUnlockConsole(Console
);
792 CSR_API(SrvSetConsoleHardwareState
)
795 PCSRSS_CONSOLE_HW_STATE ConsoleHardwareStateRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleHardwareStateRequest
;
796 PCSRSS_CONSOLE Console
;
798 DPRINT("SrvSetConsoleHardwareState\n");
800 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
801 ConsoleHardwareStateRequest
->ConsoleHandle
,
804 if (!NT_SUCCESS(Status
))
806 DPRINT1("Failed to get console handle in SrvSetConsoleHardwareState\n");
810 DPRINT("Setting console hardware state.\n");
811 Status
= SetConsoleHardwareState(Console
, ConsoleHardwareStateRequest
->State
);
813 ConioUnlockConsole(Console
);
818 CSR_API(SrvGetConsoleWindow
)
821 PCSRSS_GET_CONSOLE_WINDOW GetConsoleWindowRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetConsoleWindowRequest
;
822 PCSRSS_CONSOLE Console
;
824 DPRINT("SrvGetConsoleWindow\n");
826 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
827 if (!NT_SUCCESS(Status
)) return Status
;
829 GetConsoleWindowRequest
->WindowHandle
= Console
->hWindow
;
830 ConioUnlockConsole(Console
);
832 return STATUS_SUCCESS
;
835 CSR_API(SrvSetConsoleIcon
)
838 PCSRSS_SET_CONSOLE_ICON SetConsoleIconRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetConsoleIconRequest
;
839 PCSRSS_CONSOLE Console
;
841 DPRINT("SrvSetConsoleIcon\n");
843 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
844 if (!NT_SUCCESS(Status
)) return Status
;
846 Status
= (ConioChangeIcon(Console
, SetConsoleIconRequest
->WindowIcon
)
848 : STATUS_UNSUCCESSFUL
);
850 ConioUnlockConsole(Console
);
855 CSR_API(SrvGetConsoleCP
)
858 PCSRSS_CONSOLE_CP ConsoleCPRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleCPRequest
;
859 PCSRSS_CONSOLE Console
;
861 DPRINT("SrvGetConsoleCP, getting %s Code Page\n",
862 ConsoleCPRequest
->InputCP
? "Input" : "Output");
864 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
865 if (!NT_SUCCESS(Status
)) return Status
;
867 ConsoleCPRequest
->CodePage
= (ConsoleCPRequest
->InputCP
? Console
->CodePage
868 : Console
->OutputCodePage
);
869 ConioUnlockConsole(Console
);
870 return STATUS_SUCCESS
;
873 CSR_API(SrvSetConsoleCP
)
876 PCSRSS_CONSOLE_CP ConsoleCPRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ConsoleCPRequest
;
877 PCSRSS_CONSOLE Console
;
879 DPRINT("SrvSetConsoleCP, setting %s Code Page\n",
880 ConsoleCPRequest
->InputCP
? "Input" : "Output");
882 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
883 if (!NT_SUCCESS(Status
)) return Status
;
885 if (IsValidCodePage(ConsoleCPRequest
->CodePage
))
887 if (ConsoleCPRequest
->InputCP
)
888 Console
->CodePage
= ConsoleCPRequest
->CodePage
;
890 Console
->OutputCodePage
= ConsoleCPRequest
->CodePage
;
892 ConioUnlockConsole(Console
);
893 return STATUS_SUCCESS
;
896 ConioUnlockConsole(Console
);
897 return STATUS_INVALID_PARAMETER
;
900 CSR_API(SrvGetConsoleProcessList
)
903 PCSRSS_GET_PROCESS_LIST GetProcessListRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetProcessListRequest
;
905 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
906 PCSRSS_CONSOLE Console
;
907 PCONSOLE_PROCESS_DATA current
;
908 PLIST_ENTRY current_entry
;
911 DPRINT("SrvGetConsoleProcessList\n");
913 if (!CsrValidateMessageBuffer(ApiMessage
,
914 (PVOID
)&GetProcessListRequest
->pProcessIds
,
915 GetProcessListRequest
->nMaxIds
,
918 return STATUS_INVALID_PARAMETER
;
921 Buffer
= GetProcessListRequest
->pProcessIds
;
923 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
924 if (!NT_SUCCESS(Status
)) return Status
;
926 for (current_entry
= Console
->ProcessList
.Flink
;
927 current_entry
!= &Console
->ProcessList
;
928 current_entry
= current_entry
->Flink
)
930 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
931 if (++nItems
<= GetProcessListRequest
->nMaxIds
)
933 *Buffer
++ = HandleToUlong(current
->Process
->ClientId
.UniqueProcess
);
937 ConioUnlockConsole(Console
);
939 GetProcessListRequest
->nProcessIdsTotal
= nItems
;
940 return STATUS_SUCCESS
;
943 CSR_API(SrvGenerateConsoleCtrlEvent
)
946 PCSRSS_GENERATE_CTRL_EVENT GenerateCtrlEvent
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GenerateCtrlEvent
;
947 PCSRSS_CONSOLE Console
;
948 PCONSOLE_PROCESS_DATA current
;
949 PLIST_ENTRY current_entry
;
952 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
953 if (!NT_SUCCESS(Status
)) return Status
;
955 Group
= GenerateCtrlEvent
->ProcessGroup
;
956 Status
= STATUS_INVALID_PARAMETER
;
957 for (current_entry
= Console
->ProcessList
.Flink
;
958 current_entry
!= &Console
->ProcessList
;
959 current_entry
= current_entry
->Flink
)
961 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
962 if (Group
== 0 || current
->Process
->ProcessGroupId
== Group
)
964 ConioConsoleCtrlEvent(GenerateCtrlEvent
->Event
, current
);
965 Status
= STATUS_SUCCESS
;
969 ConioUnlockConsole(Console
);
974 CSR_API(SrvGetConsoleSelectionInfo
)
977 PCSRSS_GET_CONSOLE_SELECTION_INFO GetConsoleSelectionInfo
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetConsoleSelectionInfo
;
978 PCSRSS_CONSOLE Console
;
980 Status
= ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
);
981 if (NT_SUCCESS(Status
))
983 memset(&GetConsoleSelectionInfo
->Info
, 0, sizeof(CONSOLE_SELECTION_INFO
));
984 if (Console
->Selection
.dwFlags
!= 0)
985 GetConsoleSelectionInfo
->Info
= Console
->Selection
;
986 ConioUnlockConsole(Console
);