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