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