[ros-diffs] [tkreuzer] 47027: [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.

tkreuzer at svn.reactos.org tkreuzer at svn.reactos.org
Mon Apr 26 03:23:21 CEST 2010


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/win32csr/dllmain.c?rev=47027&r1=47026&r2=47027&view=diff
==============================================================================
--- 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/win32csr/harderror.c?rev=47027&view=auto
==============================================================================
--- 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 at mail.ru)
+ *                  Timo Kreuzer (timo.kreuzer at 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/win32csr/w32csr.h?rev=47027&r1=47026&r2=47027&view=diff
==============================================================================
--- 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/win32csr/win32csr.rbuild?rev=47027&r1=47026&r2=47027&view=diff
==============================================================================
--- 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>




More information about the Ros-diffs mailing list