Improved “PreventSetUnhandledExceptionFilter”

Starting with VS2005(VC8) it was not possible to handle all exceptions in process. I have discussed this in “SetUnhandledExceptionFilter” and VC8 and in Unhandled exceptions in VC8 and above… for x86 and x64.

It seemms that the code I posted had been used in many Projects to handle all exceptions and to write a minidump in that case. Also someone has used it in a VB6 application and for this he needed to implement this function in a separate “CrashHandler.dll”. But now he got errors during the shutdown of the VB6 application. It seems that VB6 unloads the DLL before other DLLs and it seems that some other DLL is calling “SetUnhandledExceptionFilter” during shutown. This now leads to trouble, because the DLL is already unloaded.

Now I created a better and cleaner implementation for the “PreventSetUnhandledExceptionFilter” function, which also works in any situation, even if the DLL was unloaded 😉

static BOOL PreventSetUnhandledExceptionFilter()
{
  HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
  if (hKernel32 == NULL) return FALSE;
  void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter");
  if (pOrgEntry == NULL) return FALSE;

#ifdef _M_IX86
  // Code for x86:
  // 33 C0                xor         eax,eax  
  // C2 04 00             ret         4 
  unsigned char szExecute[] = { 0x33, 0xC0, 0xC2, 0x04, 0x00 };
#elif _M_X64
  // 33 C0                xor         eax,eax 
  // C3                   ret  
  unsigned char szExecute[] = { 0x33, 0xC0, 0xC3 };
#else
#error "The following code only works for x86 and x64!"
#endif

  SIZE_T bytesWritten = 0;
  BOOL bRet = WriteProcessMemory(GetCurrentProcess(),
    pOrgEntry, szExecute, sizeof(szExecute), &bytesWritten);
  return bRet;
}

18 thoughts on “Improved “PreventSetUnhandledExceptionFilter”

  1. Anantha

    Hi ,
    abort ( ) is still not caught by this code in Windows 8 . Is it a known thing ? Any pointers for some work-around ?

    1. jkalmbach Post author

      This has nothing to do with the OS…. it is compiler dependend… In VS2012, the debug version exits the process automatically (exit(3)); the release version is calling the UnhandledExceptionHandler. You can change the abort mode by calling “_set_abort_behavior” in debug. This will also force the executing of the handler. The following code solves this issue:

      
      static LONG WINAPI MyHandler(__in struct _EXCEPTION_POINTERS *ExceptionInfo)
      {
        printf("Handler called\r\n");
        return EXCEPTION_CONTINUE_SEARCH;
      }
      int _tmain()
      {
        SetUnhandledExceptionFilter(&MyHandler);
        PreventSetUnhandledExceptionFilter();
      
      #ifdef _DEBUG
        _set_abort_behavior(0, _WRITE_ABORT_MSG);
        _set_abort_behavior(_CALL_REPORTFAULT, _CALL_REPORTFAULT);
      #endif
      
        abort();
      }
      1. Anantha

        Yes , I am using VS 2012 . The release version binary ( i hardcore abort ( ) for testing ) when i run it in win 7 , vista , xp is being caught by the Exception Handler but in windows 8 , WER dialog appears saying the application has stopped working asking to close the program . I try using signal handler and it works perfectly . Any idea ? why would abort alone fail ? because i tried null ptr exception and rest , those are caught .

  2. jkalmbach Post author

    Now I understand your problem….
    If you take a look at the CRT source code you see:

    if (IsProcessorFeaturePresent(PF_FASTFAIL_AVAILABLE))
    __fastfail(FAST_FAIL_FATAL_APP_EXIT);

    It seems that this is only present in Win8… and “__fastfail” is a Win32 method… which directly forces WER…

    1. Anantha

      Great Find jkalmbach ,
      Is there a way to unregister or suppress this fast fail by any means ?

  3. jkalmbach Post author

    You need to register an abort handler… that is currently the only way to catch the “abort” on Windows 8…

    Also be aware that you can catch local dumps by registering your app in the registry: http://msdn.microsoft.com/en-us/library/windows/desktop/bb787181

    This is the “recommended” way of getting dumps from a crash… I hope that this will also create a dump for “__fastfail”; but I have not yet tested it…

  4. Anantha

    Thanks a bunch for the immediate help rendered ! Will resort to signal handler but will not be able to write dumps . The local user mode dumps may help here. will look into it .

  5. lkkqoo

    The code work well in debug version.
    But it can’t use in release version program.
    I use vc6 and Windows XP.
    If i disable the optimization of the compiler in release mode, then it can work again.
    Is that right?
    Thanks a lot.

    1. jkalmbach Post author

      I do not think that this has something to do with compiler settings….

  6. Ananth

    To add , heap corruption cannot be caught by this filter. Any fix for this ?

  7. Raphael

    Hi ~ jkalmbach

    First of all, thank you for your posting.
    I wrote win32-app for jobs and also added minidump for tracing bugs. (v110 (visual studio) )
    but I don’t catch unhandled exceptions so called EXCEPTION_ACESS_VIOLATION c0000005.
    I called SetUnhandledExceptionFilter with callback for generating .dmp file,
    PreventSetUnhandledExceptionFilter (just copy & paste) which returned T.
    and then generated exception with c0000005 for checking. But I didn’t handle unhandled exceptions.

    if you know the solve for resolving it, let me know that.

    Thanks,
    Raphael

    1. jkalmbach Post author

      The following code works for me:
      int _tmain()
      {
      SetUnhandledExceptionFilter(&MyHandler);
      PreventSetUnhandledExceptionFilter();

      strcpy(NULL, "TEST");
      }

      1. Raphael

        HI~
        thank you for your post.
        I checked a case you posted is okay. In another case, WER(Windows Error Reporting) captured exception in my test case, before processing unhandle-callback for generating .dmp in user process.

        ===> Not try to call unhandled exception callback (MyHandler) by WER.

        –> below is my test-case.

        chat test[65];
        int main()
        {
        int k;
        SetUnhandledExceptionFilter(&MyHandler);
        PreventSetUnhandledExceptionFilter();
        for(k=0; k<1000000; k++)
        test[k] = 65;
        }

        if you know the method to solve it, let me know it.

        Thanks,
        Rephael.

  8. BaiYang

    Why use LoadLibrary and GetProcAddress? We can use “&SetUnhandledExceptionFilter” directly because this API has been exists since Win95 🙂

    1. jkalmbach Post author

      Good question… the code still compiles with VS95 😉 But you can directly use “&SetUnhandledExceptionFilter” instead of using GetProcAddress…

Comments are closed.