2 * PROJECT: ReactOS User API Server DLL
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Hard errors support.
5 * COPYRIGHT: Copyright 2007-2018 Dmitry Philippov (shedon@mail.ru)
6 * Copyright 2010-2018 Timo Kreuzer (timo.kreuzer@reactos.org)
7 * Copyright 2012-2018 Hermes Belusca-Maito
8 * Copyright 2018 Giannis Adamopoulos
11 /* INCLUDES *******************************************************************/
15 #define NTOS_MODE_USER
16 #include <ndk/mmfuncs.h>
18 #include <undocelfapi.h>
19 #include <ntstrsafe.h>
27 /* FUNCTIONS ******************************************************************/
43 UserpGetClientFileName(
44 OUT PUNICODE_STRING ClientFileNameU
,
47 PLIST_ENTRY ModuleListHead
;
49 PLDR_DATA_TABLE_ENTRY Module
;
51 PROCESS_BASIC_INFORMATION ClientBasicInfo
;
52 LDR_DATA_TABLE_ENTRY ModuleData
;
57 /* Initialize string */
58 RtlInitEmptyUnicodeString(ClientFileNameU
, NULL
, 0);
60 /* Query process information */
61 Status
= NtQueryInformationProcess(hProcess
,
62 ProcessBasicInformation
,
64 sizeof(ClientBasicInfo
),
66 if (!NT_SUCCESS(Status
)) return Status
;
68 /* Locate the process loader data table and retrieve its name from it */
70 Peb
= ClientBasicInfo
.PebBaseAddress
;
71 if (!Peb
) return STATUS_UNSUCCESSFUL
;
73 Status
= NtReadVirtualMemory(hProcess
, &Peb
->Ldr
, &Ldr
, sizeof(Ldr
), NULL
);
74 if (!NT_SUCCESS(Status
)) return Status
;
76 ModuleListHead
= &Ldr
->InLoadOrderModuleList
;
77 Status
= NtReadVirtualMemory(hProcess
,
78 &ModuleListHead
->Flink
,
82 if (!NT_SUCCESS(Status
)) return Status
;
84 if (Entry
== ModuleListHead
) return STATUS_UNSUCCESSFUL
;
86 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
88 Status
= NtReadVirtualMemory(hProcess
,
93 if (!NT_SUCCESS(Status
)) return Status
;
95 Status
= NtReadVirtualMemory(hProcess
,
96 &Peb
->ImageBaseAddress
,
98 sizeof(ClientDllBase
),
100 if (!NT_SUCCESS(Status
)) return Status
;
102 if (ClientDllBase
!= ModuleData
.DllBase
) return STATUS_UNSUCCESSFUL
;
104 ClientFileNameU
->MaximumLength
= ModuleData
.BaseDllName
.MaximumLength
;
105 ClientFileNameU
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
107 ClientFileNameU
->MaximumLength
);
108 if (!ClientFileNameU
->Buffer
)
110 RtlInitEmptyUnicodeString(ClientFileNameU
, NULL
, 0);
111 return STATUS_NO_MEMORY
;
114 Status
= NtReadVirtualMemory(hProcess
,
115 ModuleData
.BaseDllName
.Buffer
,
116 ClientFileNameU
->Buffer
,
117 ClientFileNameU
->MaximumLength
,
119 if (!NT_SUCCESS(Status
))
121 RtlFreeHeap(RtlGetProcessHeap(), 0, ClientFileNameU
->Buffer
);
122 RtlInitEmptyUnicodeString(ClientFileNameU
, NULL
, 0);
126 ClientFileNameU
->Length
= wcslen(ClientFileNameU
->Buffer
) * sizeof(WCHAR
);
127 DPRINT("ClientFileNameU = \'%wZ\'\n", &ClientFileNameU
);
129 return STATUS_SUCCESS
;
134 UserpFreeStringParameters(
135 IN OUT PULONG_PTR Parameters
,
136 IN PHARDERROR_MSG HardErrorMessage
)
140 /* Loop all parameters */
141 for (nParam
= 0; nParam
< HardErrorMessage
->NumberOfParameters
; nParam
++)
143 /* Check if the current parameter is a string */
144 if ((HardErrorMessage
->UnicodeStringParameterMask
& (1 << nParam
)) && (Parameters
[nParam
] != 0))
146 /* Free the string buffer */
147 RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID
)Parameters
[nParam
]);
154 UserpCaptureStringParameters(
155 OUT PULONG_PTR Parameters
,
156 OUT PULONG SizeOfAllUnicodeStrings
,
157 IN PHARDERROR_MSG HardErrorMessage
,
158 IN HANDLE hProcess OPTIONAL
)
160 NTSTATUS Status
= STATUS_SUCCESS
;
161 ULONG nParam
, Size
= 0;
162 UNICODE_STRING TempStringU
, ParamStringU
;
163 ANSI_STRING TempStringA
;
165 if (SizeOfAllUnicodeStrings
)
166 *SizeOfAllUnicodeStrings
= 0;
168 /* Read all strings from client space */
169 for (nParam
= 0; nParam
< HardErrorMessage
->NumberOfParameters
; nParam
++)
171 Parameters
[nParam
] = 0;
173 /* Check if the current parameter is a unicode string */
174 if (HardErrorMessage
->UnicodeStringParameterMask
& (1 << nParam
))
176 /* Skip this string if we do not have a client process */
180 /* Read the UNICODE_STRING from the process memory */
181 Status
= NtReadVirtualMemory(hProcess
,
182 (PVOID
)HardErrorMessage
->Parameters
[nParam
],
184 sizeof(ParamStringU
),
186 if (!NT_SUCCESS(Status
))
188 /* We failed, skip this string */
189 DPRINT1("NtReadVirtualMemory(HardErrorMessage->Parameters) failed, Status 0x%lx\n", Status
);
193 /* Allocate a buffer for the string */
194 TempStringU
.MaximumLength
= ParamStringU
.Length
;
195 TempStringU
.Length
= ParamStringU
.Length
;
196 TempStringU
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
198 TempStringU
.MaximumLength
);
199 if (!TempStringU
.Buffer
)
201 /* We failed, skip this string */
202 DPRINT1("Cannot allocate memory with size %u\n", TempStringU
.MaximumLength
);
203 Status
= STATUS_NO_MEMORY
;
207 /* Read the string buffer from the process memory */
208 Status
= NtReadVirtualMemory(hProcess
,
213 if (!NT_SUCCESS(Status
))
215 /* We failed, skip this string */
216 DPRINT1("NtReadVirtualMemory(ParamStringU) failed, Status 0x%lx\n", Status
);
217 RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU
.Buffer
);
221 DPRINT("ParamString = \'%wZ\'\n", &TempStringU
);
223 /* Allocate a buffer for converted to ANSI string */
224 TempStringA
.MaximumLength
= RtlUnicodeStringToAnsiSize(&TempStringU
);
225 TempStringA
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
227 TempStringA
.MaximumLength
);
228 if (!TempStringA
.Buffer
)
230 /* We failed, skip this string */
231 DPRINT1("Cannot allocate memory with size %u\n", TempStringA
.MaximumLength
);
232 RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU
.Buffer
);
233 Status
= STATUS_NO_MEMORY
;
237 /* Convert string to ANSI and free temporary buffer */
238 Status
= RtlUnicodeStringToAnsiString(&TempStringA
, &TempStringU
, FALSE
);
239 RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU
.Buffer
);
240 if (!NT_SUCCESS(Status
))
242 /* We failed, skip this string */
243 RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringA
.Buffer
);
247 /* Note: RtlUnicodeStringToAnsiString returns NULL terminated string */
248 Parameters
[nParam
] = (ULONG_PTR
)TempStringA
.Buffer
;
249 Size
+= TempStringU
.Length
;
253 /* It's not a unicode string, just copy the parameter */
254 Parameters
[nParam
] = HardErrorMessage
->Parameters
[nParam
];
259 if (!NT_SUCCESS(Status
))
261 UserpFreeStringParameters(Parameters
, HardErrorMessage
);
266 if (SizeOfAllUnicodeStrings
)
267 *SizeOfAllUnicodeStrings
= Size
;
275 OUT PUNICODE_STRING TextStringU
,
276 OUT PUNICODE_STRING CaptionStringU
,
277 IN PULONG_PTR Parameters
,
278 IN ULONG SizeOfStrings
,
279 IN PHARDERROR_MSG Message
,
280 IN HANDLE hProcess OPTIONAL
)
283 UNICODE_STRING FileNameU
, TempStringU
, FormatU
, Format2U
;
284 ANSI_STRING FormatA
, Format2A
;
285 PMESSAGE_RESOURCE_ENTRY MessageResource
;
286 ULONG_PTR CapturedParameters
[MAXIMUM_HARDERROR_PARAMETERS
];
288 ULONG ExceptionCode
, Severity
;
291 /* Copy the Parameters array locally */
292 RtlCopyMemory(&CapturedParameters
, Parameters
, sizeof(CapturedParameters
));
294 /* Get the file name of the client process */
295 Status
= STATUS_SUCCESS
;
297 Status
= UserpGetClientFileName(&FileNameU
, hProcess
);
300 * Fall back to SYSTEM process if the client process handle
301 * was NULL or we failed retrieving a file name.
303 if (!hProcess
|| !NT_SUCCESS(Status
) || !FileNameU
.Buffer
)
305 RtlInitUnicodeString(&FileNameU
, L
"System Process");
309 Severity
= (ULONG
)(Message
->Status
) >> 30;
311 /* Get text string of the error code */
312 Status
= RtlFindMessage(GetModuleHandleW(L
"ntdll"),
313 (ULONG_PTR
)RT_MESSAGETABLE
,
317 if (NT_SUCCESS(Status
))
319 if (MessageResource
->Flags
)
321 RtlInitUnicodeString(&FormatU
, (PWSTR
)MessageResource
->Text
);
322 FormatA
.Buffer
= NULL
;
326 RtlInitAnsiString(&FormatA
, (PCHAR
)MessageResource
->Text
);
327 RtlAnsiStringToUnicodeString(&FormatU
, &FormatA
, TRUE
);
332 /* Fall back to hardcoded value */
333 RtlInitUnicodeString(&FormatU
, L
"Unknown Hard Error");
334 FormatA
.Buffer
= NULL
;
337 FormatString
= FormatU
.Buffer
;
339 /* Check whether a caption exists */
340 if (FormatString
[0] == L
'{')
342 /* Set caption start */
343 TempStringU
.Buffer
= ++FormatString
;
345 /* Get size of the caption */
346 for (Size
= 0; *FormatString
!= UNICODE_NULL
&& *FormatString
!= L
'}'; Size
++)
349 /* Skip '}', '\r', '\n' */
352 TempStringU
.Length
= (USHORT
)(Size
* sizeof(WCHAR
));
353 TempStringU
.MaximumLength
= TempStringU
.Length
;
357 /* FIXME: Use localized strings! */
359 if (Severity
== STATUS_SEVERITY_SUCCESS
)
360 RtlInitUnicodeString(&TempStringU
, L
"Success");
361 else if (Severity
== STATUS_SEVERITY_INFORMATIONAL
)
362 RtlInitUnicodeString(&TempStringU
, L
"System Information");
363 else if (Severity
== STATUS_SEVERITY_WARNING
)
364 RtlInitUnicodeString(&TempStringU
, L
"System Warning");
365 else if (Severity
== STATUS_SEVERITY_ERROR
)
366 RtlInitUnicodeString(&TempStringU
, L
"System Error");
368 RtlInitEmptyUnicodeString(&TempStringU
, NULL
, 0);
371 /* Calculate buffer length for the caption */
372 CaptionStringU
->MaximumLength
= FileNameU
.Length
+ TempStringU
.Length
+
375 /* Allocate a buffer for the caption */
376 CaptionStringU
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
378 CaptionStringU
->MaximumLength
);
379 if (!CaptionStringU
->Buffer
)
381 DPRINT1("Cannot allocate memory for CaptionStringU\n");
382 Status
= STATUS_NO_MEMORY
;
385 /* Append the file name, seperator and the caption text */
386 CaptionStringU
->Length
= 0;
387 RtlAppendUnicodeStringToString(CaptionStringU
, &FileNameU
);
388 RtlAppendUnicodeToString(CaptionStringU
, L
" - ");
389 RtlAppendUnicodeStringToString(CaptionStringU
, &TempStringU
);
391 /* Zero terminate the buffer */
392 CaptionStringU
->Buffer
[CaptionStringU
->Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
394 /* Free the file name buffer */
395 RtlFreeUnicodeString(&FileNameU
);
397 // FIXME: What is 42 == ??
400 /* Check if this is an exception message */
401 if (Message
->Status
== STATUS_UNHANDLED_EXCEPTION
)
403 ExceptionCode
= CapturedParameters
[0];
405 /* Get text string of the exception code */
406 Status
= RtlFindMessage(GetModuleHandleW(L
"ntdll"),
407 (ULONG_PTR
)RT_MESSAGETABLE
,
411 if (NT_SUCCESS(Status
))
413 if (MessageResource
->Flags
)
415 RtlInitUnicodeString(&Format2U
, (PWSTR
)MessageResource
->Text
);
416 Format2A
.Buffer
= NULL
;
420 RtlInitAnsiString(&Format2A
, (PCHAR
)MessageResource
->Text
);
421 RtlAnsiStringToUnicodeString(&Format2U
, &Format2A
, TRUE
);
424 /* Handle special cases */
425 if (ExceptionCode
== STATUS_ACCESS_VIOLATION
)
427 FormatString
= Format2U
.Buffer
;
428 CapturedParameters
[0] = CapturedParameters
[1];
429 CapturedParameters
[1] = CapturedParameters
[3];
430 if (CapturedParameters
[2])
431 CapturedParameters
[2] = (ULONG_PTR
)L
"written";
433 CapturedParameters
[2] = (ULONG_PTR
)L
"read";
435 else if (ExceptionCode
== STATUS_IN_PAGE_ERROR
)
437 FormatString
= Format2U
.Buffer
;
438 CapturedParameters
[0] = CapturedParameters
[1];
439 CapturedParameters
[1] = CapturedParameters
[3];
445 /* Keep the existing FormatString */
446 CapturedParameters
[2] = CapturedParameters
[1];
447 CapturedParameters
[1] = CapturedParameters
[0];
449 pTmp
= Format2U
.Buffer
;
450 if (!_wcsnicmp(pTmp
, L
"{EXCEPTION}", 11))
453 * This is a named exception. Skip the mark and
454 * retrieve the exception name that follows it.
458 /* Skip '\r', '\n' */
461 CapturedParameters
[0] = (ULONG_PTR
)pTmp
;
465 /* Fall back to hardcoded value */
466 CapturedParameters
[0] = (ULONG_PTR
)L
"unknown software exception";
472 /* Fall back to hardcoded value, and keep the existing FormatString */
473 CapturedParameters
[2] = CapturedParameters
[1];
474 CapturedParameters
[1] = CapturedParameters
[0];
475 CapturedParameters
[0] = (ULONG_PTR
)L
"unknown software exception";
478 /* FIXME: Use localized strings! */
479 if (Message
->ValidResponseOptions
== OptionOk
||
480 Message
->ValidResponseOptions
== OptionOkCancel
)
482 // Tmp = FormatString + wcslen(FormatString);
485 Size
+= 1 + wcslen(L
"Click on OK to terminate the program.");
487 if (Message
->ValidResponseOptions
== OptionOkCancel
)
489 Size
+= 1 + wcslen(L
"Click on CANCEL to debug the program.");
493 /* Calculate length of text buffer */
494 TextStringU
->MaximumLength
= FormatU
.Length
+ SizeOfStrings
+
495 (USHORT
)(Size
* sizeof(WCHAR
)) +
496 sizeof(UNICODE_NULL
);
498 /* Allocate a buffer for the text */
499 TextStringU
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
501 TextStringU
->MaximumLength
);
502 if (!TextStringU
->Buffer
)
504 DPRINT1("Cannot allocate memory for TextStringU\n");
505 Status
= STATUS_NO_MEMORY
;
508 /* Wrap in SEH to protect from invalid string parameters */
511 /* Print the string into the buffer */
512 RtlStringCbPrintfW(TextStringU
->Buffer
,
513 TextStringU
->MaximumLength
,
515 CapturedParameters
[0],
516 CapturedParameters
[1],
517 CapturedParameters
[2],
518 CapturedParameters
[3]);
520 if (Message
->Status
== STATUS_UNHANDLED_EXCEPTION
)
522 /* FIXME: Use localized strings! */
523 if (Message
->ValidResponseOptions
== OptionOk
||
524 Message
->ValidResponseOptions
== OptionOkCancel
)
526 // Tmp = FormatString + wcslen(FormatString);
529 RtlStringCbCatW(TextStringU
->Buffer
,
530 TextStringU
->MaximumLength
,
532 RtlStringCbCatW(TextStringU
->Buffer
,
533 TextStringU
->MaximumLength
,
534 L
"Click on OK to terminate the program.");
536 if (Message
->ValidResponseOptions
== OptionOkCancel
)
538 RtlStringCbCatW(TextStringU
->Buffer
,
539 TextStringU
->MaximumLength
,
541 RtlStringCbCatW(TextStringU
->Buffer
,
542 TextStringU
->MaximumLength
,
543 L
"Click on CANCEL to debug the program.");
547 Status
= STATUS_SUCCESS
;
549 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
551 /* An exception occurred, use a default string */
552 RtlStringCbPrintfW(TextStringU
->Buffer
,
553 TextStringU
->MaximumLength
,
554 L
"Exception processing message 0x%08lx\n"
555 L
"Parameters: 0x%p 0x%p 0x%p 0x%p",
557 CapturedParameters
[0], CapturedParameters
[1],
558 CapturedParameters
[2], CapturedParameters
[3]);
560 /* Set error and free buffers */
561 // Status = _SEH2_GetExceptionCode();
562 // RtlFreeHeap(RtlGetProcessHeap(), 0, TextStringU->Buffer);
563 // RtlFreeHeap(RtlGetProcessHeap(), 0, CaptionStringU->Buffer);
567 if (NT_SUCCESS(Status
))
569 TextStringU
->Length
= wcslen(TextStringU
->Buffer
) * sizeof(WCHAR
);
572 /* Free converted Unicode strings if the original format strings were Ansi */
573 if (Format2A
.Buffer
) RtlFreeUnicodeString(&Format2U
);
574 if (FormatA
.Buffer
) RtlFreeUnicodeString(&FormatU
);
583 IN ULONG DefaultValue
)
586 ULONG Value
= DefaultValue
;
587 UNICODE_STRING String
;
588 OBJECT_ATTRIBUTES ObjectAttributes
;
591 UCHAR ValueBuffer
[sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(ULONG
)];
592 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)ValueBuffer
;
594 RtlInitUnicodeString(&String
, KeyName
);
595 InitializeObjectAttributes(&ObjectAttributes
,
597 OBJ_CASE_INSENSITIVE
,
601 /* Open the registry key */
602 Status
= NtOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
603 if (NT_SUCCESS(Status
))
605 /* Query the value */
606 RtlInitUnicodeString(&String
, ValueName
);
607 Status
= NtQueryValueKey(KeyHandle
,
609 KeyValuePartialInformation
,
614 /* Close the registry key */
617 if (NT_SUCCESS(Status
) && (ValueInfo
->Type
== REG_DWORD
))
619 /* Directly retrieve the data */
620 Value
= *(PULONG
)ValueInfo
->Data
;
628 UserpShowInformationBalloon(PWSTR Text
,
630 PHARDERROR_MSG Message
)
632 ULONG ShellErrorMode
;
634 COPYDATASTRUCT CopyData
;
635 PBALLOON_HARD_ERROR_DATA pdata
;
636 DWORD dwSize
, cbTextLen
, cbTitleLen
;
637 PWCHAR pText
, pCaption
;
640 /* Query the shell error mode value */
641 ShellErrorMode
= GetRegInt(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Windows",
642 L
"ShellErrorMode", 0);
644 /* Make the shell display the hard error message in balloon only if necessary */
645 if (ShellErrorMode
!= 1)
648 hwnd
= GetTaskmanWindow();
651 DPRINT1("Failed to find shell task window (last error %lu)\n", GetLastError());
655 cbTextLen
= ((Text
? wcslen(Text
) : 0) + 1) * sizeof(WCHAR
);
656 cbTitleLen
= ((Caption
? wcslen(Caption
) : 0) + 1) * sizeof(WCHAR
);
658 dwSize
= sizeof(BALLOON_HARD_ERROR_DATA
);
659 dwSize
+= cbTextLen
+ cbTitleLen
;
661 pdata
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, dwSize
);
664 DPRINT1("Failed to allocate balloon data\n");
668 pdata
->cbHeaderSize
= sizeof(BALLOON_HARD_ERROR_DATA
);
669 pdata
->Status
= Message
->Status
;
671 if (NT_SUCCESS(Message
->Status
))
672 pdata
->dwType
= MB_OK
;
673 else if (Message
->Status
== STATUS_SERVICE_NOTIFICATION
)
674 pdata
->dwType
= Message
->Parameters
[2];
676 pdata
->dwType
= MB_ICONINFORMATION
;
678 pdata
->TitleOffset
= pdata
->cbHeaderSize
;
679 pdata
->MessageOffset
= pdata
->TitleOffset
;
680 pdata
->MessageOffset
+= cbTitleLen
;
681 pCaption
= (PWCHAR
)((ULONG_PTR
)pdata
+ pdata
->TitleOffset
);
682 pText
= (PWCHAR
)((ULONG_PTR
)pdata
+ pdata
->MessageOffset
);
683 wcscpy(pCaption
, Caption
);
686 CopyData
.dwData
= RegisterWindowMessageW(L
"HardError");
687 CopyData
.cbData
= dwSize
;
688 CopyData
.lpData
= pdata
;
692 ret
= SendMessageTimeoutW(hwnd
, WM_COPYDATA
, 0, (LPARAM
)&CopyData
,
693 SMTO_NORMAL
| SMTO_ABORTIFHUNG
, 3000, &dwResult
);
695 RtlFreeHeap(RtlGetProcessHeap(), 0, pdata
);
697 return (ret
&& dwResult
) ? TRUE
: FALSE
;
705 IN ULONG ValidResponseOptions
,
709 ULONG Type
, MessageBoxResponse
;
711 /* Set the message box type */
712 switch (ValidResponseOptions
)
714 case OptionAbortRetryIgnore
:
715 Type
= MB_ABORTRETRYIGNORE
;
723 case OptionRetryCancel
:
724 Type
= MB_RETRYCANCEL
;
729 case OptionYesNoCancel
:
730 Type
= MB_YESNOCANCEL
;
732 case OptionShutdownSystem
:
733 Type
= MB_RETRYCANCEL
; // FIXME???
737 * At that point showing the balloon failed. Is that correct?
739 Type
= MB_OK
; // FIXME!
741 case OptionCancelTryContinue
:
742 Type
= MB_CANCELTRYCONTINUE
;
745 /* Anything else is invalid */
748 DPRINT1("Unknown ValidResponseOptions = %d\n", ValidResponseOptions
);
749 return ResponseNotHandled
;
754 // STATUS_SEVERITY_SUCCESS
755 if (Severity
== STATUS_SEVERITY_INFORMATIONAL
) Type
|= MB_ICONINFORMATION
;
756 else if (Severity
== STATUS_SEVERITY_WARNING
) Type
|= MB_ICONWARNING
;
757 else if (Severity
== STATUS_SEVERITY_ERROR
) Type
|= MB_ICONERROR
;
759 Type
|= MB_SYSTEMMODAL
| MB_SETFOREGROUND
;
761 DPRINT("Text = '%S', Caption = '%S', Severity = %d, Type = 0x%lx\n",
762 Text
, Caption
, Severity
, Type
);
764 /* Display a message box */
765 MessageBoxResponse
= MessageBoxTimeoutW(NULL
, Text
, Caption
, Type
, 0, Timeout
);
767 /* Return response value */
768 switch (MessageBoxResponse
)
770 case IDOK
: return ResponseOk
;
771 case IDCANCEL
: return ResponseCancel
;
772 case IDYES
: return ResponseYes
;
773 case IDNO
: return ResponseNo
;
774 case IDABORT
: return ResponseAbort
;
775 case IDIGNORE
: return ResponseIgnore
;
776 case IDRETRY
: return ResponseRetry
;
777 case IDTRYAGAIN
: return ResponseTryAgain
;
778 case IDCONTINUE
: return ResponseContinue
;
781 return ResponseNotHandled
;
787 IN PUNICODE_STRING TextStringU
,
788 IN PUNICODE_STRING CaptionStringU
)
792 UNICODE_STRING UNCServerNameU
= {0, 0, NULL
};
793 UNICODE_STRING SourceNameU
= RTL_CONSTANT_STRING(L
"Application Popup");
794 PUNICODE_STRING Strings
[] = {CaptionStringU
, TextStringU
};
796 Status
= ElfRegisterEventSourceW(&UNCServerNameU
, &SourceNameU
, &hEventLog
);
797 if (!NT_SUCCESS(Status
) || !hEventLog
)
799 DPRINT1("ElfRegisterEventSourceW failed with Status 0x%08lx\n", Status
);
803 Status
= ElfReportEventW(hEventLog
,
804 EVENTLOG_INFORMATION_TYPE
,
806 STATUS_LOG_HARD_ERROR
,
815 if (!NT_SUCCESS(Status
))
816 DPRINT1("ElfReportEventW failed with Status 0x%08lx\n", Status
);
818 ElfDeregisterEventSource(hEventLog
);
824 IN PCSR_THREAD ThreadData
,
825 IN PHARDERROR_MSG Message
)
827 ULONG_PTR Parameters
[MAXIMUM_HARDERROR_PARAMETERS
] = {0};
828 OBJECT_ATTRIBUTES ObjectAttributes
;
829 UNICODE_STRING TextU
, CaptionU
;
835 ASSERT(ThreadData
->Process
!= NULL
);
837 /* Default to not handled */
838 Message
->Response
= ResponseNotHandled
;
840 /* Make sure we don't have too many parameters */
841 if (Message
->NumberOfParameters
> MAXIMUM_HARDERROR_PARAMETERS
)
843 // FIXME: Windows just fails (STATUS_INVALID_PARAMETER) & returns ResponseNotHandled.
844 Message
->NumberOfParameters
= MAXIMUM_HARDERROR_PARAMETERS
;
846 if (Message
->ValidResponseOptions
> OptionCancelTryContinue
)
848 // STATUS_INVALID_PARAMETER;
849 Message
->Response
= ResponseNotHandled
;
852 // TODO: More message validation: check NumberOfParameters wrt. Message Status code.
854 /* Open client process */
855 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
856 Status
= NtOpenProcess(&hProcess
,
857 PROCESS_VM_READ
| PROCESS_QUERY_INFORMATION
,
859 &Message
->h
.ClientId
);
860 if (!NT_SUCCESS(Status
))
862 DPRINT1("NtOpenProcess failed with status 0x%08lx, possibly SYSTEM process.\n", Status
);
866 /* Capture all string parameters from the process memory */
867 Status
= UserpCaptureStringParameters(Parameters
, &Size
, Message
, hProcess
);
868 if (!NT_SUCCESS(Status
))
870 if (hProcess
) NtClose(hProcess
);
874 /* Format the message caption and text */
875 Status
= UserpFormatMessages(&TextU
,
883 UserpFreeStringParameters(Parameters
, Message
);
884 if (hProcess
) NtClose(hProcess
);
886 /* If we failed, bail out */
887 if (!NT_SUCCESS(Status
))
890 /* Log the hard error message */
891 UserpLogHardError(&TextU
, &CaptionU
);
893 /* Display a hard error popup depending on the current ErrorMode */
895 /* Query the error mode value */
896 ErrorMode
= GetRegInt(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Windows",
899 if (Message
->Status
!= STATUS_SERVICE_NOTIFICATION
&& ErrorMode
!= 0)
901 /* Returns OK for the hard error */
902 Message
->Response
= ResponseOk
;
906 if (Message
->ValidResponseOptions
== OptionOkNoWait
)
908 /* Display the balloon */
909 Message
->Response
= ResponseOk
;
910 if (UserpShowInformationBalloon(TextU
.Buffer
,
914 Message
->Response
= ResponseOk
;
919 /* Display the message box */
920 Message
->Response
= UserpMessageBox(TextU
.Buffer
,
922 Message
->ValidResponseOptions
,
923 (ULONG
)(Message
->Status
) >> 30,
927 RtlFreeUnicodeString(&TextU
);
928 RtlFreeUnicodeString(&CaptionU
);