mirror of
https://github.com/reactos/reactos.git
synced 2025-06-11 04:47:22 +00:00
[USERSRV] Hard-error improvements 7/7
- Use a more descriptive "unknown hard error" string than Windows' one. - Improve the computation of the buffer size for the hard error message by using _vscwprintf() instead of just "guessing" which size the fully printf'ed message could be.
This commit is contained in:
parent
2363fee51f
commit
29d56f2b29
1 changed files with 205 additions and 120 deletions
|
@ -61,6 +61,28 @@ RtlLoadUnicodeString(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: _scwprintf() is NOT exported by ntdll.dll,
|
||||||
|
* only _vscwprintf() is, so we need to implement it here.
|
||||||
|
* Code comes from sdk/lib/crt/printf/_scwprintf.c .
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
__cdecl
|
||||||
|
_scwprintf(
|
||||||
|
const wchar_t *format,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
len = _vscwprintf(format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
int
|
int
|
||||||
WINAPI
|
WINAPI
|
||||||
|
@ -349,9 +371,18 @@ UserpFormatMessages(
|
||||||
OUT PULONG pdwTimeout,
|
OUT PULONG pdwTimeout,
|
||||||
IN PHARDERROR_MSG Message)
|
IN PHARDERROR_MSG Message)
|
||||||
{
|
{
|
||||||
|
/* Special hardcoded messages */
|
||||||
|
static const PCWSTR pszUnknownHardError =
|
||||||
|
L"Unknown Hard Error 0x%08lx\n"
|
||||||
|
L"Parameters: 0x%p 0x%p 0x%p 0x%p";
|
||||||
|
static const PCWSTR pszExceptionHardError =
|
||||||
|
L"Exception processing message 0x%08lx\n"
|
||||||
|
L"Parameters: 0x%p 0x%p 0x%p 0x%p";
|
||||||
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
HANDLE hProcess;
|
HANDLE hProcess;
|
||||||
|
ULONG Severity = (ULONG)(Message->Status) >> 30;
|
||||||
ULONG SizeOfStrings;
|
ULONG SizeOfStrings;
|
||||||
ULONG_PTR Parameters[MAXIMUM_HARDERROR_PARAMETERS] = {0};
|
ULONG_PTR Parameters[MAXIMUM_HARDERROR_PARAMETERS] = {0};
|
||||||
ULONG_PTR CopyParameters[MAXIMUM_HARDERROR_PARAMETERS];
|
ULONG_PTR CopyParameters[MAXIMUM_HARDERROR_PARAMETERS];
|
||||||
|
@ -361,8 +392,6 @@ UserpFormatMessages(
|
||||||
PMESSAGE_RESOURCE_ENTRY MessageResource;
|
PMESSAGE_RESOURCE_ENTRY MessageResource;
|
||||||
PWSTR FormatString, pszBuffer;
|
PWSTR FormatString, pszBuffer;
|
||||||
size_t cszBuffer;
|
size_t cszBuffer;
|
||||||
ULONG Severity = (ULONG)(Message->Status) >> 30;
|
|
||||||
ULONG Size;
|
|
||||||
|
|
||||||
/* Open client process */
|
/* Open client process */
|
||||||
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
|
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
|
||||||
|
@ -379,6 +408,13 @@ UserpFormatMessages(
|
||||||
/* Capture all string parameters from the process memory */
|
/* Capture all string parameters from the process memory */
|
||||||
UserpCaptureStringParameters(Parameters, &SizeOfStrings, Message, hProcess);
|
UserpCaptureStringParameters(Parameters, &SizeOfStrings, Message, hProcess);
|
||||||
|
|
||||||
|
/* Initialize the output strings */
|
||||||
|
TextStringU->Length = 0;
|
||||||
|
TextStringU->Buffer[0] = UNICODE_NULL;
|
||||||
|
|
||||||
|
CaptionStringU->Length = 0;
|
||||||
|
CaptionStringU->Buffer[0] = UNICODE_NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check whether it is a service notification, in which case
|
* Check whether it is a service notification, in which case
|
||||||
* we format the parameters and take the short route.
|
* we format the parameters and take the short route.
|
||||||
|
@ -395,29 +431,15 @@ UserpFormatMessages(
|
||||||
*/
|
*/
|
||||||
*pdwType = (UINT)Parameters[2] & ~MB_SERVICE_NOTIFICATION;
|
*pdwType = (UINT)Parameters[2] & ~MB_SERVICE_NOTIFICATION;
|
||||||
|
|
||||||
/* Duplicate the UNICODE text message */
|
/*
|
||||||
|
* Duplicate the UNICODE text message and caption.
|
||||||
|
* If no strings or invalid ones have been provided, keep
|
||||||
|
* the original buffers and reset the string lengths to zero.
|
||||||
|
*/
|
||||||
if (Message->UnicodeStringParameterMask & 0x1)
|
if (Message->UnicodeStringParameterMask & 0x1)
|
||||||
{
|
|
||||||
/* A string has been provided: duplicate it */
|
|
||||||
UserpDuplicateParamStringToUnicodeString(TextStringU, (PCWSTR)Parameters[0]);
|
UserpDuplicateParamStringToUnicodeString(TextStringU, (PCWSTR)Parameters[0]);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* No string (or invalid one) has been provided: keep the original buffer and reset the string length to zero */
|
|
||||||
TextStringU->Length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Duplicate the UNICODE caption */
|
|
||||||
if (Message->UnicodeStringParameterMask & 0x2)
|
if (Message->UnicodeStringParameterMask & 0x2)
|
||||||
{
|
|
||||||
/* A string has been provided: duplicate it */
|
|
||||||
UserpDuplicateParamStringToUnicodeString(CaptionStringU, (PCWSTR)Parameters[1]);
|
UserpDuplicateParamStringToUnicodeString(CaptionStringU, (PCWSTR)Parameters[1]);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* No string (or invalid one) has been provided: keep the original buffer and reset the string length to zero */
|
|
||||||
CaptionStringU->Length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the timeout */
|
/* Set the timeout */
|
||||||
if (Message->NumberOfParameters >= 4)
|
if (Message->NumberOfParameters >= 4)
|
||||||
|
@ -493,7 +515,8 @@ UserpFormatMessages(
|
||||||
FileNameU = g_SystemProcessU;
|
FileNameU = g_SystemProcessU;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get text string of the error code */
|
/* Retrieve the description of the error code */
|
||||||
|
FormatA.Buffer = NULL;
|
||||||
Status = RtlFindMessage(GetModuleHandleW(L"ntdll"),
|
Status = RtlFindMessage(GetModuleHandleW(L"ntdll"),
|
||||||
(ULONG_PTR)RT_MESSAGETABLE,
|
(ULONG_PTR)RT_MESSAGETABLE,
|
||||||
LANG_NEUTRAL,
|
LANG_NEUTRAL,
|
||||||
|
@ -511,41 +534,40 @@ UserpFormatMessages(
|
||||||
RtlInitAnsiString(&FormatA, (PSTR)MessageResource->Text);
|
RtlInitAnsiString(&FormatA, (PSTR)MessageResource->Text);
|
||||||
/* Status = */ RtlAnsiStringToUnicodeString(&FormatU, &FormatA, TRUE);
|
/* Status = */ RtlAnsiStringToUnicodeString(&FormatU, &FormatA, TRUE);
|
||||||
}
|
}
|
||||||
|
ASSERT(FormatU.Buffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Fall back to hardcoded value.
|
* Fall back to unknown hard error format string.
|
||||||
* NOTE: The value used here is ReactOS-specific: it allows specifying
|
* NOTE: The value used here is ReactOS-specific: it allows specifying
|
||||||
* the exact hard error status value and the parameters. The version
|
* the exact hard error status value and the parameters, contrary to
|
||||||
* used on Windows only says "Unknown Hard Error".
|
* the one on Windows which only says: "Unknown Hard Error".
|
||||||
*/
|
*/
|
||||||
#if 0
|
RtlInitEmptyUnicodeString(&FormatU, NULL, 0);
|
||||||
RtlInitUnicodeString(&FormatU, L"Unknown Hard Error 0x%08lx\n"
|
|
||||||
L"Parameters: 0x%p 0x%p 0x%p 0x%p");
|
|
||||||
#else
|
|
||||||
RtlInitUnicodeString(&FormatU, L"Unknown Hard Error 0x%08lx");
|
|
||||||
CopyParameters[0] = Message->Status;
|
|
||||||
#endif
|
|
||||||
FormatA.Buffer = NULL;
|
FormatA.Buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
FormatString = FormatU.Buffer;
|
FormatString = FormatU.Buffer;
|
||||||
|
|
||||||
/* Check whether a caption exists */
|
/* Check whether a caption is specified in the format string */
|
||||||
if (FormatString[0] == L'{')
|
if (FormatString && FormatString[0] == L'{')
|
||||||
{
|
{
|
||||||
/* Set caption start */
|
/* Set caption start */
|
||||||
TempStringU.Buffer = ++FormatString;
|
TempStringU.Buffer = ++FormatString;
|
||||||
|
|
||||||
/* Get size of the caption */
|
/* Get the caption size and find where the format string really starts */
|
||||||
for (Size = 0; *FormatString != UNICODE_NULL && *FormatString != L'}'; Size++)
|
for (TempStringU.Length = 0;
|
||||||
FormatString++;
|
*FormatString != UNICODE_NULL && *FormatString != L'}';
|
||||||
|
++TempStringU.Length)
|
||||||
|
{
|
||||||
|
++FormatString;
|
||||||
|
}
|
||||||
|
|
||||||
/* Skip '}', '\r', '\n' */
|
/* Skip '}', '\r', '\n' */
|
||||||
FormatString += 3;
|
FormatString += 3;
|
||||||
|
|
||||||
TempStringU.Length = (USHORT)(Size * sizeof(WCHAR));
|
TempStringU.Length *= sizeof(WCHAR);
|
||||||
TempStringU.MaximumLength = TempStringU.Length;
|
TempStringU.MaximumLength = TempStringU.Length;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -612,6 +634,7 @@ UserpFormatMessages(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CaptionStringU->Length = 0;
|
CaptionStringU->Length = 0;
|
||||||
|
CaptionStringU->Buffer[0] = UNICODE_NULL;
|
||||||
|
|
||||||
/* Append the file name, the separator and the caption text */
|
/* Append the file name, the separator and the caption text */
|
||||||
RtlStringCbPrintfW(CaptionStringU->Buffer,
|
RtlStringCbPrintfW(CaptionStringU->Buffer,
|
||||||
|
@ -620,19 +643,22 @@ UserpFormatMessages(
|
||||||
&WindowTitleU, &FileNameU, &TempStringU);
|
&WindowTitleU, &FileNameU, &TempStringU);
|
||||||
CaptionStringU->Length = (USHORT)(wcslen(CaptionStringU->Buffer) * sizeof(WCHAR));
|
CaptionStringU->Length = (USHORT)(wcslen(CaptionStringU->Buffer) * sizeof(WCHAR));
|
||||||
|
|
||||||
/* Free string buffers if needed */
|
/* Free the strings if needed */
|
||||||
if (WindowTitleU.Buffer) RtlFreeUnicodeString(&WindowTitleU);
|
if (WindowTitleU.Buffer) RtlFreeUnicodeString(&WindowTitleU);
|
||||||
if (hProcess) RtlFreeUnicodeString(&FileNameU);
|
if (hProcess) RtlFreeUnicodeString(&FileNameU);
|
||||||
|
|
||||||
// FIXME: What is 42 == ??
|
Format2A.Buffer = NULL;
|
||||||
Size = 42;
|
|
||||||
|
/* If we have an unknown hard error, skip the special cases handling */
|
||||||
|
if (!FormatString)
|
||||||
|
goto BuildMessage;
|
||||||
|
|
||||||
/* Check if this is an exception message */
|
/* Check if this is an exception message */
|
||||||
if (Message->Status == STATUS_UNHANDLED_EXCEPTION)
|
if (Message->Status == STATUS_UNHANDLED_EXCEPTION)
|
||||||
{
|
{
|
||||||
ULONG ExceptionCode = CopyParameters[0];
|
ULONG ExceptionCode = CopyParameters[0];
|
||||||
|
|
||||||
/* Get text string of the exception code */
|
/* Retrieve the description of the exception code */
|
||||||
Status = RtlFindMessage(GetModuleHandleW(L"ntdll"),
|
Status = RtlFindMessage(GetModuleHandleW(L"ntdll"),
|
||||||
(ULONG_PTR)RT_MESSAGETABLE,
|
(ULONG_PTR)RT_MESSAGETABLE,
|
||||||
LANG_NEUTRAL,
|
LANG_NEUTRAL,
|
||||||
|
@ -650,10 +676,12 @@ UserpFormatMessages(
|
||||||
RtlInitAnsiString(&Format2A, (PSTR)MessageResource->Text);
|
RtlInitAnsiString(&Format2A, (PSTR)MessageResource->Text);
|
||||||
/* Status = */ RtlAnsiStringToUnicodeString(&Format2U, &Format2A, TRUE);
|
/* Status = */ RtlAnsiStringToUnicodeString(&Format2U, &Format2A, TRUE);
|
||||||
}
|
}
|
||||||
|
ASSERT(Format2U.Buffer);
|
||||||
|
|
||||||
/* Handle special cases */
|
/* Handle special cases */
|
||||||
if (ExceptionCode == STATUS_ACCESS_VIOLATION)
|
if (ExceptionCode == STATUS_ACCESS_VIOLATION)
|
||||||
{
|
{
|
||||||
|
/* Use a new FormatString */
|
||||||
FormatString = Format2U.Buffer;
|
FormatString = Format2U.Buffer;
|
||||||
CopyParameters[0] = CopyParameters[1];
|
CopyParameters[0] = CopyParameters[1];
|
||||||
CopyParameters[1] = CopyParameters[3];
|
CopyParameters[1] = CopyParameters[3];
|
||||||
|
@ -664,6 +692,7 @@ UserpFormatMessages(
|
||||||
}
|
}
|
||||||
else if (ExceptionCode == STATUS_IN_PAGE_ERROR)
|
else if (ExceptionCode == STATUS_IN_PAGE_ERROR)
|
||||||
{
|
{
|
||||||
|
/* Use a new FormatString */
|
||||||
FormatString = Format2U.Buffer;
|
FormatString = Format2U.Buffer;
|
||||||
CopyParameters[0] = CopyParameters[1];
|
CopyParameters[0] = CopyParameters[1];
|
||||||
CopyParameters[1] = CopyParameters[3];
|
CopyParameters[1] = CopyParameters[3];
|
||||||
|
@ -702,24 +731,64 @@ UserpFormatMessages(
|
||||||
CopyParameters[1] = CopyParameters[0];
|
CopyParameters[1] = CopyParameters[0];
|
||||||
CopyParameters[0] = (ULONG_PTR)L"unknown software exception";
|
CopyParameters[0] = (ULONG_PTR)L"unknown software exception";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add explanation text for dialog buttons */
|
|
||||||
if (Message->ValidResponseOptions == OptionOk ||
|
|
||||||
Message->ValidResponseOptions == OptionOkCancel)
|
|
||||||
{
|
|
||||||
/* Reserve space for one newline and the OK-terminate-program string */
|
|
||||||
Size += 1 + (g_OKTerminateU.Length / sizeof(WCHAR));
|
|
||||||
}
|
|
||||||
if (Message->ValidResponseOptions == OptionOkCancel)
|
|
||||||
{
|
|
||||||
/* Reserve space for one newline and the CANCEL-debug-program string */
|
|
||||||
Size += 1 + (g_CancelDebugU.Length / sizeof(WCHAR));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate buffer length for the text message */
|
BuildMessage:
|
||||||
cszBuffer = FormatU.Length + SizeOfStrings + Size * sizeof(WCHAR) +
|
/*
|
||||||
sizeof(UNICODE_NULL);
|
* Calculate buffer length for the text message. If FormatString
|
||||||
|
* is NULL this means we have an unknown hard error whose format
|
||||||
|
* string is in FormatU.
|
||||||
|
*/
|
||||||
|
cszBuffer = 0;
|
||||||
|
/* Wrap in SEH to protect from invalid string parameters */
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
if (!FormatString)
|
||||||
|
{
|
||||||
|
/* Fall back to unknown hard error format string, and use the original parameters */
|
||||||
|
cszBuffer = _scwprintf(pszUnknownHardError,
|
||||||
|
Message->Status,
|
||||||
|
Parameters[0], Parameters[1],
|
||||||
|
Parameters[2], Parameters[3]);
|
||||||
|
cszBuffer *= sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cszBuffer = _scwprintf(FormatString,
|
||||||
|
CopyParameters[0], CopyParameters[1],
|
||||||
|
CopyParameters[2], CopyParameters[3]);
|
||||||
|
cszBuffer *= sizeof(WCHAR);
|
||||||
|
|
||||||
|
/* Add a description for the dialog buttons */
|
||||||
|
if (Message->Status == STATUS_UNHANDLED_EXCEPTION)
|
||||||
|
{
|
||||||
|
if (Message->ValidResponseOptions == OptionOk ||
|
||||||
|
Message->ValidResponseOptions == OptionOkCancel)
|
||||||
|
{
|
||||||
|
/* Reserve space for one newline and the OK-terminate-program string */
|
||||||
|
cszBuffer += sizeof(WCHAR) + g_OKTerminateU.Length;
|
||||||
|
}
|
||||||
|
if (Message->ValidResponseOptions == OptionOkCancel)
|
||||||
|
{
|
||||||
|
/* Reserve space for one newline and the CANCEL-debug-program string */
|
||||||
|
cszBuffer += sizeof(WCHAR) + g_CancelDebugU.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
/* An exception occurred, use a default string with the original parameters */
|
||||||
|
cszBuffer = _scwprintf(pszExceptionHardError,
|
||||||
|
Message->Status,
|
||||||
|
Parameters[0], Parameters[1],
|
||||||
|
Parameters[2], Parameters[3]);
|
||||||
|
cszBuffer *= sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
|
cszBuffer += SizeOfStrings + sizeof(UNICODE_NULL);
|
||||||
|
|
||||||
if (TextStringU->MaximumLength < cszBuffer)
|
if (TextStringU->MaximumLength < cszBuffer)
|
||||||
{
|
{
|
||||||
/* Allocate a larger buffer for the text message */
|
/* Allocate a larger buffer for the text message */
|
||||||
|
@ -737,6 +806,7 @@ UserpFormatMessages(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TextStringU->Length = 0;
|
TextStringU->Length = 0;
|
||||||
|
TextStringU->Buffer[0] = UNICODE_NULL;
|
||||||
|
|
||||||
/* Wrap in SEH to protect from invalid string parameters */
|
/* Wrap in SEH to protect from invalid string parameters */
|
||||||
_SEH2_TRY
|
_SEH2_TRY
|
||||||
|
@ -744,32 +814,45 @@ UserpFormatMessages(
|
||||||
/* Print the string into the buffer */
|
/* Print the string into the buffer */
|
||||||
pszBuffer = TextStringU->Buffer;
|
pszBuffer = TextStringU->Buffer;
|
||||||
cszBuffer = TextStringU->MaximumLength;
|
cszBuffer = TextStringU->MaximumLength;
|
||||||
RtlStringCbPrintfExW(pszBuffer, cszBuffer,
|
|
||||||
&pszBuffer, &cszBuffer,
|
|
||||||
STRSAFE_IGNORE_NULLS,
|
|
||||||
FormatString,
|
|
||||||
CopyParameters[0], CopyParameters[1],
|
|
||||||
CopyParameters[2], CopyParameters[3]);
|
|
||||||
|
|
||||||
/* Add explanation text for dialog buttons */
|
if (!FormatString)
|
||||||
if (Message->Status == STATUS_UNHANDLED_EXCEPTION)
|
|
||||||
{
|
{
|
||||||
if (Message->ValidResponseOptions == OptionOk ||
|
/* Fall back to unknown hard error format string, and use the original parameters */
|
||||||
Message->ValidResponseOptions == OptionOkCancel)
|
RtlStringCbPrintfW(pszBuffer, cszBuffer,
|
||||||
|
pszUnknownHardError,
|
||||||
|
Message->Status,
|
||||||
|
Parameters[0], Parameters[1],
|
||||||
|
Parameters[2], Parameters[3]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RtlStringCbPrintfExW(pszBuffer, cszBuffer,
|
||||||
|
&pszBuffer, &cszBuffer,
|
||||||
|
0,
|
||||||
|
FormatString,
|
||||||
|
CopyParameters[0], CopyParameters[1],
|
||||||
|
CopyParameters[2], CopyParameters[3]);
|
||||||
|
|
||||||
|
/* Add a description for the dialog buttons */
|
||||||
|
if (Message->Status == STATUS_UNHANDLED_EXCEPTION)
|
||||||
{
|
{
|
||||||
RtlStringCbPrintfExW(pszBuffer, cszBuffer,
|
if (Message->ValidResponseOptions == OptionOk ||
|
||||||
&pszBuffer, &cszBuffer,
|
Message->ValidResponseOptions == OptionOkCancel)
|
||||||
STRSAFE_IGNORE_NULLS,
|
{
|
||||||
L"\n%wZ",
|
RtlStringCbPrintfExW(pszBuffer, cszBuffer,
|
||||||
&g_OKTerminateU);
|
&pszBuffer, &cszBuffer,
|
||||||
}
|
0,
|
||||||
if (Message->ValidResponseOptions == OptionOkCancel)
|
L"\n%wZ",
|
||||||
{
|
&g_OKTerminateU);
|
||||||
RtlStringCbPrintfExW(pszBuffer, cszBuffer,
|
}
|
||||||
&pszBuffer, &cszBuffer,
|
if (Message->ValidResponseOptions == OptionOkCancel)
|
||||||
STRSAFE_IGNORE_NULLS,
|
{
|
||||||
L"\n%wZ",
|
RtlStringCbPrintfExW(pszBuffer, cszBuffer,
|
||||||
&g_CancelDebugU);
|
&pszBuffer, &cszBuffer,
|
||||||
|
0,
|
||||||
|
L"\n%wZ",
|
||||||
|
&g_CancelDebugU);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -781,8 +864,7 @@ UserpFormatMessages(
|
||||||
|
|
||||||
RtlStringCbPrintfW(TextStringU->Buffer,
|
RtlStringCbPrintfW(TextStringU->Buffer,
|
||||||
TextStringU->MaximumLength,
|
TextStringU->MaximumLength,
|
||||||
L"Exception processing message 0x%08lx\n"
|
pszExceptionHardError,
|
||||||
L"Parameters: 0x%p 0x%p 0x%p 0x%p",
|
|
||||||
Message->Status,
|
Message->Status,
|
||||||
Parameters[0], Parameters[1],
|
Parameters[0], Parameters[1],
|
||||||
Parameters[2], Parameters[3]);
|
Parameters[2], Parameters[3]);
|
||||||
|
@ -791,12 +873,12 @@ UserpFormatMessages(
|
||||||
|
|
||||||
TextStringU->Length = (USHORT)(wcslen(TextStringU->Buffer) * sizeof(WCHAR));
|
TextStringU->Length = (USHORT)(wcslen(TextStringU->Buffer) * sizeof(WCHAR));
|
||||||
|
|
||||||
/* Free converted Unicode strings */
|
/* Free the converted UNICODE strings */
|
||||||
if (Format2A.Buffer) RtlFreeUnicodeString(&Format2U);
|
if (Format2A.Buffer) RtlFreeUnicodeString(&Format2U);
|
||||||
if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU);
|
if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU);
|
||||||
|
|
||||||
Quit:
|
Quit:
|
||||||
/* Final cleanup */
|
/* Free the captured parameters */
|
||||||
UserpFreeStringParameters(Parameters, Message);
|
UserpFreeStringParameters(Parameters, Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -850,40 +932,43 @@ GetRegInt(
|
||||||
|
|
||||||
static BOOL
|
static BOOL
|
||||||
UserpShowInformationBalloon(
|
UserpShowInformationBalloon(
|
||||||
IN PCWSTR Text,
|
IN PUNICODE_STRING TextStringU,
|
||||||
IN PCWSTR Caption,
|
IN PUNICODE_STRING CaptionStringU,
|
||||||
IN UINT Type,
|
IN UINT Type,
|
||||||
IN PHARDERROR_MSG Message)
|
IN PHARDERROR_MSG Message)
|
||||||
{
|
{
|
||||||
ULONG ShellErrorMode;
|
ULONG ShellErrorMode;
|
||||||
HWND hwnd;
|
HWND hWndTaskman;
|
||||||
COPYDATASTRUCT CopyData;
|
COPYDATASTRUCT CopyData;
|
||||||
PBALLOON_HARD_ERROR_DATA pdata;
|
PBALLOON_HARD_ERROR_DATA pdata;
|
||||||
DWORD dwSize, cbTextLen, cbTitleLen;
|
DWORD dwSize, cbTextLen, cbTitleLen;
|
||||||
PWCHAR pText, pCaption;
|
PWCHAR pText, pCaption;
|
||||||
DWORD ret, dwResult;
|
DWORD ret;
|
||||||
|
DWORD_PTR dwResult;
|
||||||
|
|
||||||
/* Query the shell error mode value */
|
/* Query the shell error mode value */
|
||||||
ShellErrorMode = GetRegInt(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Windows",
|
ShellErrorMode = GetRegInt(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Windows",
|
||||||
L"ShellErrorMode", 0);
|
L"ShellErrorMode", 0);
|
||||||
|
|
||||||
/* Make the shell display the hard error message in balloon only if necessary */
|
/* Make the shell display the hard error message only if necessary */
|
||||||
if (ShellErrorMode != 1)
|
if (ShellErrorMode != 1)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
hwnd = GetTaskmanWindow();
|
/* Retrieve the shell task window */
|
||||||
if (!hwnd)
|
hWndTaskman = GetTaskmanWindow();
|
||||||
|
if (!hWndTaskman)
|
||||||
{
|
{
|
||||||
DPRINT1("Failed to find shell task window (last error %lu)\n", GetLastError());
|
DPRINT1("Failed to find shell task window (last error %lu)\n", GetLastError());
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
cbTextLen = ((Text ? wcslen(Text) : 0) + 1) * sizeof(WCHAR);
|
cbTextLen = TextStringU->Length + sizeof(UNICODE_NULL);
|
||||||
cbTitleLen = ((Caption ? wcslen(Caption) : 0) + 1) * sizeof(WCHAR);
|
cbTitleLen = CaptionStringU->Length + sizeof(UNICODE_NULL);
|
||||||
|
|
||||||
dwSize = sizeof(BALLOON_HARD_ERROR_DATA);
|
dwSize = sizeof(BALLOON_HARD_ERROR_DATA);
|
||||||
dwSize += cbTextLen + cbTitleLen;
|
dwSize += cbTextLen + cbTitleLen;
|
||||||
|
|
||||||
|
/* Build the data buffer */
|
||||||
pdata = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
|
pdata = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
|
||||||
if (!pdata)
|
if (!pdata)
|
||||||
{
|
{
|
||||||
|
@ -893,31 +978,27 @@ UserpShowInformationBalloon(
|
||||||
|
|
||||||
pdata->cbHeaderSize = sizeof(BALLOON_HARD_ERROR_DATA);
|
pdata->cbHeaderSize = sizeof(BALLOON_HARD_ERROR_DATA);
|
||||||
pdata->Status = Message->Status;
|
pdata->Status = Message->Status;
|
||||||
|
pdata->dwType = Type;
|
||||||
|
|
||||||
if (NT_SUCCESS(Message->Status))
|
pdata->TitleOffset = pdata->cbHeaderSize;
|
||||||
pdata->dwType = MB_OK;
|
pdata->MessageOffset = pdata->TitleOffset + cbTitleLen;
|
||||||
else if (Message->Status == STATUS_SERVICE_NOTIFICATION)
|
|
||||||
pdata->dwType = Type;
|
|
||||||
else
|
|
||||||
pdata->dwType = MB_ICONINFORMATION;
|
|
||||||
|
|
||||||
pdata->TitleOffset = pdata->cbHeaderSize;
|
|
||||||
pdata->MessageOffset = pdata->TitleOffset;
|
|
||||||
pdata->MessageOffset += cbTitleLen;
|
|
||||||
pCaption = (PWCHAR)((ULONG_PTR)pdata + pdata->TitleOffset);
|
pCaption = (PWCHAR)((ULONG_PTR)pdata + pdata->TitleOffset);
|
||||||
pText = (PWCHAR)((ULONG_PTR)pdata + pdata->MessageOffset);
|
pText = (PWCHAR)((ULONG_PTR)pdata + pdata->MessageOffset);
|
||||||
wcscpy(pCaption, Caption);
|
RtlStringCbCopyNW(pCaption, cbTitleLen, CaptionStringU->Buffer, CaptionStringU->Length);
|
||||||
wcscpy(pText, Text);
|
RtlStringCbCopyNW(pText, cbTextLen, TextStringU->Buffer, TextStringU->Length);
|
||||||
|
|
||||||
|
/* Send the message */
|
||||||
|
|
||||||
|
/* Retrieve a unique system-wide message to communicate hard error data with the shell */
|
||||||
CopyData.dwData = RegisterWindowMessageW(L"HardError");
|
CopyData.dwData = RegisterWindowMessageW(L"HardError");
|
||||||
CopyData.cbData = dwSize;
|
CopyData.cbData = dwSize;
|
||||||
CopyData.lpData = pdata;
|
CopyData.lpData = pdata;
|
||||||
|
|
||||||
dwResult = FALSE;
|
dwResult = FALSE;
|
||||||
|
ret = SendMessageTimeoutW(hWndTaskman, WM_COPYDATA, 0, (LPARAM)&CopyData,
|
||||||
ret = SendMessageTimeoutW(hwnd, WM_COPYDATA, 0, (LPARAM)&CopyData,
|
|
||||||
SMTO_NORMAL | SMTO_ABORTIFHUNG, 3000, &dwResult);
|
SMTO_NORMAL | SMTO_ABORTIFHUNG, 3000, &dwResult);
|
||||||
|
|
||||||
|
/* Free the buffer */
|
||||||
RtlFreeHeap(RtlGetProcessHeap(), 0, pdata);
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pdata);
|
||||||
|
|
||||||
return (ret && dwResult) ? TRUE : FALSE;
|
return (ret && dwResult) ? TRUE : FALSE;
|
||||||
|
@ -926,18 +1007,21 @@ UserpShowInformationBalloon(
|
||||||
static
|
static
|
||||||
HARDERROR_RESPONSE
|
HARDERROR_RESPONSE
|
||||||
UserpMessageBox(
|
UserpMessageBox(
|
||||||
IN PCWSTR Text,
|
IN PUNICODE_STRING TextStringU,
|
||||||
IN PCWSTR Caption,
|
IN PUNICODE_STRING CaptionStringU,
|
||||||
IN UINT Type,
|
IN UINT Type,
|
||||||
IN ULONG Timeout)
|
IN ULONG Timeout)
|
||||||
{
|
{
|
||||||
ULONG MessageBoxResponse;
|
ULONG MessageBoxResponse;
|
||||||
|
|
||||||
DPRINT("Text = '%S', Caption = '%S', Type = 0x%lx\n",
|
DPRINT("Text = '%S', Caption = '%S', Type = 0x%lx\n",
|
||||||
Text, Caption, Type);
|
TextStringU->Buffer, CaptionStringU->Buffer, Type);
|
||||||
|
|
||||||
/* Display a message box */
|
/* Display a message box */
|
||||||
MessageBoxResponse = MessageBoxTimeoutW(NULL, Text, Caption, Type, 0, Timeout);
|
MessageBoxResponse = MessageBoxTimeoutW(NULL,
|
||||||
|
TextStringU->Buffer,
|
||||||
|
CaptionStringU->Buffer,
|
||||||
|
Type, 0, Timeout);
|
||||||
|
|
||||||
/* Return response value */
|
/* Return response value */
|
||||||
switch (MessageBoxResponse)
|
switch (MessageBoxResponse)
|
||||||
|
@ -1028,7 +1112,8 @@ UserServerHardError(
|
||||||
{
|
{
|
||||||
if (Message->NumberOfParameters < 3)
|
if (Message->NumberOfParameters < 3)
|
||||||
{
|
{
|
||||||
DPRINT1("Invalid NumberOfParameters = %d for STATUS_SERVICE_NOTIFICATION\n", Message->NumberOfParameters);
|
DPRINT1("Invalid NumberOfParameters = %d for STATUS_SERVICE_NOTIFICATION\n",
|
||||||
|
Message->NumberOfParameters);
|
||||||
return; // STATUS_INVALID_PARAMETER;
|
return; // STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
// (Message->UnicodeStringParameterMask & 0x3)
|
// (Message->UnicodeStringParameterMask & 0x3)
|
||||||
|
@ -1062,8 +1147,8 @@ UserServerHardError(
|
||||||
{
|
{
|
||||||
/* Display the balloon */
|
/* Display the balloon */
|
||||||
Message->Response = ResponseOk;
|
Message->Response = ResponseOk;
|
||||||
if (UserpShowInformationBalloon(TextU.Buffer,
|
if (UserpShowInformationBalloon(&TextU,
|
||||||
CaptionU.Buffer,
|
&CaptionU,
|
||||||
dwType,
|
dwType,
|
||||||
Message))
|
Message))
|
||||||
{
|
{
|
||||||
|
@ -1073,8 +1158,8 @@ UserServerHardError(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Display the message box */
|
/* Display the message box */
|
||||||
Message->Response = UserpMessageBox(TextU.Buffer,
|
Message->Response = UserpMessageBox(&TextU,
|
||||||
CaptionU.Buffer,
|
&CaptionU,
|
||||||
dwType,
|
dwType,
|
||||||
Timeout);
|
Timeout);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue