Starting with VC8 (VS2005) it is not possible to catch all unhandled exceptions with your installed exception-filter (via SetUnhandledExceptionFilter). In some situations, the CRT forces the call of WER (Windows Error Reporting). One situation (/GS buffer overruns) can never be catched in your filter. If you want to catch all exception inside your filter, you need to intercept calls to SetUnhandledExceptionFilter to prevent the removing of all previous installed filters.
See also my previous post about this problem:
“SetUnhandledExceptionFilter” and VC8″
Here is the code to “hook” the SetUnhandledExceptionFilter which works now for x86 and x64:
#include
#include
#include
#if defined _M_X64 || defined _M_IX86
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI
MyDummySetUnhandledExceptionFilter(
LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
{
return NULL;
}
#else
#error "This code works only for x86 and x64!"
#endif
BOOL PreventSetUnhandledExceptionFilter()
{
HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
if (hKernel32 == NULL) return FALSE;
void *pOrgEntry = GetProcAddress(hKernel32,
"SetUnhandledExceptionFilter");
if(pOrgEntry == NULL) return FALSE;
DWORD dwOldProtect = 0;
SIZE_T jmpSize = 5;
#ifdef _M_X64
jmpSize = 13;
#endif
BOOL bProt = VirtualProtect(pOrgEntry, jmpSize,
PAGE_EXECUTE_READWRITE, &dwOldProtect);
BYTE newJump[20];
void *pNewFunc = &MyDummySetUnhandledExceptionFilter;
#ifdef _M_IX86
DWORD dwOrgEntryAddr = (DWORD) pOrgEntry;
dwOrgEntryAddr += jmpSize; // add 5 for 5 op-codes for jmp rel32
DWORD dwNewEntryAddr = (DWORD) pNewFunc;
DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr;
// JMP rel32: Jump near, relative, displacement relative to next instruction.
newJump[0] = 0xE9; // JMP rel32
memcpy(&newJump[1], &dwRelativeAddr, sizeof(pNewFunc));
#elif _M_X64
// We must use R10 or R11, because these are "scratch" registers
// which need not to be preserved accross function calls
// For more info see: Register Usage for x64 64-Bit
// http://msdn.microsoft.com/en-us/library/ms794547.aspx
// Thanks to Matthew Smith!!!
newJump[0] = 0x49; // MOV R11, ...
newJump[1] = 0xBB; // ...
memcpy(&newJump[2], &pNewFunc, sizeof (pNewFunc));
//pCur += sizeof (ULONG_PTR);
newJump[10] = 0x41; // JMP R11, ...
newJump[11] = 0xFF; // ...
newJump[12] = 0xE3; // ...
#endif
SIZE_T bytesWritten;
BOOL bRet = WriteProcessMemory(GetCurrentProcess(),
pOrgEntry, newJump, jmpSize, &bytesWritten);
if (bProt != FALSE)
{
DWORD dwBuf;
VirtualProtect(pOrgEntry, jmpSize, dwOldProtect, &dwBuf);
}
return bRet;
}
LONG WINAPI MyUnhandledExceptionFilter(
struct _EXCEPTION_POINTERS *lpTopLevelExceptionFilter)
{
// TODO: MiniDumpWriteDump
FatalAppExit(0, _T("Unhandled Exception occured!"));
return EXCEPTION_CONTINUE_SEARCH;
}
int _tmain()
{
SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
BOOL bRet = PreventSetUnhandledExceptionFilter();
_tprintf(_T("Prevented: %d"), bRet);
abort(); // force Dr.Watson in release!
}