[WIN32CSR]
[reactos.git] / reactos / win32ss / user / 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(PCSR_PROCESS 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, PCSR_PROCESS ProcessData, DWORD Timeout)
42 {
43 HANDLE Thread;
44
45 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData->ClientId.UniqueProcess);
46
47 if (ProcessData->CtrlDispatcher)
48 {
49
50 Thread = CreateRemoteThread(ProcessData->ProcessHandle, 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, PCSR_PROCESS ProcessData)
65 {
66 ConioConsoleCtrlEventTimeout(Event, ProcessData, 0);
67 }
68
69 static NTSTATUS WINAPI
70 CsrInitConsole(PCSRSS_CONSOLE Console, int ShowCmd)
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 /*
135 * If we are not in GUI-mode, start the text-mode console. If we fail,
136 * try to start the GUI-mode console (win32k will automatically switch
137 * to graphical mode, therefore no additional code is needed).
138 */
139 if (!GuiMode)
140 {
141 DPRINT1("WIN32CSR: Opening text-mode console\n");
142 Status = TuiInitConsole(Console);
143 if (!NT_SUCCESS(Status))
144 {
145 DPRINT1("Failed to open text-mode console, switching to gui-mode, Status = 0x%08lx\n", Status);
146 GuiMode = TRUE;
147 }
148 }
149
150 /*
151 * Try to open the GUI-mode console. Two cases are possible:
152 * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
153 * failed and we start GUI-mode console.
154 * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
155 * succeeded BUT we failed at starting text-mode console. Then GuiMode
156 * was switched to TRUE in order to try to open the console in GUI-mode.
157 */
158 if (GuiMode)
159 {
160 DPRINT1("WIN32CSR: Opening GUI-mode console\n");
161 Status = GuiInitConsole(Console, ShowCmd);
162 if (!NT_SUCCESS(Status))
163 {
164 HeapFree(Win32CsrApiHeap,0, NewBuffer);
165 RtlFreeUnicodeString(&Console->Title);
166 DeleteCriticalSection(&Console->Lock);
167 CloseHandle(Console->ActiveEvent);
168 DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status);
169 return Status;
170 }
171 }
172
173 Status = CsrInitConsoleScreenBuffer(Console, NewBuffer);
174 if (!NT_SUCCESS(Status))
175 {
176 ConioCleanupConsole(Console);
177 RtlFreeUnicodeString(&Console->Title);
178 DeleteCriticalSection(&Console->Lock);
179 CloseHandle(Console->ActiveEvent);
180 HeapFree(Win32CsrApiHeap, 0, NewBuffer);
181 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
182 return Status;
183 }
184
185 /* copy buffer contents to screen */
186 ConioDrawConsole(Console);
187
188 return STATUS_SUCCESS;
189 }
190
191 CSR_API(CsrAllocConsole)
192 {
193 PCSRSS_CONSOLE Console;
194 NTSTATUS Status = STATUS_SUCCESS;
195 BOOLEAN NewConsole = FALSE;
196
197 DPRINT("CsrAllocConsole\n");
198
199 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
200 if (ProcessData->Console)
201 {
202 DPRINT1("Process already has a console\n");
203 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
204 return STATUS_INVALID_PARAMETER;
205 }
206
207 /* If we don't need a console, then get out of here */
208 if (!Request->Data.AllocConsoleRequest.ConsoleNeeded)
209 {
210 DPRINT("No console needed\n");
211 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
212 return STATUS_SUCCESS;
213 }
214
215 /* If we already have one, then don't create a new one... */
216 if (!Request->Data.AllocConsoleRequest.Console ||
217 Request->Data.AllocConsoleRequest.Console != ProcessData->ParentConsole)
218 {
219 /* Allocate a console structure */
220 NewConsole = TRUE;
221 Console = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_CONSOLE));
222 if (NULL == Console)
223 {
224 DPRINT1("Not enough memory for console\n");
225 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
226 return STATUS_NO_MEMORY;
227 }
228 /* initialize list head */
229 InitializeListHead(&Console->ProcessList);
230 /* insert process data required for GUI initialization */
231 InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
232 /* Initialize the Console */
233 Status = CsrInitConsole(Console, Request->Data.AllocConsoleRequest.ShowCmd);
234 if (!NT_SUCCESS(Status))
235 {
236 DPRINT1("Console init failed\n");
237 HeapFree(Win32CsrApiHeap, 0, Console);
238 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
239 return Status;
240 }
241 }
242 else
243 {
244 /* Reuse our current console */
245 Console = Request->Data.AllocConsoleRequest.Console;
246 }
247
248 /* Set the Process Console */
249 ProcessData->Console = Console;
250
251 /* Return it to the caller */
252 Request->Data.AllocConsoleRequest.Console = Console;
253
254 /* Add a reference count because the process is tied to the console */
255 _InterlockedIncrement(&Console->ReferenceCount);
256
257 if (NewConsole || !ProcessData->bInheritHandles)
258 {
259 /* Insert the Objects */
260 Status = Win32CsrInsertObject(ProcessData,
261 &Request->Data.AllocConsoleRequest.InputHandle,
262 &Console->Header,
263 GENERIC_READ | GENERIC_WRITE,
264 TRUE,
265 FILE_SHARE_READ | FILE_SHARE_WRITE);
266 if (! NT_SUCCESS(Status))
267 {
268 DPRINT1("Failed to insert object\n");
269 ConioDeleteConsole((Object_t *) Console);
270 ProcessData->Console = 0;
271 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
272 return Status;
273 }
274
275 Status = Win32CsrInsertObject(ProcessData,
276 &Request->Data.AllocConsoleRequest.OutputHandle,
277 &Console->ActiveBuffer->Header,
278 GENERIC_READ | GENERIC_WRITE,
279 TRUE,
280 FILE_SHARE_READ | FILE_SHARE_WRITE);
281 if (!NT_SUCCESS(Status))
282 {
283 DPRINT1("Failed to insert object\n");
284 ConioDeleteConsole((Object_t *) Console);
285 Win32CsrReleaseObject(ProcessData,
286 Request->Data.AllocConsoleRequest.InputHandle);
287 ProcessData->Console = 0;
288 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
289 return Status;
290 }
291 }
292
293 /* Duplicate the Event */
294 if (!DuplicateHandle(GetCurrentProcess(),
295 ProcessData->Console->ActiveEvent,
296 ProcessData->ProcessHandle,
297 &ProcessData->ConsoleEvent,
298 EVENT_ALL_ACCESS,
299 FALSE,
300 0))
301 {
302 DPRINT1("DuplicateHandle() failed: %lu\n", GetLastError());
303 ConioDeleteConsole((Object_t *) Console);
304 if (NewConsole || !ProcessData->bInheritHandles)
305 {
306 Win32CsrReleaseObject(ProcessData,
307 Request->Data.AllocConsoleRequest.OutputHandle);
308 Win32CsrReleaseObject(ProcessData,
309 Request->Data.AllocConsoleRequest.InputHandle);
310 }
311 ProcessData->Console = 0;
312 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
313 return Status;
314 }
315
316 /* Set the Ctrl Dispatcher */
317 ProcessData->CtrlDispatcher = Request->Data.AllocConsoleRequest.CtrlDispatcher;
318 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher);
319
320 if (!NewConsole)
321 {
322 /* Insert into the list if it has not been added */
323 InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ConsoleLink);
324 }
325
326 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
327 return STATUS_SUCCESS;
328 }
329
330 CSR_API(CsrFreeConsole)
331 {
332 Win32CsrReleaseConsole(ProcessData);
333 return STATUS_SUCCESS;
334 }
335
336 VOID WINAPI
337 ConioDeleteConsole(Object_t *Object)
338 {
339 PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) Object;
340 ConsoleInput *Event;
341
342 DPRINT("ConioDeleteConsole\n");
343
344 /* Drain input event queue */
345 while (Console->InputEvents.Flink != &Console->InputEvents)
346 {
347 Event = (ConsoleInput *) Console->InputEvents.Flink;
348 Console->InputEvents.Flink = Console->InputEvents.Flink->Flink;
349 Console->InputEvents.Flink->Flink->Blink = &Console->InputEvents;
350 HeapFree(Win32CsrApiHeap, 0, Event);
351 }
352
353 ConioCleanupConsole(Console);
354 if (Console->LineBuffer)
355 RtlFreeHeap(Win32CsrApiHeap, 0, Console->LineBuffer);
356 while (!IsListEmpty(&Console->HistoryBuffers))
357 HistoryDeleteBuffer((struct tagHISTORY_BUFFER *)Console->HistoryBuffers.Flink);
358
359 ConioDeleteScreenBuffer(Console->ActiveBuffer);
360 if (!IsListEmpty(&Console->BufferList))
361 {
362 DPRINT1("BUG: screen buffer list not empty\n");
363 }
364
365 CloseHandle(Console->ActiveEvent);
366 if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent);
367 DeleteCriticalSection(&Console->Lock);
368 RtlFreeUnicodeString(&Console->Title);
369 IntDeleteAllAliases(Console->Aliases);
370 HeapFree(Win32CsrApiHeap, 0, Console);
371 }
372
373 VOID WINAPI
374 CsrInitConsoleSupport(VOID)
375 {
376 DPRINT("CSR: CsrInitConsoleSupport()\n");
377
378 /* Should call LoadKeyboardLayout */
379 }
380
381 VOID FASTCALL
382 ConioPause(PCSRSS_CONSOLE Console, UINT Flags)
383 {
384 Console->PauseFlags |= Flags;
385 if (!Console->UnpauseEvent)
386 Console->UnpauseEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
387 }
388
389 VOID FASTCALL
390 ConioUnpause(PCSRSS_CONSOLE Console, UINT Flags)
391 {
392 Console->PauseFlags &= ~Flags;
393 if (Console->PauseFlags == 0 && Console->UnpauseEvent)
394 {
395 SetEvent(Console->UnpauseEvent);
396 CloseHandle(Console->UnpauseEvent);
397 Console->UnpauseEvent = NULL;
398 }
399 }
400
401 CSR_API(CsrSetConsoleMode)
402 {
403 NTSTATUS Status;
404 PCSRSS_CONSOLE Console;
405 PCSRSS_SCREEN_BUFFER Buff;
406
407 DPRINT("CsrSetConsoleMode\n");
408
409 Status = Win32CsrLockObject(ProcessData,
410 Request->Data.SetConsoleModeRequest.ConsoleHandle,
411 (Object_t **) &Console, GENERIC_WRITE, 0);
412 if (! NT_SUCCESS(Status))
413 {
414 return Status;
415 }
416
417 Buff = (PCSRSS_SCREEN_BUFFER)Console;
418 if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
419 {
420 Console->Mode = Request->Data.SetConsoleModeRequest.Mode & CONSOLE_INPUT_MODE_VALID;
421 }
422 else if (CONIO_SCREEN_BUFFER_MAGIC == Console->Header.Type)
423 {
424 Buff->Mode = Request->Data.SetConsoleModeRequest.Mode & CONSOLE_OUTPUT_MODE_VALID;
425 }
426 else
427 {
428 Status = STATUS_INVALID_HANDLE;
429 }
430
431 Win32CsrUnlockObject((Object_t *)Console);
432
433 return Status;
434 }
435
436 CSR_API(CsrGetConsoleMode)
437 {
438 NTSTATUS Status;
439 PCSRSS_CONSOLE Console;
440 PCSRSS_SCREEN_BUFFER Buff; /* gee, I really wish I could use an anonymous union here */
441
442 DPRINT("CsrGetConsoleMode\n");
443
444 Status = Win32CsrLockObject(ProcessData, Request->Data.GetConsoleModeRequest.ConsoleHandle,
445 (Object_t **) &Console, GENERIC_READ, 0);
446 if (! NT_SUCCESS(Status))
447 {
448 return Status;
449 }
450 Status = STATUS_SUCCESS;
451 Buff = (PCSRSS_SCREEN_BUFFER) Console;
452 if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
453 {
454 Request->Data.GetConsoleModeRequest.ConsoleMode = Console->Mode;
455 }
456 else if (CONIO_SCREEN_BUFFER_MAGIC == Buff->Header.Type)
457 {
458 Request->Data.GetConsoleModeRequest.ConsoleMode = Buff->Mode;
459 }
460 else
461 {
462 Status = STATUS_INVALID_HANDLE;
463 }
464
465 Win32CsrUnlockObject((Object_t *)Console);
466 return Status;
467 }
468
469 CSR_API(CsrSetTitle)
470 {
471 NTSTATUS Status;
472 PCSRSS_CONSOLE Console;
473 PWCHAR Buffer;
474
475 DPRINT("CsrSetTitle\n");
476
477 if (!Win32CsrValidateBuffer(ProcessData, Request->Data.SetTitleRequest.Title,
478 Request->Data.SetTitleRequest.Length, 1))
479 {
480 return STATUS_ACCESS_VIOLATION;
481 }
482
483 Status = ConioConsoleFromProcessData(ProcessData, &Console);
484 if(NT_SUCCESS(Status))
485 {
486 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Request->Data.SetTitleRequest.Length);
487 if (Buffer)
488 {
489 /* copy title to console */
490 RtlFreeUnicodeString(&Console->Title);
491 Console->Title.Buffer = Buffer;
492 Console->Title.Length = Console->Title.MaximumLength = Request->Data.SetTitleRequest.Length;
493 memcpy(Console->Title.Buffer, Request->Data.SetTitleRequest.Title, Console->Title.Length);
494 if (! ConioChangeTitle(Console))
495 {
496 Status = STATUS_UNSUCCESSFUL;
497 }
498 else
499 {
500 Status = STATUS_SUCCESS;
501 }
502 }
503 else
504 {
505 Status = STATUS_NO_MEMORY;
506 }
507 ConioUnlockConsole(Console);
508 }
509
510 return Status;
511 }
512
513 CSR_API(CsrGetTitle)
514 {
515 NTSTATUS Status;
516 PCSRSS_CONSOLE Console;
517 DWORD Length;
518
519 DPRINT("CsrGetTitle\n");
520
521
522 if (!Win32CsrValidateBuffer(ProcessData, Request->Data.GetTitleRequest.Title,
523 Request->Data.GetTitleRequest.Length, 1))
524 {
525 return STATUS_ACCESS_VIOLATION;
526 }
527
528 Status = ConioConsoleFromProcessData(ProcessData, &Console);
529 if (! NT_SUCCESS(Status))
530 {
531 DPRINT1("Can't get console\n");
532 return Status;
533 }
534
535 /* Copy title of the console to the user title buffer */
536 if (Request->Data.GetTitleRequest.Length >= sizeof(WCHAR))
537 {
538 Length = min(Request->Data.GetTitleRequest.Length - sizeof(WCHAR), Console->Title.Length);
539 memcpy(Request->Data.GetTitleRequest.Title, Console->Title.Buffer, Length);
540 Request->Data.GetTitleRequest.Title[Length / sizeof(WCHAR)] = L'\0';
541 }
542
543 Request->Data.GetTitleRequest.Length = Console->Title.Length;
544
545 ConioUnlockConsole(Console);
546 return STATUS_SUCCESS;
547 }
548
549 /**********************************************************************
550 * HardwareStateProperty
551 *
552 * DESCRIPTION
553 * Set/Get the value of the HardwareState and switch
554 * between direct video buffer ouput and GDI windowed
555 * output.
556 * ARGUMENTS
557 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
558 * object. We use the same object to Request.
559 * NOTE
560 * ConsoleHwState has the correct size to be compatible
561 * with NT's, but values are not.
562 */
563 static NTSTATUS FASTCALL
564 SetConsoleHardwareState (PCSRSS_CONSOLE Console, DWORD ConsoleHwState)
565 {
566 DPRINT1("Console Hardware State: %d\n", ConsoleHwState);
567
568 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState)
569 ||(CONSOLE_HARDWARE_STATE_DIRECT == ConsoleHwState))
570 {
571 if (Console->HardwareState != ConsoleHwState)
572 {
573 /* TODO: implement switching from full screen to windowed mode */
574 /* TODO: or back; now simply store the hardware state */
575 Console->HardwareState = ConsoleHwState;
576 }
577
578 return STATUS_SUCCESS;
579 }
580
581 return STATUS_INVALID_PARAMETER_3; /* Client: (handle, set_get, [mode]) */
582 }
583
584 CSR_API(CsrHardwareStateProperty)
585 {
586 PCSRSS_CONSOLE Console;
587 NTSTATUS Status;
588
589 DPRINT("CsrHardwareStateProperty\n");
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 Status = ConioConsoleFromProcessData(ProcessData, &Console);
630 if (! NT_SUCCESS(Status))
631 {
632 return Status;
633 }
634
635 Request->Data.GetConsoleWindowRequest.WindowHandle = Console->hWindow;
636 ConioUnlockConsole(Console);
637
638 return STATUS_SUCCESS;
639 }
640
641 CSR_API(CsrSetConsoleIcon)
642 {
643 PCSRSS_CONSOLE Console;
644 NTSTATUS Status;
645
646 DPRINT("CsrSetConsoleIcon\n");
647
648 Status = ConioConsoleFromProcessData(ProcessData, &Console);
649 if (! NT_SUCCESS(Status))
650 {
651 return Status;
652 }
653
654 Status = (ConioChangeIcon(Console, Request->Data.SetConsoleIconRequest.WindowIcon)
655 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
656 ConioUnlockConsole(Console);
657
658 return Status;
659 }
660
661 CSR_API(CsrGetConsoleCodePage)
662 {
663 PCSRSS_CONSOLE Console;
664 NTSTATUS Status;
665
666 DPRINT("CsrGetConsoleCodePage\n");
667
668 Status = ConioConsoleFromProcessData(ProcessData, &Console);
669 if (! NT_SUCCESS(Status))
670 {
671 return Status;
672 }
673
674 Request->Data.GetConsoleCodePage.CodePage = Console->CodePage;
675 ConioUnlockConsole(Console);
676 return STATUS_SUCCESS;
677 }
678
679 CSR_API(CsrSetConsoleCodePage)
680 {
681 PCSRSS_CONSOLE Console;
682 NTSTATUS Status;
683
684 DPRINT("CsrSetConsoleCodePage\n");
685
686 Status = ConioConsoleFromProcessData(ProcessData, &Console);
687 if (! NT_SUCCESS(Status))
688 {
689 return Status;
690 }
691
692 if (IsValidCodePage(Request->Data.SetConsoleCodePage.CodePage))
693 {
694 Console->CodePage = Request->Data.SetConsoleCodePage.CodePage;
695 ConioUnlockConsole(Console);
696 return STATUS_SUCCESS;
697 }
698
699 ConioUnlockConsole(Console);
700 return STATUS_INVALID_PARAMETER;
701 }
702
703 CSR_API(CsrGetConsoleOutputCodePage)
704 {
705 PCSRSS_CONSOLE Console;
706 NTSTATUS Status;
707
708 DPRINT("CsrGetConsoleOutputCodePage\n");
709
710 Status = ConioConsoleFromProcessData(ProcessData, &Console);
711 if (! NT_SUCCESS(Status))
712 {
713 return Status;
714 }
715
716 Request->Data.GetConsoleOutputCodePage.CodePage = Console->OutputCodePage;
717 ConioUnlockConsole(Console);
718 return STATUS_SUCCESS;
719 }
720
721 CSR_API(CsrSetConsoleOutputCodePage)
722 {
723 PCSRSS_CONSOLE Console;
724 NTSTATUS Status;
725
726 DPRINT("CsrSetConsoleOutputCodePage\n");
727
728 Status = ConioConsoleFromProcessData(ProcessData, &Console);
729 if (! NT_SUCCESS(Status))
730 {
731 return Status;
732 }
733
734 if (IsValidCodePage(Request->Data.SetConsoleOutputCodePage.CodePage))
735 {
736 Console->OutputCodePage = Request->Data.SetConsoleOutputCodePage.CodePage;
737 ConioUnlockConsole(Console);
738 return STATUS_SUCCESS;
739 }
740
741 ConioUnlockConsole(Console);
742 return STATUS_INVALID_PARAMETER;
743 }
744
745 CSR_API(CsrGetProcessList)
746 {
747 PDWORD Buffer;
748 PCSRSS_CONSOLE Console;
749 PCSR_PROCESS current;
750 PLIST_ENTRY current_entry;
751 ULONG nItems = 0;
752 NTSTATUS Status;
753
754 DPRINT("CsrGetProcessList\n");
755
756 Buffer = Request->Data.GetProcessListRequest.ProcessId;
757 if (!Win32CsrValidateBuffer(ProcessData, Buffer, Request->Data.GetProcessListRequest.nMaxIds, sizeof(DWORD)))
758 return STATUS_ACCESS_VIOLATION;
759
760 Status = ConioConsoleFromProcessData(ProcessData, &Console);
761 if (! NT_SUCCESS(Status))
762 {
763 return Status;
764 }
765
766 for (current_entry = Console->ProcessList.Flink;
767 current_entry != &Console->ProcessList;
768 current_entry = current_entry->Flink)
769 {
770 current = CONTAINING_RECORD(current_entry, CSR_PROCESS, ConsoleLink);
771 if (++nItems <= Request->Data.GetProcessListRequest.nMaxIds)
772 {
773 *Buffer++ = HandleToUlong(current->ClientId.UniqueProcess);
774 }
775 }
776
777 ConioUnlockConsole(Console);
778
779 Request->Data.GetProcessListRequest.nProcessIdsTotal = nItems;
780 return STATUS_SUCCESS;
781 }
782
783 CSR_API(CsrGenerateCtrlEvent)
784 {
785 PCSRSS_CONSOLE Console;
786 PCSR_PROCESS current;
787 PLIST_ENTRY current_entry;
788 DWORD Group;
789 NTSTATUS Status;
790
791 Status = ConioConsoleFromProcessData(ProcessData, &Console);
792 if (! NT_SUCCESS(Status))
793 {
794 return Status;
795 }
796
797 Group = Request->Data.GenerateCtrlEvent.ProcessGroup;
798 Status = STATUS_INVALID_PARAMETER;
799 for (current_entry = Console->ProcessList.Flink;
800 current_entry != &Console->ProcessList;
801 current_entry = current_entry->Flink)
802 {
803 current = CONTAINING_RECORD(current_entry, CSR_PROCESS, ConsoleLink);
804 if (Group == 0 || current->ProcessGroupId == Group)
805 {
806 ConioConsoleCtrlEvent(Request->Data.GenerateCtrlEvent.Event, current);
807 Status = STATUS_SUCCESS;
808 }
809 }
810
811 ConioUnlockConsole(Console);
812
813 return Status;
814 }
815
816 CSR_API(CsrGetConsoleSelectionInfo)
817 {
818 NTSTATUS Status;
819 PCSRSS_CONSOLE Console;
820
821 Status = ConioConsoleFromProcessData(ProcessData, &Console);
822 if (NT_SUCCESS(Status))
823 {
824 memset(&Request->Data.GetConsoleSelectionInfo.Info, 0, sizeof(CONSOLE_SELECTION_INFO));
825 if (Console->Selection.dwFlags != 0)
826 Request->Data.GetConsoleSelectionInfo.Info = Console->Selection;
827 ConioUnlockConsole(Console);
828 }
829 return Status;
830 }
831
832 /* EOF */