mirror of
https://github.com/reactos/reactos.git
synced 2025-05-07 18:56:48 +00:00
[USERSRV] Hard-error improvements 5/7 - Implement STATUS_SERVICE_NOTIFICATION handling.
- In UserpCaptureStringParameters(), always capture the parameter strings with a terminating NULL. Also, no need to convert them to ANSI if they are used with a STATUS_SERVICE_NOTIFICATION message. - Determine within UserpFormatMessages() the message box flags to be used, either from the message parameters (if STATUS_SERVICE_NOTIFICATION) or from the proposed response options and message status severity. These flags are then used by both UserpShowInformationBalloon()/UserpShellHardError() and by UserpMessageBox(). - Improve Message validation (especially for STATUS_SERVICE_NOTIFICATION). - Try to display the hard error status number if it's an unknown one.
This commit is contained in:
parent
9ea2783e56
commit
08d70697a3
1 changed files with 212 additions and 107 deletions
|
@ -114,8 +114,8 @@ UserpCaptureStringParameters(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate a buffer for the string */
|
/* Allocate a buffer for the string and reserve a NULL terminator */
|
||||||
TempStringU.MaximumLength = ParamStringU.Length;
|
TempStringU.MaximumLength = ParamStringU.Length + sizeof(UNICODE_NULL);
|
||||||
TempStringU.Length = ParamStringU.Length;
|
TempStringU.Length = ParamStringU.Length;
|
||||||
TempStringU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
TempStringU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||||
HEAP_ZERO_MEMORY,
|
HEAP_ZERO_MEMORY,
|
||||||
|
@ -140,36 +140,47 @@ UserpCaptureStringParameters(
|
||||||
RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer);
|
RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
/* NULL-terminate the string */
|
||||||
|
TempStringU.Buffer[TempStringU.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||||
|
|
||||||
DPRINT("ParamString = \'%wZ\'\n", &TempStringU);
|
DPRINT("ParamString = \'%wZ\'\n", &TempStringU);
|
||||||
|
|
||||||
/* Allocate a buffer for converted to ANSI string */
|
if (Message->Status == STATUS_SERVICE_NOTIFICATION)
|
||||||
TempStringA.MaximumLength = RtlUnicodeStringToAnsiSize(&TempStringU);
|
|
||||||
TempStringA.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
||||||
HEAP_ZERO_MEMORY,
|
|
||||||
TempStringA.MaximumLength);
|
|
||||||
if (!TempStringA.Buffer)
|
|
||||||
{
|
{
|
||||||
/* We failed, skip this string */
|
/* Just keep the allocated NULL-terminated UNICODE string */
|
||||||
DPRINT1("Cannot allocate memory with size %u, skipping.\n", TempStringA.MaximumLength);
|
Parameters[nParam] = (ULONG_PTR)TempStringU.Buffer;
|
||||||
|
Size += TempStringU.Length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Allocate a buffer for converted to ANSI string */
|
||||||
|
TempStringA.MaximumLength = RtlUnicodeStringToAnsiSize(&TempStringU);
|
||||||
|
TempStringA.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||||
|
HEAP_ZERO_MEMORY,
|
||||||
|
TempStringA.MaximumLength);
|
||||||
|
if (!TempStringA.Buffer)
|
||||||
|
{
|
||||||
|
/* We failed, skip this string */
|
||||||
|
DPRINT1("Cannot allocate memory with size %u, skipping.\n", TempStringA.MaximumLength);
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert string to ANSI and free temporary buffer */
|
||||||
|
Status = RtlUnicodeStringToAnsiString(&TempStringA, &TempStringU, FALSE);
|
||||||
RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer);
|
RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer);
|
||||||
continue;
|
if (!NT_SUCCESS(Status))
|
||||||
}
|
{
|
||||||
|
/* We failed, skip this string */
|
||||||
|
DPRINT1("RtlUnicodeStringToAnsiString() failed, Status 0x%lx, skipping.\n", Status);
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringA.Buffer);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert string to ANSI and free temporary buffer */
|
/* Note: RtlUnicodeStringToAnsiString() returns a NULL-terminated string */
|
||||||
Status = RtlUnicodeStringToAnsiString(&TempStringA, &TempStringU, FALSE);
|
Parameters[nParam] = (ULONG_PTR)TempStringA.Buffer;
|
||||||
RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer);
|
Size += TempStringU.Length;
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
/* We failed, skip this string */
|
|
||||||
DPRINT1("RtlUnicodeStringToAnsiString() failed, Status 0x%lx, skipping.\n", Status);
|
|
||||||
RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringA.Buffer);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: RtlUnicodeStringToAnsiString returns NULL terminated string */
|
|
||||||
Parameters[nParam] = (ULONG_PTR)TempStringA.Buffer;
|
|
||||||
Size += TempStringU.Length;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -293,11 +304,48 @@ UserpGetClientFileName(
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
UserpDuplicateParamStringToUnicodeString(
|
||||||
|
IN OUT PUNICODE_STRING UnicodeString,
|
||||||
|
IN PCWSTR ParamString)
|
||||||
|
{
|
||||||
|
UNICODE_STRING FormatU, TempStringU;
|
||||||
|
|
||||||
|
/* Calculate buffer length for the text message */
|
||||||
|
RtlInitUnicodeString(&FormatU, (PWSTR)ParamString);
|
||||||
|
if (UnicodeString->MaximumLength < FormatU.MaximumLength)
|
||||||
|
{
|
||||||
|
/* Duplicate the text message in a larger buffer */
|
||||||
|
if (NT_SUCCESS(RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
|
||||||
|
&FormatU, &TempStringU)))
|
||||||
|
{
|
||||||
|
*UnicodeString = TempStringU;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We could not allocate a larger buffer; continue using the smaller original buffer */
|
||||||
|
DPRINT1("Cannot allocate memory for UnicodeString, use original buffer.\n");
|
||||||
|
|
||||||
|
/* Copy the truncated string, NULL-terminate it */
|
||||||
|
FormatU.MaximumLength = UnicodeString->MaximumLength;
|
||||||
|
FormatU.Length = FormatU.MaximumLength - sizeof(UNICODE_NULL);
|
||||||
|
RtlCopyUnicodeString(UnicodeString, &FormatU);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Copy the string, NULL-terminate it */
|
||||||
|
RtlCopyUnicodeString(UnicodeString, &FormatU);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
VOID
|
VOID
|
||||||
UserpFormatMessages(
|
UserpFormatMessages(
|
||||||
IN OUT PUNICODE_STRING TextStringU,
|
IN OUT PUNICODE_STRING TextStringU,
|
||||||
IN OUT PUNICODE_STRING CaptionStringU,
|
IN OUT PUNICODE_STRING CaptionStringU,
|
||||||
|
OUT PUINT pdwType,
|
||||||
IN PHARDERROR_MSG Message)
|
IN PHARDERROR_MSG Message)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -312,7 +360,7 @@ UserpFormatMessages(
|
||||||
PMESSAGE_RESOURCE_ENTRY MessageResource;
|
PMESSAGE_RESOURCE_ENTRY MessageResource;
|
||||||
PWSTR FormatString, pszBuffer;
|
PWSTR FormatString, pszBuffer;
|
||||||
size_t cszBuffer;
|
size_t cszBuffer;
|
||||||
ULONG Severity;
|
ULONG Severity = (ULONG)(Message->Status) >> 30;
|
||||||
ULONG Size;
|
ULONG Size;
|
||||||
|
|
||||||
/* Open client process */
|
/* Open client process */
|
||||||
|
@ -330,6 +378,90 @@ 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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether it is a service notification, in which case
|
||||||
|
* we format the parameters and take the short route.
|
||||||
|
*/
|
||||||
|
if (Message->Status == STATUS_SERVICE_NOTIFICATION)
|
||||||
|
{
|
||||||
|
/* Close the process handle */
|
||||||
|
if (hProcess) NtClose(hProcess);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve the message box flags. Note that we filter out
|
||||||
|
* MB_SERVICE_NOTIFICATION to not enter an infinite recursive
|
||||||
|
* loop when we will call MessageBox() later on.
|
||||||
|
*/
|
||||||
|
*pdwType = (UINT)Parameters[2] & ~MB_SERVICE_NOTIFICATION;
|
||||||
|
|
||||||
|
/* Duplicate the UNICODE text message */
|
||||||
|
if (Message->UnicodeStringParameterMask & 0x1)
|
||||||
|
{
|
||||||
|
/* A string has been provided: duplicate it */
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
/* A string has been provided: duplicate it */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the message box type */
|
||||||
|
*pdwType = 0;
|
||||||
|
switch (Message->ValidResponseOptions)
|
||||||
|
{
|
||||||
|
case OptionAbortRetryIgnore:
|
||||||
|
*pdwType = MB_ABORTRETRYIGNORE;
|
||||||
|
break;
|
||||||
|
case OptionOk:
|
||||||
|
*pdwType = MB_OK;
|
||||||
|
break;
|
||||||
|
case OptionOkCancel:
|
||||||
|
*pdwType = MB_OKCANCEL;
|
||||||
|
break;
|
||||||
|
case OptionRetryCancel:
|
||||||
|
*pdwType = MB_RETRYCANCEL;
|
||||||
|
break;
|
||||||
|
case OptionYesNo:
|
||||||
|
*pdwType = MB_YESNO;
|
||||||
|
break;
|
||||||
|
case OptionYesNoCancel:
|
||||||
|
*pdwType = MB_YESNOCANCEL;
|
||||||
|
break;
|
||||||
|
case OptionShutdownSystem:
|
||||||
|
*pdwType = MB_OK;
|
||||||
|
break;
|
||||||
|
case OptionOkNoWait:
|
||||||
|
*pdwType = MB_OK;
|
||||||
|
break;
|
||||||
|
case OptionCancelTryContinue:
|
||||||
|
*pdwType = MB_CANCELTRYCONTINUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the severity icon */
|
||||||
|
// STATUS_SEVERITY_SUCCESS
|
||||||
|
if (Severity == STATUS_SEVERITY_INFORMATIONAL) *pdwType |= MB_ICONINFORMATION;
|
||||||
|
else if (Severity == STATUS_SEVERITY_WARNING) *pdwType |= MB_ICONWARNING;
|
||||||
|
else if (Severity == STATUS_SEVERITY_ERROR) *pdwType |= MB_ICONERROR;
|
||||||
|
|
||||||
|
*pdwType |= MB_SYSTEMMODAL | MB_SETFOREGROUND;
|
||||||
|
|
||||||
/* Copy the Parameters array locally */
|
/* Copy the Parameters array locally */
|
||||||
RtlCopyMemory(&CopyParameters, Parameters, sizeof(CopyParameters));
|
RtlCopyMemory(&CopyParameters, Parameters, sizeof(CopyParameters));
|
||||||
|
|
||||||
|
@ -351,8 +483,6 @@ UserpFormatMessages(
|
||||||
FileNameU = g_SystemProcessU;
|
FileNameU = g_SystemProcessU;
|
||||||
}
|
}
|
||||||
|
|
||||||
Severity = (ULONG)(Message->Status) >> 30;
|
|
||||||
|
|
||||||
/* Get text string of the error code */
|
/* Get text string of the error code */
|
||||||
Status = RtlFindMessage(GetModuleHandleW(L"ntdll"),
|
Status = RtlFindMessage(GetModuleHandleW(L"ntdll"),
|
||||||
(ULONG_PTR)RT_MESSAGETABLE,
|
(ULONG_PTR)RT_MESSAGETABLE,
|
||||||
|
@ -368,14 +498,25 @@ UserpFormatMessages(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RtlInitAnsiString(&FormatA, (PCHAR)MessageResource->Text);
|
RtlInitAnsiString(&FormatA, (PSTR)MessageResource->Text);
|
||||||
/* Status = */ RtlAnsiStringToUnicodeString(&FormatU, &FormatA, TRUE);
|
/* Status = */ RtlAnsiStringToUnicodeString(&FormatU, &FormatA, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Fall back to hardcoded value */
|
/*
|
||||||
RtlInitUnicodeString(&FormatU, L"Unknown Hard Error");
|
* Fall back to hardcoded value.
|
||||||
|
* NOTE: The value used here is ReactOS-specific: it allows specifying
|
||||||
|
* the exact hard error status value and the parameters. The version
|
||||||
|
* used on Windows only says "Unknown Hard Error".
|
||||||
|
*/
|
||||||
|
#if 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,7 +585,7 @@ UserpFormatMessages(
|
||||||
/* Calculate buffer length for the caption */
|
/* Calculate buffer length for the caption */
|
||||||
cszBuffer = WindowTitleU.Length + FileNameU.Length + TempStringU.Length +
|
cszBuffer = WindowTitleU.Length + FileNameU.Length + TempStringU.Length +
|
||||||
3 * sizeof(WCHAR) + sizeof(UNICODE_NULL);
|
3 * sizeof(WCHAR) + sizeof(UNICODE_NULL);
|
||||||
if (cszBuffer > CaptionStringU->MaximumLength)
|
if (CaptionStringU->MaximumLength < cszBuffer)
|
||||||
{
|
{
|
||||||
/* Allocate a larger buffer for the caption */
|
/* Allocate a larger buffer for the caption */
|
||||||
pszBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
pszBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||||
|
@ -452,8 +593,8 @@ UserpFormatMessages(
|
||||||
cszBuffer);
|
cszBuffer);
|
||||||
if (!pszBuffer)
|
if (!pszBuffer)
|
||||||
{
|
{
|
||||||
/* We could not allocate a larger buffer; continue using the smaller static buffer */
|
/* We could not allocate a larger buffer; continue using the smaller original buffer */
|
||||||
DPRINT1("Cannot allocate memory for CaptionStringU, use static buffer.\n");
|
DPRINT1("Cannot allocate memory for CaptionStringU, use original buffer.\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -496,7 +637,7 @@ UserpFormatMessages(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RtlInitAnsiString(&Format2A, (PCHAR)MessageResource->Text);
|
RtlInitAnsiString(&Format2A, (PSTR)MessageResource->Text);
|
||||||
/* Status = */ RtlAnsiStringToUnicodeString(&Format2U, &Format2A, TRUE);
|
/* Status = */ RtlAnsiStringToUnicodeString(&Format2U, &Format2A, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,6 +693,7 @@ UserpFormatMessages(
|
||||||
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 ||
|
if (Message->ValidResponseOptions == OptionOk ||
|
||||||
Message->ValidResponseOptions == OptionOkCancel)
|
Message->ValidResponseOptions == OptionOkCancel)
|
||||||
{
|
{
|
||||||
|
@ -568,7 +710,7 @@ UserpFormatMessages(
|
||||||
/* Calculate buffer length for the text message */
|
/* Calculate buffer length for the text message */
|
||||||
cszBuffer = FormatU.Length + SizeOfStrings + Size * sizeof(WCHAR) +
|
cszBuffer = FormatU.Length + SizeOfStrings + Size * sizeof(WCHAR) +
|
||||||
sizeof(UNICODE_NULL);
|
sizeof(UNICODE_NULL);
|
||||||
if (cszBuffer > TextStringU->MaximumLength)
|
if (TextStringU->MaximumLength < cszBuffer)
|
||||||
{
|
{
|
||||||
/* Allocate a larger buffer for the text message */
|
/* Allocate a larger buffer for the text message */
|
||||||
pszBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
pszBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||||
|
@ -576,8 +718,8 @@ UserpFormatMessages(
|
||||||
cszBuffer);
|
cszBuffer);
|
||||||
if (!pszBuffer)
|
if (!pszBuffer)
|
||||||
{
|
{
|
||||||
/* We could not allocate a larger buffer; continue using the smaller static buffer */
|
/* We could not allocate a larger buffer; continue using the smaller original buffer */
|
||||||
DPRINT1("Cannot allocate memory for TextStringU, use static buffer.\n");
|
DPRINT1("Cannot allocate memory for TextStringU, use original buffer.\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -599,6 +741,7 @@ UserpFormatMessages(
|
||||||
CopyParameters[0], CopyParameters[1],
|
CopyParameters[0], CopyParameters[1],
|
||||||
CopyParameters[2], CopyParameters[3]);
|
CopyParameters[2], CopyParameters[3]);
|
||||||
|
|
||||||
|
/* Add explanation text for dialog buttons */
|
||||||
if (Message->Status == STATUS_UNHANDLED_EXCEPTION)
|
if (Message->Status == STATUS_UNHANDLED_EXCEPTION)
|
||||||
{
|
{
|
||||||
if (Message->ValidResponseOptions == OptionOk ||
|
if (Message->ValidResponseOptions == OptionOk ||
|
||||||
|
@ -642,6 +785,7 @@ UserpFormatMessages(
|
||||||
if (Format2A.Buffer) RtlFreeUnicodeString(&Format2U);
|
if (Format2A.Buffer) RtlFreeUnicodeString(&Format2U);
|
||||||
if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU);
|
if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU);
|
||||||
|
|
||||||
|
Quit:
|
||||||
/* Final cleanup */
|
/* Final cleanup */
|
||||||
UserpFreeStringParameters(Parameters, Message);
|
UserpFreeStringParameters(Parameters, Message);
|
||||||
}
|
}
|
||||||
|
@ -695,9 +839,11 @@ GetRegInt(
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL
|
static BOOL
|
||||||
UserpShowInformationBalloon(PWSTR Text,
|
UserpShowInformationBalloon(
|
||||||
PWSTR Caption,
|
IN PCWSTR Text,
|
||||||
PHARDERROR_MSG Message)
|
IN PCWSTR Caption,
|
||||||
|
IN UINT Type,
|
||||||
|
IN PHARDERROR_MSG Message)
|
||||||
{
|
{
|
||||||
ULONG ShellErrorMode;
|
ULONG ShellErrorMode;
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
|
@ -741,7 +887,7 @@ UserpShowInformationBalloon(PWSTR Text,
|
||||||
if (NT_SUCCESS(Message->Status))
|
if (NT_SUCCESS(Message->Status))
|
||||||
pdata->dwType = MB_OK;
|
pdata->dwType = MB_OK;
|
||||||
else if (Message->Status == STATUS_SERVICE_NOTIFICATION)
|
else if (Message->Status == STATUS_SERVICE_NOTIFICATION)
|
||||||
pdata->dwType = Message->Parameters[2];
|
pdata->dwType = Type;
|
||||||
else
|
else
|
||||||
pdata->dwType = MB_ICONINFORMATION;
|
pdata->dwType = MB_ICONINFORMATION;
|
||||||
|
|
||||||
|
@ -768,68 +914,17 @@ UserpShowInformationBalloon(PWSTR Text,
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
ULONG
|
HARDERROR_RESPONSE
|
||||||
UserpMessageBox(
|
UserpMessageBox(
|
||||||
IN PCWSTR Text,
|
IN PCWSTR Text,
|
||||||
IN PCWSTR Caption,
|
IN PCWSTR Caption,
|
||||||
IN ULONG ValidResponseOptions,
|
IN UINT Type,
|
||||||
IN ULONG Severity,
|
IN ULONG Timeout)
|
||||||
IN ULONG Timeout)
|
|
||||||
{
|
{
|
||||||
ULONG Type, MessageBoxResponse;
|
ULONG MessageBoxResponse;
|
||||||
|
|
||||||
/* Set the message box type */
|
DPRINT("Text = '%S', Caption = '%S', Type = 0x%lx\n",
|
||||||
switch (ValidResponseOptions)
|
Text, Caption, Type);
|
||||||
{
|
|
||||||
case OptionAbortRetryIgnore:
|
|
||||||
Type = MB_ABORTRETRYIGNORE;
|
|
||||||
break;
|
|
||||||
case OptionOk:
|
|
||||||
Type = MB_OK;
|
|
||||||
break;
|
|
||||||
case OptionOkCancel:
|
|
||||||
Type = MB_OKCANCEL;
|
|
||||||
break;
|
|
||||||
case OptionRetryCancel:
|
|
||||||
Type = MB_RETRYCANCEL;
|
|
||||||
break;
|
|
||||||
case OptionYesNo:
|
|
||||||
Type = MB_YESNO;
|
|
||||||
break;
|
|
||||||
case OptionYesNoCancel:
|
|
||||||
Type = MB_YESNOCANCEL;
|
|
||||||
break;
|
|
||||||
case OptionShutdownSystem:
|
|
||||||
Type = MB_RETRYCANCEL; // FIXME???
|
|
||||||
break;
|
|
||||||
case OptionOkNoWait:
|
|
||||||
/*
|
|
||||||
* At that point showing the balloon failed. Is that correct?
|
|
||||||
*/
|
|
||||||
Type = MB_OK; // FIXME!
|
|
||||||
break;
|
|
||||||
case OptionCancelTryContinue:
|
|
||||||
Type = MB_CANCELTRYCONTINUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Anything else is invalid */
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
DPRINT1("Unknown ValidResponseOptions = %d\n", ValidResponseOptions);
|
|
||||||
return ResponseNotHandled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set severity */
|
|
||||||
// STATUS_SEVERITY_SUCCESS
|
|
||||||
if (Severity == STATUS_SEVERITY_INFORMATIONAL) Type |= MB_ICONINFORMATION;
|
|
||||||
else if (Severity == STATUS_SEVERITY_WARNING) Type |= MB_ICONWARNING;
|
|
||||||
else if (Severity == STATUS_SEVERITY_ERROR) Type |= MB_ICONERROR;
|
|
||||||
|
|
||||||
Type |= MB_SYSTEMMODAL | MB_SETFOREGROUND;
|
|
||||||
|
|
||||||
DPRINT("Text = '%S', Caption = '%S', Severity = %d, Type = 0x%lx\n",
|
|
||||||
Text, Caption, Severity, Type);
|
|
||||||
|
|
||||||
/* Display a message box */
|
/* Display a message box */
|
||||||
MessageBoxResponse = MessageBoxTimeoutW(NULL, Text, Caption, Type, 0, Timeout);
|
MessageBoxResponse = MessageBoxTimeoutW(NULL, Text, Caption, Type, 0, Timeout);
|
||||||
|
@ -846,6 +941,7 @@ UserpMessageBox(
|
||||||
case IDRETRY: return ResponseRetry;
|
case IDRETRY: return ResponseRetry;
|
||||||
case IDTRYAGAIN: return ResponseTryAgain;
|
case IDTRYAGAIN: return ResponseTryAgain;
|
||||||
case IDCONTINUE: return ResponseContinue;
|
case IDCONTINUE: return ResponseContinue;
|
||||||
|
default: return ResponseNotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseNotHandled;
|
return ResponseNotHandled;
|
||||||
|
@ -895,6 +991,7 @@ UserServerHardError(
|
||||||
IN PHARDERROR_MSG Message)
|
IN PHARDERROR_MSG Message)
|
||||||
{
|
{
|
||||||
ULONG ErrorMode;
|
ULONG ErrorMode;
|
||||||
|
UINT dwType = 0;
|
||||||
UNICODE_STRING TextU, CaptionU;
|
UNICODE_STRING TextU, CaptionU;
|
||||||
WCHAR LocalTextBuffer[256];
|
WCHAR LocalTextBuffer[256];
|
||||||
WCHAR LocalCaptionBuffer[256];
|
WCHAR LocalCaptionBuffer[256];
|
||||||
|
@ -907,16 +1004,24 @@ UserServerHardError(
|
||||||
/* Make sure we don't have too many parameters */
|
/* Make sure we don't have too many parameters */
|
||||||
if (Message->NumberOfParameters > MAXIMUM_HARDERROR_PARAMETERS)
|
if (Message->NumberOfParameters > MAXIMUM_HARDERROR_PARAMETERS)
|
||||||
{
|
{
|
||||||
// FIXME: Windows just fails (STATUS_INVALID_PARAMETER) & returns ResponseNotHandled.
|
// NOTE: Windows just fails (STATUS_INVALID_PARAMETER) & returns ResponseNotHandled.
|
||||||
|
DPRINT1("Invalid NumberOfParameters = %d\n", Message->NumberOfParameters);
|
||||||
Message->NumberOfParameters = MAXIMUM_HARDERROR_PARAMETERS;
|
Message->NumberOfParameters = MAXIMUM_HARDERROR_PARAMETERS;
|
||||||
}
|
}
|
||||||
if (Message->ValidResponseOptions > OptionCancelTryContinue)
|
if (Message->ValidResponseOptions > OptionCancelTryContinue)
|
||||||
{
|
{
|
||||||
// STATUS_INVALID_PARAMETER;
|
DPRINT1("Unknown ValidResponseOptions = %d\n", Message->ValidResponseOptions);
|
||||||
Message->Response = ResponseNotHandled;
|
return; // STATUS_INVALID_PARAMETER;
|
||||||
return;
|
}
|
||||||
|
if (Message->Status == STATUS_SERVICE_NOTIFICATION)
|
||||||
|
{
|
||||||
|
if (Message->NumberOfParameters < 3)
|
||||||
|
{
|
||||||
|
DPRINT1("Invalid NumberOfParameters = %d for STATUS_SERVICE_NOTIFICATION\n", Message->NumberOfParameters);
|
||||||
|
return; // STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
// (Message->UnicodeStringParameterMask & 0x3)
|
||||||
}
|
}
|
||||||
// TODO: More message validation: check NumberOfParameters wrt. Message Status code.
|
|
||||||
|
|
||||||
/* Re-initialize the hard errors cache */
|
/* Re-initialize the hard errors cache */
|
||||||
UserInitHardErrorsCache();
|
UserInitHardErrorsCache();
|
||||||
|
@ -924,7 +1029,7 @@ UserServerHardError(
|
||||||
/* Format the message caption and text */
|
/* Format the message caption and text */
|
||||||
RtlInitEmptyUnicodeString(&TextU, LocalTextBuffer, sizeof(LocalTextBuffer));
|
RtlInitEmptyUnicodeString(&TextU, LocalTextBuffer, sizeof(LocalTextBuffer));
|
||||||
RtlInitEmptyUnicodeString(&CaptionU, LocalCaptionBuffer, sizeof(LocalCaptionBuffer));
|
RtlInitEmptyUnicodeString(&CaptionU, LocalCaptionBuffer, sizeof(LocalCaptionBuffer));
|
||||||
UserpFormatMessages(&TextU, &CaptionU, Message);
|
UserpFormatMessages(&TextU, &CaptionU, &dwType, /* &Timeout, */ Message);
|
||||||
|
|
||||||
/* Log the hard error message */
|
/* Log the hard error message */
|
||||||
UserpLogHardError(&TextU, &CaptionU);
|
UserpLogHardError(&TextU, &CaptionU);
|
||||||
|
@ -948,6 +1053,7 @@ UserServerHardError(
|
||||||
Message->Response = ResponseOk;
|
Message->Response = ResponseOk;
|
||||||
if (UserpShowInformationBalloon(TextU.Buffer,
|
if (UserpShowInformationBalloon(TextU.Buffer,
|
||||||
CaptionU.Buffer,
|
CaptionU.Buffer,
|
||||||
|
dwType,
|
||||||
Message))
|
Message))
|
||||||
{
|
{
|
||||||
Message->Response = ResponseOk;
|
Message->Response = ResponseOk;
|
||||||
|
@ -958,8 +1064,7 @@ UserServerHardError(
|
||||||
/* Display the message box */
|
/* Display the message box */
|
||||||
Message->Response = UserpMessageBox(TextU.Buffer,
|
Message->Response = UserpMessageBox(TextU.Buffer,
|
||||||
CaptionU.Buffer,
|
CaptionU.Buffer,
|
||||||
Message->ValidResponseOptions,
|
dwType,
|
||||||
(ULONG)(Message->Status) >> 30,
|
|
||||||
(ULONG)-1);
|
(ULONG)-1);
|
||||||
|
|
||||||
Quit:
|
Quit:
|
||||||
|
|
Loading…
Reference in a new issue