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