Advertisement
Guest User

Untitled

a guest
Jun 16th, 2019
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.23 KB | None | 0 0
  1. #include <csignal>
  2. #include <Windows.h>
  3. #include <Dbghelp.h>
  4. #include <crtdbg.h>
  5.  
  6. // Путь к программе. Инициализируется на старте.
  7. static wchar_t appPath[MAX_PATH];
  8.  
  9. // Функция, которая пишет дамп в файл |fileName|.
  10. static bool make_dump(EXCEPTION_POINTERS* e, const wchar_t* fileName) {
  11. // Грузим системную библиотеку создания дампов.
  12. // Возможно её не будет в системе, тогда надо положить её рядом с программой.
  13. auto hDbgHelp = LoadLibraryW(L"dbghelp.dll");
  14. if (!hDbgHelp)
  15. return false;
  16.  
  17. auto pMiniDumpWriteDump =
  18. (decltype(&MiniDumpWriteDump))GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
  19. if (!pMiniDumpWriteDump)
  20. return false;
  21.  
  22. // Открываем файл.
  23. HANDLE hFile = ::CreateFileW(fileName, GENERIC_WRITE, FILE_SHARE_READ, 0,
  24. CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  25. if (hFile == INVALID_HANDLE_VALUE || hFile == nullptr)
  26. return false;
  27.  
  28. MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
  29. exceptionInfo.ThreadId = ::GetCurrentThreadId();
  30. exceptionInfo.ExceptionPointers = e;
  31. exceptionInfo.ClientPointers = FALSE;
  32.  
  33. const DWORD DUMP_FLAGS = MiniDumpWithDataSegs | MiniDumpWithPrivateReadWriteMemory;
  34.  
  35. // Пишем дамп в файл.
  36. BOOL dumped = pMiniDumpWriteDump(
  37. ::GetCurrentProcess(),
  38. ::GetCurrentProcessId(),
  39. hFile,
  40. MINIDUMP_TYPE(DUMP_FLAGS),
  41. e ? &exceptionInfo : NULL,
  42. NULL,
  43. NULL);
  44.  
  45. // Если не удалось сделать дамп - пишем ошибку.
  46. if (!dumped) {
  47. DWORD err = GetLastError();
  48. DWORD written;
  49. ::WriteFile(hFile, &err, 4, &written, 0);
  50. }
  51.  
  52. ::CloseHandle(hFile);
  53.  
  54. return true;
  55. }
  56.  
  57. // Старый обработчик исключений.
  58. static LPTOP_LEVEL_EXCEPTION_FILTER s_oldEH;
  59.  
  60. // Наш обработчик исключений.
  61. static LONG CALLBACK unhandled_exception_handler(EXCEPTION_POINTERS* e) {
  62. // Формируем имя файла.
  63. SYSTEMTIME t;
  64. GetSystemTime(&t);
  65. static wchar_t fileName[1024];
  66. wsprintfW(fileName, L"%s\dump_%d%02d%02d_%02d%02d%02d.dmp", appPath,
  67. t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
  68.  
  69. // Пишем дамп в файл.
  70. auto dumpOk = make_dump(e, fileName);
  71.  
  72. // Если он не записался, передаем исключение дальше.
  73. if (!dumpOk)
  74. return s_oldEH ? s_oldEH(e) : EXCEPTION_CONTINUE_SEARCH;
  75.  
  76. // Показываем пользователю куда записался дамп.
  77. static wchar_t buf[1024];
  78. wsprintfW(buf,
  79. L"Application will be closed due to a fatal error.rn"
  80. L"Crash dump was saved torn%s",
  81. fileName);
  82. MessageBox(nullptr, buf, nullptr, MB_ICONERROR | MB_OK);
  83.  
  84. // Убиваем процесс.
  85. ::TerminateProcess(::GetCurrentProcess(), 5);
  86. return 0;
  87. }
  88.  
  89. // Обработка |abort()|.
  90. static void abort_handler(int) {
  91. ::RaiseException(0x00BAD00A, 0, 0, NULL);
  92. }
  93.  
  94. // Обработка вызова pure virtual функции.
  95. static void purecall_handler() {
  96. ::RaiseException(0x00BAD00C, 0, 0, NULL);
  97. }
  98.  
  99. // Еще какие-то ошибки CRT.
  100. static int crt_report_handler(int reportType, wchar_t*, int* pRet) {
  101. if (reportType == _CRT_WARN) {
  102. if (pRet)
  103. *pRet = 0;
  104.  
  105. return 0;
  106. }
  107.  
  108. ::RaiseException(0x00BAD00E, 0, 0, NULL);
  109. return 0;
  110. }
  111.  
  112. // Функция инициализации.
  113. static void init() {
  114. // Сохраняем путь к .exe , на случай если креш не даст его получить потом.
  115. ::GetModuleFileNameW(GetModuleHandle(nullptr), appPath, MAX_PATH);
  116. // Обрезаем до папки.
  117. *wcsrchr(appPath, L'\') = '';
  118.  
  119. // Устанавливаем обработчики.
  120. s_oldEH = ::SetUnhandledExceptionFilter(unhandled_exception_handler);
  121.  
  122. ::_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
  123. ::signal(SIGABRT, abort_handler);
  124.  
  125. ::_set_purecall_handler(purecall_handler);
  126.  
  127. _CrtSetReportHookW2(_CRT_RPTHOOK_INSTALL, crt_report_handler);
  128. (void)&crt_report_handler;
  129. }
  130.  
  131. // Инициализируемся до main()
  132. bool g_crashdump_initialized = (init(), false);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement