[USERSRV] Hard-error improvements 2/7 - More failure path handling.

In particular do not always fail as soon as there is an error, because they may be the sign of an OS problem and this is precisely in this case that we want to display a hard-error.
This commit is contained in:
Hermès Bélusca-Maïto 2018-03-04 17:39:44 +01:00
parent 6718a1aa83
commit 2b299f5fec
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0

View file

@ -26,6 +26,18 @@
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
/* FIXME */
int
WINAPI
MessageBoxTimeoutW(
HWND hWnd,
LPCWSTR lpText,
LPCWSTR lpCaption,
UINT uType,
WORD wLanguageId,
DWORD dwTime);
static static
NTSTATUS NTSTATUS
UserpGetClientFileName( UserpGetClientFileName(
@ -43,9 +55,7 @@ UserpGetClientFileName(
PPEB Peb; PPEB Peb;
/* Initialize string */ /* Initialize string */
ClientFileNameU->MaximumLength = 0; RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0);
ClientFileNameU->Length = 0;
ClientFileNameU->Buffer = NULL;
/* Query process information */ /* Query process information */
Status = NtQueryInformationProcess(hProcess, Status = NtQueryInformationProcess(hProcess,
@ -55,6 +65,8 @@ UserpGetClientFileName(
NULL); NULL);
if (!NT_SUCCESS(Status)) return Status; if (!NT_SUCCESS(Status)) return Status;
/* Locate the process loader data table and retrieve its name from it */
Peb = ClientBasicInfo.PebBaseAddress; Peb = ClientBasicInfo.PebBaseAddress;
if (!Peb) return STATUS_UNSUCCESSFUL; if (!Peb) return STATUS_UNSUCCESSFUL;
@ -91,8 +103,13 @@ UserpGetClientFileName(
ClientFileNameU->MaximumLength = ModuleData.BaseDllName.MaximumLength; ClientFileNameU->MaximumLength = ModuleData.BaseDllName.MaximumLength;
ClientFileNameU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), ClientFileNameU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
ClientFileNameU->MaximumLength); ClientFileNameU->MaximumLength);
if (!ClientFileNameU->Buffer)
{
RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0);
return STATUS_NO_MEMORY;
}
Status = NtReadVirtualMemory(hProcess, Status = NtReadVirtualMemory(hProcess,
ModuleData.BaseDllName.Buffer, ModuleData.BaseDllName.Buffer,
@ -102,13 +119,12 @@ UserpGetClientFileName(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
RtlFreeHeap(RtlGetProcessHeap(), 0, ClientFileNameU->Buffer); RtlFreeHeap(RtlGetProcessHeap(), 0, ClientFileNameU->Buffer);
ClientFileNameU->Buffer = NULL; RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0);
ClientFileNameU->MaximumLength = 0;
return Status; return Status;
} }
ClientFileNameU->Length = wcslen(ClientFileNameU->Buffer) * sizeof(WCHAR); ClientFileNameU->Length = wcslen(ClientFileNameU->Buffer) * sizeof(WCHAR);
DPRINT("ClientFileNameU=\'%wZ\'\n", &ClientFileNameU); DPRINT("ClientFileNameU = \'%wZ\'\n", &ClientFileNameU);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -125,7 +141,7 @@ UserpFreeStringParameters(
for (nParam = 0; nParam < HardErrorMessage->NumberOfParameters; nParam++) for (nParam = 0; nParam < HardErrorMessage->NumberOfParameters; nParam++)
{ {
/* Check if the current parameter is a string */ /* Check if the current parameter is a string */
if ((HardErrorMessage->UnicodeStringParameterMask & (1 << nParam)) && Parameters[nParam]) if ((HardErrorMessage->UnicodeStringParameterMask & (1 << nParam)) && (Parameters[nParam] != 0))
{ {
/* Free the string buffer */ /* Free the string buffer */
RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)Parameters[nParam]); RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)Parameters[nParam]);
@ -139,10 +155,10 @@ UserpCaptureStringParameters(
OUT PULONG_PTR Parameters, OUT PULONG_PTR Parameters,
OUT PULONG SizeOfAllUnicodeStrings, OUT PULONG SizeOfAllUnicodeStrings,
IN PHARDERROR_MSG HardErrorMessage, IN PHARDERROR_MSG HardErrorMessage,
IN HANDLE hProcess) IN HANDLE hProcess OPTIONAL)
{ {
ULONG nParam, Size = 0;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
ULONG nParam, Size = 0;
UNICODE_STRING TempStringU, ParamStringU; UNICODE_STRING TempStringU, ParamStringU;
ANSI_STRING TempStringA; ANSI_STRING TempStringA;
@ -157,6 +173,10 @@ UserpCaptureStringParameters(
/* Check if the current parameter is a unicode string */ /* Check if the current parameter is a unicode string */
if (HardErrorMessage->UnicodeStringParameterMask & (1 << nParam)) if (HardErrorMessage->UnicodeStringParameterMask & (1 << nParam))
{ {
/* Skip this string if we do not have a client process */
if (!hProcess)
continue;
/* Read the UNICODE_STRING from the process memory */ /* Read the UNICODE_STRING from the process memory */
Status = NtReadVirtualMemory(hProcess, Status = NtReadVirtualMemory(hProcess,
(PVOID)HardErrorMessage->Parameters[nParam], (PVOID)HardErrorMessage->Parameters[nParam],
@ -164,7 +184,11 @@ UserpCaptureStringParameters(
sizeof(ParamStringU), sizeof(ParamStringU),
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
break; {
/* We failed, skip this string */
DPRINT1("NtReadVirtualMemory(HardErrorMessage->Parameters) failed, Status 0x%lx\n", Status);
continue;
}
/* Allocate a buffer for the string */ /* Allocate a buffer for the string */
TempStringU.MaximumLength = ParamStringU.Length; TempStringU.MaximumLength = ParamStringU.Length;
@ -174,8 +198,10 @@ UserpCaptureStringParameters(
TempStringU.MaximumLength); TempStringU.MaximumLength);
if (!TempStringU.Buffer) if (!TempStringU.Buffer)
{ {
DPRINT1("Cannot allocate memory %u\n", TempStringU.MaximumLength); /* We failed, skip this string */
DPRINT1("Cannot allocate memory with size %u\n", TempStringU.MaximumLength);
Status = STATUS_NO_MEMORY; Status = STATUS_NO_MEMORY;
continue;
} }
/* Read the string buffer from the process memory */ /* Read the string buffer from the process memory */
@ -186,12 +212,13 @@ UserpCaptureStringParameters(
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("NtReadVirtualMemory failed with code: %lx\n", Status); /* We failed, skip this string */
DPRINT1("NtReadVirtualMemory(ParamStringU) failed, Status 0x%lx\n", Status);
RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer); RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer);
break; continue;
} }
DPRINT("ParamString=\'%wZ\'\n", &TempStringU); DPRINT("ParamString = \'%wZ\'\n", &TempStringU);
/* Allocate a buffer for converted to ANSI string */ /* Allocate a buffer for converted to ANSI string */
TempStringA.MaximumLength = RtlUnicodeStringToAnsiSize(&TempStringU); TempStringA.MaximumLength = RtlUnicodeStringToAnsiSize(&TempStringU);
@ -200,10 +227,11 @@ UserpCaptureStringParameters(
TempStringA.MaximumLength); TempStringA.MaximumLength);
if (!TempStringA.Buffer) if (!TempStringA.Buffer)
{ {
DPRINT1("Cannot allocate memory %u\n", TempStringA.MaximumLength); /* We failed, skip this string */
DPRINT1("Cannot allocate memory with size %u\n", TempStringA.MaximumLength);
RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer); RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer);
Status = STATUS_NO_MEMORY; Status = STATUS_NO_MEMORY;
break; continue;
} }
/* Convert string to ANSI and free temporary buffer */ /* Convert string to ANSI and free temporary buffer */
@ -211,8 +239,9 @@ UserpCaptureStringParameters(
RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer); RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
/* We failed, skip this string */
RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringA.Buffer); RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringA.Buffer);
break; continue;
} }
/* Note: RtlUnicodeStringToAnsiString returns NULL terminated string */ /* Note: RtlUnicodeStringToAnsiString returns NULL terminated string */
@ -221,16 +250,18 @@ UserpCaptureStringParameters(
} }
else else
{ {
/* It's not a unicode string */ /* It's not a unicode string, just copy the parameter */
Parameters[nParam] = HardErrorMessage->Parameters[nParam]; Parameters[nParam] = HardErrorMessage->Parameters[nParam];
} }
} }
#if 0
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
UserpFreeStringParameters(Parameters, HardErrorMessage); UserpFreeStringParameters(Parameters, HardErrorMessage);
return Status; return Status;
} }
#endif
if (SizeOfAllUnicodeStrings) if (SizeOfAllUnicodeStrings)
*SizeOfAllUnicodeStrings = Size; *SizeOfAllUnicodeStrings = Size;
@ -246,24 +277,33 @@ UserpFormatMessages(
IN PULONG_PTR Parameters, IN PULONG_PTR Parameters,
IN ULONG SizeOfStrings, IN ULONG SizeOfStrings,
IN PHARDERROR_MSG Message, IN PHARDERROR_MSG Message,
IN HANDLE hProcess) IN HANDLE hProcess OPTIONAL)
{ {
NTSTATUS Status; NTSTATUS Status;
UNICODE_STRING FileNameU, TempStringU, FormatU, Format2U; UNICODE_STRING FileNameU, TempStringU, FormatU, Format2U;
ANSI_STRING FormatA, Format2A; ANSI_STRING FormatA, Format2A;
PMESSAGE_RESOURCE_ENTRY MessageResource; PMESSAGE_RESOURCE_ENTRY MessageResource;
ULONG_PTR CapturedParameters[MAXIMUM_HARDERROR_PARAMETERS];
PWSTR FormatString; PWSTR FormatString;
ULONG ExceptionCode, Severity; ULONG ExceptionCode, Severity;
ULONG Size; ULONG Size;
/* Get the file name of the client process */ /* Copy the Parameters array locally */
UserpGetClientFileName(&FileNameU, hProcess); RtlCopyMemory(&CapturedParameters, Parameters, sizeof(CapturedParameters));
/* Check if we have a file name */ /* Get the file name of the client process */
if (!FileNameU.Buffer) Status = STATUS_SUCCESS;
if (hProcess)
Status = UserpGetClientFileName(&FileNameU, hProcess);
/*
* Fall back to SYSTEM process if the client process handle
* was NULL or we failed retrieving a file name.
*/
if (!hProcess || !NT_SUCCESS(Status) || !FileNameU.Buffer)
{ {
/* No, this is system process */
RtlInitUnicodeString(&FileNameU, L"System Process"); RtlInitUnicodeString(&FileNameU, L"System Process");
hProcess = NULL;
} }
Severity = (ULONG)(Message->Status) >> 30; Severity = (ULONG)(Message->Status) >> 30;
@ -334,8 +374,13 @@ UserpFormatMessages(
/* Allocate a buffer for the caption */ /* Allocate a buffer for the caption */
CaptionStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), CaptionStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
CaptionStringU->MaximumLength); CaptionStringU->MaximumLength);
if (!CaptionStringU->Buffer)
{
DPRINT1("Cannot allocate memory for CaptionStringU\n");
Status = STATUS_NO_MEMORY;
}
/* Append the file name, seperator and the caption text */ /* Append the file name, seperator and the caption text */
CaptionStringU->Length = 0; CaptionStringU->Length = 0;
@ -355,7 +400,7 @@ UserpFormatMessages(
/* 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)
{ {
ExceptionCode = Parameters[0]; ExceptionCode = CapturedParameters[0];
/* Get text string of the exception code */ /* Get text string of the exception code */
Status = RtlFindMessage(GetModuleHandleW(L"ntdll"), Status = RtlFindMessage(GetModuleHandleW(L"ntdll"),
@ -376,30 +421,30 @@ UserpFormatMessages(
RtlAnsiStringToUnicodeString(&Format2U, &Format2A, TRUE); RtlAnsiStringToUnicodeString(&Format2U, &Format2A, TRUE);
} }
/* Handle the special cases */ /* Handle special cases */
if (ExceptionCode == STATUS_ACCESS_VIOLATION) if (ExceptionCode == STATUS_ACCESS_VIOLATION)
{ {
FormatString = Format2U.Buffer; FormatString = Format2U.Buffer;
Parameters[0] = Parameters[1]; CapturedParameters[0] = CapturedParameters[1];
Parameters[1] = Parameters[3]; CapturedParameters[1] = CapturedParameters[3];
if (Parameters[2]) if (CapturedParameters[2])
Parameters[2] = (ULONG_PTR)L"written"; CapturedParameters[2] = (ULONG_PTR)L"written";
else else
Parameters[2] = (ULONG_PTR)L"read"; CapturedParameters[2] = (ULONG_PTR)L"read";
} }
else if (ExceptionCode == STATUS_IN_PAGE_ERROR) else if (ExceptionCode == STATUS_IN_PAGE_ERROR)
{ {
FormatString = Format2U.Buffer; FormatString = Format2U.Buffer;
Parameters[0] = Parameters[1]; CapturedParameters[0] = CapturedParameters[1];
Parameters[1] = Parameters[3]; CapturedParameters[1] = CapturedParameters[3];
} }
else else
{ {
PWSTR pTmp; PWSTR pTmp;
/* Keep the existing FormatString */ /* Keep the existing FormatString */
Parameters[2] = Parameters[1]; CapturedParameters[2] = CapturedParameters[1];
Parameters[1] = Parameters[0]; CapturedParameters[1] = CapturedParameters[0];
pTmp = Format2U.Buffer; pTmp = Format2U.Buffer;
if (!_wcsnicmp(pTmp, L"{EXCEPTION}", 11)) if (!_wcsnicmp(pTmp, L"{EXCEPTION}", 11))
@ -413,21 +458,21 @@ UserpFormatMessages(
/* Skip '\r', '\n' */ /* Skip '\r', '\n' */
pTmp += 2; pTmp += 2;
Parameters[0] = (ULONG_PTR)pTmp; CapturedParameters[0] = (ULONG_PTR)pTmp;
} }
else else
{ {
/* Fall back to hardcoded value */ /* Fall back to hardcoded value */
Parameters[0] = (ULONG_PTR)L"unknown software exception"; CapturedParameters[0] = (ULONG_PTR)L"unknown software exception";
} }
} }
} }
else else
{ {
/* Fall back to hardcoded value, and keep the existing FormatString */ /* Fall back to hardcoded value, and keep the existing FormatString */
Parameters[2] = Parameters[1]; CapturedParameters[2] = CapturedParameters[1];
Parameters[1] = Parameters[0]; CapturedParameters[1] = CapturedParameters[0];
Parameters[0] = (ULONG_PTR)L"unknown software exception"; CapturedParameters[0] = (ULONG_PTR)L"unknown software exception";
} }
/* FIXME: Use localized strings! */ /* FIXME: Use localized strings! */
@ -437,7 +482,7 @@ UserpFormatMessages(
// Tmp = FormatString + wcslen(FormatString); // Tmp = FormatString + wcslen(FormatString);
// *++Tmp = L'\n'; // *++Tmp = L'\n';
// *++Tmp = L'\n'; // *++Tmp = L'\n';
Size += 2 + wcslen(L"Click on OK to terminate the program."); Size += 1 + wcslen(L"Click on OK to terminate the program.");
} }
if (Message->ValidResponseOptions == OptionOkCancel) if (Message->ValidResponseOptions == OptionOkCancel)
{ {
@ -454,6 +499,11 @@ UserpFormatMessages(
TextStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), TextStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
TextStringU->MaximumLength); TextStringU->MaximumLength);
if (!TextStringU->Buffer)
{
DPRINT1("Cannot allocate memory for TextStringU\n");
Status = STATUS_NO_MEMORY;
}
/* Wrap in SEH to protect from invalid string parameters */ /* Wrap in SEH to protect from invalid string parameters */
_SEH2_TRY _SEH2_TRY
@ -462,10 +512,10 @@ UserpFormatMessages(
RtlStringCbPrintfW(TextStringU->Buffer, RtlStringCbPrintfW(TextStringU->Buffer,
TextStringU->MaximumLength, TextStringU->MaximumLength,
FormatString, FormatString,
Parameters[0], CapturedParameters[0],
Parameters[1], CapturedParameters[1],
Parameters[2], CapturedParameters[2],
Parameters[3]); CapturedParameters[3]);
if (Message->Status == STATUS_UNHANDLED_EXCEPTION) if (Message->Status == STATUS_UNHANDLED_EXCEPTION)
{ {
@ -478,13 +528,16 @@ UserpFormatMessages(
// *++Tmp = L'\n'; // *++Tmp = L'\n';
RtlStringCbCatW(TextStringU->Buffer, RtlStringCbCatW(TextStringU->Buffer,
TextStringU->MaximumLength, TextStringU->MaximumLength,
L"\n\n"); L"\n");
RtlStringCbCatW(TextStringU->Buffer, RtlStringCbCatW(TextStringU->Buffer,
TextStringU->MaximumLength, TextStringU->MaximumLength,
L"Click on OK to terminate the program."); L"Click on OK to terminate the program.");
} }
if (Message->ValidResponseOptions == OptionOkCancel) if (Message->ValidResponseOptions == OptionOkCancel)
{ {
RtlStringCbCatW(TextStringU->Buffer,
TextStringU->MaximumLength,
L"\n");
RtlStringCbCatW(TextStringU->Buffer, RtlStringCbCatW(TextStringU->Buffer,
TextStringU->MaximumLength, TextStringU->MaximumLength,
L"Click on CANCEL to debug the program."); L"Click on CANCEL to debug the program.");
@ -498,16 +551,16 @@ UserpFormatMessages(
/* An exception occurred, use a default string */ /* An exception occurred, use a default string */
RtlStringCbPrintfW(TextStringU->Buffer, RtlStringCbPrintfW(TextStringU->Buffer,
TextStringU->MaximumLength, TextStringU->MaximumLength,
L"Exception processing message 0x%lx\n" L"Exception processing message 0x%08lx\n"
L"Parameters 0x%lx 0x%lx 0x%lx 0x%lx", L"Parameters: 0x%p 0x%p 0x%p 0x%p",
Message->Status, Message->Status,
Parameters[0], Parameters[1], CapturedParameters[0], CapturedParameters[1],
Parameters[2], Parameters[3]); CapturedParameters[2], CapturedParameters[3]);
/* Set error and free buffers */ /* Set error and free buffers */
Status = _SEH2_GetExceptionCode(); // Status = _SEH2_GetExceptionCode();
RtlFreeHeap(RtlGetProcessHeap(), 0, TextStringU->Buffer); // RtlFreeHeap(RtlGetProcessHeap(), 0, TextStringU->Buffer);
RtlFreeHeap(RtlGetProcessHeap(), 0, CaptionStringU->Buffer); // RtlFreeHeap(RtlGetProcessHeap(), 0, CaptionStringU->Buffer);
} }
_SEH2_END; _SEH2_END;
@ -523,6 +576,54 @@ UserpFormatMessages(
return Status; return Status;
} }
static ULONG
GetRegInt(
IN PCWSTR KeyName,
IN PCWSTR ValueName,
IN ULONG DefaultValue)
{
NTSTATUS Status;
ULONG Value = DefaultValue;
UNICODE_STRING String;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE KeyHandle;
ULONG ResultLength;
UCHAR ValueBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
RtlInitUnicodeString(&String, KeyName);
InitializeObjectAttributes(&ObjectAttributes,
&String,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
/* Open the registry key */
Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
if (NT_SUCCESS(Status))
{
/* Query the value */
RtlInitUnicodeString(&String, ValueName);
Status = NtQueryValueKey(KeyHandle,
&String,
KeyValuePartialInformation,
ValueInfo,
sizeof(ValueBuffer),
&ResultLength);
/* Close the registry key */
NtClose(KeyHandle);
if (NT_SUCCESS(Status) && (ValueInfo->Type == REG_DWORD))
{
/* Directly retrieve the data */
Value = *(PULONG)ValueInfo->Data;
}
}
return Value;
}
static BOOL static BOOL
UserpShowInformationBalloon(PWSTR Text, UserpShowInformationBalloon(PWSTR Text,
PWSTR Caption, PWSTR Caption,
@ -596,55 +697,6 @@ UserpShowInformationBalloon(PWSTR Text,
return (ret && dwResult) ? TRUE : FALSE; return (ret && dwResult) ? TRUE : FALSE;
} }
static ULONG
GetRegInt(
IN PCWSTR KeyName,
IN PCWSTR ValueName,
IN ULONG DefaultValue)
{
NTSTATUS Status;
ULONG Value = DefaultValue;
UNICODE_STRING String;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE KeyHandle;
ULONG ResultLength;
UCHAR ValueBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
RtlInitUnicodeString(&String, KeyName);
InitializeObjectAttributes(&ObjectAttributes,
&String,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
/* Open the registry key */
Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
if (NT_SUCCESS(Status))
{
/* Query the value */
RtlInitUnicodeString(&String, ValueName);
Status = NtQueryValueKey(KeyHandle,
&String,
KeyValuePartialInformation,
ValueInfo,
sizeof(ValueBuffer),
&ResultLength);
/* Close the registry key */
NtClose(KeyHandle);
if (NT_SUCCESS(Status) && (ValueInfo->Type == REG_DWORD))
{
/* Directly retrieve the data */
Value = *(PULONG)ValueInfo->Data;
}
}
return Value;
}
static static
ULONG ULONG
UserpMessageBox( UserpMessageBox(
@ -799,29 +851,27 @@ UserServerHardError(
} }
// TODO: More message validation: check NumberOfParameters wrt. Message Status code. // TODO: More message validation: check NumberOfParameters wrt. Message Status code.
/* Initialize object attributes */
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
/* Open client process */ /* Open client process */
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
Status = NtOpenProcess(&hProcess, Status = NtOpenProcess(&hProcess,
PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
&ObjectAttributes, &ObjectAttributes,
&Message->h.ClientId); &Message->h.ClientId);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("NtOpenProcess failed with status 0x%08lx\n", Status); DPRINT1("NtOpenProcess failed with status 0x%08lx, possibly SYSTEM process.\n", Status);
return; hProcess = NULL;
} }
/* Capture all string parameters from the process memory */ /* Capture all string parameters from the process memory */
Status = UserpCaptureStringParameters(Parameters, &Size, Message, hProcess); Status = UserpCaptureStringParameters(Parameters, &Size, Message, hProcess);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
NtClose(hProcess); if (hProcess) NtClose(hProcess);
return; return;
} }
/* Format the caption and message box text */ /* Format the message caption and text */
Status = UserpFormatMessages(&TextU, Status = UserpFormatMessages(&TextU,
&CaptionU, &CaptionU,
Parameters, Parameters,
@ -831,7 +881,7 @@ UserServerHardError(
/* Cleanup */ /* Cleanup */
UserpFreeStringParameters(Parameters, Message); UserpFreeStringParameters(Parameters, Message);
NtClose(hProcess); if (hProcess) NtClose(hProcess);
/* If we failed, bail out */ /* If we failed, bail out */
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -846,7 +896,7 @@ UserServerHardError(
ErrorMode = GetRegInt(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Windows", ErrorMode = GetRegInt(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Windows",
L"ErrorMode", 0); L"ErrorMode", 0);
if (ErrorMode != 0) if (Message->Status != STATUS_SERVICE_NOTIFICATION && ErrorMode != 0)
{ {
/* Returns OK for the hard error */ /* Returns OK for the hard error */
Message->Response = ResponseOk; Message->Response = ResponseOk;