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