Merge trunk head (r43756)
[reactos.git] / reactos / dll / win32 / kernel32 / except / except.c
index 5691f53..fda2e4b 100644 (file)
@@ -15,7 +15,7 @@
 #define NDEBUG
 #include <debug.h>
 
-LPTOP_LEVEL_EXCEPTION_FILTER GlobalTopLevelExceptionFilter = UnhandledExceptionFilter;
+LPTOP_LEVEL_EXCEPTION_FILTER GlobalTopLevelExceptionFilter = NULL;
 
 UINT
 WINAPI
@@ -124,10 +124,11 @@ _module_name_from_addr(const void* addr, void **module_start_addr,
    return psz;
 }
 
-#ifdef _M_IX86
+
 static VOID
 _dump_context(PCONTEXT pc)
 {
+#ifdef _M_IX86
    /*
     * Print out the CPU registers
     */
@@ -138,14 +139,19 @@ _dump_context(PCONTEXT pc)
    DbgPrint("EDX: %.8x   EBP: %.8x   ESI: %.8x   ESP: %.8x\n", pc->Edx,
            pc->Ebp, pc->Esi, pc->Esp);
    DbgPrint("EDI: %.8x   EFLAGS: %.8x\n", pc->Edi, pc->EFlags);
-}
+#elif defined(_M_AMD64)
+   DbgPrint("CS:EIP %x:%I64x\n", pc->SegCs&0xffff, pc->Rip );
+   DbgPrint("DS %x ES %x FS %x GS %x\n", pc->SegDs&0xffff, pc->SegEs&0xffff,
+           pc->SegFs&0xffff, pc->SegGs&0xfff);
+   DbgPrint("RAX: %I64x   RBX: %I64x   RCX: %I64x RDI: %I64x\n", pc->Rax, pc->Rbx, pc->Rcx, pc->Rdi);
+   DbgPrint("RDX: %I64x   RBP: %I64x   RSI: %I64x   RSP: %I64x\n", pc->Rdx, pc->Rbp, pc->Rsi, pc->Rsp);
+   DbgPrint("R8: %I64x   R9: %I64x   R10: %I64x   R11: %I64x\n", pc->R8, pc->R9, pc->R10, pc->R11);
+   DbgPrint("R12: %I64x   R13: %I64x   R14: %I64x   R15: %I64x\n", pc->R12, pc->R13, pc->R14, pc->R15);
+   DbgPrint("EFLAGS: %.8x\n", pc->EFlags);
 #else
 #warning Unknown architecture
-static VOID
-_dump_context(PCONTEXT pc)
-{
-}
 #endif
+}
 
 static LONG
 BasepCheckForReadOnlyResource(IN PVOID Ptr)
@@ -170,7 +176,7 @@ BasepCheckForReadOnlyResource(IN PVOID Ptr)
            use SEH here because we don't know if it's actually a
            resource mapping */
 
-        _SEH_TRY
+        _SEH2_TRY
         {
             Data = RtlImageDirectoryEntryToData(mbi.AllocationBase,
                                                 TRUE,
@@ -195,10 +201,10 @@ BasepCheckForReadOnlyResource(IN PVOID Ptr)
                 }
             }
         }
-        _SEH_HANDLE
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
         }
-        _SEH_END;
+        _SEH2_END;
     }
 
     return Ret;
@@ -207,22 +213,32 @@ BasepCheckForReadOnlyResource(IN PVOID Ptr)
 /*
  * @unimplemented
  */
