[USERSRV] Hard-error improvements 4/7

- Make UserpFormatMessages() always succeed by falling back on
  static string buffers if allocating large string buffers fail due to
  lack of memory. Then the hard error popups will have truncated
  strings, but at least something will be displayed instead of nothing,
  thus alerting the user that something went wrong anyway.
- Simplify a bit the code by moving the NtOpenProcess(),
  UserpCaptureStringParameters() and UserpFreeStringParameters() calls
  inside UserpFormatMessages(). This also allows simplifying its
  prototype.
This commit is contained in:
Hermès Bélusca-Maïto 2018-03-24 22:47:50 +01:00
parent 5a1a35ca5a
commit 9ea2783e56
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0

View file

@ -73,117 +73,6 @@ MessageBoxTimeoutW(
DWORD dwTime); DWORD dwTime);
static
NTSTATUS
UserpGetClientFileName(
OUT PUNICODE_STRING ClientFileNameU,
IN HANDLE hProcess)
{
PLIST_ENTRY ModuleListHead;
PLIST_ENTRY Entry;
PLDR_DATA_TABLE_ENTRY Module;
PPEB_LDR_DATA Ldr;
PROCESS_BASIC_INFORMATION ClientBasicInfo;
LDR_DATA_TABLE_ENTRY ModuleData;
PVOID ClientDllBase;
NTSTATUS Status;
PPEB Peb;
/* Initialize string */
RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0);
/* Query process information */
Status = NtQueryInformationProcess(hProcess,
ProcessBasicInformation,
&ClientBasicInfo,
sizeof(ClientBasicInfo),
NULL);
if (!NT_SUCCESS(Status)) return Status;
/* Locate the process loader data table and retrieve its name from it */
Peb = ClientBasicInfo.PebBaseAddress;
if (!Peb) return STATUS_UNSUCCESSFUL;
Status = NtReadVirtualMemory(hProcess, &Peb->Ldr, &Ldr, sizeof(Ldr), NULL);
if (!NT_SUCCESS(Status)) return Status;
ModuleListHead = &Ldr->InLoadOrderModuleList;
Status = NtReadVirtualMemory(hProcess,
&ModuleListHead->Flink,
&Entry,
sizeof(Entry),
NULL);
if (!NT_SUCCESS(Status)) return Status;
if (Entry == ModuleListHead) return STATUS_UNSUCCESSFUL;
Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
Status = NtReadVirtualMemory(hProcess,
Module,
&ModuleData,
sizeof(ModuleData),
NULL);
if (!NT_SUCCESS(Status)) return Status;
Status = NtReadVirtualMemory(hProcess,
&Peb->ImageBaseAddress,
&ClientDllBase,
sizeof(ClientDllBase),
NULL);
if (!NT_SUCCESS(Status)) return Status;
if (ClientDllBase != ModuleData.DllBase) return STATUS_UNSUCCESSFUL;
ClientFileNameU->MaximumLength = ModuleData.BaseDllName.MaximumLength;
ClientFileNameU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
ClientFileNameU->MaximumLength);
if (!ClientFileNameU->Buffer)
{
RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0);
return STATUS_NO_MEMORY;
}
Status = NtReadVirtualMemory(hProcess,
ModuleData.BaseDllName.Buffer,
ClientFileNameU->Buffer,
ClientFileNameU->MaximumLength,
NULL);
if (!NT_SUCCESS(Status))
{
RtlFreeHeap(RtlGetProcessHeap(), 0, ClientFileNameU->Buffer);
RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0);
return Status;
}
ClientFileNameU->Length = wcslen(ClientFileNameU->Buffer) * sizeof(WCHAR);
DPRINT("ClientFileNameU = \'%wZ\'\n", &ClientFileNameU);
return STATUS_SUCCESS;
}
static
VOID
UserpFreeStringParameters(
IN OUT PULONG_PTR Parameters,
IN PHARDERROR_MSG Message)
{
ULONG nParam;
/* Loop all parameters */
for (nParam = 0; nParam < Message->NumberOfParameters; ++nParam)
{
/* Check if the current parameter is a string */
if ((Message->UnicodeStringParameterMask & (1 << nParam)) && (Parameters[nParam] != 0))
{
/* Free the string buffer */
RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)Parameters[nParam]);
}
}
}
static static
VOID VOID
UserpCaptureStringParameters( UserpCaptureStringParameters(
@ -293,35 +182,165 @@ UserpCaptureStringParameters(
*SizeOfAllUnicodeStrings = Size; *SizeOfAllUnicodeStrings = Size;
} }
static
VOID
UserpFreeStringParameters(
IN OUT PULONG_PTR Parameters,
IN PHARDERROR_MSG Message)
{
ULONG nParam;
/* Loop all parameters */
for (nParam = 0; nParam < Message->NumberOfParameters; ++nParam)
{
/* Check if the current parameter is a string */
if ((Message->UnicodeStringParameterMask & (1 << nParam)) && (Parameters[nParam] != 0))
{
/* Free the string buffer */
RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)Parameters[nParam]);
}
}
}
static static
NTSTATUS NTSTATUS
UserpGetClientFileName(
OUT PUNICODE_STRING ClientFileNameU,
IN HANDLE hProcess)
{
PLIST_ENTRY ModuleListHead;
PLIST_ENTRY Entry;
PLDR_DATA_TABLE_ENTRY Module;
PPEB_LDR_DATA Ldr;
PROCESS_BASIC_INFORMATION ClientBasicInfo;
LDR_DATA_TABLE_ENTRY ModuleData;
PVOID ClientDllBase;
NTSTATUS Status;
PPEB Peb;
/* Initialize string */
RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0);
/* Query process information */
Status = NtQueryInformationProcess(hProcess,
ProcessBasicInformation,
&ClientBasicInfo,
sizeof(ClientBasicInfo),
NULL);
if (!NT_SUCCESS(Status)) return Status;
/* Locate the process loader data table and retrieve its name from it */
Peb = ClientBasicInfo.PebBaseAddress;
if (!Peb) return STATUS_UNSUCCESSFUL;
Status = NtReadVirtualMemory(hProcess, &Peb->Ldr, &Ldr, sizeof(Ldr), NULL);
if (!NT_SUCCESS(Status)) return Status;
ModuleListHead = &Ldr->InLoadOrderModuleList;
Status = NtReadVirtualMemory(hProcess,
&ModuleListHead->Flink,
&Entry,
sizeof(Entry),
NULL);
if (!NT_SUCCESS(Status)) return Status;
if (Entry == ModuleListHead) return STATUS_UNSUCCESSFUL;
Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
Status = NtReadVirtualMemory(hProcess,
Module,
&ModuleData,
sizeof(ModuleData),
NULL);
if (!NT_SUCCESS(Status)) return Status;
Status = NtReadVirtualMemory(hProcess,
&Peb->ImageBaseAddress,
&ClientDllBase,
sizeof(ClientDllBase),
NULL);
if (!NT_SUCCESS(Status)) return Status;
if (ClientDllBase != ModuleData.DllBase) return STATUS_UNSUCCESSFUL;
ClientFileNameU->MaximumLength = ModuleData.BaseDllName.MaximumLength;
ClientFileNameU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
ClientFileNameU->MaximumLength);
if (!ClientFileNameU->Buffer)
{
RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0);
return STATUS_NO_MEMORY;
}
Status = NtReadVirtualMemory(hProcess,
ModuleData.BaseDllName.Buffer,
ClientFileNameU->Buffer,
ClientFileNameU->MaximumLength,
NULL);
if (!NT_SUCCESS(Status))
{
RtlFreeHeap(RtlGetProcessHeap(), 0, ClientFileNameU->Buffer);
RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0);
return Status;
}
ClientFileNameU->Length = (USHORT)(wcslen(ClientFileNameU->Buffer) * sizeof(WCHAR));
DPRINT("ClientFileNameU = \'%wZ\'\n", &ClientFileNameU);
return STATUS_SUCCESS;
}
static
VOID
UserpFormatMessages( UserpFormatMessages(
OUT PUNICODE_STRING TextStringU, IN OUT PUNICODE_STRING TextStringU,
OUT PUNICODE_STRING CaptionStringU, IN OUT PUNICODE_STRING CaptionStringU,
IN PULONG_PTR Parameters, IN PHARDERROR_MSG Message)
IN ULONG SizeOfStrings,
IN PHARDERROR_MSG Message,
IN HANDLE hProcess OPTIONAL)
{ {
NTSTATUS Status; NTSTATUS Status;
UNICODE_STRING FileNameU, TempStringU, WindowTitleU, FormatU, Format2U; OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE hProcess;
ULONG SizeOfStrings;
ULONG_PTR Parameters[MAXIMUM_HARDERROR_PARAMETERS] = {0};
ULONG_PTR CopyParameters[MAXIMUM_HARDERROR_PARAMETERS];
UNICODE_STRING WindowTitleU, FileNameU, TempStringU, FormatU, Format2U;
ANSI_STRING FormatA, Format2A; ANSI_STRING FormatA, Format2A;
HWND hwndOwner; HWND hwndOwner;
PMESSAGE_RESOURCE_ENTRY MessageResource; PMESSAGE_RESOURCE_ENTRY MessageResource;
ULONG_PTR CapturedParameters[MAXIMUM_HARDERROR_PARAMETERS];
PWSTR FormatString, pszBuffer; PWSTR FormatString, pszBuffer;
size_t cchBuffer; size_t cszBuffer;
ULONG ExceptionCode, Severity; ULONG Severity;
ULONG Size; ULONG Size;
/* Open client process */
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
Status = NtOpenProcess(&hProcess,
PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
&ObjectAttributes,
&Message->h.ClientId);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtOpenProcess failed with status 0x%08lx, possibly SYSTEM process.\n", Status);
hProcess = NULL;
}
/* Capture all string parameters from the process memory */
UserpCaptureStringParameters(Parameters, &SizeOfStrings, Message, hProcess);
/* Copy the Parameters array locally */ /* Copy the Parameters array locally */
RtlCopyMemory(&CapturedParameters, Parameters, sizeof(CapturedParameters)); RtlCopyMemory(&CopyParameters, Parameters, sizeof(CopyParameters));
/* Get the file name of the client process */ /* Get the file name of the client process */
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
if (hProcess) if (hProcess)
Status = UserpGetClientFileName(&FileNameU, hProcess); Status = UserpGetClientFileName(&FileNameU, hProcess);
/* Close the process handle but keep its original value to know where stuff came from */
if (hProcess) NtClose(hProcess);
/* /*
* Fall back to SYSTEM process if the client process handle * Fall back to SYSTEM process if the client process handle
* was NULL or we failed retrieving a file name. * was NULL or we failed retrieving a file name.
@ -389,7 +408,7 @@ UserpFormatMessages(
else if (Severity == STATUS_SEVERITY_ERROR) else if (Severity == STATUS_SEVERITY_ERROR)
TempStringU = g_ErrorU; TempStringU = g_ErrorU;
else else
RtlInitEmptyUnicodeString(&TempStringU, NULL, 0); ASSERT(FALSE); // Unexpected, since Severity is only <= 3.
} }
/* Retrieve the window title of the client, if it has one */ /* Retrieve the window title of the client, if it has one */
@ -399,20 +418,20 @@ UserpFormatMessages(
FindTopLevelWnd, (LPARAM)&hwndOwner); FindTopLevelWnd, (LPARAM)&hwndOwner);
if (hwndOwner) if (hwndOwner)
{ {
cchBuffer = GetWindowTextLengthW(hwndOwner); cszBuffer = GetWindowTextLengthW(hwndOwner);
if (cchBuffer != 0) if (cszBuffer != 0)
{ {
cchBuffer += 3; // 2 characters for ": " and a NULL terminator. cszBuffer += 3; // 2 characters for ": " and a NULL terminator.
WindowTitleU.MaximumLength = (USHORT)(cchBuffer * sizeof(WCHAR)); WindowTitleU.MaximumLength = (USHORT)(cszBuffer * sizeof(WCHAR));
WindowTitleU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), WindowTitleU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
WindowTitleU.MaximumLength); WindowTitleU.MaximumLength);
if (WindowTitleU.Buffer) if (WindowTitleU.Buffer)
{ {
cchBuffer = GetWindowTextW(hwndOwner, cszBuffer = GetWindowTextW(hwndOwner,
WindowTitleU.Buffer, WindowTitleU.Buffer,
WindowTitleU.MaximumLength / sizeof(WCHAR)); WindowTitleU.MaximumLength / sizeof(WCHAR));
WindowTitleU.Length = (USHORT)(cchBuffer * sizeof(WCHAR)); WindowTitleU.Length = (USHORT)(cszBuffer * sizeof(WCHAR));
RtlAppendUnicodeToString(&WindowTitleU, L": "); RtlAppendUnicodeToString(&WindowTitleU, L": ");
} }
else else
@ -423,26 +442,32 @@ UserpFormatMessages(
} }
/* Calculate buffer length for the caption */ /* Calculate buffer length for the caption */
CaptionStringU->MaximumLength = WindowTitleU.Length + cszBuffer = WindowTitleU.Length + FileNameU.Length + TempStringU.Length +
FileNameU.Length + TempStringU.Length + 3 * sizeof(WCHAR) + sizeof(UNICODE_NULL);
3 * sizeof(WCHAR) + sizeof(UNICODE_NULL); if (cszBuffer > CaptionStringU->MaximumLength)
/* Allocate a buffer for the caption */
CaptionStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
CaptionStringU->MaximumLength);
if (!CaptionStringU->Buffer)
{ {
DPRINT1("Cannot allocate memory for CaptionStringU\n"); /* Allocate a larger buffer for the caption */
Status = STATUS_NO_MEMORY; pszBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
cszBuffer);
if (!pszBuffer)
{
/* We could not allocate a larger buffer; continue using the smaller static buffer */
DPRINT1("Cannot allocate memory for CaptionStringU, use static buffer.\n");
}
else
{
RtlInitEmptyUnicodeString(CaptionStringU, pszBuffer, (USHORT)cszBuffer);
}
} }
CaptionStringU->Length = 0;
/* 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,
CaptionStringU->MaximumLength, CaptionStringU->MaximumLength,
L"%wZ%wZ - %wZ", L"%wZ%wZ - %wZ",
&WindowTitleU, &FileNameU, &TempStringU); &WindowTitleU, &FileNameU, &TempStringU);
CaptionStringU->Length = wcslen(CaptionStringU->Buffer) * sizeof(WCHAR); CaptionStringU->Length = (USHORT)(wcslen(CaptionStringU->Buffer) * sizeof(WCHAR));
/* Free string buffers if needed */ /* Free string buffers if needed */
if (WindowTitleU.Buffer) RtlFreeUnicodeString(&WindowTitleU); if (WindowTitleU.Buffer) RtlFreeUnicodeString(&WindowTitleU);
@ -454,7 +479,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 = CapturedParameters[0]; ULONG ExceptionCode = CopyParameters[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"),
@ -479,24 +504,24 @@ UserpFormatMessages(
if (ExceptionCode == STATUS_ACCESS_VIOLATION) if (ExceptionCode == STATUS_ACCESS_VIOLATION)
{ {
FormatString = Format2U.Buffer; FormatString = Format2U.Buffer;
CapturedParameters[0] = CapturedParameters[1]; CopyParameters[0] = CopyParameters[1];
CapturedParameters[1] = CapturedParameters[3]; CopyParameters[1] = CopyParameters[3];
if (CapturedParameters[2]) if (CopyParameters[2])
CapturedParameters[2] = (ULONG_PTR)L"written"; CopyParameters[2] = (ULONG_PTR)L"written";
else else
CapturedParameters[2] = (ULONG_PTR)L"read"; CopyParameters[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;
CapturedParameters[0] = CapturedParameters[1]; CopyParameters[0] = CopyParameters[1];
CapturedParameters[1] = CapturedParameters[3]; CopyParameters[1] = CopyParameters[3];
} }
else else
{ {
/* Keep the existing FormatString */ /* Keep the existing FormatString */
CapturedParameters[2] = CapturedParameters[1]; CopyParameters[2] = CopyParameters[1];
CapturedParameters[1] = CapturedParameters[0]; CopyParameters[1] = CopyParameters[0];
pszBuffer = Format2U.Buffer; pszBuffer = Format2U.Buffer;
if (!_wcsnicmp(pszBuffer, L"{EXCEPTION}", 11)) if (!_wcsnicmp(pszBuffer, L"{EXCEPTION}", 11))
@ -510,21 +535,21 @@ UserpFormatMessages(
/* Skip '\r', '\n' */ /* Skip '\r', '\n' */
pszBuffer += 2; pszBuffer += 2;
CapturedParameters[0] = (ULONG_PTR)pszBuffer; CopyParameters[0] = (ULONG_PTR)pszBuffer;
} }
else else
{ {
/* Fall back to hardcoded value */ /* Fall back to hardcoded value */
CapturedParameters[0] = (ULONG_PTR)L"unknown software exception"; CopyParameters[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 */
CapturedParameters[2] = CapturedParameters[1]; CopyParameters[2] = CopyParameters[1];
CapturedParameters[1] = CapturedParameters[0]; CopyParameters[1] = CopyParameters[0];
CapturedParameters[0] = (ULONG_PTR)L"unknown software exception"; CopyParameters[0] = (ULONG_PTR)L"unknown software exception";
} }
if (Message->ValidResponseOptions == OptionOk || if (Message->ValidResponseOptions == OptionOk ||
@ -540,53 +565,55 @@ UserpFormatMessages(
} }
} }
/* Calculate length of text buffer */ /* Calculate buffer length for the text message */
TextStringU->MaximumLength = FormatU.Length + SizeOfStrings + cszBuffer = FormatU.Length + SizeOfStrings + Size * sizeof(WCHAR) +
(USHORT)(Size * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
sizeof(UNICODE_NULL); if (cszBuffer > TextStringU->MaximumLength)
/* Allocate a buffer for the text */
TextStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
TextStringU->MaximumLength);
if (!TextStringU->Buffer)
{ {
DPRINT1("Cannot allocate memory for TextStringU\n"); /* Allocate a larger buffer for the text message */
Status = STATUS_NO_MEMORY; pszBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
cszBuffer);
if (!pszBuffer)
{
/* We could not allocate a larger buffer; continue using the smaller static buffer */
DPRINT1("Cannot allocate memory for TextStringU, use static buffer.\n");
}
else
{
RtlInitEmptyUnicodeString(TextStringU, pszBuffer, (USHORT)cszBuffer);
}
} }
TextStringU->Length = 0;
Status = STATUS_SUCCESS;
/* Wrap in SEH to protect from invalid string parameters */ /* Wrap in SEH to protect from invalid string parameters */
_SEH2_TRY _SEH2_TRY
{ {
/* Print the string into the buffer */ /* Print the string into the buffer */
pszBuffer = TextStringU->Buffer; pszBuffer = TextStringU->Buffer;
cchBuffer = TextStringU->MaximumLength; cszBuffer = TextStringU->MaximumLength;
RtlStringCbPrintfExW(pszBuffer, cchBuffer, RtlStringCbPrintfExW(pszBuffer, cszBuffer,
&pszBuffer, &cchBuffer, &pszBuffer, &cszBuffer,
STRSAFE_IGNORE_NULLS, STRSAFE_IGNORE_NULLS,
FormatString, FormatString,
CapturedParameters[0], CopyParameters[0], CopyParameters[1],
CapturedParameters[1], CopyParameters[2], CopyParameters[3]);
CapturedParameters[2],
CapturedParameters[3]);
if (Message->Status == STATUS_UNHANDLED_EXCEPTION) if (Message->Status == STATUS_UNHANDLED_EXCEPTION)
{ {
if (Message->ValidResponseOptions == OptionOk || if (Message->ValidResponseOptions == OptionOk ||
Message->ValidResponseOptions == OptionOkCancel) Message->ValidResponseOptions == OptionOkCancel)
{ {
RtlStringCbPrintfExW(pszBuffer, cchBuffer, RtlStringCbPrintfExW(pszBuffer, cszBuffer,
&pszBuffer, &cchBuffer, &pszBuffer, &cszBuffer,
STRSAFE_IGNORE_NULLS, STRSAFE_IGNORE_NULLS,
L"\n%wZ", L"\n%wZ",
&g_OKTerminateU); &g_OKTerminateU);
} }
if (Message->ValidResponseOptions == OptionOkCancel) if (Message->ValidResponseOptions == OptionOkCancel)
{ {
RtlStringCbPrintfExW(pszBuffer, cchBuffer, RtlStringCbPrintfExW(pszBuffer, cszBuffer,
&pszBuffer, &cchBuffer, &pszBuffer, &cszBuffer,
STRSAFE_IGNORE_NULLS, STRSAFE_IGNORE_NULLS,
L"\n%wZ", L"\n%wZ",
&g_CancelDebugU); &g_CancelDebugU);
@ -595,7 +622,7 @@ UserpFormatMessages(
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
/* An exception occurred, use a default string */ /* An exception occurred, use a default string with the original parameters */
DPRINT1("Exception 0x%08lx occurred while building hard-error message, fall back to default message.\n", DPRINT1("Exception 0x%08lx occurred while building hard-error message, fall back to default message.\n",
_SEH2_GetExceptionCode()); _SEH2_GetExceptionCode());
@ -604,24 +631,19 @@ UserpFormatMessages(
L"Exception processing message 0x%08lx\n" L"Exception processing message 0x%08lx\n"
L"Parameters: 0x%p 0x%p 0x%p 0x%p", L"Parameters: 0x%p 0x%p 0x%p 0x%p",
Message->Status, Message->Status,
CapturedParameters[0], CapturedParameters[1], Parameters[0], Parameters[1],
CapturedParameters[2], CapturedParameters[3]); Parameters[2], Parameters[3]);
/* Set error and free buffers */
// Status = _SEH2_GetExceptionCode();
} }
_SEH2_END; _SEH2_END;
if (NT_SUCCESS(Status)) TextStringU->Length = (USHORT)(wcslen(TextStringU->Buffer) * sizeof(WCHAR));
{
TextStringU->Length = wcslen(TextStringU->Buffer) * sizeof(WCHAR);
}
/* Free converted Unicode strings */ /* Free converted Unicode strings */
if (Format2A.Buffer) RtlFreeUnicodeString(&Format2U); if (Format2A.Buffer) RtlFreeUnicodeString(&Format2U);
if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU); if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU);
return Status; /* Final cleanup */
UserpFreeStringParameters(Parameters, Message);
} }
static ULONG static ULONG
@ -872,13 +894,10 @@ UserServerHardError(
IN PCSR_THREAD ThreadData, IN PCSR_THREAD ThreadData,
IN PHARDERROR_MSG Message) IN PHARDERROR_MSG Message)
{ {
ULONG_PTR Parameters[MAXIMUM_HARDERROR_PARAMETERS] = {0};
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING TextU, CaptionU;
NTSTATUS Status;
HANDLE hProcess;
ULONG Size;
ULONG ErrorMode; ULONG ErrorMode;
UNICODE_STRING TextU, CaptionU;
WCHAR LocalTextBuffer[256];
WCHAR LocalCaptionBuffer[256];
ASSERT(ThreadData->Process != NULL); ASSERT(ThreadData->Process != NULL);
@ -899,39 +918,13 @@ UserServerHardError(
} }
// TODO: More message validation: check NumberOfParameters wrt. Message Status code. // TODO: More message validation: check NumberOfParameters wrt. Message Status code.
/* Open client process */
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
Status = NtOpenProcess(&hProcess,
PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
&ObjectAttributes,
&Message->h.ClientId);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtOpenProcess failed with status 0x%08lx, possibly SYSTEM process.\n", Status);
hProcess = NULL;
}
/* Re-initialize the hard errors cache */ /* Re-initialize the hard errors cache */
UserInitHardErrorsCache(); UserInitHardErrorsCache();
/* Capture all string parameters from the process memory */
UserpCaptureStringParameters(Parameters, &Size, Message, hProcess);
/* Format the message caption and text */ /* Format the message caption and text */
Status = UserpFormatMessages(&TextU, RtlInitEmptyUnicodeString(&TextU, LocalTextBuffer, sizeof(LocalTextBuffer));
&CaptionU, RtlInitEmptyUnicodeString(&CaptionU, LocalCaptionBuffer, sizeof(LocalCaptionBuffer));
Parameters, UserpFormatMessages(&TextU, &CaptionU, Message);
Size,
Message,
hProcess);
/* Cleanup */
UserpFreeStringParameters(Parameters, Message);
if (hProcess) NtClose(hProcess);
/* If we failed, bail out */
if (!NT_SUCCESS(Status))
return;
/* Log the hard error message */ /* Log the hard error message */
UserpLogHardError(&TextU, &CaptionU); UserpLogHardError(&TextU, &CaptionU);
@ -970,8 +963,11 @@ UserServerHardError(
(ULONG)-1); (ULONG)-1);
Quit: Quit:
RtlFreeUnicodeString(&TextU); /* Free the strings if they have been reallocated */
RtlFreeUnicodeString(&CaptionU); if (TextU.Buffer != LocalTextBuffer)
RtlFreeUnicodeString(&TextU);
if (CaptionU.Buffer != LocalCaptionBuffer)
RtlFreeUnicodeString(&CaptionU);
return; return;
} }