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