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