#pragma once #include #include #include namespace HBD { void CreateDumpFile(LPCWSTR lpstrDumpFilePathName, EXCEPTION_POINTERS *pException) { HANDLE hDumpFile = CreateFileW(lpstrDumpFilePathName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); MINIDUMP_EXCEPTION_INFORMATION dumpInfo; dumpInfo.ExceptionPointers = pException; dumpInfo.ThreadId = GetCurrentThreadId(); dumpInfo.ClientPointers = TRUE; MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL); CloseHandle(hDumpFile); } LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) { return NULL; } 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 UnhandledExceptionFilterEx(struct _EXCEPTION_POINTERS *pException) { WCHAR szMbsFile[MAX_PATH] = { 0 }; ::GetModuleFileNameW(NULL, szMbsFile, MAX_PATH); WCHAR* pFind = wcsrchr(szMbsFile, '\\'); if (pFind) { *(pFind + 1) = 0; SYSTEMTIME stLocalTime; GetLocalTime(&stLocalTime); WCHAR buffer[1024]; wsprintfW(buffer, L"%04d%02d%02d-%02d%02d%02d.dmp", stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond); wcscat(szMbsFile, buffer); CreateDumpFile(szMbsFile, pException); } return EXCEPTION_CONTINUE_SEARCH; } void RunCrashHandler() { SetUnhandledExceptionFilter(UnhandledExceptionFilterEx); PreventSetUnhandledExceptionFilter(); } };