-LONG STDCALL
+LONG WINAPI
 UnhandledExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
 {
    LONG RetValue;
    HANDLE DebugPort = NULL;
    NTSTATUS ErrCode;
+   ULONG_PTR ErrorParameters[4];
+   ULONG ErrorResponse;
 
-   if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION &&
-       ExceptionInfo->ExceptionRecord->ExceptionInformation[0])
+   if ((NTSTATUS)ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION &&
+       ExceptionInfo->ExceptionRecord->NumberParameters >= 2)
    {
-      /* Change the protection on some write attempts, some InstallShield setups
-         have this bug */
-      RetValue = BasepCheckForReadOnlyResource(
-         (PVOID)ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
-      if (RetValue == EXCEPTION_CONTINUE_EXECUTION)
-         return EXCEPTION_CONTINUE_EXECUTION;
+      switch(ExceptionInfo->ExceptionRecord->ExceptionInformation[0])
+      {
+      case EXCEPTION_WRITE_FAULT:
+         /* Change the protection on some write attempts, some InstallShield setups
+            have this bug */
+         RetValue = BasepCheckForReadOnlyResource(
+            (PVOID)ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
+         if (RetValue == EXCEPTION_CONTINUE_EXECUTION)
+            return EXCEPTION_CONTINUE_EXECUTION;
+         break;
+      case EXCEPTION_EXECUTE_FAULT:
+         /* FIXME */
+         break;
+      }
    }
 
    /* Is there a debugger running ? */
@@ -241,9 +257,16 @@ UnhandledExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
       return EXCEPTION_CONTINUE_SEARCH;
    }
 
+   if (GlobalTopLevelExceptionFilter)
+   {
+      LONG ret = GlobalTopLevelExceptionFilter( ExceptionInfo );
+      if (ret != EXCEPTION_CONTINUE_SEARCH)
+         return ret;
+   }
+
    if ((GetErrorMode() & SEM_NOGPFAULTERRORBOX) == 0)
    {
-#ifdef _X86_
+#ifdef __i386__
       PULONG Frame;
 #endif
       PVOID StartAddr;
@@ -252,7 +275,7 @@ UnhandledExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
       /* Print a stack trace. */
       DbgPrint("Unhandled exception\n");
       DbgPrint("ExceptionCode:    %8x\n", ExceptionInfo->ExceptionRecord->ExceptionCode);
-      if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION &&
+      if ((NTSTATUS)ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION &&
           ExceptionInfo->ExceptionRecord->NumberParameters == 2)
       {
          DbgPrint("Faulting Address: %8x\n", ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
@@ -261,9 +284,9 @@ UnhandledExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
          ExceptionInfo->ExceptionRecord->ExceptionAddress,
          _module_name_from_addr(ExceptionInfo->ExceptionRecord->ExceptionAddress, &StartAddr, szMod, sizeof(szMod)));
       _dump_context ( ExceptionInfo->ContextRecord );
-#ifdef _X86_
+#ifdef __i386__
       DbgPrint("Frames:\n");
-      _SEH_TRY
+      _SEH2_TRY
       {
          Frame = (PULONG)ExceptionInfo->ContextRecord->Ebp;
          while (Frame[1] != 0 && Frame[1] != 0xdeadbeef)
@@ -283,14 +306,42 @@ UnhandledExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
             Frame = (PULONG)Frame[0];
          }
       }
-      _SEH_HANDLE
+      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
       {
-         DbgPrint("<error dumping stack trace: 0x%x>\n", _SEH_GetExceptionCode());
+         DbgPrint("<error dumping stack trace: 0x%x>\n", _SEH2_GetExceptionCode());
       }
-      _SEH_END;
+      _SEH2_END;
 #endif
    }
 
+   /* Save exception code and address */
+   ErrorParameters[0] = (ULONG)ExceptionInfo->ExceptionRecord->ExceptionCode;
+   ErrorParameters[1] = (ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress;
+
+   if ((NTSTATUS)ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION)
+   {
+       /* get the type of operation that caused the access violation */
+       ErrorParameters[2] = ExceptionInfo->ExceptionRecord->ExceptionInformation[0];
+   }
+   else
+   {
+       ErrorParameters[2] = ExceptionInfo->ExceptionRecord->ExceptionInformation[2];
+   }
+
+   /* Save faulting address */
+   ErrorParameters[3] = ExceptionInfo->ExceptionRecord->ExceptionInformation[1];
+
+   /* Raise the harderror */
+   ErrCode = NtRaiseHardError(STATUS_UNHANDLED_EXCEPTION | 0x10000000,
+       4, 0, ErrorParameters, OptionOkCancel, &ErrorResponse);
+
+   if (NT_SUCCESS(ErrCode) && (ErrorResponse == ResponseCancel))
+   {
+       /* FIXME: Check the result, if the "Cancel" button was
+                 clicked run a debugger */
+       DPRINT1("Debugging is not implemented yet\n");
+   }
+
    /*
     * Returning EXCEPTION_EXECUTE_HANDLER means that the code in
     * the __except block will be executed. Normally this will end up in a
@@ -346,6 +397,24 @@ RaiseException(IN DWORD dwExceptionCode,
         }
     }
 
+    if (dwExceptionCode == 0xeedface)
+    {
+        DPRINT1("Delphi Exception at address: %p\n", ExceptionRecord.ExceptionInformation[0]);
+        DPRINT1("Exception-Object: %p\n", ExceptionRecord.ExceptionInformation[1]);
+        DPRINT1("Exception text: %s\n", ExceptionRecord.ExceptionInformation[2]);
+    }
+
+    /* Trace the wine special error and show the modulename and functionname */
+    if (dwExceptionCode == 0x80000100 /*EXCEPTION_WINE_STUB*/)
+    {
+       /* Numbers of parameter must be equal to two */
+       if (ExceptionRecord.NumberParameters == 2)
+       {
+          DPRINT1("Missing function in   : %s\n", ExceptionRecord.ExceptionInformation[0]);
+          DPRINT1("with the functionname : %s\n", ExceptionRecord.ExceptionInformation[1]);
+       }
+    }
+
     /* Raise the exception */
     RtlRaiseException(&ExceptionRecord);
 }