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