[KERNEL32/CONSRV]
[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_SET_CONSOLE_MODE SetConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetConsoleModeRequest;
467 PCSRSS_CONSOLE Console;
468 PCSRSS_SCREEN_BUFFER Buff;
469
470 DPRINT("SrvSetConsoleMode\n");
471
472 Status = Win32CsrLockObject(CsrGetClientThread()->Process,
473 SetConsoleModeRequest->ConsoleHandle,
474 (Object_t **) &Console, GENERIC_WRITE, 0);
475 if (! NT_SUCCESS(Status))
476 {
477 return Status;
478 }
479
480 Buff = (PCSRSS_SCREEN_BUFFER)Console;
481 if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
482 {
483 Console->Mode = SetConsoleModeRequest->Mode & CONSOLE_INPUT_MODE_VALID;
484 }
485 else if (CONIO_SCREEN_BUFFER_MAGIC == Console->Header.Type)
486 {
487 Buff->Mode = SetConsoleModeRequest->Mode & CONSOLE_OUTPUT_MODE_VALID;
488 }
489 else
490 {
491 Status = STATUS_INVALID_HANDLE;
492 }
493
494 Win32CsrUnlockObject((Object_t *)Console);
495
496 return Status;
497 }
498
499 CSR_API(SrvGetConsoleMode)
500 {
501 NTSTATUS Status;
502 PCSRSS_GET_CONSOLE_MODE GetConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleModeRequest;
503 PCSRSS_CONSOLE Console;
504 PCSRSS_SCREEN_BUFFER Buff;
505
506 DPRINT("SrvGetConsoleMode\n");
507
508 Status = Win32CsrLockObject(CsrGetClientThread()->Process, GetConsoleModeRequest->ConsoleHandle,
509 (Object_t **) &Console, GENERIC_READ, 0);
510 if (! NT_SUCCESS(Status))
511 {
512 return Status;
513 }
514 Status = STATUS_SUCCESS;
515 Buff = (PCSRSS_SCREEN_BUFFER) Console;
516 if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
517 {
518 GetConsoleModeRequest->ConsoleMode = Console->Mode;
519 }
520 else if (CONIO_SCREEN_BUFFER_MAGIC == Buff->Header.Type)
521 {
522 GetConsoleModeRequest->ConsoleMode = Buff->Mode;
523 }
524 else
525 {
526 Status = STATUS_INVALID_HANDLE;
527 }
528
529 Win32CsrUnlockObject((Object_t *)Console);
530 return Status;
531 }
532
533 CSR_API(SrvSetConsoleTitle)
534 {
535 NTSTATUS Status;
536 PCSRSS_SET_TITLE SetTitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetTitleRequest;
537 PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
538 PCSRSS_CONSOLE Console;
539 PWCHAR Buffer;
540
541 DPRINT("SrvSetConsoleTitle\n");
542
543 if (!Win32CsrValidateBuffer(ProcessData, SetTitleRequest->Title,
544 SetTitleRequest->Length, 1))
545 {
546 return STATUS_ACCESS_VIOLATION;
547 }
548
549 Status = ConioConsoleFromProcessData(ProcessData, &Console);
550 if(NT_SUCCESS(Status))
551 {
552 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, SetTitleRequest->Length);
553 if (Buffer)
554 {
555 /* copy title to console */
556 RtlFreeUnicodeString(&Console->Title);
557 Console->Title.Buffer = Buffer;
558 Console->Title.Length = Console->Title.MaximumLength = SetTitleRequest->Length;
559 memcpy(Console->Title.Buffer, SetTitleRequest->Title, Console->Title.Length);
560 if (! ConioChangeTitle(Console))
561 {
562 Status = STATUS_UNSUCCESSFUL;
563 }
564 else
565 {
566 Status = STATUS_SUCCESS;
567 }
568 }
569 else
570 {
571 Status = STATUS_NO_MEMORY;
572 }
573 ConioUnlockConsole(Console);
574 }
575
576 return Status;
577 }
578
579 CSR_API(SrvGetConsoleTitle)
580 {
581 NTSTATUS Status;
582 PCSRSS_GET_TITLE GetTitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetTitleRequest;
583 PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
584 PCSRSS_CONSOLE Console;
585 DWORD Length;
586
587 DPRINT("SrvGetConsoleTitle\n");
588
589 if (!Win32CsrValidateBuffer(ProcessData, GetTitleRequest->Title,
590 GetTitleRequest->Length, 1))
591 {
592 return STATUS_ACCESS_VIOLATION;
593 }
594
595 Status = ConioConsoleFromProcessData(ProcessData, &Console);
596 if (! NT_SUCCESS(Status))
597 {
598 DPRINT1("Can't get console\n");
599 return Status;
600 }
601
602 /* Copy title of the console to the user title buffer */
603 if (GetTitleRequest->Length >= sizeof(WCHAR))
604 {
605 Length = min(GetTitleRequest->Length - sizeof(WCHAR), Console->Title.Length);
606 memcpy(GetTitleRequest->Title, Console->Title.Buffer, Length);
607 GetTitleRequest->Title[Length / sizeof(WCHAR)] = L'\0';
608 }
609
610 GetTitleRequest->Length = Console->Title.Length;
611
612 ConioUnlockConsole(Console);
613 return STATUS_SUCCESS;
614 }
615
616 /**********************************************************************
617 * HardwareStateProperty
618 *
619 * DESCRIPTION
620 * Set/Get the value of the HardwareState and switch
621 * between direct video buffer ouput and GDI windowed
622 * output.
623 * ARGUMENTS
624 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
625 * object. We use the same object to Request.
626 * NOTE
627 * ConsoleHwState has the correct size to be compatible
628 * with NT's, but values are not.
629 */
630 static NTSTATUS FASTCALL
631 SetConsoleHardwareState(PCSRSS_CONSOLE Console, DWORD ConsoleHwState)
632 {
633 DPRINT1("Console Hardware State: %d\n", ConsoleHwState);
634
635 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState)
636 ||(CONSOLE_HARDWARE_STATE_DIRECT == ConsoleHwState))
637 {
638 if (Console->HardwareState != ConsoleHwState)
639 {
640 /* TODO: implement switching from full screen to windowed mode */
641 /* TODO: or back; now simply store the hardware state */
642 Console->HardwareState = ConsoleHwState;
643 }
644
645 return STATUS_SUCCESS;
646 }
647
648 return STATUS_INVALID_PARAMETER_3; /* Client: (handle, set_get, [mode]) */
649 }
650
651 CSR_API(SrvGetConsoleHardwareState)
652 {
653 PCSRSS_SETGET_CONSOLE_HW_STATE ConsoleHardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleHardwareStateRequest;
654 PCSRSS_CONSOLE Console;
655 NTSTATUS Status;
656
657 DPRINT("SrvGetConsoleHardwareState\n");
658
659 Status = ConioLockConsole(CsrGetClientThread()->Process,
660 ConsoleHardwareStateRequest->ConsoleHandle,
661 &Console,
662 GENERIC_READ);
663 if (! NT_SUCCESS(Status))
664 {
665 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
666 return Status;
667 }
668
669 switch (ConsoleHardwareStateRequest->SetGet)
670 {
671 case CONSOLE_HARDWARE_STATE_GET:
672 ConsoleHardwareStateRequest->State = Console->HardwareState;
673 break;
674
675 case CONSOLE_HARDWARE_STATE_SET:
676 DPRINT("Setting console hardware state.\n");
677 Status = SetConsoleHardwareState(Console, ConsoleHardwareStateRequest->State);
678 break;
679
680 default:
681 Status = STATUS_INVALID_PARAMETER_2; /* Client: (handle, [set_get], mode) */
682 break;
683 }
684
685 ConioUnlockConsole(Console);
686
687 return Status;
688 }
689
690 CSR_API(SrvSetConsoleHardwareState)
691 {
692 PCSRSS_SETGET_CONSOLE_HW_STATE ConsoleHardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleHardwareStateRequest;
693 PCSRSS_CONSOLE Console;
694 NTSTATUS Status;
695
696 DPRINT("SrvSetConsoleHardwareState\n");
697
698 Status = ConioLockConsole(CsrGetClientThread()->Process,
699 ConsoleHardwareStateRequest->ConsoleHandle,
700 &Console,
701 GENERIC_READ);
702 if (! NT_SUCCESS(Status))
703 {
704 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
705 return Status;
706 }
707
708 switch (ConsoleHardwareStateRequest->SetGet)
709 {
710 case CONSOLE_HARDWARE_STATE_GET:
711 ConsoleHardwareStateRequest->State = Console->HardwareState;
712 break;
713
714 case CONSOLE_HARDWARE_STATE_SET:
715 DPRINT("Setting console hardware state.\n");
716 Status = SetConsoleHardwareState(Console, ConsoleHardwareStateRequest->State);
717 break;
718
719 default:
720 Status = STATUS_INVALID_PARAMETER_2; /* Client: (handle, [set_get], mode) */
721 break;
722 }
723
724 ConioUnlockConsole(Console);
725
726 return Status;
727 }
728
729 CSR_API(SrvGetConsoleWindow)
730 {
731 PCSRSS_GET_CONSOLE_WINDOW GetConsoleWindowRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleWindowRequest;
732 PCSRSS_CONSOLE Console;
733 NTSTATUS Status;
734
735 DPRINT("SrvGetConsoleWindow\n");
736
737 Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
738 if (! NT_SUCCESS(Status))
739 {
740 return Status;
741 }
742
743 GetConsoleWindowRequest->WindowHandle = Console->hWindow;
744 ConioUnlockConsole(Console);
745
746 return STATUS_SUCCESS;
747 }
748
749 CSR_API(SrvSetConsoleIcon)
750 {
751 PCSRSS_SET_CONSOLE_ICON SetConsoleIconRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetConsoleIconRequest;
752 PCSRSS_CONSOLE Console;
753 NTSTATUS Status;
754
755 DPRINT("SrvSetConsoleIcon\n");
756
757 Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
758 if (! NT_SUCCESS(Status))
759 {
760 return Status;
761 }
762
763 Status = (ConioChangeIcon(Console, SetConsoleIconRequest->WindowIcon)
764 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
765 ConioUnlockConsole(Console);
766
767 return Status;
768 }
769
770 CSR_API(SrvGetConsoleCP)
771 {
772 PCSRSS_GET_CONSOLE_CP GetConsoleCodePage = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleCodePage;
773 PCSRSS_CONSOLE Console;
774 NTSTATUS Status;
775
776 DPRINT("SrvGetConsoleCP\n");
777
778 Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
779 if (! NT_SUCCESS(Status))
780 {
781 return Status;
782 }
783
784 GetConsoleCodePage->CodePage = Console->CodePage;
785 ConioUnlockConsole(Console);
786 return STATUS_SUCCESS;
787 }
788
789 CSR_API(CsrGetConsoleOutputCodePage) // TODO: Merge this function with the other one.
790 {
791 PCSRSS_GET_CONSOLE_OUTPUT_CP GetConsoleOutputCodePage = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleOutputCodePage;
792 PCSRSS_CONSOLE Console;
793 NTSTATUS Status;
794
795 DPRINT("CsrGetConsoleOutputCodePage\n");
796
797 Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
798 if (! NT_SUCCESS(Status))
799 {
800 return Status;
801 }
802
803 GetConsoleOutputCodePage->CodePage = Console->OutputCodePage;
804 ConioUnlockConsole(Console);
805 return STATUS_SUCCESS;
806 }
807
808 CSR_API(SrvSetConsoleCP)
809 {
810 PCSRSS_SET_CONSOLE_CP SetConsoleCodePage = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetConsoleCodePage;
811 PCSRSS_CONSOLE Console;
812 NTSTATUS Status;
813
814 DPRINT("SrvSetConsoleCP\n");
815
816 Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
817 if (! NT_SUCCESS(Status))
818 {
819 return Status;
820 }
821
822 if (IsValidCodePage(SetConsoleCodePage->CodePage))
823 {
824 Console->CodePage = SetConsoleCodePage->CodePage;
825 ConioUnlockConsole(Console);
826 return STATUS_SUCCESS;
827 }
828
829 ConioUnlockConsole(Console);
830 return STATUS_INVALID_PARAMETER;
831 }
832
833 CSR_API(CsrSetConsoleOutputCodePage) // TODO: Merge this function with the other one.
834 {
835 PCSRSS_SET_CONSOLE_OUTPUT_CP SetConsoleOutputCodePage = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetConsoleOutputCodePage;
836 PCSRSS_CONSOLE Console;
837 NTSTATUS Status;
838
839 DPRINT("CsrSetConsoleOutputCodePage\n");
840
841 Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
842 if (! NT_SUCCESS(Status))
843 {
844 return Status;
845 }
846
847 if (IsValidCodePage(SetConsoleOutputCodePage->CodePage))
848 {
849 Console->OutputCodePage = SetConsoleOutputCodePage->CodePage;
850 ConioUnlockConsole(Console);
851 return STATUS_SUCCESS;
852 }
853
854 ConioUnlockConsole(Console);
855 return STATUS_INVALID_PARAMETER;
856 }
857
858 CSR_API(SrvGetConsoleProcessList)
859 {
860 PCSRSS_GET_PROCESS_LIST GetProcessListRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetProcessListRequest;
861 PDWORD Buffer;
862 PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
863 PCSRSS_CONSOLE Console;
864 PCSR_PROCESS current;
865 PLIST_ENTRY current_entry;
866 ULONG nItems = 0;
867 NTSTATUS Status;
868
869 DPRINT("SrvGetConsoleProcessList\n");
870
871 Buffer = GetProcessListRequest->ProcessId;
872 if (!Win32CsrValidateBuffer(ProcessData, Buffer, GetProcessListRequest->nMaxIds, sizeof(DWORD)))
873 return STATUS_ACCESS_VIOLATION;
874
875 Status = ConioConsoleFromProcessData(ProcessData, &Console);
876 if (! NT_SUCCESS(Status))
877 {
878 return Status;
879 }
880
881 for (current_entry = Console->ProcessList.Flink;
882 current_entry != &Console->ProcessList;
883 current_entry = current_entry->Flink)
884 {
885 current = CONTAINING_RECORD(current_entry, CSR_PROCESS, ConsoleLink);
886 if (++nItems <= GetProcessListRequest->nMaxIds)
887 {
888 *Buffer++ = HandleToUlong(current->ClientId.UniqueProcess);
889 }
890 }
891
892 ConioUnlockConsole(Console);
893
894 GetProcessListRequest->nProcessIdsTotal = nItems;
895 return STATUS_SUCCESS;
896 }
897
898 CSR_API(SrvGenerateConsoleCtrlEvent)
899 {
900 PCSRSS_GENERATE_CTRL_EVENT GenerateCtrlEvent = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GenerateCtrlEvent;
901 PCSRSS_CONSOLE Console;
902 PCSR_PROCESS current;
903 PLIST_ENTRY current_entry;
904 DWORD Group;
905 NTSTATUS Status;
906
907 Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
908 if (! NT_SUCCESS(Status))
909 {
910 return Status;
911 }
912
913 Group = GenerateCtrlEvent->ProcessGroup;
914 Status = STATUS_INVALID_PARAMETER;
915 for (current_entry = Console->ProcessList.Flink;
916 current_entry != &Console->ProcessList;
917 current_entry = current_entry->Flink)
918 {
919 current = CONTAINING_RECORD(current_entry, CSR_PROCESS, ConsoleLink);
920 if (Group == 0 || current->ProcessGroupId == Group)
921 {
922 ConioConsoleCtrlEvent(GenerateCtrlEvent->Event, current);
923 Status = STATUS_SUCCESS;
924 }
925 }
926
927 ConioUnlockConsole(Console);
928
929 return Status;
930 }
931
932 CSR_API(SrvGetConsoleSelectionInfo)
933 {
934 NTSTATUS Status;
935 PCSRSS_GET_CONSOLE_SELECTION_INFO GetConsoleSelectionInfo = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleSelectionInfo;
936 PCSRSS_CONSOLE Console;
937
938 Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
939 if (NT_SUCCESS(Status))
940 {
941 memset(&GetConsoleSelectionInfo->Info, 0, sizeof(CONSOLE_SELECTION_INFO));
942 if (Console->Selection.dwFlags != 0)
943 GetConsoleSelectionInfo->Info = Console->Selection;
944 ConioUnlockConsole(Console);
945 }
946 return Status;
947 }
948
949 /* EOF */