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