mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-17 13:57:05 +02:00
Most crashes are caught by the game's own fatal handlers, which write a dump of thread stacks only; the launcher could only copy it after the game had exited. A crash on a freed or overwritten object then showed the faulting registers but not the object or the list it came from. - game_fatal_dump: the game's MiniDumpWriteDump import points at ReSkate. Before the game writes its dump, the crash reporter takes its own of the still-running game for the faulting thread; the game's dump follows as before. Reports say capture.source "game-fatal-handler". - The reporter's dumps include the memory the stacks point at (MiniDumpWithIndirectlyReferencedMemory), a few MB more a report. - The shared report says who asked for the dump (protocol version 4). - Tests: a game-handler crash is captured with a heap block only its stack points at; ReSkate's own capture keeps it too.
45 lines
2.0 KiB
C++
45 lines
2.0 KiB
C++
#pragma once
|
|
#include <Windows.h>
|
|
#include <array>
|
|
#include <string>
|
|
|
|
namespace dingosdk::crash_report {
|
|
inline constexpr DWORD protocol_version = 4;
|
|
// Who asked for the dump: ReSkate's last-chance filter, or the game's own fatal handler about to
|
|
// write its dump (which it does without ever reaching that filter).
|
|
enum class CaptureSource : DWORD { unhandled_exception, game_fatal_handler };
|
|
inline constexpr DWORD capture_timeout_ms = 15000;
|
|
struct SharedReport {
|
|
DWORD version{protocol_version};
|
|
DWORD thread_id{};
|
|
EXCEPTION_POINTERS* exception{}; // Address in the parent; MiniDumpWriteDump uses ClientPointers=TRUE.
|
|
std::array<wchar_t, 4096> url{};
|
|
std::array<wchar_t, 32768> directory{};
|
|
std::array<wchar_t, 260> application{};
|
|
std::array<wchar_t, 32768> native_directory{};
|
|
// What the game was doing, for the report's tags: the level it loaded last, and the graphics
|
|
// card it renders on with its driver's version. Written by the game as they change, read by
|
|
// the helper after a crash (a torn read only spoils a tag).
|
|
std::array<wchar_t, 512> destination{};
|
|
std::array<wchar_t, 128> gpu_name{};
|
|
std::array<wchar_t, 32> gpu_driver{};
|
|
CaptureSource source{};
|
|
};
|
|
// Explicitly inherited unnamed handles; no token or paths on the command line.
|
|
enum HandleIndex : std::size_t { mapping, requested, captured, stopping, ready, parent, handle_count };
|
|
struct Handle {
|
|
HANDLE value{};
|
|
Handle() = default;
|
|
explicit Handle(HANDLE handle) : value(handle) {}
|
|
~Handle() { if (value && value != INVALID_HANDLE_VALUE) CloseHandle(value); }
|
|
Handle(const Handle&) = delete;
|
|
Handle& operator=(const Handle&) = delete;
|
|
HANDLE release() { const auto result = value; value = nullptr; return result; }
|
|
};
|
|
inline std::wstring environment(const wchar_t* name) {
|
|
std::array<wchar_t, 32768> buffer{};
|
|
const auto size = GetEnvironmentVariableW(name, buffer.data(), static_cast<DWORD>(buffer.size()));
|
|
return size && size < buffer.size() ? std::wstring(buffer.data(), size) : std::wstring{};
|
|
}
|
|
}
|