Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <csignal>
- #include <Windows.h>
- #include <Dbghelp.h>
- #include <crtdbg.h>
- // Путь к программе. Инициализируется на старте.
- static wchar_t appPath[MAX_PATH];
- // Функция, которая пишет дамп в файл |fileName|.
- static bool make_dump(EXCEPTION_POINTERS* e, const wchar_t* fileName) {
- // Грузим системную библиотеку создания дампов.
- // Возможно её не будет в системе, тогда надо положить её рядом с программой.
- auto hDbgHelp = LoadLibraryW(L"dbghelp.dll");
- if (!hDbgHelp)
- return false;
- auto pMiniDumpWriteDump =
- (decltype(&MiniDumpWriteDump))GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
- if (!pMiniDumpWriteDump)
- return false;
- // Открываем файл.
- HANDLE hFile = ::CreateFileW(fileName, GENERIC_WRITE, FILE_SHARE_READ, 0,
- CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
- if (hFile == INVALID_HANDLE_VALUE || hFile == nullptr)
- return false;
- MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
- exceptionInfo.ThreadId = ::GetCurrentThreadId();
- exceptionInfo.ExceptionPointers = e;
- exceptionInfo.ClientPointers = FALSE;
- const DWORD DUMP_FLAGS = MiniDumpWithDataSegs | MiniDumpWithPrivateReadWriteMemory;
- // Пишем дамп в файл.
- BOOL dumped = pMiniDumpWriteDump(
- ::GetCurrentProcess(),
- ::GetCurrentProcessId(),
- hFile,
- MINIDUMP_TYPE(DUMP_FLAGS),
- e ? &exceptionInfo : NULL,
- NULL,
- NULL);
- // Если не удалось сделать дамп - пишем ошибку.
- if (!dumped) {
- DWORD err = GetLastError();
- DWORD written;
- ::WriteFile(hFile, &err, 4, &written, 0);
- }
- ::CloseHandle(hFile);
- return true;
- }
- // Старый обработчик исключений.
- static LPTOP_LEVEL_EXCEPTION_FILTER s_oldEH;
- // Наш обработчик исключений.
- static LONG CALLBACK unhandled_exception_handler(EXCEPTION_POINTERS* e) {
- // Формируем имя файла.
- SYSTEMTIME t;
- GetSystemTime(&t);
- static wchar_t fileName[1024];
- wsprintfW(fileName, L"%s\dump_%d%02d%02d_%02d%02d%02d.dmp", appPath,
- t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
- // Пишем дамп в файл.
- auto dumpOk = make_dump(e, fileName);
- // Если он не записался, передаем исключение дальше.
- if (!dumpOk)
- return s_oldEH ? s_oldEH(e) : EXCEPTION_CONTINUE_SEARCH;
- // Показываем пользователю куда записался дамп.
- static wchar_t buf[1024];
- wsprintfW(buf,
- L"Application will be closed due to a fatal error.rn"
- L"Crash dump was saved torn%s",
- fileName);
- MessageBox(nullptr, buf, nullptr, MB_ICONERROR | MB_OK);
- // Убиваем процесс.
- ::TerminateProcess(::GetCurrentProcess(), 5);
- return 0;
- }
- // Обработка |abort()|.
- static void abort_handler(int) {
- ::RaiseException(0x00BAD00A, 0, 0, NULL);
- }
- // Обработка вызова pure virtual функции.
- static void purecall_handler() {
- ::RaiseException(0x00BAD00C, 0, 0, NULL);
- }
- // Еще какие-то ошибки CRT.
- static int crt_report_handler(int reportType, wchar_t*, int* pRet) {
- if (reportType == _CRT_WARN) {
- if (pRet)
- *pRet = 0;
- return 0;
- }
- ::RaiseException(0x00BAD00E, 0, 0, NULL);
- return 0;
- }
- // Функция инициализации.
- static void init() {
- // Сохраняем путь к .exe , на случай если креш не даст его получить потом.
- ::GetModuleFileNameW(GetModuleHandle(nullptr), appPath, MAX_PATH);
- // Обрезаем до папки.
- *wcsrchr(appPath, L'\') = '