1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
#include "crashdump.h"
#ifdef WIN32
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable:4091) // a microsoft header has warnings. Very nice.
#endif
// clang-format off
#include <windows.h>
#include <dbghelp.h>
// clang-format on
#ifdef _MSC_VER
#pragma warning (pop)
#endif
#include "globalincs/pstypes.h"
void make_minidump(EXCEPTION_POINTERS* e)
{
const auto hDbgHelp = LoadLibraryA("dbghelp");
if (hDbgHelp == nullptr)
return;
const auto pMiniDumpWriteDump = reinterpret_cast<decltype(&MiniDumpWriteDump)>(
reinterpret_cast<void*>(GetProcAddress(hDbgHelp, "MiniDumpWriteDump")));
if (pMiniDumpWriteDump == nullptr)
return;
char name[MAX_PATH];
{
const auto nameEnd = name + GetModuleFileNameA(GetModuleHandleA(nullptr), name, MAX_PATH);
SYSTEMTIME t;
GetSystemTime(&t);
wsprintfA(nameEnd - strlen(".exe"), "_%4d%02d%02d_%02d%02d%02d.mdmp", t.wYear, t.wMonth, t.wDay, t.wHour,
t.wMinute, t.wSecond);
}
const auto hFile = CreateFileA(name, GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE)
return;
MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
exceptionInfo.ThreadId = GetCurrentThreadId();
exceptionInfo.ExceptionPointers = e;
exceptionInfo.ClientPointers = FALSE;
pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile,
MINIDUMP_TYPE(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory),
e ? &exceptionInfo : nullptr, nullptr, nullptr);
CloseHandle(hFile);
mprintf(("CRASH DETECTED!!! Wrote crash dump to %s\n", name));
}
LONG CALLBACK unhandled_handler(EXCEPTION_POINTERS* e)
{
make_minidump(e);
return EXCEPTION_CONTINUE_SEARCH;
}
#endif
namespace crashdump {
void installCrashHandler()
{
#ifdef WIN32
SetUnhandledExceptionFilter(unhandled_handler);
#endif
}
} // namespace crashdump
|