1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Client/Server Runtime SubSystem
4 * FILE: subsystems/win32/csrsrv/server.c
5 * PURPOSE: CSR Server DLL Server Functions
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "srv.h"
12
13 #include <ndk/mmfuncs.h>
14
15 #define NDEBUG
16 #include <debug.h>
17
18 /* DATA ***********************************************************************/
19
20 PCSR_SERVER_DLL CsrLoadedServerDll[CSR_SERVER_DLL_MAX];
21 PVOID CsrSrvSharedSectionHeap = NULL;
22 PVOID CsrSrvSharedSectionBase = NULL;
23 PVOID *CsrSrvSharedStaticServerData = NULL;
24 ULONG CsrSrvSharedSectionSize = 0;
25 HANDLE CsrSrvSharedSection = NULL;
26
27 PCSR_API_ROUTINE CsrServerApiDispatchTable[CsrpMaxApiNumber] =
28 {
29 CsrSrvClientConnect,
30 CsrSrvUnusedFunction, // <= WinNT4: CsrSrvThreadConnect
31 CsrSrvUnusedFunction, // <= WinNT4: CsrSrvProfileControl
32 #if (NTDDI_VERSION < NTDDI_WS03)
33 CsrSrvIdentifyAlertableThread
34 CsrSrvSetPriorityClass
35 #else
36 CsrSrvUnusedFunction, // <= WinXP : CsrSrvIdentifyAlertableThread
37 CsrSrvUnusedFunction // <= WinXP : CsrSrvSetPriorityClass
38 #endif
39 };
40
41 BOOLEAN CsrServerApiServerValidTable[CsrpMaxApiNumber] =
42 {
43 TRUE,
44 FALSE,
45 FALSE,
46 #if (NTDDI_VERSION < NTDDI_WS03)
47 TRUE,
48 TRUE
49 #else
50 FALSE,
51 FALSE
52 #endif
53 };
54
55 /*
56 * On Windows Server 2003, CSR Servers contain
57 * the API Names Table only in Debug Builds.
58 */
59 #ifdef CSR_DBG
60 PCHAR CsrServerApiNameTable[CsrpMaxApiNumber] =
61 {
62 "ClientConnect",
63 "ThreadConnect",
64 "ProfileControl",
65 "IdentifyAlertableThread",
66 "SetPriorityClass"
67 };
68 #endif
69
70 /* PRIVATE FUNCTIONS **********************************************************/
71
72 /*++
73 * @name CsrServerDllInitialization
74 * @implemented NT4
75 *
76 * The CsrServerDllInitialization is the initialization routine
77 * for this Server DLL.
78 *
79 * @param LoadedServerDll
80 * Pointer to the CSR Server DLL structure representing this Server DLL.
81 *
82 * @return STATUS_SUCCESS.
83 *
84 * @remarks None.
85 *
86 *--*/
CSR_SERVER_DLL_INIT(CsrServerDllInitialization)87 CSR_SERVER_DLL_INIT(CsrServerDllInitialization)
88 {
89 /* Setup the DLL Object */
90 LoadedServerDll->ApiBase = CSRSRV_FIRST_API_NUMBER;
91 LoadedServerDll->HighestApiSupported = CsrpMaxApiNumber;
92 LoadedServerDll->DispatchTable = CsrServerApiDispatchTable;
93 LoadedServerDll->ValidTable = CsrServerApiServerValidTable;
94 #ifdef CSR_DBG
95 LoadedServerDll->NameTable = CsrServerApiNameTable;
96 #endif
97 LoadedServerDll->SizeOfProcessData = 0;
98 LoadedServerDll->ConnectCallback = NULL;
99 LoadedServerDll->DisconnectCallback = NULL;
100
101 /* All done */
102 return STATUS_SUCCESS;
103 }
104
105 /*++
106 * @name CsrLoadServerDll
107 * @implemented NT4
108 *
109 * The CsrLoadServerDll routine loads a CSR Server DLL and calls its entrypoint.
110 *
111 * @param DllString
112 * Pointer to the CSR Server DLL to load and call.
113 *
114 * @param EntryPoint
115 * Pointer to the name of the server's initialization function.
116 * If this parameter is NULL, the default ServerDllInitialize
117 * will be assumed.
118 *
119 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
120 *
121 * @remarks None.
122 *
123 *--*/
124 NTSTATUS
125 NTAPI
CsrLoadServerDll(IN PCHAR DllString,IN PCHAR EntryPoint OPTIONAL,IN ULONG ServerId)126 CsrLoadServerDll(IN PCHAR DllString,
127 IN PCHAR EntryPoint OPTIONAL,
128 IN ULONG ServerId)
129 {
130 NTSTATUS Status;
131 ANSI_STRING DllName;
132 UNICODE_STRING TempString, ErrorString;
133 ULONG_PTR Parameters[2];
134 HANDLE hServerDll = NULL;
135 ULONG Size;
136 PCSR_SERVER_DLL ServerDll;
137 STRING EntryPointString;
138 PCSR_SERVER_DLL_INIT_CALLBACK ServerDllInitProcedure;
139 ULONG Response;
140
141 /* Check if it's beyond the maximum we support */
142 if (ServerId >= CSR_SERVER_DLL_MAX) return STATUS_TOO_MANY_NAMES;
143
144 /* Check if it's already been loaded */
145 if (CsrLoadedServerDll[ServerId]) return STATUS_INVALID_PARAMETER;
146
147 /* Convert the name to Unicode */
148 ASSERT(DllString != NULL);
149 RtlInitAnsiString(&DllName, DllString);
150 Status = RtlAnsiStringToUnicodeString(&TempString, &DllName, TRUE);
151 if (!NT_SUCCESS(Status)) return Status;
152
153 /* If we are loading ourselves, don't actually load us */
154 if (ServerId != CSRSRV_SERVERDLL_INDEX)
155 {
156 /* Load the DLL */
157 Status = LdrLoadDll(NULL, 0, &TempString, &hServerDll);
158 if (!NT_SUCCESS(Status))
159 {
160 /* Setup error parameters */
161 Parameters[0] = (ULONG_PTR)&TempString;
162 Parameters[1] = (ULONG_PTR)&ErrorString;
163 RtlInitUnicodeString(&ErrorString, L"Default Load Path");
164
165 /* Send a hard error */
166 NtRaiseHardError(Status,
167 2,
168 3,
169 Parameters,
170 OptionOk,
171 &Response);
172 }
173
174 /* Get rid of the string */
175 RtlFreeUnicodeString(&TempString);
176 if (!NT_SUCCESS(Status)) return Status;
177 }
178
179 /* Allocate a CSR DLL Object */
180 Size = sizeof(CSR_SERVER_DLL) + DllName.MaximumLength;
181 ServerDll = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, Size);
182 if (!ServerDll)
183 {
184 if (hServerDll) LdrUnloadDll(hServerDll);
185 return STATUS_NO_MEMORY;
186 }
187
188 /* Set up the Object */
189 ServerDll->Length = Size;
190 ServerDll->SizeOfProcessData = 0;
191 ServerDll->SharedSection = CsrSrvSharedSectionHeap; // Send to the server dll our shared heap pointer.
192 ServerDll->Name.Length = DllName.Length;
193 ServerDll->Name.MaximumLength = DllName.MaximumLength;
194 ServerDll->Name.Buffer = (PCHAR)(ServerDll + 1);
195 if (DllName.Length)
196 {
197 strncpy(ServerDll->Name.Buffer, DllName.Buffer, DllName.Length);
198 }
199 ServerDll->ServerId = ServerId;
200 ServerDll->ServerHandle = hServerDll;
201
202 /* Now get the entrypoint */
203 if (hServerDll)
204 {
205 /* Initialize a string for the entrypoint, or use the default */
206 RtlInitAnsiString(&EntryPointString,
207 EntryPoint ? EntryPoint : "ServerDllInitialization");
208
209 /* Get a pointer to it */
210 Status = LdrGetProcedureAddress(hServerDll,
211 &EntryPointString,
212 0,
213 (PVOID)&ServerDllInitProcedure);
214 }
215 else
216 {
217 /* No handle, so we are loading ourselves */
218 #ifdef CSR_DBG
219 RtlInitAnsiString(&EntryPointString, "CsrServerDllInitialization");
220 #endif
221 ServerDllInitProcedure = CsrServerDllInitialization;
222 Status = STATUS_SUCCESS;
223 }
224
225 /* Check if we got the pointer, and call it */
226 if (NT_SUCCESS(Status))
227 {
228 /* Call the Server DLL entrypoint */
229 _SEH2_TRY
230 {
231 Status = ServerDllInitProcedure(ServerDll);
232 }
233 _SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
234 {
235 Status = _SEH2_GetExceptionCode();
236 #ifdef CSR_DBG
237 DPRINT1("CSRSS: Exception 0x%lx while calling Server DLL entrypoint %Z!%Z()\n",
238 Status, &DllName, &EntryPointString);
239 #endif
240 }
241 _SEH2_END;
242
243 if (NT_SUCCESS(Status))
244 {
245 /*
246 * Add this Server's Per-Process Data Size to the total that each
247 * process will need.
248 */
249 CsrTotalPerProcessDataLength += ServerDll->SizeOfProcessData;
250
251 /* Save the pointer in our list */
252 CsrLoadedServerDll[ServerDll->ServerId] = ServerDll;
253
254 /* Does it use our generic heap? */
255 if (ServerDll->SharedSection != CsrSrvSharedSectionHeap)
256 {
257 /* No, save the pointer to its shared section in our list */
258 CsrSrvSharedStaticServerData[ServerDll->ServerId] = ServerDll->SharedSection;
259 }
260 }
261 }
262
263 if (!NT_SUCCESS(Status))
264 {
265 /* Server Init failed, unload it */
266 if (hServerDll) LdrUnloadDll(hServerDll);
267
268 /* Delete the Object */
269 RtlFreeHeap(CsrHeap, 0, ServerDll);
270 }
271
272 /* Return to caller */
273 return Status;
274 }
275
276 /*++
277 * @name CsrSrvClientConnect
278 *
279 * The CsrSrvClientConnect CSR API handles a new connection to a server DLL.
280 *
281 * @param ApiMessage
282 * Pointer to the CSR API Message for this request.
283 *
284 * @param ReplyCode
285 * Optional reply to this request.
286 *
287 * @return STATUS_SUCCESS in case of success, STATUS_INVALID_PARAMETER
288 * or STATUS_TOO_MANY_NAMES in case of failure.
289 *
290 * @remarks None.
291 *
292 *--*/
CSR_API(CsrSrvClientConnect)293 CSR_API(CsrSrvClientConnect)
294 {
295 NTSTATUS Status;
296 PCSR_CLIENT_CONNECT ClientConnect = &ApiMessage->Data.CsrClientConnect;
297 PCSR_SERVER_DLL ServerDll;
298 PCSR_PROCESS CurrentProcess = CsrGetClientThread()->Process;
299
300 /* Set default reply */
301 *ReplyCode = CsrReplyImmediately;
302
303 /* Validate the ServerID */
304 if (ClientConnect->ServerId >= CSR_SERVER_DLL_MAX)
305 {
306 return STATUS_TOO_MANY_NAMES;
307 }
308 else if (!CsrLoadedServerDll[ClientConnect->ServerId])
309 {
310 return STATUS_INVALID_PARAMETER;
311 }
312
313 /* Validate the Message Buffer */
314 if (!(CsrValidateMessageBuffer(ApiMessage,
315 &ClientConnect->ConnectionInfo,
316 ClientConnect->ConnectionInfoSize,
317 sizeof(BYTE))))
318 {
319 /* Fail due to buffer overflow or other invalid buffer */
320 return STATUS_INVALID_PARAMETER;
321 }
322
323 /* Load the Server DLL */
324 ServerDll = CsrLoadedServerDll[ClientConnect->ServerId];
325
326 /* Check if it has a Connect Callback */
327 if (ServerDll->ConnectCallback)
328 {
329 /* Call the callback */
330 Status = ServerDll->ConnectCallback(CurrentProcess,
331 ClientConnect->ConnectionInfo,
332 &ClientConnect->ConnectionInfoSize);
333 }
334 else
335 {
336 /* Assume success */
337 Status = STATUS_SUCCESS;
338 }
339
340 /* Return status */
341 return Status;
342 }
343
344 /*++
345 * @name CsrSrvCreateSharedSection
346 *
347 * The CsrSrvCreateSharedSection creates the Shared Section that all
348 * CSR Server DLLs and Clients can use to share data.
349 *
350 * @param ParameterValue
351 * Specially formatted string from our registry command-line which
352 * specifies various arguments for the shared section.
353 *
354 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
355 *
356 * @remarks None.
357 *
358 *--*/
359 NTSTATUS
360 NTAPI
CsrSrvCreateSharedSection(IN PCHAR ParameterValue)361 CsrSrvCreateSharedSection(IN PCHAR ParameterValue)
362 {
363 PCHAR SizeValue = ParameterValue;
364 ULONG Size;
365 NTSTATUS Status;
366 LARGE_INTEGER SectionSize;
367 SIZE_T ViewSize = 0;
368 PPEB Peb = NtCurrentPeb();
369
370 /* If there's no parameter, fail */
371 if (!ParameterValue) return STATUS_INVALID_PARAMETER;
372
373 /* Find the first comma, and null terminate */
374 while (*SizeValue)
375 {
376 if (*SizeValue == ',')
377 {
378 *SizeValue++ = ANSI_NULL;
379 break;
380 }
381 else
382 {
383 SizeValue++;
384 }
385 }
386
387 /* Make sure it's valid */
388 if (!*SizeValue) return STATUS_INVALID_PARAMETER;
389
390 /* Convert it to an integer */
391 Status = RtlCharToInteger(SizeValue, 0, &Size);
392 if (!NT_SUCCESS(Status)) return Status;
393
394 /* Multiply by 1024 entries and round to page size */
395 CsrSrvSharedSectionSize = ROUND_UP(Size * 1024, CsrNtSysInfo.PageSize);
396
397 /* Create the Secion */
398 SectionSize.LowPart = CsrSrvSharedSectionSize;
399 SectionSize.HighPart = 0;
400 Status = NtCreateSection(&CsrSrvSharedSection,
401 SECTION_ALL_ACCESS,
402 NULL,
403 &SectionSize,
404 PAGE_EXECUTE_READWRITE,
405 SEC_BASED | SEC_RESERVE,
406 NULL);
407 if (!NT_SUCCESS(Status)) return Status;
408
409 /* Map the section */
410 Status = NtMapViewOfSection(CsrSrvSharedSection,
411 NtCurrentProcess(),
412 &CsrSrvSharedSectionBase,
413 0,
414 0,
415 NULL,
416 &ViewSize,
417 ViewUnmap,
418 MEM_TOP_DOWN,
419 PAGE_EXECUTE_READWRITE);
420 if (!NT_SUCCESS(Status))
421 {
422 /* Fail */
423 NtClose(CsrSrvSharedSection);
424 return Status;
425 }
426
427 /* FIXME: Write the value to registry */
428
429 /* The Heap is the same place as the Base */
430 CsrSrvSharedSectionHeap = CsrSrvSharedSectionBase;
431
432 /* Create the heap */
433 if (!(RtlCreateHeap(HEAP_ZERO_MEMORY | HEAP_CLASS_7,
434 CsrSrvSharedSectionHeap,
435 CsrSrvSharedSectionSize,
436 PAGE_SIZE,
437 0,
438 0)))
439 {
440 /* Failure, unmap section and return */
441 NtUnmapViewOfSection(NtCurrentProcess(), CsrSrvSharedSectionBase);
442 NtClose(CsrSrvSharedSection);
443 return STATUS_NO_MEMORY;
444 }
445
446 /* Now allocate space from the heap for the Shared Data */
447 CsrSrvSharedStaticServerData = RtlAllocateHeap(CsrSrvSharedSectionHeap,
448 HEAP_ZERO_MEMORY,
449 CSR_SERVER_DLL_MAX * sizeof(PVOID));
450 if (!CsrSrvSharedStaticServerData) return STATUS_NO_MEMORY;
451
452 /* Write the values to the PEB */
453 Peb->ReadOnlySharedMemoryBase = CsrSrvSharedSectionBase;
454 Peb->ReadOnlySharedMemoryHeap = CsrSrvSharedSectionHeap;
455 Peb->ReadOnlyStaticServerData = CsrSrvSharedStaticServerData;
456
457 /* Return */
458 return STATUS_SUCCESS;
459 }
460
461 /*++
462 * @name CsrSrvAttachSharedSection
463 *
464 * The CsrSrvAttachSharedSection maps the CSR Shared Section into a new
465 * CSR Process' address space, and returns the pointers to the section
466 * through the Connection Info structure.
467 *
468 * @param CsrProcess
469 * Pointer to the CSR Process that is attempting a connection.
470 *
471 * @param ConnectInfo
472 * Pointer to the CSR Connection Info structure for the incoming
473 * connection.
474 *
475 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
476 *
477 * @remarks None.
478 *
479 *--*/
480 NTSTATUS
481 NTAPI
CsrSrvAttachSharedSection(IN PCSR_PROCESS CsrProcess OPTIONAL,OUT PCSR_API_CONNECTINFO ConnectInfo)482 CsrSrvAttachSharedSection(IN PCSR_PROCESS CsrProcess OPTIONAL,
483 OUT PCSR_API_CONNECTINFO ConnectInfo)
484 {
485 NTSTATUS Status;
486 SIZE_T ViewSize = 0;
487
488 /* Check if we have a process */
489 if (CsrProcess)
490 {
491 /* Map the section into this process */
492 Status = NtMapViewOfSection(CsrSrvSharedSection,
493 CsrProcess->ProcessHandle,
494 &CsrSrvSharedSectionBase,
495 0,
496 0,
497 NULL,
498 &ViewSize,
499 ViewUnmap,
500 SEC_NO_CHANGE,
501 PAGE_EXECUTE_READ);
502 if (!NT_SUCCESS(Status)) return Status;
503 }
504
505 /* Write the values in the Connection Info structure */
506 ConnectInfo->SharedSectionBase = CsrSrvSharedSectionBase;
507 ConnectInfo->SharedSectionHeap = CsrSrvSharedSectionHeap;
508 ConnectInfo->SharedStaticServerData = CsrSrvSharedStaticServerData;
509
510 /* Return success */
511 return STATUS_SUCCESS;
512 }
513
514 #if (NTDDI_VERSION < NTDDI_WS03)
515
516 /*++
517 * @name CsrSrvIdentifyAlertableThread
518 * @implemented NT4, up to WinXP
519 *
520 * The CsrSrvIdentifyAlertableThread CSR API marks a CSR Thread as alertable.
521 *
522 * @param ApiMessage
523 * Pointer to the CSR API Message for this request.
524 *
525 * @param ReplyCode
526 * Pointer to an optional reply to this request.
527 *
528 * @return STATUS_SUCCESS.
529 *
530 * @remarks Deprecated.
531 *
532 *--*/
CSR_API(CsrSrvIdentifyAlertableThread)533 CSR_API(CsrSrvIdentifyAlertableThread)
534 {
535 PCSR_THREAD CsrThread = CsrGetClientThread();
536
537 UNREFERENCED_PARAMETER(ApiMessage);
538 UNREFERENCED_PARAMETER(ReplyCode);
539
540 /* Set the alertable flag */
541 CsrThread->Flags |= CsrThreadAlertable;
542
543 /* Return success */
544 return STATUS_SUCCESS;
545 }
546
547 /*++
548 * @name CsrSrvSetPriorityClass
549 * @implemented NT4, up to WinXP
550 *
551 * The CsrSrvSetPriorityClass CSR API is deprecated.
552 *
553 * @param ApiMessage
554 * Pointer to the CSR API Message for this request.
555 *
556 * @param ReplyCode
557 * Pointer to an optional reply to this request.
558 *
559 * @return STATUS_SUCCESS.
560 *
561 * @remarks Deprecated.
562 *
563 *--*/
CSR_API(CsrSrvSetPriorityClass)564 CSR_API(CsrSrvSetPriorityClass)
565 {
566 UNREFERENCED_PARAMETER(ApiMessage);
567 UNREFERENCED_PARAMETER(ReplyCode);
568
569 /* Deprecated */
570 return STATUS_SUCCESS;
571 }
572
573 #endif // (NTDDI_VERSION < NTDDI_WS03)
574
575 /*++
576 * @name CsrSrvUnusedFunction
577 * @implemented NT4
578 *
579 * The CsrSrvUnusedFunction CSR API is a stub for deprecated APIs.
580 *
581 * @param ApiMessage
582 * Pointer to the CSR API Message for this request.
583 *
584 * @param ReplyCode
585 * Pointer to an optional reply to this request.
586 *
587 * @return STATUS_INVALID_PARAMETER.
588 *
589 * @remarks CsrSrvSetPriorityClass does not use this stub because
590 * it must return success.
591 *
592 *--*/
CSR_API(CsrSrvUnusedFunction)593 CSR_API(CsrSrvUnusedFunction)
594 {
595 UNREFERENCED_PARAMETER(ApiMessage);
596 UNREFERENCED_PARAMETER(ReplyCode);
597
598 /* Deprecated */
599 return STATUS_INVALID_PARAMETER;
600 }
601
602 /* PUBLIC FUNCTIONS ***********************************************************/
603
604 /*++
605 * @name CsrSetCallingSpooler
606 * @implemented NT4
607 *
608 * the CsrSetCallingSpooler routine is deprecated.
609 *
610 * @param Reserved
611 * Deprecated
612 *
613 * @return None.
614 *
615 * @remarks This routine was used in archaic versions of NT for Printer Drivers.
616 *
617 *--*/
618 VOID
619 NTAPI
CsrSetCallingSpooler(ULONG Reserved)620 CsrSetCallingSpooler(ULONG Reserved)
621 {
622 /* Deprecated */
623 return;
624 }
625
626 /*++
627 * @name CsrUnhandledExceptionFilter
628 * @implemented NT5
629 *
630 * The CsrUnhandledExceptionFilter routine handles all exceptions
631 * within SEH-protected blocks.
632 *
633 * @param ExceptionPointers
634 * System-defined Argument.
635 *
636 * @return EXCEPTION_EXECUTE_HANDLER.
637 *
638 * @remarks None.
639 *
640 *--*/
641 EXCEPTION_DISPOSITION
642 NTAPI
CsrUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo)643 CsrUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo)
644 {
645 SYSTEM_KERNEL_DEBUGGER_INFORMATION DebuggerInfo;
646 EXCEPTION_DISPOSITION Result = EXCEPTION_EXECUTE_HANDLER;
647 BOOLEAN OldValue;
648 NTSTATUS Status;
649 UNICODE_STRING ErrorSource;
650 ULONG_PTR ErrorParameters[4];
651 ULONG Response;
652
653 DPRINT1("CsrUnhandledExceptionFilter called\n");
654
655 /* Check if a debugger is installed */
656 Status = NtQuerySystemInformation(SystemKernelDebuggerInformation,
657 &DebuggerInfo,
658 sizeof(DebuggerInfo),
659 NULL);
660
661 /* Check if this is Session 0, and the Debugger is Enabled */
662 if ((NtCurrentPeb()->SessionId != 0) && (NT_SUCCESS(Status)) &&
663 (DebuggerInfo.KernelDebuggerEnabled))
664 {
665 /* Call the Unhandled Exception Filter */
666 Result = RtlUnhandledExceptionFilter(ExceptionInfo);
667 if (Result != EXCEPTION_CONTINUE_EXECUTION)
668 {
669 /* We're going to raise an error. Get Shutdown Privilege first */
670 Status = RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
671 TRUE,
672 TRUE,
673 &OldValue);
674
675 /* Use the Process token if that failed */
676 if (Status == STATUS_NO_TOKEN)
677 {
678 Status = RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
679 TRUE,
680 FALSE,
681 &OldValue);
682 }
683 if (!NT_SUCCESS(Status))
684 {
685 DPRINT1("CsrUnhandledExceptionFilter(): RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE) failed, Status = 0x%08lx\n", Status);
686 goto NoPrivilege;
687 }
688
689 /* Initialize our Name String */
690 RtlInitUnicodeString(&ErrorSource, L"Windows SubSystem");
691
692 /* Set the parameters */
693 ErrorParameters[0] = (ULONG_PTR)&ErrorSource;
694 ErrorParameters[1] = ExceptionInfo->ExceptionRecord->ExceptionCode;
695 ErrorParameters[2] = (ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress;
696 ErrorParameters[3] = (ULONG_PTR)ExceptionInfo->ContextRecord;
697
698 /* Bugcheck */
699 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
700 4,
701 1,
702 ErrorParameters,
703 OptionShutdownSystem,
704 &Response);
705 }
706
707 NoPrivilege:
708 /* Just terminate us */
709 NtTerminateProcess(NtCurrentProcess(),
710 ExceptionInfo->ExceptionRecord->ExceptionCode);
711 }
712
713 return Result;
714 }
715
716 /* EOF */
717