* Sync up to trunk HEAD (r62975).
[reactos.git] / win32ss / user / winsrv / consrv / console.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/winsrv/consrv/console.c
5 * PURPOSE: Console Management Functions
6 * PROGRAMMERS: Gé van Geldorp
7 * Jeffrey Morlan
8 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
9 */
10
11 /* INCLUDES *******************************************************************/
12
13 #include "consrv.h"
14
15 #include <ndk/psfuncs.h>
16
17 #include "procinit.h"
18
19 #ifdef TUITERM_COMPILE
20 #include "frontends/tui/tuiterm.h"
21 #endif
22
23 #define NDEBUG
24 #include <debug.h>
25
26 /* GLOBALS ********************************************************************/
27
28 /***************/
29 #ifdef TUITERM_COMPILE
30 NTSTATUS NTAPI
31 TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
32 IN OUT PCONSOLE_INFO ConsoleInfo,
33 IN OUT PVOID ExtraConsoleInfo,
34 IN ULONG ProcessId);
35 NTSTATUS NTAPI
36 TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
37 #endif
38
39 NTSTATUS NTAPI
40 GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
41 IN OUT PCONSOLE_INFO ConsoleInfo,
42 IN OUT PVOID ExtraConsoleInfo,
43 IN ULONG ProcessId);
44 NTSTATUS NTAPI
45 GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
46 /***************/
47
48 typedef
49 NTSTATUS (NTAPI *FRONTEND_LOAD)(IN OUT PFRONTEND FrontEnd,
50 IN OUT PCONSOLE_INFO ConsoleInfo,
51 IN OUT PVOID ExtraConsoleInfo,
52 IN ULONG ProcessId);
53
54 typedef
55 NTSTATUS (NTAPI *FRONTEND_UNLOAD)(IN OUT PFRONTEND FrontEnd);
56
57 /*
58 * If we are not in GUI-mode, start the text-mode terminal emulator.
59 * If we fail, try to start the GUI-mode terminal emulator.
60 *
61 * Try to open the GUI-mode terminal emulator. Two cases are possible:
62 * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
63 * failed and we start GUI-mode terminal emulator.
64 * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
65 * succeeded BUT we failed at starting text-mode terminal emulator.
66 * Then GuiMode was switched to TRUE in order to try to open the GUI-mode
67 * terminal emulator (Win32k will automatically switch to graphical mode,
68 * therefore no additional code is needed).
69 */
70
71 /*
72 * NOTE: Each entry of the table should be retrieved when loading a front-end
73 * (examples of the CSR servers which register some data for CSRSS).
74 */
75 struct
76 {
77 CHAR FrontEndName[80];
78 FRONTEND_LOAD FrontEndLoad;
79 FRONTEND_UNLOAD FrontEndUnload;
80 } FrontEndLoadingMethods[] =
81 {
82 #ifdef TUITERM_COMPILE
83 {"TUI", TuiLoadFrontEnd, TuiUnloadFrontEnd},
84 #endif
85 {"GUI", GuiLoadFrontEnd, GuiUnloadFrontEnd},
86
87 // {"Not found", 0, NULL}
88 };
89
90
91 /* PRIVATE FUNCTIONS **********************************************************/
92
93 #if 0000
94 VOID FASTCALL
95 ConioPause(PCONSOLE Console, UINT Flags)
96 {
97 Console->PauseFlags |= Flags;
98 if (!Console->UnpauseEvent)
99 Console->UnpauseEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
100 }
101
102 VOID FASTCALL
103 ConioUnpause(PCONSOLE Console, UINT Flags)
104 {
105 Console->PauseFlags &= ~Flags;
106
107 // if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0)
108 if (Console->PauseFlags == 0 && Console->UnpauseEvent)
109 {
110 SetEvent(Console->UnpauseEvent);
111 CloseHandle(Console->UnpauseEvent);
112 Console->UnpauseEvent = NULL;
113
114 CsrNotifyWait(&Console->WriteWaitQueue,
115 TRUE,
116 NULL,
117 NULL);
118 if (!IsListEmpty(&Console->WriteWaitQueue))
119 {
120 CsrDereferenceWait(&Console->WriteWaitQueue);
121 }
122 }
123 }
124 #endif
125
126
127 NTSTATUS FASTCALL
128 ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData,
129 PCONSOLE* Console,
130 BOOL LockConsole)
131 {
132 NTSTATUS Status = STATUS_SUCCESS;
133 PCONSOLE ProcessConsole;
134
135 ASSERT(Console);
136 *Console = NULL;
137
138 // RtlEnterCriticalSection(&ProcessData->HandleTableLock);
139
140 Status = ConDrvGetConsole(&ProcessConsole, ProcessData->ConsoleHandle, LockConsole);
141 if (NT_SUCCESS(Status)) *Console = ProcessConsole;
142
143 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
144 return Status;
145 }
146
147 VOID FASTCALL
148 ConSrvReleaseConsole(PCONSOLE Console,
149 BOOL WasConsoleLocked)
150 {
151 /* Just call the driver */
152 ConDrvReleaseConsole(Console, WasConsoleLocked);
153 }
154
155
156 NTSTATUS NTAPI
157 ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
158 OUT PCONSOLE* NewConsole,
159 IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
160 IN ULONG ConsoleLeaderProcessId)
161 {
162 NTSTATUS Status;
163 HANDLE ConsoleHandle;
164 PCONSOLE Console;
165 CONSOLE_INFO ConsoleInfo;
166 SIZE_T Length = 0;
167 ULONG i = 0;
168 FRONTEND FrontEnd;
169
170 if (NewConsole == NULL || ConsoleStartInfo == NULL)
171 return STATUS_INVALID_PARAMETER;
172
173 *NewConsole = NULL;
174
175 /*
176 * Load the console settings
177 */
178
179 /* 1. Load the default settings */
180 ConSrvGetDefaultSettings(&ConsoleInfo, ConsoleLeaderProcessId);
181
182 /* 2. Get the title of the console (initialize ConsoleInfo.ConsoleTitle) */
183 Length = min(wcslen(ConsoleStartInfo->ConsoleTitle),
184 sizeof(ConsoleInfo.ConsoleTitle) / sizeof(ConsoleInfo.ConsoleTitle[0]) - 1);
185 wcsncpy(ConsoleInfo.ConsoleTitle, ConsoleStartInfo->ConsoleTitle, Length);
186 ConsoleInfo.ConsoleTitle[Length] = L'\0';
187
188
189 /*
190 * Choose an adequate terminal front-end to load, and load it
191 */
192 Status = STATUS_SUCCESS;
193 for (i = 0; i < sizeof(FrontEndLoadingMethods) / sizeof(FrontEndLoadingMethods[0]); ++i)
194 {
195 DPRINT("CONSRV: Trying to load %s terminal emulator...\n", FrontEndLoadingMethods[i].FrontEndName);
196 Status = FrontEndLoadingMethods[i].FrontEndLoad(&FrontEnd,
197 &ConsoleInfo,
198 ConsoleStartInfo,
199 ConsoleLeaderProcessId);
200 if (NT_SUCCESS(Status))
201 {
202 DPRINT("CONSRV: %s terminal emulator loaded successfully\n", FrontEndLoadingMethods[i].FrontEndName);
203 break;
204 }
205 else
206 {
207 DPRINT1("CONSRV: Loading %s terminal emulator failed, Status = 0x%08lx , continuing...\n", FrontEndLoadingMethods[i].FrontEndName, Status);
208 }
209 }
210
211 if (!NT_SUCCESS(Status))
212 {
213 DPRINT1("CONSRV: Failed to initialize a frontend, Status = 0x%08lx\n", Status);
214 return Status;
215 }
216
217 DPRINT("CONSRV: Frontend initialized\n");
218
219
220 /******************************************************************************/
221 /*
222 * 4. Load the remaining console settings via the registry.
223 */
224 if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
225 {
226 /*
227 * Either we weren't created by an app launched via a shell-link,
228 * or we failed to load shell-link console properties.
229 * Therefore, load the console infos for the application from the registry.
230 */
231 ConSrvReadUserSettings(&ConsoleInfo, ConsoleLeaderProcessId);
232
233 /*
234 * Now, update them with the properties the user might gave to us
235 * via the STARTUPINFO structure before calling CreateProcess
236 * (and which was transmitted via the ConsoleStartInfo structure).
237 * We therefore overwrite the values read in the registry.
238 */
239 if (ConsoleStartInfo->dwStartupFlags & STARTF_USEFILLATTRIBUTE)
240 {
241 ConsoleInfo.ScreenAttrib = (USHORT)ConsoleStartInfo->wFillAttribute;
242 }
243 if (ConsoleStartInfo->dwStartupFlags & STARTF_USECOUNTCHARS)
244 {
245 ConsoleInfo.ScreenBufferSize = ConsoleStartInfo->dwScreenBufferSize;
246 }
247 if (ConsoleStartInfo->dwStartupFlags & STARTF_USESIZE)
248 {
249 ConsoleInfo.ConsoleSize = ConsoleStartInfo->dwWindowSize;
250 }
251 }
252
253 /* Set-up the code page */
254 ConsoleInfo.CodePage = GetOEMCP();
255 /******************************************************************************/
256
257 Status = ConDrvInitConsole(&ConsoleHandle,
258 &Console,
259 &ConsoleInfo,
260 ConsoleLeaderProcessId);
261 if (!NT_SUCCESS(Status))
262 {
263 DPRINT1("Creating a new console failed, Status = 0x%08lx\n", Status);
264 FrontEndLoadingMethods[i].FrontEndUnload(&FrontEnd);
265 return Status;
266 }
267
268 ASSERT(Console);
269 DPRINT("Console initialized\n");
270
271 Status = ConDrvRegisterFrontEnd(Console, &FrontEnd);
272 if (!NT_SUCCESS(Status))
273 {
274 DPRINT1("Failed to register frontend to the given console, Status = 0x%08lx\n", Status);
275 ConDrvDeleteConsole(Console);
276 FrontEndLoadingMethods[i].FrontEndUnload(&FrontEnd);
277 return Status;
278 }
279 DPRINT("FrontEnd registered\n");
280
281 /* Return the newly created console to the caller and a success code too */
282 *NewConsoleHandle = ConsoleHandle;
283 *NewConsole = Console;
284 return STATUS_SUCCESS;
285 }
286
287 VOID NTAPI
288 ConSrvDeleteConsole(PCONSOLE Console)
289 {
290 DPRINT("ConSrvDeleteConsole\n");
291
292 /* Just call the driver. ConSrvDeregisterFrontEnd is called on-demand. */
293 ConDrvDeleteConsole(Console);
294 }
295
296
297 /* PUBLIC SERVER APIS *********************************************************/
298
299 CSR_API(SrvAllocConsole)
300 {
301 NTSTATUS Status = STATUS_SUCCESS;
302 PCONSOLE_ALLOCCONSOLE AllocConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AllocConsoleRequest;
303 PCSR_PROCESS CsrProcess = CsrGetClientThread()->Process;
304 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
305
306 if (ProcessData->ConsoleHandle != NULL)
307 {
308 DPRINT1("Process already has a console\n");
309 return STATUS_ACCESS_DENIED;
310 }
311
312 if (!CsrValidateMessageBuffer(ApiMessage,
313 (PVOID*)&AllocConsoleRequest->ConsoleStartInfo,
314 1,
315 sizeof(CONSOLE_START_INFO)))
316 {
317 return STATUS_INVALID_PARAMETER;
318 }
319
320 /* Initialize a new Console owned by the Console Leader Process */
321 Status = ConSrvAllocateConsole(ProcessData,
322 &AllocConsoleRequest->InputHandle,
323 &AllocConsoleRequest->OutputHandle,
324 &AllocConsoleRequest->ErrorHandle,
325 AllocConsoleRequest->ConsoleStartInfo);
326 if (!NT_SUCCESS(Status))
327 {
328 DPRINT1("Console allocation failed\n");
329 return Status;
330 }
331
332 /* Return the console handle and the input wait handle to the caller */
333 AllocConsoleRequest->ConsoleHandle = ProcessData->ConsoleHandle;
334 AllocConsoleRequest->InputWaitHandle = ProcessData->ConsoleEvent;
335
336 /* Set the Property-Dialog and Control-Dispatcher handlers */
337 ProcessData->PropDispatcher = AllocConsoleRequest->PropDispatcher;
338 ProcessData->CtrlDispatcher = AllocConsoleRequest->CtrlDispatcher;
339
340 return STATUS_SUCCESS;
341 }
342
343 CSR_API(SrvAttachConsole)
344 {
345 NTSTATUS Status = STATUS_SUCCESS;
346 PCONSOLE_ATTACHCONSOLE AttachConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AttachConsoleRequest;
347 PCSR_PROCESS SourceProcess = NULL; // The parent process.
348 PCSR_PROCESS TargetProcess = CsrGetClientThread()->Process; // Ourselves.
349 HANDLE ProcessId = ULongToHandle(AttachConsoleRequest->ProcessId);
350 PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
351
352 TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
353
354 if (TargetProcessData->ConsoleHandle != NULL)
355 {
356 DPRINT1("Process already has a console\n");
357 return STATUS_ACCESS_DENIED;
358 }
359
360 /* Check whether we try to attach to the parent's console */
361 if (ProcessId == ULongToHandle(ATTACH_PARENT_PROCESS))
362 {
363 PROCESS_BASIC_INFORMATION ProcessInfo;
364 ULONG Length = sizeof(ProcessInfo);
365
366 /* Get the real parent's ID */
367
368 Status = NtQueryInformationProcess(TargetProcess->ProcessHandle,
369 ProcessBasicInformation,
370 &ProcessInfo,
371 Length, &Length);
372 if (!NT_SUCCESS(Status))
373 {
374 DPRINT1("SrvAttachConsole - Cannot retrieve basic process info, Status = %lu\n", Status);
375 return Status;
376 }
377
378 ProcessId = ULongToHandle(ProcessInfo.InheritedFromUniqueProcessId);
379 }
380
381 /* Lock the source process via its PID */
382 Status = CsrLockProcessByClientId(ProcessId, &SourceProcess);
383 if (!NT_SUCCESS(Status)) return Status;
384
385 SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
386
387 if (SourceProcessData->ConsoleHandle == NULL)
388 {
389 Status = STATUS_INVALID_HANDLE;
390 goto Quit;
391 }
392
393 /*
394 * Inherit the console from the parent,
395 * if any, otherwise return an error.
396 */
397 Status = ConSrvInheritConsole(TargetProcessData,
398 SourceProcessData->ConsoleHandle,
399 TRUE,
400 &AttachConsoleRequest->InputHandle,
401 &AttachConsoleRequest->OutputHandle,
402 &AttachConsoleRequest->ErrorHandle);
403 if (!NT_SUCCESS(Status))
404 {
405 DPRINT1("Console inheritance failed\n");
406 goto Quit;
407 }
408
409 /* Return the console handle and the input wait handle to the caller */
410 AttachConsoleRequest->ConsoleHandle = TargetProcessData->ConsoleHandle;
411 AttachConsoleRequest->InputWaitHandle = TargetProcessData->ConsoleEvent;
412
413 /* Set the Property-Dialog and Control-Dispatcher handlers */
414 TargetProcessData->PropDispatcher = AttachConsoleRequest->PropDispatcher;
415 TargetProcessData->CtrlDispatcher = AttachConsoleRequest->CtrlDispatcher;
416
417 Status = STATUS_SUCCESS;
418
419 Quit:
420 /* Unlock the "source" process and exit */
421 CsrUnlockProcess(SourceProcess);
422 return Status;
423 }
424
425 CSR_API(SrvFreeConsole)
426 {
427 ConSrvRemoveConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process));
428 return STATUS_SUCCESS;
429 }
430
431 NTSTATUS NTAPI
432 ConDrvGetConsoleMode(IN PCONSOLE Console,
433 IN PCONSOLE_IO_OBJECT Object,
434 OUT PULONG ConsoleMode);
435 CSR_API(SrvGetConsoleMode)
436 {
437 NTSTATUS Status;
438 PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
439 PCONSOLE_IO_OBJECT Object;
440
441 Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
442 ConsoleModeRequest->Handle,
443 &Object, NULL, GENERIC_READ, TRUE, 0);
444 if (!NT_SUCCESS(Status)) return Status;
445
446 Status = ConDrvGetConsoleMode(Object->Console, Object,
447 &ConsoleModeRequest->Mode);
448
449 ConSrvReleaseObject(Object, TRUE);
450 return Status;
451 }
452
453 NTSTATUS NTAPI
454 ConDrvSetConsoleMode(IN PCONSOLE Console,
455 IN PCONSOLE_IO_OBJECT Object,
456 IN ULONG ConsoleMode);
457 CSR_API(SrvSetConsoleMode)
458 {
459 NTSTATUS Status;
460 PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
461 PCONSOLE_IO_OBJECT Object;
462
463 Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
464 ConsoleModeRequest->Handle,
465 &Object, NULL, GENERIC_WRITE, TRUE, 0);
466 if (!NT_SUCCESS(Status)) return Status;
467
468 Status = ConDrvSetConsoleMode(Object->Console, Object,
469 ConsoleModeRequest->Mode);
470
471 ConSrvReleaseObject(Object, TRUE);
472 return Status;
473 }
474
475 NTSTATUS NTAPI
476 ConDrvGetConsoleTitle(IN PCONSOLE Console,
477 IN BOOLEAN Unicode,
478 IN OUT PVOID TitleBuffer,
479 IN OUT PULONG BufLength);
480 CSR_API(SrvGetConsoleTitle)
481 {
482 NTSTATUS Status;
483 PCONSOLE_GETSETCONSOLETITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
484 PCONSOLE Console;
485
486 if (!CsrValidateMessageBuffer(ApiMessage,
487 (PVOID)&TitleRequest->Title,
488 TitleRequest->Length,
489 sizeof(BYTE)))
490 {
491 return STATUS_INVALID_PARAMETER;
492 }
493
494 Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
495 if (!NT_SUCCESS(Status))
496 {
497 DPRINT1("Can't get console\n");
498 return Status;
499 }
500
501 Status = ConDrvGetConsoleTitle(Console,
502 TitleRequest->Unicode,
503 TitleRequest->Title,
504 &TitleRequest->Length);
505
506 ConSrvReleaseConsole(Console, TRUE);
507 return Status;
508 }
509
510 NTSTATUS NTAPI
511 ConDrvSetConsoleTitle(IN PCONSOLE Console,
512 IN BOOLEAN Unicode,
513 IN PVOID TitleBuffer,
514 IN ULONG BufLength);
515 CSR_API(SrvSetConsoleTitle)
516 {
517 NTSTATUS Status;
518 PCONSOLE_GETSETCONSOLETITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
519 PCONSOLE Console;
520
521 if (!CsrValidateMessageBuffer(ApiMessage,
522 (PVOID)&TitleRequest->Title,
523 TitleRequest->Length,
524 sizeof(BYTE)))
525 {
526 return STATUS_INVALID_PARAMETER;
527 }
528
529 Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
530 if (!NT_SUCCESS(Status))
531 {
532 DPRINT1("Can't get console\n");
533 return Status;
534 }
535
536 Status = ConDrvSetConsoleTitle(Console,
537 TitleRequest->Unicode,
538 TitleRequest->Title,
539 TitleRequest->Length);
540 if (NT_SUCCESS(Status)) TermChangeTitle(Console);
541
542 ConSrvReleaseConsole(Console, TRUE);
543 return Status;
544 }
545
546 NTSTATUS NTAPI
547 ConDrvGetConsoleCP(IN PCONSOLE Console,
548 OUT PUINT CodePage,
549 IN BOOLEAN OutputCP);
550 CSR_API(SrvGetConsoleCP)
551 {
552 NTSTATUS Status;
553 PCONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleCPRequest;
554 PCONSOLE Console;
555
556 DPRINT("SrvGetConsoleCP, getting %s Code Page\n",
557 GetConsoleCPRequest->OutputCP ? "Output" : "Input");
558
559 Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
560 if (!NT_SUCCESS(Status)) return Status;
561
562 Status = ConDrvGetConsoleCP(Console,
563 &GetConsoleCPRequest->CodePage,
564 GetConsoleCPRequest->OutputCP);
565
566 ConSrvReleaseConsole(Console, TRUE);
567 return Status;
568 }
569
570 NTSTATUS NTAPI
571 ConDrvSetConsoleCP(IN PCONSOLE Console,
572 IN UINT CodePage,
573 IN BOOLEAN OutputCP);
574 CSR_API(SrvSetConsoleCP)
575 {
576 NTSTATUS Status = STATUS_INVALID_PARAMETER;
577 PCONSOLE_SETINPUTOUTPUTCP SetConsoleCPRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetConsoleCPRequest;
578 PCONSOLE Console;
579
580 DPRINT("SrvSetConsoleCP, setting %s Code Page\n",
581 SetConsoleCPRequest->OutputCP ? "Output" : "Input");
582
583 Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
584 if (!NT_SUCCESS(Status)) return Status;
585
586 Status = ConDrvSetConsoleCP(Console,
587 SetConsoleCPRequest->CodePage,
588 SetConsoleCPRequest->OutputCP);
589
590 ConSrvReleaseConsole(Console, TRUE);
591 return Status;
592 }
593
594 NTSTATUS NTAPI
595 ConDrvGetConsoleProcessList(IN PCONSOLE Console,
596 IN OUT PULONG ProcessIdsList,
597 IN ULONG MaxIdListItems,
598 OUT PULONG ProcessIdsTotal);
599 CSR_API(SrvGetConsoleProcessList)
600 {
601 NTSTATUS Status;
602 PCONSOLE_GETPROCESSLIST GetProcessListRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetProcessListRequest;
603 PCONSOLE Console;
604
605 if (!CsrValidateMessageBuffer(ApiMessage,
606 (PVOID)&GetProcessListRequest->ProcessIdsList,
607 GetProcessListRequest->ProcessCount,
608 sizeof(DWORD)))
609 {
610 return STATUS_INVALID_PARAMETER;
611 }
612
613 Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
614 if (!NT_SUCCESS(Status)) return Status;
615
616 Status = ConDrvGetConsoleProcessList(Console,
617 GetProcessListRequest->ProcessIdsList,
618 GetProcessListRequest->ProcessCount,
619 &GetProcessListRequest->ProcessCount);
620
621 ConSrvReleaseConsole(Console, TRUE);
622 return Status;
623 }
624
625 CSR_API(SrvGenerateConsoleCtrlEvent)
626 {
627 NTSTATUS Status;
628 PCONSOLE_GENERATECTRLEVENT GenerateCtrlEventRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GenerateCtrlEventRequest;
629 PCONSOLE Console;
630
631 Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
632 if (!NT_SUCCESS(Status)) return Status;
633
634 Status = ConDrvConsoleProcessCtrlEvent(Console,
635 GenerateCtrlEventRequest->ProcessGroupId,
636 GenerateCtrlEventRequest->CtrlEvent);
637
638 ConSrvReleaseConsole(Console, TRUE);
639 return Status;
640 }
641
642 CSR_API(SrvConsoleNotifyLastClose)
643 {
644 NTSTATUS Status;
645 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
646 PCONSOLE Console;
647
648 Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
649 if (!NT_SUCCESS(Status)) return Status;
650
651 /* Only one process is allowed to be registered for last close notification */
652 if (!Console->NotifyLastClose)
653 {
654 Console->NotifyLastClose = TRUE;
655 Console->NotifiedLastCloseProcess = ProcessData;
656 Status = STATUS_SUCCESS;
657 }
658 else
659 {
660 Status = STATUS_ACCESS_DENIED;
661 }
662
663 ConSrvReleaseConsole(Console, TRUE);
664 return Status;
665 }
666
667
668
669 CSR_API(SrvGetConsoleMouseInfo)
670 {
671 DPRINT1("%s not yet implemented\n", __FUNCTION__);
672 return STATUS_NOT_IMPLEMENTED;
673 }
674
675 CSR_API(SrvSetConsoleKeyShortcuts)
676 {
677 DPRINT1("%s not yet implemented\n", __FUNCTION__);
678 return STATUS_NOT_IMPLEMENTED;
679 }
680
681 CSR_API(SrvGetConsoleKeyboardLayoutName)
682 {
683 DPRINT1("%s not yet implemented\n", __FUNCTION__);
684 return STATUS_NOT_IMPLEMENTED;
685 }
686
687 CSR_API(SrvGetConsoleCharType)
688 {
689 DPRINT1("%s not yet implemented\n", __FUNCTION__);
690 return STATUS_NOT_IMPLEMENTED;
691 }
692
693 CSR_API(SrvSetConsoleLocalEUDC)
694 {
695 DPRINT1("%s not yet implemented\n", __FUNCTION__);
696 return STATUS_NOT_IMPLEMENTED;
697 }
698
699 CSR_API(SrvSetConsoleCursorMode)
700 {
701 DPRINT1("%s not yet implemented\n", __FUNCTION__);
702 return STATUS_NOT_IMPLEMENTED;
703 }
704
705 CSR_API(SrvGetConsoleCursorMode)
706 {
707 DPRINT1("%s not yet implemented\n", __FUNCTION__);
708 return STATUS_NOT_IMPLEMENTED;
709 }
710
711 CSR_API(SrvGetConsoleNlsMode)
712 {
713 DPRINT1("%s not yet implemented\n", __FUNCTION__);
714 return STATUS_NOT_IMPLEMENTED;
715 }
716
717 CSR_API(SrvSetConsoleNlsMode)
718 {
719 DPRINT1("%s not yet implemented\n", __FUNCTION__);
720 return STATUS_NOT_IMPLEMENTED;
721 }
722
723 CSR_API(SrvGetConsoleLangId)
724 {
725 DPRINT1("%s not yet implemented\n", __FUNCTION__);
726 return STATUS_NOT_IMPLEMENTED;
727 }
728
729 /* EOF */