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