[CONSRV]: Reorganize/rename/add some fields to CONSRV_API_CONNECTINFO, partially...
[reactos.git] / reactos / 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 #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->wFillAttribute;
253 }
254 if (ConsoleStartInfo->dwStartupFlags & STARTF_USECOUNTCHARS)
255 {
256 ConsoleInfo.ScreenBufferSize = ConsoleStartInfo->dwScreenBufferSize;
257 }
258 if (ConsoleStartInfo->dwStartupFlags & STARTF_USESIZE)
259 {
260 ConsoleInfo.ConsoleSize = ConsoleStartInfo->dwWindowSize;
261 }
262 }
263
264 /* Set-up the code page */
265 ConsoleInfo.CodePage = GetOEMCP();
266 /******************************************************************************/
267
268 Status = ConDrvInitConsole(&ConsoleHandle,
269 &Console,
270 &ConsoleInfo,
271 ConsoleLeaderProcessId);
272 if (!NT_SUCCESS(Status))
273 {
274 DPRINT1("Creating a new console failed, Status = 0x%08lx\n", Status);
275 FrontEndLoadingMethods[i].FrontEndUnload(&FrontEnd);
276 return Status;
277 }
278
279 ASSERT(Console);
280 DPRINT("Console initialized\n");
281
282 Status = ConDrvRegisterFrontEnd(Console, &FrontEnd);
283 if (!NT_SUCCESS(Status))
284 {
285 DPRINT1("Failed to register frontend to the given console, Status = 0x%08lx\n", Status);
286 ConDrvDeleteConsole(Console);
287 FrontEndLoadingMethods[i].FrontEndUnload(&FrontEnd);
288 return Status;
289 }
290 DPRINT("FrontEnd registered\n");
291
292 /* Return the newly created console to the caller and a success code too */
293 *NewConsoleHandle = ConsoleHandle;
294 *NewConsole = Console;
295 return STATUS_SUCCESS;
296 }
297
298 VOID WINAPI
299 ConSrvDeleteConsole(PCONSOLE Console)
300 {
301 DPRINT("ConSrvDeleteConsole\n");
302
303 /* Just call the driver. ConSrvDeregisterFrontEnd is called on-demand. */
304 ConDrvDeleteConsole(Console);
305 }
306
307
308 /* PUBLIC SERVER APIS *********************************************************/
309
310 CSR_API(SrvAllocConsole)
311 {
312 NTSTATUS Status = STATUS_SUCCESS;
313 PCONSOLE_ALLOCCONSOLE AllocConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AllocConsoleRequest;
314 PCSR_PROCESS CsrProcess = CsrGetClientThread()->Process;
315 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
316
317 if (ProcessData->ConsoleHandle != NULL)
318 {
319 DPRINT1("Process already has a console\n");
320 return STATUS_ACCESS_DENIED;
321 }
322
323 if (!CsrValidateMessageBuffer(ApiMessage,
324 (PVOID*)&AllocConsoleRequest->ConsoleStartInfo,
325 1,
326 sizeof(CONSOLE_START_INFO)))
327 {
328 return STATUS_INVALID_PARAMETER;
329 }
330
331 /* Initialize a new Console owned by the Console Leader Process */
332 Status = ConSrvAllocateConsole(ProcessData,
333 &AllocConsoleRequest->InputHandle,
334 &AllocConsoleRequest->OutputHandle,
335 &AllocConsoleRequest->ErrorHandle,
336 AllocConsoleRequest->ConsoleStartInfo);
337 if (!NT_SUCCESS(Status))
338 {
339 DPRINT1("Console allocation failed\n");
340 return Status;
341 }
342
343 /* Return the console handle and the input wait handle to the caller */
344 AllocConsoleRequest->ConsoleHandle = ProcessData->ConsoleHandle;
345 AllocConsoleRequest->InputWaitHandle = ProcessData->ConsoleEvent;
346
347 /* Set the Property-Dialog and Control-Dispatcher handlers */
348 ProcessData->PropDispatcher = AllocConsoleRequest->PropDispatcher;
349 ProcessData->CtrlDispatcher = AllocConsoleRequest->CtrlDispatcher;
350
351 return STATUS_SUCCESS;
352 }
353
354 CSR_API(SrvAttachConsole)
355 {
356 NTSTATUS Status = STATUS_SUCCESS;
357 PCONSOLE_ATTACHCONSOLE AttachConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AttachConsoleRequest;
358 PCSR_PROCESS SourceProcess = NULL; // The parent process.
359 PCSR_PROCESS TargetProcess = CsrGetClientThread()->Process; // Ourselves.
360 HANDLE ProcessId = ULongToHandle(AttachConsoleRequest->ProcessId);
361 PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
362
363 TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
364
365 if (TargetProcessData->ConsoleHandle != NULL)
366 {
367 DPRINT1("Process already has a console\n");
368 return STATUS_ACCESS_DENIED;
369 }
370
371 /* Check whether we try to attach to the parent's console */
372 if (ProcessId == ULongToHandle(ATTACH_PARENT_PROCESS))
373 {
374 PROCESS_BASIC_INFORMATION ProcessInfo;
375 ULONG Length = sizeof(ProcessInfo);
376
377 /* Get the real parent's ID */
378
379 Status = NtQueryInformationProcess(TargetProcess->ProcessHandle,
380 ProcessBasicInformation,
381 &ProcessInfo,
382 Length, &Length);
383 if (!NT_SUCCESS(Status))
384 {
385 DPRINT1("SrvAttachConsole - Cannot retrieve basic process info, Status = %lu\n", Status);
386 return Status;
387 }
388
389 ProcessId = ULongToHandle(ProcessInfo.InheritedFromUniqueProcessId);
390 }
391
392 /* Lock the source process via its PID */
393 Status = CsrLockProcessByClientId(ProcessId, &SourceProcess);
394 if (!NT_SUCCESS(Status)) return Status;
395
396 SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
397
398 if (SourceProcessData->ConsoleHandle == NULL)
399 {
400 Status = STATUS_INVALID_HANDLE;
401 goto Quit;
402 }
403
404 /*
405 * Inherit the console from the parent,
406 * if any, otherwise return an error.
407 */
408 Status = ConSrvInheritConsole(TargetProcessData,
409 SourceProcessData->ConsoleHandle,
410 TRUE,
411 &AttachConsoleRequest->InputHandle,
412 &AttachConsoleRequest->OutputHandle,
413 &AttachConsoleRequest->ErrorHandle);
414 if (!NT_SUCCESS(Status))
415 {
416 DPRINT1("Console inheritance failed\n");
417 goto Quit;
418 }
419
420 /* Return the console handle and the input wait handle to the caller */
421 AttachConsoleRequest->ConsoleHandle = TargetProcessData->ConsoleHandle;
422 AttachConsoleRequest->InputWaitHandle = TargetProcessData->ConsoleEvent;
423
424 /* Set the Property-Dialog and Control-Dispatcher handlers */
425 TargetProcessData->PropDispatcher = AttachConsoleRequest->PropDispatcher;
426 TargetProcessData->CtrlDispatcher = AttachConsoleRequest->CtrlDispatcher;
427
428 Status = STATUS_SUCCESS;
429
430 Quit:
431 /* Unlock the "source" process and exit */
432 CsrUnlockProcess(SourceProcess);
433 return Status;
434 }
435
436 CSR_API(SrvFreeConsole)
437 {
438 ConSrvRemoveConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process));
439 return STATUS_SUCCESS;
440 }
441
442 NTSTATUS NTAPI
443 ConDrvGetConsoleMode(IN PCONSOLE Console,
444 IN PCONSOLE_IO_OBJECT Object,
445 OUT PULONG ConsoleMode);
446 CSR_API(SrvGetConsoleMode)
447 {
448 NTSTATUS Status;
449 PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
450 PCONSOLE_IO_OBJECT Object;
451
452 Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
453 ConsoleModeRequest->ConsoleHandle,
454 &Object, NULL, GENERIC_READ, TRUE, 0);
455 if (!NT_SUCCESS(Status)) return Status;
456
457 Status = ConDrvGetConsoleMode(Object->Console, Object,
458 &ConsoleModeRequest->ConsoleMode);
459
460 ConSrvReleaseObject(Object, TRUE);
461 return Status;
462 }
463
464 NTSTATUS NTAPI
465 ConDrvSetConsoleMode(IN PCONSOLE Console,
466 IN PCONSOLE_IO_OBJECT Object,
467 IN ULONG ConsoleMode);
468 CSR_API(SrvSetConsoleMode)
469 {
470 NTSTATUS Status;
471 PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
472 PCONSOLE_IO_OBJECT Object;
473
474 Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
475 ConsoleModeRequest->ConsoleHandle,
476 &Object, NULL, GENERIC_WRITE, TRUE, 0);
477 if (!NT_SUCCESS(Status)) return Status;
478
479 Status = ConDrvSetConsoleMode(Object->Console, Object,
480 ConsoleModeRequest->ConsoleMode);
481
482 ConSrvReleaseObject(Object, TRUE);
483 return Status;
484 }
485
486 NTSTATUS NTAPI
487 ConDrvGetConsoleTitle(IN PCONSOLE Console,
488 IN OUT PWCHAR Title,
489 IN OUT PULONG BufLength);
490 CSR_API(SrvGetConsoleTitle)
491 {
492 NTSTATUS Status;
493 PCONSOLE_GETSETCONSOLETITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
494 PCONSOLE Console;
495
496 if (!CsrValidateMessageBuffer(ApiMessage,
497 (PVOID)&TitleRequest->Title,
498 TitleRequest->Length,
499 sizeof(BYTE)))
500 {
501 return STATUS_INVALID_PARAMETER;
502 }
503
504 Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
505 if (!NT_SUCCESS(Status))
506 {
507 DPRINT1("Can't get console\n");
508 return Status;
509 }
510
511 Status = ConDrvGetConsoleTitle(Console,
512 TitleRequest->Title,
513 &TitleRequest->Length);
514
515 ConSrvReleaseConsole(Console, TRUE);
516 return Status;
517 }
518
519 NTSTATUS NTAPI
520 ConDrvSetConsoleTitle(IN PCONSOLE Console,
521 IN PWCHAR Title,
522 IN ULONG BufLength);
523 CSR_API(SrvSetConsoleTitle)
524 {
525 NTSTATUS Status;
526 PCONSOLE_GETSETCONSOLETITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
527 PCONSOLE Console;
528
529 if (!CsrValidateMessageBuffer(ApiMessage,
530 (PVOID)&TitleRequest->Title,
531 TitleRequest->Length,
532 sizeof(BYTE)))
533 {
534 return STATUS_INVALID_PARAMETER;
535 }
536
537 Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
538 if (!NT_SUCCESS(Status))
539 {
540 DPRINT1("Can't get console\n");
541 return Status;
542 }
543
544 Status = ConDrvSetConsoleTitle(Console,
545 TitleRequest->Title,
546 TitleRequest->Length);
547
548 if (NT_SUCCESS(Status)) ConioChangeTitle(Console);
549
550 ConSrvReleaseConsole(Console, TRUE);
551 return Status;
552 }
553
554 NTSTATUS NTAPI
555 ConDrvGetConsoleCP(IN PCONSOLE Console,
556 OUT PUINT CodePage,
557 IN BOOLEAN InputCP);
558 CSR_API(SrvGetConsoleCP)
559 {
560 NTSTATUS Status;
561 PCONSOLE_GETSETINPUTOUTPUTCP ConsoleCPRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleCPRequest;
562 PCONSOLE Console;
563
564 DPRINT("SrvGetConsoleCP, getting %s Code Page\n",
565 ConsoleCPRequest->InputCP ? "Input" : "Output");
566
567 Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
568 if (!NT_SUCCESS(Status)) return Status;
569
570 Status = ConDrvGetConsoleCP(Console,
571 &ConsoleCPRequest->CodePage,
572 ConsoleCPRequest->InputCP);
573
574 ConSrvReleaseConsole(Console, TRUE);
575 return Status;
576 }
577
578 NTSTATUS NTAPI
579 ConDrvSetConsoleCP(IN PCONSOLE Console,
580 IN UINT CodePage,
581 IN BOOLEAN InputCP);
582 CSR_API(SrvSetConsoleCP)
583 {
584 NTSTATUS Status = STATUS_INVALID_PARAMETER;
585 PCONSOLE_GETSETINPUTOUTPUTCP ConsoleCPRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleCPRequest;
586 PCONSOLE Console;
587
588 DPRINT("SrvSetConsoleCP, setting %s Code Page\n",
589 ConsoleCPRequest->InputCP ? "Input" : "Output");
590
591 Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
592 if (!NT_SUCCESS(Status)) return Status;
593
594 Status = ConDrvSetConsoleCP(Console,
595 ConsoleCPRequest->CodePage,
596 ConsoleCPRequest->InputCP);
597
598 ConSrvReleaseConsole(Console, TRUE);
599 return Status;
600 }
601
602 NTSTATUS NTAPI
603 ConDrvGetConsoleProcessList(IN PCONSOLE Console,
604 IN OUT PULONG ProcessIdsList,
605 IN ULONG MaxIdListItems,
606 OUT PULONG ProcessIdsTotal);
607 CSR_API(SrvGetConsoleProcessList)
608 {
609 NTSTATUS Status;
610 PCONSOLE_GETPROCESSLIST GetProcessListRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetProcessListRequest;
611 PCONSOLE Console;
612
613 if (!CsrValidateMessageBuffer(ApiMessage,
614 (PVOID)&GetProcessListRequest->pProcessIds,
615 GetProcessListRequest->nMaxIds,
616 sizeof(DWORD)))
617 {
618 return STATUS_INVALID_PARAMETER;
619 }
620
621 Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
622 if (!NT_SUCCESS(Status)) return Status;
623
624 Status = ConDrvGetConsoleProcessList(Console,
625 GetProcessListRequest->pProcessIds,
626 GetProcessListRequest->nMaxIds,
627 &GetProcessListRequest->nProcessIdsTotal);
628
629 ConSrvReleaseConsole(Console, TRUE);
630 return Status;
631 }
632
633 CSR_API(SrvGenerateConsoleCtrlEvent)
634 {
635 NTSTATUS Status;
636 PCONSOLE_GENERATECTRLEVENT GenerateCtrlEventRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GenerateCtrlEventRequest;
637 PCONSOLE Console;
638
639 Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
640 if (!NT_SUCCESS(Status)) return Status;
641
642 Status = ConDrvConsoleProcessCtrlEvent(Console,
643 GenerateCtrlEventRequest->ProcessGroup,
644 GenerateCtrlEventRequest->Event);
645
646 ConSrvReleaseConsole(Console, TRUE);
647 return Status;
648 }
649
650 /* EOF */