Author: tkreuzer
Date: Mon Apr 26 03:23:21 2010
New Revision: 47027
URL:
http://svn.reactos.org/svn/reactos?rev=47027&view=rev
Log:
[WIN32CSR]
- Rewrite harderror handling.
The old code was a monster function, leaking memory, using ansi rather than unicode
strings and not getting this right. It was also vulnerable to attacks, making csrss crash,
when corrupt parameters were sent.
Added:
trunk/reactos/subsystems/win32/csrss/win32csr/harderror.c (with props)
Modified:
trunk/reactos/subsystems/win32/csrss/win32csr/dllmain.c
trunk/reactos/subsystems/win32/csrss/win32csr/w32csr.h
trunk/reactos/subsystems/win32/csrss/win32csr/win32csr.rbuild
Modified: trunk/reactos/subsystems/win32/csrss/win32csr/dllmain.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/win…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/win32csr/dllmain.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/win32csr/dllmain.c [iso-8859-1] Mon Apr 26
03:23:21 2010
@@ -180,402 +180,6 @@
return TRUE;
}
-static BOOL WINAPI
-Win32CsrHardError(IN PCSRSS_PROCESS_DATA ProcessData,
- IN PHARDERROR_MSG HardErrorMessage)
-{
- UINT responce = MB_OK;
- NTSTATUS Status;
- HANDLE hProcess;
- OBJECT_ATTRIBUTES ObjectAttributes;
- ULONG nParam = 0;
- PRTL_MESSAGE_RESOURCE_ENTRY MessageResource;
- ULONG_PTR ParameterList[MAXIMUM_HARDERROR_PARAMETERS];
- LPSTR CaptionText, MessageBody;
- LPWSTR szxCaptionText, szxMessageBody;
- DWORD SizeOfAllUnicodeStrings = 0;
- PROCESS_BASIC_INFORMATION ClientBasicInfo;
- UNICODE_STRING ClientFileNameU;
- UNICODE_STRING TempStringU;
- UNICODE_STRING ParameterStringU;
- ANSI_STRING ParamStringA;
- ULONG UnicodeStringParameterMask = HardErrorMessage->UnicodeStringParameterMask;
- int MessageBoxResponse;
-
- HardErrorMessage->Response = ResponseNotHandled;
-
- DPRINT("NumberOfParameters = %d\n",
HardErrorMessage->NumberOfParameters);
- DPRINT("Status = %lx\n", HardErrorMessage->Status);
-
- // open client process
- InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
- Status = NtOpenProcess(&hProcess, PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
&ObjectAttributes, &HardErrorMessage->h.ClientId);
- if( !NT_SUCCESS(Status) ) {
- DPRINT1("NtOpenProcess failed with code: %lx\n", Status);
- return FALSE;
- }
-
- // let's get a name of the client process to display it in the caption of a
message box
-
- ClientFileNameU.MaximumLength = 0;
- ClientFileNameU.Length = 0;
- ClientFileNameU.Buffer = NULL;
- Status = NtQueryInformationProcess(hProcess,
- ProcessBasicInformation,
- &ClientBasicInfo,
- sizeof(ClientBasicInfo),
- NULL);
- if( NT_SUCCESS(Status) ) {
- PLIST_ENTRY ModuleListHead;
- PLIST_ENTRY Entry;
- PLDR_DATA_TABLE_ENTRY Module;
- PPEB_LDR_DATA Ldr;
- PPEB Peb = ClientBasicInfo.PebBaseAddress;
-
- if( Peb )
- {
- Status = NtReadVirtualMemory(hProcess, &Peb->Ldr, &Ldr,
sizeof(Ldr), NULL);
- if( NT_SUCCESS(Status) ) {
- ModuleListHead = &Ldr->InLoadOrderModuleList;
- Status = NtReadVirtualMemory(
- hProcess,
- &ModuleListHead->Flink,
- &Entry,
- sizeof(Entry),
- NULL
- );
-
- if( NT_SUCCESS(Status) )
- {
- if (Entry != ModuleListHead)
- {
- LDR_DATA_TABLE_ENTRY ModuleData;
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY,
InLoadOrderLinks);
-
- Status = NtReadVirtualMemory(hProcess, Module, &ModuleData,
sizeof(ModuleData), NULL);
- if( NT_SUCCESS(Status) ) {
- PVOID ClientDllBase;
-
- Status = NtReadVirtualMemory(
- hProcess,
- &Peb->ImageBaseAddress,
- &ClientDllBase,
- sizeof(ClientDllBase),
- NULL
- );
- if( NT_SUCCESS(Status) && (ClientDllBase ==
ModuleData.DllBase) ) {
-
- ClientFileNameU.MaximumLength =
ModuleData.BaseDllName.MaximumLength;
- ClientFileNameU.Buffer =
RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, ClientFileNameU.MaximumLength);
- Status = NtReadVirtualMemory(
- hProcess,
- ModuleData.BaseDllName.Buffer,
- ClientFileNameU.Buffer,
- ClientFileNameU.MaximumLength,
- NULL
- );
- if( NT_SUCCESS(Status) ) {
- ClientFileNameU.Length =
wcslen(ClientFileNameU.Buffer)*sizeof(wchar_t);
- }
- else {
- RtlFreeHeap (RtlGetProcessHeap(), 0,
ClientFileNameU.Buffer);
- ClientFileNameU.Buffer = NULL;
- }
-
- DPRINT("ClientFileNameU=\'%wZ\'\n",
&ClientFileNameU);
- }
- }
- }
- }
- }
- }
- }
-
- // read all unicode strings from client space
- for(nParam = 0; nParam < HardErrorMessage->NumberOfParameters; nParam++,
UnicodeStringParameterMask >>= 1)
- {
- if( UnicodeStringParameterMask & 0x01 ) {
- Status = NtReadVirtualMemory(hProcess,
- (PVOID)HardErrorMessage->Parameters[nParam],
- (PVOID)&TempStringU,
- sizeof(TempStringU),
- NULL);
-
- if( NT_SUCCESS(Status) ) {
- ParameterStringU.Buffer = (PWSTR)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, TempStringU.MaximumLength);
- if( !ParameterStringU.Buffer ) {
- DPRINT1("Cannot allocate memory %d\n",
TempStringU.MaximumLength);
- NtClose(hProcess);
- if( ClientFileNameU.Buffer ) {
- RtlFreeHeap (RtlGetProcessHeap(), 0, ClientFileNameU.Buffer);
- }
- return FALSE;
- }
-
- Status = NtReadVirtualMemory(hProcess,
- (PVOID)TempStringU.Buffer,
- (PVOID)ParameterStringU.Buffer,
- TempStringU.MaximumLength,
- NULL);
- if( !NT_SUCCESS(Status) ) {
- DPRINT1("NtReadVirtualMemory failed with code: %lx\n",
Status);
- RtlFreeHeap (RtlGetProcessHeap(), 0, ParameterStringU.Buffer);
- if( ClientFileNameU.Buffer ) {
- RtlFreeHeap (RtlGetProcessHeap(), 0, ClientFileNameU.Buffer);
- }
- NtClose(hProcess);
- return FALSE;
- }
- ParameterStringU.Length = TempStringU.Length;
- ParameterStringU.MaximumLength = TempStringU.MaximumLength;
- DPRINT("ParameterStringU=\'%wZ\'\n",
&ParameterStringU);
- RtlUnicodeStringToAnsiString(&ParamStringA, &ParameterStringU,
TRUE);
- ParameterList[nParam] = (ULONG_PTR)ParamStringA.Buffer;
- SizeOfAllUnicodeStrings += ParamStringA.MaximumLength;
- }
- }
- else {
- // it's not a unicode string
- ParameterList[nParam] = HardErrorMessage->Parameters[nParam];
- }
- }
-
- NtClose(hProcess);
-
- // get text string of the error code
- Status = RtlFindMessage(
- (PVOID)GetModuleHandle(TEXT("ntdll")),
- (ULONG_PTR)RT_MESSAGETABLE,
- LANG_NEUTRAL,
- HardErrorMessage->Status,
- &MessageResource );
- if( !NT_SUCCESS(Status) ) {
- // WE HAVE TO DISPLAY HERE: "Unknown hard error"
- if( ClientFileNameU.Buffer ) {
- szxCaptionText = (LPWSTR)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, ClientFileNameU.MaximumLength+64);
- wsprintfW(szxCaptionText, L"%s - %hs", ClientFileNameU.Buffer,
"Application Error");
- } else {
- szxCaptionText = (LPWSTR)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, 64);
- wsprintfW(szxCaptionText, L"System - Application Error");
- }
- MessageBody = (LPSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 38);
- wsprintfA(MessageBody, "Unknown hard error");
- }
- else {
- LPSTR NtStatusString;
- UNICODE_STRING MessageU;
- ANSI_STRING MessageA;
- USHORT CaptionSize = 0;
-
- if( !MessageResource->Flags ) {
- /* we've got an ansi string */
- DPRINT("MessageResource->Text=%s\n",
(PSTR)MessageResource->Text);
- RtlInitAnsiString(&MessageA, MessageResource->Text);
- }
- else {
- /* we've got a unicode string */
- DPRINT("MessageResource->Text=%S\n",
(PWSTR)MessageResource->Text);
- RtlInitUnicodeString(&MessageU, (PWSTR)MessageResource->Text);
- RtlUnicodeStringToAnsiString(&MessageA, &MessageU, TRUE);
- }
-
- // check whether a caption exists
- if( *MessageA.Buffer == '{' ) {
- // get size of the caption
- for( CaptionSize = 0; (CaptionSize < MessageA.Length) &&
('}' != MessageA.Buffer[CaptionSize]); CaptionSize++);
-
- CaptionText = (LPSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
CaptionSize);
- RtlCopyMemory(CaptionText, MessageA.Buffer+1, CaptionSize-1);
- CaptionSize += 2; // "}\r\n" - 3
-
- szxCaptionText = (LPWSTR)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, sizeof(wchar_t)*CaptionSize+ClientFileNameU.MaximumLength+128);
- if( ClientFileNameU.Buffer ) {
- wsprintfW(szxCaptionText, L"%s - %hs", ClientFileNameU.Buffer,
CaptionText);
- } else {
- wsprintfW(szxCaptionText, L"System - %hs", CaptionText);
- }
- RtlFreeHeap (RtlGetProcessHeap(), 0, CaptionText);
- }
- else {
- if( ClientFileNameU.Buffer ) {
- szxCaptionText = (LPWSTR)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, ClientFileNameU.MaximumLength);
- wsprintfW(szxCaptionText, L"%s", ClientFileNameU.Buffer);
- } else {
- szxCaptionText = (LPWSTR)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, 14); // 14 - "System\0\0"
- wsprintfW(szxCaptionText, L"System");
- }
- }
- DPRINT("ParameterList[0]=0x%lx\n", ParameterList[0]);
- if( STATUS_UNHANDLED_EXCEPTION == HardErrorMessage->Status )
- {
- PRTL_MESSAGE_RESOURCE_ENTRY MsgResException;
- MessageBody = NULL;
- Status = RtlFindMessage(
- (PVOID)GetModuleHandle(TEXT("ntdll")),
- (ULONG_PTR)RT_MESSAGETABLE,
- LANG_NEUTRAL,
- ParameterList[0],
- &MsgResException);
-
- if( NT_SUCCESS(Status) )
- {
- UNICODE_STRING ExcMessageU;
- ANSI_STRING ExcMessageA;
- if( !MsgResException->Flags ) {
- /* we've got an ansi string */
- DPRINT("MsgResException->Text=%s\n",
(PSTR)MsgResException->Text);
- RtlInitAnsiString(&ExcMessageA, MsgResException->Text);
- }
- else {
- /* we've got a unicode string */
- DPRINT("MsgResException->Text=%S\n",
(PWSTR)MsgResException->Text);
- RtlInitUnicodeString(&ExcMessageU,
(PWSTR)MsgResException->Text);
- RtlUnicodeStringToAnsiString(&ExcMessageA, &ExcMessageU,
TRUE);
- }
-
- MessageBody = (LPSTR)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, MsgResException->Length+SizeOfAllUnicodeStrings+1024); // 1024 is a
magic number I think it should be enough
- if( STATUS_ACCESS_VIOLATION == ParameterList[0] ) {
- LPSTR pOperationType;
- if( ParameterList[2] ) pOperationType = "written";
- else pOperationType = "read";
- wsprintfA(MessageBody, ExcMessageA.Buffer, ParameterList[1],
ParameterList[3], pOperationType);
- }
- else if( STATUS_IN_PAGE_ERROR == ParameterList[0] ) {
- wsprintfA(MessageBody, ExcMessageA.Buffer, ParameterList[1],
ParameterList[3], ParameterList[2]);
- }
- }
- if( !MessageBody ) {
- NtStatusString = (LPSTR)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, MessageResource->Length-CaptionSize);
- RtlCopyMemory(NtStatusString, MessageA.Buffer+CaptionSize,
(MessageResource->Length-CaptionSize)-1);
-
- MessageBody = (LPSTR)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, MessageResource->Length+SizeOfAllUnicodeStrings+1024); // 1024 is a
magic number I think it should be enough
-
- wsprintfA(MessageBody, NtStatusString,
- L"Unknown software exception",
- ParameterList[0],
- ParameterList[1]);
-
- RtlFreeHeap (RtlGetProcessHeap(), 0, NtStatusString);
- }
- }
- else
- {
- NtStatusString = (LPSTR)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, MessageResource->Length-CaptionSize);
- RtlCopyMemory(NtStatusString, MessageA.Buffer+CaptionSize,
(MessageResource->Length-CaptionSize)-1);
-
- MessageBody = (LPSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
MessageResource->Length+SizeOfAllUnicodeStrings+1024); // 1024 is a magic number I
think it should be enough
-
- wsprintfA(MessageBody, NtStatusString,
- ParameterList[0],
- ParameterList[1],
- ParameterList[2],
- ParameterList[3]);
-
- RtlFreeHeap (RtlGetProcessHeap(), 0, NtStatusString);
- }
- if( MessageResource->Flags ) {
- /* we've got a unicode string */
- RtlFreeAnsiString(&MessageA);
- }
- }
- if( ClientFileNameU.Buffer ) {
- RtlFreeHeap (RtlGetProcessHeap(), 0, ClientFileNameU.Buffer);
- }
-
- szxMessageBody = (LPWSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(wchar_t)*(strlen(MessageBody)+1));
- wsprintfW(szxMessageBody, L"%hs", MessageBody);
- RtlFreeHeap (RtlGetProcessHeap(), 0, MessageBody);
-
- switch ( HardErrorMessage->ValidResponseOptions )
- {
- case OptionAbortRetryIgnore:
- responce = MB_ABORTRETRYIGNORE;
- break;
-
- case OptionOk:
- responce = MB_OK;
- break;
-
- case OptionOkCancel:
- responce = MB_OKCANCEL;
- break;
-
- case OptionRetryCancel:
- responce = MB_RETRYCANCEL;
- break;
-
- case OptionYesNo:
- responce = MB_YESNO;
- break;
-
- case OptionYesNoCancel:
- responce = MB_YESNOCANCEL;
- break;
-
- case OptionShutdownSystem:
- // XZ??
- break;
-
- default:
- DPRINT1("Wrong option: ValidResponseOptions = %d\n",
HardErrorMessage->ValidResponseOptions);
- ASSERT(FALSE);
- break;
- }
-
- // FIXME: We should not use MessageBox !!!!
- DPRINT1("%S\n", szxMessageBody);
- MessageBoxResponse = MessageBoxW(0, szxMessageBody, szxCaptionText,
responce|MB_ICONERROR|MB_SYSTEMMODAL|MB_SETFOREGROUND);
-
- RtlFreeHeap (RtlGetProcessHeap(), 0, szxMessageBody);
- RtlFreeHeap (RtlGetProcessHeap(), 0, szxCaptionText);
-
- switch( MessageBoxResponse )
- {
- case IDOK:
- HardErrorMessage->Response = ResponseOk;
- break;
-
- case IDCANCEL:
- HardErrorMessage->Response = ResponseCancel;
- break;
-
- case IDYES:
- HardErrorMessage->Response = ResponseYes;
- break;
-
- case IDNO:
- HardErrorMessage->Response = ResponseNo;
- break;
-
- case IDABORT:
- HardErrorMessage->Response = ResponseAbort;
- break;
-
- case IDIGNORE:
- HardErrorMessage->Response = ResponseIgnore;
- break;
-
- case IDRETRY:
- HardErrorMessage->Response = ResponseRetry;
- break;
-
- case 10://IDTRYAGAIN:
- HardErrorMessage->Response = ResponseTryAgain;
- break;
-
- case 11://IDCONTINUE:
- HardErrorMessage->Response = ResponseContinue;
- break;
-
- default:
- ASSERT(FALSE);
- break;
- }
-
- return TRUE;
-}
-
-
BOOL WINAPI
Win32CsrInitialization(PCSRSS_API_DEFINITION *ApiDefinitions,
PCSRSS_OBJECT_DEFINITION *ObjectDefinitions,
Added: trunk/reactos/subsystems/win32/csrss/win32csr/harderror.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/win…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/win32csr/harderror.c (added)
+++ trunk/reactos/subsystems/win32/csrss/win32csr/harderror.c [iso-8859-1] Mon Apr 26
03:23:21 2010
@@ -1,0 +1,552 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS system libraries
+ * FILE: subsys/csrss/win32csr/dllmain.c
+ * PURPOSE: Initialization
+ * PROGRAMMERS: Dmitry Philippov (shedon(a)mail.ru)
+ * Timo Kreuzer (timo.kreuzer(a)reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#define NDEBUG
+#include "w32csr.h"
+#include <debug.h>
+#include <strsafe.h>
+
+#define IDTRYAGAIN 10
+#define IDCONTINUE 11
+
+/* FUNCTIONS *****************************************************************/
+
+static
+NTSTATUS
+CsrpGetClientFileName(
+ OUT PUNICODE_STRING ClientFileNameU,
+ 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 */
+ ClientFileNameU->MaximumLength = 0;
+ ClientFileNameU->Length = 0;
+ ClientFileNameU->Buffer = NULL;
+
+ /* Query process information */
+ Status = NtQueryInformationProcess(hProcess,
+ ProcessBasicInformation,
+ &ClientBasicInfo,
+ sizeof(ClientBasicInfo),
+ NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ 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);
+
+ Status = NtReadVirtualMemory(hProcess,
+ ModuleData.BaseDllName.Buffer,
+ ClientFileNameU->Buffer,
+ ClientFileNameU->MaximumLength,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, ClientFileNameU->Buffer);
+ ClientFileNameU->Buffer = NULL;
+ ClientFileNameU->MaximumLength = 0;
+ return Status;
+ }
+
+ ClientFileNameU->Length = wcslen(ClientFileNameU->Buffer)*sizeof(wchar_t);
+ DPRINT("ClientFileNameU=\'%wZ\'\n", &ClientFileNameU);
+
+ return STATUS_SUCCESS;
+}
+
+
+static
+NTSTATUS
+CsrpCaptureStringParameters(
+ OUT PULONG_PTR Parameters,
+ OUT PULONG SizeOfAllUnicodeStrings,
+ IN PHARDERROR_MSG HardErrorMessage,
+ HANDLE hProcess)
+{
+ ULONG nParam, UnicodeStringParameterMask, Size = 0;
+ NTSTATUS Status;
+ UNICODE_STRING TempStringU;
+ PWSTR ParamString;
+
+ UnicodeStringParameterMask = HardErrorMessage->UnicodeStringParameterMask;
+
+ /* Read all strings from client space */
+ for (nParam = 0;
+ nParam < HardErrorMessage->NumberOfParameters;
+ nParam++, UnicodeStringParameterMask >>= 1)
+ {
+ Parameters[nParam] = 0;
+
+ /* Check if the current parameter is a unicode string */
+ if (UnicodeStringParameterMask & 0x01)
+ {
+ /* Read the UNICODE_STRING from the process memory */
+ Status = NtReadVirtualMemory(hProcess,
+ (PVOID)HardErrorMessage->Parameters[nParam],
+ &TempStringU,
+ sizeof(TempStringU),
+ NULL);
+
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Allocate a buffer for the string */
+ ParamString = RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ TempStringU.Length + sizeof(WCHAR));
+
+ if (!ParamString)
+ {
+ DPRINT1("Cannot allocate memory %d\n", TempStringU.Length);
+ return STATUS_NO_MEMORY;
+ }
+
+ /* Read the string buffer from the process memory */
+ Status = NtReadVirtualMemory(hProcess,
+ TempStringU.Buffer,
+ ParamString,
+ TempStringU.Length,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtReadVirtualMemory failed with code: %lx\n",
Status);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, ParamString);
+ return Status;
+ }
+
+ /* Zero terminate the string */
+ ParamString[TempStringU.Length / sizeof(WCHAR)] = 0;
+ DPRINT("ParamString=\'%S\'\n", ParamString);
+
+ Parameters[nParam] = (ULONG_PTR)ParamString;
+ Size += TempStringU.Length;
+ }
+ else
+ {
+ /* It's not a unicode string */
+ Parameters[nParam] = HardErrorMessage->Parameters[nParam];
+ }
+ }
+
+ *SizeOfAllUnicodeStrings = Size;
+ return STATUS_SUCCESS;
+}
+
+static
+VOID
+CsrpFreeStringParameters(
+ IN OUT PULONG_PTR Parameters,
+ IN PHARDERROR_MSG HardErrorMessage)
+{
+ ULONG nParam, UnicodeStringParameterMask;
+
+ UnicodeStringParameterMask = HardErrorMessage->UnicodeStringParameterMask;
+
+ /* Loop all parameters */
+ for (nParam = 0;
+ nParam < HardErrorMessage->NumberOfParameters;
+ nParam++, UnicodeStringParameterMask >>= 1)
+ {
+ /* Check if the current parameter is a string */
+ if (UnicodeStringParameterMask & 0x01)
+ {
+ /* Free the string buffer */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)Parameters[nParam]);
+ }
+ }
+}
+
+
+static
+NTSTATUS
+CsrpFormatMessages(
+ OUT PUNICODE_STRING TextStringU,
+ OUT PUNICODE_STRING CaptionStringU,
+ IN PULONG_PTR Parameters,
+ IN ULONG SizeOfStrings,
+ IN PHARDERROR_MSG Message,
+ IN HANDLE hProcess)
+{
+ NTSTATUS Status;
+ UNICODE_STRING FileNameU, TempStringU, FormatU;
+ ANSI_STRING FormatA;
+ PRTL_MESSAGE_RESOURCE_ENTRY MessageResource;
+ PWSTR FormatString;
+ ULONG Size;
+
+ /* Get the file name of the client process */
+ CsrpGetClientFileName(&FileNameU, hProcess);
+
+ /* Check if we have a file name */
+ if (!FileNameU.Buffer)
+ {
+ /* No, use system */
+ RtlInitUnicodeString(&FileNameU, L"System");
+ }
+
+ /* Get text string of the error code */
+ Status = RtlFindMessage(GetModuleHandleW(L"ntdll"),
+ (ULONG_PTR)RT_MESSAGETABLE,
+ LANG_NEUTRAL,
+ Message->Status,
+ &MessageResource);
+
+ if (NT_SUCCESS(Status))
+ {
+ if (MessageResource->Flags)
+ {
+ RtlInitUnicodeString(&FormatU, (PWSTR)MessageResource->Text);
+ FormatA.Buffer = NULL;
+ }
+ else
+ {
+ RtlInitAnsiString(&FormatA, MessageResource->Text);
+ RtlAnsiStringToUnicodeString(&FormatU, &FormatA, TRUE);
+ }
+ }
+ else
+ {
+ /* Fall back to hardcoded value */
+ RtlInitUnicodeString(&FormatU, L"Unknown Hard Error");
+ FormatA.Buffer = NULL;
+ }
+
+ FormatString = FormatU.Buffer;
+
+ /* Check whether a caption exists */
+ if (FormatString[0] == L'{')
+ {
+ /* Set caption start */
+ TempStringU.Buffer = ++FormatString;
+
+ /* Get size of the caption */
+ for (Size = 0; *FormatString != 0 && *FormatString != L'}';
Size++)
+ FormatString++;
+
+ /* Skip '}', '\r', '\n' */
+ FormatString += 3;
+
+ TempStringU.Length = Size * sizeof(WCHAR);
+ TempStringU.MaximumLength = TempStringU.Length;
+ }
+ else
+ {
+ /* FIXME: Set string based on severity */
+ RtlInitUnicodeString(&TempStringU, L"Application Error");
+ }
+
+ /* Calculate buffer length for the caption */
+ CaptionStringU->MaximumLength = FileNameU.Length + TempStringU.Length +
+ 4 * sizeof(WCHAR);
+
+ /* Allocate a buffer for the caption */
+ CaptionStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ CaptionStringU->MaximumLength);
+
+ /* Append the file name, seperator and the caption text */
+ CaptionStringU->Length = 0;
+ RtlAppendUnicodeStringToString(CaptionStringU, &FileNameU);
+ RtlAppendUnicodeToString(CaptionStringU, L" - ");
+ RtlAppendUnicodeStringToString(CaptionStringU, &TempStringU);
+
+ /* Zero terminate the buffer */
+ CaptionStringU->Buffer[CaptionStringU->Length] = 0;
+
+ /* Free the file name buffer */
+ RtlFreeUnicodeString(&FileNameU);
+
+ /* Check if this is an exception message */
+ if (Message->Status == STATUS_UNHANDLED_EXCEPTION)
+ {
+ /* Handle special cases */
+ if (Parameters[0] == STATUS_ACCESS_VIOLATION)
+ {
+ Parameters[0] = Parameters[1];
+ Parameters[1] = Parameters[3];
+ if (Parameters[2]) Parameters[2] = (ULONG_PTR)L"written";
+ else Parameters[2] = (ULONG_PTR)L"read";
+ MessageResource = NULL;
+ }
+ else if (Parameters[0] == STATUS_IN_PAGE_ERROR)
+ {
+ Parameters[0] = Parameters[1];
+ Parameters[1] = Parameters[3];
+ MessageResource = NULL;
+ }
+ else
+ {
+ /* Fall back to hardcoded value */
+ Parameters[2] = Parameters[1];
+ Parameters[1] = Parameters[0];
+ Parameters[0] = (ULONG_PTR)L"unknown software exception";
+ }
+
+ if (!MessageResource)
+ {
+ /* Get text string of the exception code */
+ Status = RtlFindMessage(GetModuleHandleW(L"ntdll"),
+ (ULONG_PTR)RT_MESSAGETABLE,
+ LANG_NEUTRAL,
+ Parameters[0],
+ &MessageResource);
+
+ if (NT_SUCCESS(Status))
+ {
+ if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU);
+
+ if (MessageResource->Flags)
+ {
+ RtlInitUnicodeString(&FormatU, (PWSTR)MessageResource->Text);
+ FormatA.Buffer = NULL;
+ }
+ else
+ {
+ RtlInitAnsiString(&FormatA, MessageResource->Text);
+ RtlAnsiStringToUnicodeString(&FormatU, &FormatA, TRUE);
+ }
+ }
+ else
+ {
+ /* Fall back to hardcoded value */
+ Parameters[2] = Parameters[1];
+ Parameters[1] = Parameters[0];
+ Parameters[0] = (ULONG_PTR)L"unknown software exception";
+ }
+ }
+ }
+
+ /* Calculate length of text buffer */
+ TextStringU->MaximumLength = wcslen(FormatString) * sizeof(WCHAR) +
+ SizeOfStrings + 42 * sizeof(WCHAR);
+
+ /* Allocate a buffer for the text */
+ TextStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ TextStringU->MaximumLength);
+
+ /* Wrap in SEH to protect from invalid string parameters */
+ _SEH2_TRY
+ {
+ /* Print the string into the buffer */
+ StringCbPrintfW(TextStringU->Buffer,
+ TextStringU->MaximumLength,
+ FormatString,
+ Parameters[0],
+ Parameters[1],
+ Parameters[2],
+ Parameters[3],
+ Parameters[4]);
+ Status = STATUS_SUCCESS;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Set error and free buffers */
+ Status = _SEH2_GetExceptionCode();
+ RtlFreeHeap(RtlGetProcessHeap(), 0, TextStringU->Buffer);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, CaptionStringU->Buffer);
+ }
+ _SEH2_END
+
+ if (NT_SUCCESS(Status))
+ {
+ TextStringU->Length = wcslen(TextStringU->Buffer) * sizeof(WCHAR);
+ }
+
+ if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU);
+
+ return Status;
+}
+
+static
+ULONG
+CsrpMessageBox(
+ PWSTR Text,
+ PWSTR Caption,
+ ULONG ValidResponseOptions,
+ ULONG Severity)
+{
+ ULONG Type, MessageBoxResponse;
+
+ /* Set the message box type */
+ switch (ValidResponseOptions)
+ {
+ 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;
+ /* Anything else is invalid */
+ default:
+ return ResponseNotHandled;
+ }
+
+ /* Set severity */
+ 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 */
+ MessageBoxResponse = MessageBoxW(0, Text, Caption, Type);
+
+ /* Return response value */
+ switch (MessageBoxResponse)
+ {
+ case IDOK: return ResponseOk;
+ case IDCANCEL: return ResponseCancel;
+ case IDYES: return ResponseYes;
+ case IDNO: return ResponseNo;
+ case IDABORT: return ResponseAbort;
+ case IDIGNORE: return ResponseIgnore;
+ case IDRETRY: return ResponseRetry;
+ case IDTRYAGAIN: return ResponseTryAgain;
+ case IDCONTINUE: return ResponseContinue;
+ }
+
+ return ResponseNotHandled;
+}
+
+BOOL
+WINAPI
+Win32CsrHardError(
+ IN PCSRSS_PROCESS_DATA ProcessData,
+ IN PHARDERROR_MSG Message)
+{
+ ULONG_PTR Parameters[MAXIMUM_HARDERROR_PARAMETERS];
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING TextU, CaptionU;
+ NTSTATUS Status;
+ HANDLE hProcess;
+ ULONG Size;
+
+ /* Default to not handled */
+ Message->Response = ResponseNotHandled;
+
+ /* Make sure we don't have too many parameters */
+ if (Message->NumberOfParameters > MAXIMUM_HARDERROR_PARAMETERS)
+ Message->NumberOfParameters = MAXIMUM_HARDERROR_PARAMETERS;
+
+ /* Initialize object attributes */
+ InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
+
+ /* Open client process */
+ Status = NtOpenProcess(&hProcess,
+ PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
+ &ObjectAttributes,
+ &Message->h.ClientId);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtOpenProcess failed with code: %lx\n", Status);
+ return FALSE;
+ }
+
+ /* Capture all string parameters from the process memory */
+ Status = CsrpCaptureStringParameters(Parameters, &Size, Message, hProcess);
+ if (!NT_SUCCESS(Status))
+ {
+ NtClose(hProcess);
+ return FALSE;
+ }
+
+ /* Format the caption and message box text */
+ Status = CsrpFormatMessages(&TextU,
+ &CaptionU,
+ Parameters,
+ Size,
+ Message,
+ hProcess);
+
+ /* Cleanup */
+ CsrpFreeStringParameters(Parameters, Message);
+ NtClose(hProcess);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return FALSE;
+ }
+
+ /* Display the message box */
+ Message->Response = CsrpMessageBox(TextU.Buffer,
+ CaptionU.Buffer,
+ Message->ValidResponseOptions,
+ (ULONG)Message->Status >> 30);
+
+ RtlFreeUnicodeString(&TextU);
+ RtlFreeUnicodeString(&CaptionU);
+
+ return TRUE;
+}
+
Propchange: trunk/reactos/subsystems/win32/csrss/win32csr/harderror.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/subsystems/win32/csrss/win32csr/w32csr.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/win…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/win32csr/w32csr.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/win32csr/w32csr.h [iso-8859-1] Mon Apr 26
03:23:21 2010
@@ -35,4 +35,11 @@
/* shared header with console.dll */
#include "console.h"
+
+BOOL
+WINAPI
+Win32CsrHardError(
+ IN PCSRSS_PROCESS_DATA ProcessData,
+ IN PHARDERROR_MSG Message);
+
/* EOF */
Modified: trunk/reactos/subsystems/win32/csrss/win32csr/win32csr.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/win…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/win32csr/win32csr.rbuild [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/win32csr/win32csr.rbuild [iso-8859-1] Mon Apr 26
03:23:21 2010
@@ -14,6 +14,7 @@
<library>advapi32</library>
<library>win32ksys</library>
<library>psapi</library>
+ <library>pseh</library>
<pch>w32csr.h</pch>
<file>alias.c</file>
<file>conio.c</file>
@@ -21,6 +22,7 @@
<file>dllmain.c</file>
<file>exitros.c</file>
<file>guiconsole.c</file>
+ <file>harderror.c</file>
<file>tuiconsole.c</file>
<file>appswitch.c</file>
<file>win32csr.rc</file>