| 98 | } |
| 99 | |
| 100 | static void WriteMinidumpAndCallstack(PEXCEPTION_POINTERS exi) |
| 101 | { |
| 102 | s_in_crash_handler = true; |
| 103 | |
| 104 | wchar_t filename[1024] = {}; |
| 105 | GenerateCrashFilename(filename, std::size(filename), s_write_directory.empty() ? nullptr : s_write_directory.c_str(), L"txt"); |
| 106 | |
| 107 | // might fail |
| 108 | HANDLE hFile = CreateFileW(filename, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, nullptr); |
| 109 | if (exi && hFile != INVALID_HANDLE_VALUE) |
| 110 | { |
| 111 | char line[1024]; |
| 112 | DWORD written; |
| 113 | std::snprintf(line, std::size(line), "Exception 0x%08X at 0x%p\n", static_cast<unsigned>(exi->ExceptionRecord->ExceptionCode), |
| 114 | exi->ExceptionRecord->ExceptionAddress); |
| 115 | WriteFile(hFile, line, static_cast<DWORD>(std::strlen(line)), &written, nullptr); |
| 116 | } |
| 117 | |
| 118 | GenerateCrashFilename(filename, std::size(filename), s_write_directory.empty() ? nullptr : s_write_directory.c_str(), L"dmp"); |
| 119 | |
| 120 | const MINIDUMP_TYPE minidump_type = |
| 121 | static_cast<MINIDUMP_TYPE>(MiniDumpNormal | MiniDumpWithHandleData | MiniDumpWithProcessThreadData | |
| 122 | MiniDumpWithThreadInfo | MiniDumpWithIndirectlyReferencedMemory); |
| 123 | const HANDLE hMinidumpFile = CreateFileW(filename, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, nullptr); |
| 124 | if (hMinidumpFile == INVALID_HANDLE_VALUE || |
| 125 | !WriteMinidump(static_cast<HMODULE>(s_dbghelp_module.GetHandle()), hMinidumpFile, GetCurrentProcess(), GetCurrentProcessId(), |
| 126 | GetCurrentThreadId(), exi, minidump_type)) |
| 127 | { |
| 128 | static const char error_message[] = "Failed to write minidump file.\n"; |
| 129 | if (hFile != INVALID_HANDLE_VALUE) |
| 130 | { |
| 131 | DWORD written; |
| 132 | WriteFile(hFile, error_message, sizeof(error_message) - 1, &written, nullptr); |
| 133 | } |
| 134 | } |
| 135 | if (hMinidumpFile != INVALID_HANDLE_VALUE) |
| 136 | CloseHandle(hMinidumpFile); |
| 137 | |
| 138 | CrashHandlerStackWalker sw(hFile); |
| 139 | sw.ShowCallstack(GetCurrentThread(), exi ? exi->ContextRecord : nullptr); |
| 140 | |
| 141 | if (hFile != INVALID_HANDLE_VALUE) |
| 142 | CloseHandle(hFile); |
| 143 | } |
| 144 | |
| 145 | static LONG NTAPI ExceptionHandler(PEXCEPTION_POINTERS exi) |
| 146 | { |
no test coverage detected