[CONSRV]
[reactos.git] / win32ss / user / consrv / console.c
1 /*
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
6 * PROGRAMMERS:
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "consrv.h"
12 #include "guiconsole.h"
13 #include "tuiconsole.h"
14
15 #define NDEBUG
16 #include <debug.h>
17
18 /* FUNCTIONS *****************************************************************/
19
20 BOOL FASTCALL
21 DtbgIsDesktopVisible(VOID)
22 {
23 HWND VisibleDesktopWindow = GetDesktopWindow(); // DESKTOPWNDPROC
24
25 if (VisibleDesktopWindow != NULL &&
26 !IsWindowVisible(VisibleDesktopWindow))
27 {
28 VisibleDesktopWindow = NULL;
29 }
30
31 return VisibleDesktopWindow != NULL;
32 }
33
34 NTSTATUS FASTCALL
35 ConioConsoleFromProcessData(PCONSOLE_PROCESS_DATA ProcessData,
36 PCSRSS_CONSOLE *Console)
37 {
38 PCSRSS_CONSOLE ProcessConsole;
39
40 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
41 ProcessConsole = ProcessData->Console;
42
43 if (!ProcessConsole)
44 {
45 *Console = NULL;
46 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
47 return STATUS_INVALID_HANDLE;
48 }
49
50 InterlockedIncrement(&ProcessConsole->ReferenceCount);
51 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
52 EnterCriticalSection(&(ProcessConsole->Lock));
53 *Console = ProcessConsole;
54
55 return STATUS_SUCCESS;
56 }
57
58 VOID FASTCALL
59 ConioConsoleCtrlEventTimeout(DWORD Event,
60 PCONSOLE_PROCESS_DATA ProcessData,
61 DWORD Timeout)
62 {
63 HANDLE Thread;
64
65 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess);
66
67 if (ProcessData->CtrlDispatcher)
68 {
69 Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
70 ProcessData->CtrlDispatcher,
71 UlongToPtr(Event), 0, NULL);
72 if (NULL == Thread)
73 {
74 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
75 return;
76 }
77
78 WaitForSingleObject(Thread, Timeout);
79 CloseHandle(Thread);
80 }
81 }
82
83 VOID FASTCALL
84 ConioConsoleCtrlEvent(DWORD Event, PCONSOLE_PROCESS_DATA ProcessData)
85 {
86 ConioConsoleCtrlEventTimeout(Event, ProcessData, 0);
87 }
88
89 static NTSTATUS WINAPI
90 CsrInitConsole(PCSRSS_CONSOLE Console, int ShowCmd)
91 {
92 NTSTATUS Status;
93 SECURITY_ATTRIBUTES SecurityAttributes;
94 PCSRSS_SCREEN_BUFFER NewBuffer;
95 BOOL GuiMode;
96 WCHAR Title[255];
97
98 Console->Title.MaximumLength = Console->Title.Length = 0;
99 Console->Title.Buffer = NULL;
100
101 if (LoadStringW(ConSrvDllInstance, IDS_COMMAND_PROMPT, Title, sizeof(Title) / sizeof(Title[0])))
102 {
103 RtlCreateUnicodeString(&Console->Title, Title);
104 }
105 else
106 {
107 RtlCreateUnicodeString(&Console->Title, L"Command Prompt");
108 }
109
110 Console->ReferenceCount = 0;
111 Console->LineBuffer = NULL;
112 Console->Header.Type = CONIO_CONSOLE_MAGIC;
113 Console->Header.Console = Console;
114 Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
115 InitializeListHead(&Console->BufferList);
116 Console->ActiveBuffer = NULL;
117 InitializeListHead(&Console->ReadWaitQueue);
118 InitializeListHead(&Console->WriteWaitQueue);
119 InitializeListHead(&Console->InputEvents);
120 InitializeListHead(&Console->HistoryBuffers);
121 Console->CodePage = GetOEMCP();
122 Console->OutputCodePage = GetOEMCP();
123
124 SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
125 SecurityAttributes.lpSecurityDescriptor = NULL;
126 SecurityAttributes.bInheritHandle = TRUE;
127
128 Console->ActiveEvent = CreateEventW(&SecurityAttributes, TRUE, FALSE, NULL);
129 if (NULL == Console->ActiveEvent)
130 {
131 RtlFreeUnicodeString(&Console->Title);
132 return STATUS_UNSUCCESSFUL;
133 }
134 Console->PrivateData = NULL;
135 InitializeCriticalSection(&Console->Lock);
136
137 GuiMode = DtbgIsDesktopVisible();
138
139 /* allocate console screen buffer */
140 NewBuffer = HeapAlloc(ConSrvHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_SCREEN_BUFFER));
141 if (NULL == NewBuffer)
142 {
143 RtlFreeUnicodeString(&Console->Title);
144 DeleteCriticalSection(&Console->Lock);
145 CloseHandle(Console->ActiveEvent);
146 return STATUS_INSUFFICIENT_RESOURCES;
147 }
148 /* init screen buffer with defaults */
149 NewBuffer->CursorInfo.bVisible = TRUE;
150 NewBuffer->CursorInfo.dwSize = CSR_DEFAULT_CURSOR_SIZE;
151 /* make console active, and insert into console list */
152 Console->ActiveBuffer = (PCSRSS_SCREEN_BUFFER) NewBuffer;
153
154 /*
155 * If we are not in GUI-mode, start the text-mode console. If we fail,
156 * try to start the GUI-mode console (win32k will automatically switch
157 * to graphical mode, therefore no additional code is needed).
158 */
159 if (!GuiMode)
160 {
161 DPRINT1("CONSRV: Opening text-mode console\n");
162 Status = TuiInitConsole(Console);
163 if (!NT_SUCCESS(Status))
164 {
165 DPRINT1("Failed to open text-mode console, switching to gui-mode, Status = 0x%08lx\n", Status);
166 GuiMode = TRUE;
167 }
168 }
169
170 /*
171 * Try to open the GUI-mode console. Two cases are possible:
172 * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
173 * failed and we start GUI-mode console.
174 * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
175 * succeeded BUT we failed at starting text-mode console. Then GuiMode
176 * was switched to TRUE in order to try to open the console in GUI-mode.
177 */
178 if (GuiMode)
179 {
180 DPRINT1("CONSRV: Opening GUI-mode console\n");
181 Status = GuiInitConsole(Console, ShowCmd);
182 if (!NT_SUCCESS(Status))
183 {
184 HeapFree(ConSrvHeap,0, NewBuffer);
185 RtlFreeUnicodeString(&Console->Title);
186 DeleteCriticalSection(&Console->Lock);
187 CloseHandle(Console->ActiveEvent);
188 DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status);
189 return Status;
190 }
191 }
192
193 Status = CsrInitConsoleScreenBuffer(Console, NewBuffer);
194 if (!NT_SUCCESS(Status))
195 {
196 ConioCleanupConsole(Console);
197 RtlFreeUnicodeString(&Console->Title);
198 DeleteCriticalSection(&Console->Lock);
199 CloseHandle(Console->ActiveEvent);
200 HeapFree(ConSrvHeap, 0, NewBuffer);
201 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
202 return Status;
203 }
204
205 /* copy buffer contents to screen */
206 ConioDrawConsole(Console);
207
208 return STATUS_SUCCESS;
209 }
210
211 CSR_API(SrvOpenConsole)
212 {
213 NTSTATUS Status = STATUS_SUCCESS;
214 PCSRSS_OPEN_CONSOLE OpenConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.OpenConsoleRequest;
215 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
216
217 DPRINT("SrvOpenConsole\n");
218
219 OpenConsoleRequest->Handle = INVALID_HANDLE_VALUE;
220
221 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
222
223 DPRINT1("SrvOpenConsole - Checkpoint 1\n");
224 DPRINT1("ProcessData = 0x%p ; ProcessData->Console = 0x%p\n", ProcessData, ProcessData->Console);
225
226 if (ProcessData->Console)
227 {
228 DWORD DesiredAccess = OpenConsoleRequest->Access;
229 DWORD ShareMode = OpenConsoleRequest->ShareMode;
230
231 PCSRSS_CONSOLE Console = ProcessData->Console;
232 Object_t *Object;
233
234 DPRINT1("SrvOpenConsole - Checkpoint 2\n");
235 EnterCriticalSection(&Console->Lock);
236 DPRINT1("SrvOpenConsole - Checkpoint 3\n");
237
238 if (OpenConsoleRequest->HandleType == HANDLE_OUTPUT)
239 Object = &Console->ActiveBuffer->Header;
240 else // HANDLE_INPUT
241 Object = &Console->Header;
242
243 if (((DesiredAccess & GENERIC_READ) && Object->ExclusiveRead != 0) ||
244 ((DesiredAccess & GENERIC_WRITE) && Object->ExclusiveWrite != 0) ||
245 (!(ShareMode & FILE_SHARE_READ) && Object->AccessRead != 0) ||
246 (!(ShareMode & FILE_SHARE_WRITE) && Object->AccessWrite != 0))
247 {
248 DPRINT1("Sharing violation\n");
249 Status = STATUS_SHARING_VIOLATION;
250 }
251 else
252 {
253 Status = Win32CsrInsertObject(ProcessData,
254 &OpenConsoleRequest->Handle,
255 Object,
256 DesiredAccess,
257 OpenConsoleRequest->Inheritable,
258 ShareMode);
259 }
260
261 LeaveCriticalSection(&Console->Lock);
262 }
263
264 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
265
266 return Status;
267 }
268
269 CSR_API(SrvAllocConsole)
270 {
271 NTSTATUS Status = STATUS_SUCCESS;
272 PCSRSS_ALLOC_CONSOLE AllocConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AllocConsoleRequest;
273 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
274 PCSRSS_CONSOLE Console;
275 BOOLEAN NewConsole = FALSE;
276
277 DPRINT("SrvAllocConsole\n");
278
279 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
280
281 if (ProcessData->Console)
282 {
283 DPRINT1("Process already has a console\n");
284 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
285 return STATUS_INVALID_PARAMETER;
286 }
287
288 DPRINT1("SrvAllocConsole - Checkpoint 1\n");
289
290 /* If we don't need a console, then get out of here */
291 if (!AllocConsoleRequest->ConsoleNeeded)
292 {
293 DPRINT("No console needed\n");
294 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
295 return STATUS_SUCCESS;
296 }
297
298 /* If we already have one, then don't create a new one... */
299 if (!AllocConsoleRequest->Console ||
300 AllocConsoleRequest->Console != ProcessData->ParentConsole)
301 {
302 /* Allocate a console structure */
303 NewConsole = TRUE;
304 Console = HeapAlloc(ConSrvHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_CONSOLE));
305 if (NULL == Console)
306 {
307 DPRINT1("Not enough memory for console\n");
308 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
309 return STATUS_NO_MEMORY;
310 }
311
312 /* Initialize list head */
313 InitializeListHead(&Console->ProcessList);
314
315 /* Insert process data required for GUI initialization */
316 InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
317
318 /* Initialize the Console */
319 Status = CsrInitConsole(Console, AllocConsoleRequest->ShowCmd);
320 if (!NT_SUCCESS(Status))
321 {
322 DPRINT1("Console init failed\n");
323 HeapFree(ConSrvHeap, 0, Console);
324 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
325 return Status;
326 }
327 }
328 else
329 {
330 /* Reuse our current console */
331 Console = AllocConsoleRequest->Console;
332 }
333
334 /* Set the Process Console */
335 ProcessData->Console = Console;
336
337 /* Return it to the caller */
338 AllocConsoleRequest->Console = Console;
339
340 /* Add a reference count because the process is tied to the console */
341 _InterlockedIncrement(&Console->ReferenceCount);
342
343 if (NewConsole || !ProcessData->bInheritHandles)
344 {
345 /* Insert the Objects */
346 Status = Win32CsrInsertObject(ProcessData,
347 &AllocConsoleRequest->InputHandle,
348 &Console->Header,
349 GENERIC_READ | GENERIC_WRITE,
350 TRUE,
351 FILE_SHARE_READ | FILE_SHARE_WRITE);
352 if (! NT_SUCCESS(Status))
353 {
354 DPRINT1("Failed to insert object\n");
355 ConioDeleteConsole((Object_t *) Console);
356 ProcessData->Console = NULL;
357 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
358 return Status;
359 }
360
361 Status = Win32CsrInsertObject(ProcessData,
362 &AllocConsoleRequest->OutputHandle,
363 &Console->ActiveBuffer->Header,
364 GENERIC_READ | GENERIC_WRITE,
365 TRUE,
366 FILE_SHARE_READ | FILE_SHARE_WRITE);
367 if (!NT_SUCCESS(Status))
368 {
369 DPRINT1("Failed to insert object\n");
370 ConioDeleteConsole((Object_t *) Console);
371 Win32CsrReleaseObject(ProcessData,
372 AllocConsoleRequest->InputHandle);
373 ProcessData->Console = NULL;
374 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
375 return Status;
376 }
377 }
378
379 /* Duplicate the Event */
380 Status = NtDuplicateObject(NtCurrentProcess(),
381 ProcessData->Console->ActiveEvent,
382 ProcessData->Process->ProcessHandle,
383 &ProcessData->ConsoleEvent,
384 EVENT_ALL_ACCESS, 0, 0);
385 if (!NT_SUCCESS(Status))
386 {
387 DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
388 ConioDeleteConsole((Object_t *) Console);
389 if (NewConsole || !ProcessData->bInheritHandles)
390 {
391 Win32CsrReleaseObject(ProcessData,
392 AllocConsoleRequest->OutputHandle);
393 Win32CsrReleaseObject(ProcessData,
394 AllocConsoleRequest->InputHandle);
395 }
396 ProcessData->Console = NULL;
397 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
398 return Status;
399 }
400
401 /* Set the Ctrl Dispatcher */
402 ProcessData->CtrlDispatcher = AllocConsoleRequest->CtrlDispatcher;
403 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher);
404
405 if (!NewConsole)
406 {
407 /* Insert into the list if it has not been added */
408 InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ConsoleLink);
409 }
410
411 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
412 return STATUS_SUCCESS;
413 }
414
415 CSR_API(SrvFreeConsole)
416 {
417 Win32CsrReleaseConsole(CsrGetClientThread()->Process);
418 return STATUS_SUCCESS;
419 }
420
421 VOID WINAPI
422 ConioDeleteConsole(Object_t *Object)
423 {
424 PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) Object;
425 ConsoleInput *Event;
426
427 DPRINT("ConioDeleteConsole\n");
428
429 /* TODO: Dereference all the waits in Console->ReadWaitQueue */
430 /* TODO: Dereference all the waits in Console->WriteWaitQueue */
431
432 /* Drain input event queue */
433 while (Console->InputEvents.Flink != &Console->InputEvents)
434 {
435 Event = (ConsoleInput *) Console->InputEvents.Flink;
436 Console->InputEvents.Flink = Console->InputEvents.Flink->Flink;
437 Console->InputEvents.Flink->Flink->Blink = &Console->InputEvents;
438 HeapFree(ConSrvHeap, 0, Event);
439 }
440
441 ConioCleanupConsole(Console);
442 if (Console->LineBuffer)
443 RtlFreeHeap(ConSrvHeap, 0, Console->LineBuffer);
444 while (!IsListEmpty(&Console->HistoryBuffers))
445 HistoryDeleteBuffer((struct tagHISTORY_BUFFER *)Console->HistoryBuffers.Flink);
446
447 ConioDeleteScreenBuffer(Console->ActiveBuffer);
448 if (!IsListEmpty(&Console->BufferList))
449 {
450 DPRINT1("BUG: screen buffer list not empty\n");
451 }
452
453 CloseHandle(Console->ActiveEvent);
454 if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent);
455 DeleteCriticalSection(&Console->Lock);
456 RtlFreeUnicodeString(&Console->Title);
457 IntDeleteAllAliases(Console->Aliases);
458 HeapFree(ConSrvHeap, 0, Console);
459 }
460
461 VOID WINAPI
462 CsrInitConsoleSupport(VOID)
463 {
464 DPRINT("CSR: CsrInitConsoleSupport()\n");
465
466 /* Should call LoadKeyboardLayout */
467 }
468
469 VOID FASTCALL
470 ConioPause(PCSRSS_CONSOLE Console, UINT Flags)
471 {
472 Console->PauseFlags |= Flags;
473 if (!Console->UnpauseEvent)
474 Console->UnpauseEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
475 }
476
477 VOID FASTCALL
478 ConioUnpause(PCSRSS_CONSOLE Console, UINT Flags)
479 {
480 Console->PauseFlags &= ~Flags;
481
482 // if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0)
483 if (Console->PauseFlags == 0 && Console->UnpauseEvent)
484 {
485 SetEvent(Console->UnpauseEvent);
486 CloseHandle(Console->UnpauseEvent);
487 Console->UnpauseEvent = NULL;
488
489 CsrNotifyWait(&Console->WriteWaitQueue,
490 WaitAll,
491 NULL,
492 NULL);
493 }
494 }
495
496 CSR_API(SrvSetConsoleMode)
497 {
498 NTSTATUS Status;
499 PCSRSS_CONSOLE_MODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
500 PCSRSS_CONSOLE Console;
501 PCSRSS_SCREEN_BUFFER Buff;
502
503 DPRINT("SrvSetConsoleMode\n");
504
505 Status = Win32CsrLockObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
506 ConsoleModeRequest->ConsoleHandle,
507 (Object_t **) &Console, GENERIC_WRITE, 0);
508 if (!NT_SUCCESS(Status)) return Status;
509
510 Buff = (PCSRSS_SCREEN_BUFFER)Console;
511
512 if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
513 {
514 Console->Mode = ConsoleModeRequest->ConsoleMode & CONSOLE_INPUT_MODE_VALID;
515 }
516 else if (CONIO_SCREEN_BUFFER_MAGIC == Console->Header.Type)
517 {
518 Buff->Mode = ConsoleModeRequest->ConsoleMode & CONSOLE_OUTPUT_MODE_VALID;
519 }
520 else
521 {
522 Status = STATUS_INVALID_HANDLE;
523 }
524
525 Win32CsrUnlockObject((Object_t *)Console);
526
527 return Status;
528 }
529
530 CSR_API(SrvGetConsoleMode)
531 {
532 NTSTATUS Status;
533 PCSRSS_CONSOLE_MODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
534 PCSRSS_CONSOLE Console;
535 PCSRSS_SCREEN_BUFFER Buff;
536
537 DPRINT("SrvGetConsoleMode\n");
538
539 Status = Win32CsrLockObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
540 ConsoleModeRequest->ConsoleHandle,
541 (Object_t **) &Console, GENERIC_READ, 0);
542 if (!NT_SUCCESS(Status)) return Status;
543
544 Status = STATUS_SUCCESS;
545 Buff = (PCSRSS_SCREEN_BUFFER) Console;
546
547 if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
548 {
549 ConsoleModeRequest->ConsoleMode = Console->Mode;
550 }
551 else if (CONIO_SCREEN_BUFFER_MAGIC == Buff->Header.Type)
552 {
553 ConsoleModeRequest->ConsoleMode = Buff->Mode;
554 }
555 else
556 {
557 Status = STATUS_INVALID_HANDLE;
558 }
559
560 Win32CsrUnlockObject((Object_t *)Console);
561 return Status;
562 }
563
564 CSR_API(SrvSetConsoleTitle)
565 {
566 NTSTATUS Status;
567 PCSRSS_CONSOLE_TITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
568 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
569 PCSRSS_CONSOLE Console;
570 PWCHAR Buffer;
571
572 DPRINT("SrvSetConsoleTitle\n");
573
574 if (!CsrValidateMessageBuffer(ApiMessage,
575 (PVOID)&TitleRequest->Title,
576 TitleRequest->Length,
577 sizeof(BYTE)))
578 {
579 return STATUS_INVALID_PARAMETER;
580 }
581
582 Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
583 if(NT_SUCCESS(Status))
584 {
585 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, TitleRequest->Length);
586 if (Buffer)
587 {
588 /* Copy title to console */
589 RtlFreeUnicodeString(&Console->Title);
590 Console->Title.Buffer = Buffer;
591 Console->Title.Length = Console->Title.MaximumLength = TitleRequest->Length;
592 memcpy(Console->Title.Buffer, TitleRequest->Title, Console->Title.Length);
593
594 if (!ConioChangeTitle(Console))
595 {
596 Status = STATUS_UNSUCCESSFUL;
597 }
598 else
599 {
600 Status = STATUS_SUCCESS;
601 }
602 }
603 else
604 {
605 Status = STATUS_NO_MEMORY;
606 }
607
608 ConioUnlockConsole(Console);
609 }
610
611 return Status;
612 }
613
614 CSR_API(SrvGetConsoleTitle)
615 {
616 NTSTATUS Status;
617 PCSRSS_CONSOLE_TITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
618 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
619 PCSRSS_CONSOLE Console;
620 DWORD Length;
621
622 DPRINT("SrvGetConsoleTitle\n");
623
624 if (!CsrValidateMessageBuffer(ApiMessage,
625 (PVOID)&TitleRequest->Title,
626 TitleRequest->Length,
627 sizeof(BYTE)))
628 {
629 return STATUS_INVALID_PARAMETER;
630 }
631
632 Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
633 if (!NT_SUCCESS(Status))
634 {
635 DPRINT1("Can't get console\n");
636 return Status;
637 }
638
639 /* Copy title of the console to the user title buffer */
640 if (TitleRequest->Length >= sizeof(WCHAR))
641 {
642 Length = min(TitleRequest->Length - sizeof(WCHAR), Console->Title.Length);
643 memcpy(TitleRequest->Title, Console->Title.Buffer, Length);
644 TitleRequest->Title[Length / sizeof(WCHAR)] = L'\0';
645 }
646
647 TitleRequest->Length = Console->Title.Length;
648
649 ConioUnlockConsole(Console);
650 return STATUS_SUCCESS;
651 }
652
653 /**********************************************************************
654 * HardwareStateProperty
655 *
656 * DESCRIPTION
657 * Set/Get the value of the HardwareState and switch
658 * between direct video buffer ouput and GDI windowed
659 * output.
660 * ARGUMENTS
661 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
662 * object. We use the same object to Request.
663 * NOTE
664 * ConsoleHwState has the correct size to be compatible
665 * with NT's, but values are not.
666 */
667 static NTSTATUS FASTCALL
668 SetConsoleHardwareState(PCSRSS_CONSOLE Console, DWORD ConsoleHwState)
669 {
670 DPRINT1("Console Hardware State: %d\n", ConsoleHwState);
671
672 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState)
673 ||(CONSOLE_HARDWARE_STATE_DIRECT == ConsoleHwState))
674 {
675 if (Console->HardwareState != ConsoleHwState)
676 {
677 /* TODO: implement switching from full screen to windowed mode */
678 /* TODO: or back; now simply store the hardware state */
679 Console->HardwareState = ConsoleHwState;
680 }
681
682 return STATUS_SUCCESS;
683 }
684
685 return STATUS_INVALID_PARAMETER_3; /* Client: (handle, set_get, [mode]) */
686 }
687
688 CSR_API(SrvGetConsoleHardwareState)
689 {
690 NTSTATUS Status;
691 PCSRSS_CONSOLE_HW_STATE ConsoleHardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleHardwareStateRequest;
692 PCSRSS_CONSOLE Console;
693
694 DPRINT("SrvGetConsoleHardwareState\n");
695
696 Status = ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
697 ConsoleHardwareStateRequest->ConsoleHandle,
698 &Console,
699 GENERIC_READ);
700 if (!NT_SUCCESS(Status))
701 {
702 DPRINT1("Failed to get console handle in SrvGetConsoleHardwareState\n");
703 return Status;
704 }
705
706 ConsoleHardwareStateRequest->State = Console->HardwareState;
707
708 ConioUnlockConsole(Console);
709
710 return Status;
711 }
712
713 CSR_API(SrvSetConsoleHardwareState)
714 {
715 NTSTATUS Status;
716 PCSRSS_CONSOLE_HW_STATE ConsoleHardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleHardwareStateRequest;
717 PCSRSS_CONSOLE Console;
718
719 DPRINT("SrvSetConsoleHardwareState\n");
720
721 Status = ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
722 ConsoleHardwareStateRequest->ConsoleHandle,
723 &Console,
724 GENERIC_READ);
725 if (!NT_SUCCESS(Status))
726 {
727 DPRINT1("Failed to get console handle in SrvSetConsoleHardwareState\n");
728 return Status;
729 }
730
731 DPRINT("Setting console hardware state.\n");
732 Status = SetConsoleHardwareState(Console, ConsoleHardwareStateRequest->State);
733
734 ConioUnlockConsole(Console);
735
736 return Status;
737 }
738
739 CSR_API(SrvGetConsoleWindow)
740 {
741 NTSTATUS Status;
742 PCSRSS_GET_CONSOLE_WINDOW GetConsoleWindowRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleWindowRequest;
743 PCSRSS_CONSOLE Console;
744
745 DPRINT("SrvGetConsoleWindow\n");
746
747 Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
748 if (!NT_SUCCESS(Status)) return Status;
749
750 GetConsoleWindowRequest->WindowHandle = Console->hWindow;
751 ConioUnlockConsole(Console);
752
753 return STATUS_SUCCESS;
754 }
755
756 CSR_API(SrvSetConsoleIcon)
757 {
758 NTSTATUS Status;
759 PCSRSS_SET_CONSOLE_ICON SetConsoleIconRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetConsoleIconRequest;
760 PCSRSS_CONSOLE Console;
761
762 DPRINT("SrvSetConsoleIcon\n");
763
764 Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
765 if (!NT_SUCCESS(Status)) return Status;
766
767 Status = (ConioChangeIcon(Console, SetConsoleIconRequest->WindowIcon)
768 ? STATUS_SUCCESS
769 : STATUS_UNSUCCESSFUL);
770
771 ConioUnlockConsole(Console);
772
773 return Status;
774 }
775
776 CSR_API(SrvGetConsoleCP)
777 {
778 NTSTATUS Status;
779 PCSRSS_CONSOLE_CP ConsoleCPRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleCPRequest;
780 PCSRSS_CONSOLE Console;
781
782 DPRINT("SrvGetConsoleCP, getting %s Code Page\n",
783 ConsoleCPRequest->InputCP ? "Input" : "Output");
784
785 Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
786 if (!NT_SUCCESS(Status)) return Status;
787
788 ConsoleCPRequest->CodePage = (ConsoleCPRequest->InputCP ? Console->CodePage
789 : Console->OutputCodePage);
790 ConioUnlockConsole(Console);
791 return STATUS_SUCCESS;
792 }
793
794 CSR_API(SrvSetConsoleCP)
795 {
796 NTSTATUS Status;
797 PCSRSS_CONSOLE_CP ConsoleCPRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleCPRequest;
798 PCSRSS_CONSOLE Console;
799
800 DPRINT("SrvSetConsoleCP, setting %s Code Page\n",
801 ConsoleCPRequest->InputCP ? "Input" : "Output");
802
803 Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
804 if (!NT_SUCCESS(Status)) return Status;
805
806 if (IsValidCodePage(ConsoleCPRequest->CodePage))
807 {
808 if (ConsoleCPRequest->InputCP)
809 Console->CodePage = ConsoleCPRequest->CodePage;
810 else
811 Console->OutputCodePage = ConsoleCPRequest->CodePage;
812
813 ConioUnlockConsole(Console);
814 return STATUS_SUCCESS;
815 }
816
817 ConioUnlockConsole(Console);
818 return STATUS_INVALID_PARAMETER;
819 }
820
821 CSR_API(SrvGetConsoleProcessList)
822 {
823 NTSTATUS Status;
824 PCSRSS_GET_PROCESS_LIST GetProcessListRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetProcessListRequest;
825 PDWORD Buffer;
826 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
827 PCSRSS_CONSOLE Console;
828 PCONSOLE_PROCESS_DATA current;
829 PLIST_ENTRY current_entry;
830 ULONG nItems = 0;
831
832 DPRINT("SrvGetConsoleProcessList\n");
833
834 if (!CsrValidateMessageBuffer(ApiMessage,
835 (PVOID)&GetProcessListRequest->pProcessIds,
836 GetProcessListRequest->nMaxIds,
837 sizeof(DWORD)))
838 {
839 return STATUS_INVALID_PARAMETER;
840 }
841
842 Buffer = GetProcessListRequest->pProcessIds;
843
844 Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
845 if (!NT_SUCCESS(Status)) return Status;
846
847 for (current_entry = Console->ProcessList.Flink;
848 current_entry != &Console->ProcessList;
849 current_entry = current_entry->Flink)
850 {
851 current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
852 if (++nItems <= GetProcessListRequest->nMaxIds)
853 {
854 *Buffer++ = HandleToUlong(current->Process->ClientId.UniqueProcess);
855 }
856 }
857
858 ConioUnlockConsole(Console);
859
860 GetProcessListRequest->nProcessIdsTotal = nItems;
861 return STATUS_SUCCESS;
862 }
863
864 CSR_API(SrvGenerateConsoleCtrlEvent)
865 {
866 NTSTATUS Status;
867 PCSRSS_GENERATE_CTRL_EVENT GenerateCtrlEvent = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GenerateCtrlEvent;
868 PCSRSS_CONSOLE Console;
869 PCONSOLE_PROCESS_DATA current;
870 PLIST_ENTRY current_entry;
871 DWORD Group;
872
873 Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
874 if (!NT_SUCCESS(Status)) return Status;
875
876 Group = GenerateCtrlEvent->ProcessGroup;
877 Status = STATUS_INVALID_PARAMETER;
878 for (current_entry = Console->ProcessList.Flink;
879 current_entry != &Console->ProcessList;
880 current_entry = current_entry->Flink)
881 {
882 current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
883 if (Group == 0 || current->Process->ProcessGroupId == Group)
884 {
885 ConioConsoleCtrlEvent(GenerateCtrlEvent->Event, current);
886 Status = STATUS_SUCCESS;
887 }
888 }
889
890 ConioUnlockConsole(Console);
891
892 return Status;
893 }
894
895 CSR_API(SrvGetConsoleSelectionInfo)
896 {
897 NTSTATUS Status;
898 PCSRSS_GET_CONSOLE_SELECTION_INFO GetConsoleSelectionInfo = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleSelectionInfo;
899 PCSRSS_CONSOLE Console;
900
901 Status = ConioConsoleFromProcessData(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console);
902 if (NT_SUCCESS(Status))
903 {
904 memset(&GetConsoleSelectionInfo->Info, 0, sizeof(CONSOLE_SELECTION_INFO));
905 if (Console->Selection.dwFlags != 0)
906 GetConsoleSelectionInfo->Info = Console->Selection;
907 ConioUnlockConsole(Console);
908 }
909
910 return Status;
911 }
912
913 /* EOF */