mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
make Dalamud handle top-level SEH
This commit is contained in:
parent
63f32322f5
commit
f4af8e509b
4 changed files with 45 additions and 67 deletions
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "hooks.h"
|
||||||
|
|
||||||
#include "crashhandler_shared.h"
|
#include "crashhandler_shared.h"
|
||||||
#include "DalamudStartInfo.h"
|
#include "DalamudStartInfo.h"
|
||||||
|
|
@ -24,6 +25,7 @@
|
||||||
|
|
||||||
PVOID g_veh_handle = nullptr;
|
PVOID g_veh_handle = nullptr;
|
||||||
bool g_veh_do_full_dump = false;
|
bool g_veh_do_full_dump = false;
|
||||||
|
std::optional<hooks::import_hook<decltype(SetUnhandledExceptionFilter)>> g_HookSetUnhandledExceptionFilter;
|
||||||
|
|
||||||
HANDLE g_crashhandler_process = nullptr;
|
HANDLE g_crashhandler_process = nullptr;
|
||||||
HANDLE g_crashhandler_event = nullptr;
|
HANDLE g_crashhandler_event = nullptr;
|
||||||
|
|
@ -143,21 +145,7 @@ static void append_injector_launch_args(std::vector<std::wstring>& args)
|
||||||
|
|
||||||
LONG exception_handler(EXCEPTION_POINTERS* ex)
|
LONG exception_handler(EXCEPTION_POINTERS* ex)
|
||||||
{
|
{
|
||||||
if (ex->ExceptionRecord->ExceptionCode == 0x12345678)
|
// block any other exceptions hitting the handler while the messagebox is open
|
||||||
{
|
|
||||||
// pass
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!is_whitelist_exception(ex->ExceptionRecord->ExceptionCode))
|
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
|
||||||
|
|
||||||
if (!is_ffxiv_address(L"ffxiv_dx11.exe", ex->ContextRecord->Rip) &&
|
|
||||||
!is_ffxiv_address(L"cimgui.dll", ex->ContextRecord->Rip))
|
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
// block any other exceptions hitting the veh while the messagebox is open
|
|
||||||
const auto lock = std::lock_guard(g_exception_handler_mutex);
|
const auto lock = std::lock_guard(g_exception_handler_mutex);
|
||||||
|
|
||||||
exception_info exinfo{};
|
exception_info exinfo{};
|
||||||
|
|
@ -167,7 +155,7 @@ LONG exception_handler(EXCEPTION_POINTERS* ex)
|
||||||
exinfo.ExceptionRecord = ex->ExceptionRecord ? *ex->ExceptionRecord : EXCEPTION_RECORD{};
|
exinfo.ExceptionRecord = ex->ExceptionRecord ? *ex->ExceptionRecord : EXCEPTION_RECORD{};
|
||||||
const auto time_now = std::chrono::system_clock::now();
|
const auto time_now = std::chrono::system_clock::now();
|
||||||
auto lifetime = std::chrono::duration_cast<std::chrono::seconds>(
|
auto lifetime = std::chrono::duration_cast<std::chrono::seconds>(
|
||||||
time_now.time_since_epoch()).count()
|
time_now.time_since_epoch()).count()
|
||||||
- std::chrono::duration_cast<std::chrono::seconds>(
|
- std::chrono::duration_cast<std::chrono::seconds>(
|
||||||
g_time_start.time_since_epoch()).count();
|
g_time_start.time_since_epoch()).count();
|
||||||
exinfo.nLifetime = lifetime;
|
exinfo.nLifetime = lifetime;
|
||||||
|
|
@ -217,13 +205,44 @@ LONG exception_handler(EXCEPTION_POINTERS* ex)
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LONG WINAPI structured_exception_handler(EXCEPTION_POINTERS* ex)
|
||||||
|
{
|
||||||
|
return exception_handler(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG WINAPI vectored_exception_handler(EXCEPTION_POINTERS* ex)
|
||||||
|
{
|
||||||
|
if (ex->ExceptionRecord->ExceptionCode == 0x12345678)
|
||||||
|
{
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!is_whitelist_exception(ex->ExceptionRecord->ExceptionCode))
|
||||||
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
|
|
||||||
|
if (!is_ffxiv_address(L"ffxiv_dx11.exe", ex->ContextRecord->Rip) &&
|
||||||
|
!is_ffxiv_address(L"cimgui.dll", ex->ContextRecord->Rip))
|
||||||
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
return exception_handler(ex);
|
||||||
|
}
|
||||||
|
|
||||||
bool veh::add_handler(bool doFullDump, const std::string& workingDirectory)
|
bool veh::add_handler(bool doFullDump, const std::string& workingDirectory)
|
||||||
{
|
{
|
||||||
if (g_veh_handle)
|
if (g_veh_handle)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
g_veh_handle = AddVectoredExceptionHandler(1, exception_handler);
|
g_veh_handle = AddVectoredExceptionHandler(TRUE, vectored_exception_handler);
|
||||||
SetUnhandledExceptionFilter(nullptr);
|
|
||||||
|
g_HookSetUnhandledExceptionFilter.emplace("kernel32.dll!SetUnhandledExceptionFilter (lpTopLevelExceptionFilter)", "kernel32.dll", "SetUnhandledExceptionFilter", 0);
|
||||||
|
g_HookSetUnhandledExceptionFilter->set_detour([](LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) -> LPTOP_LEVEL_EXCEPTION_FILTER
|
||||||
|
{
|
||||||
|
logging::I("Overwriting UnhandledExceptionFilter from {} to {}", reinterpret_cast<ULONG_PTR>(lpTopLevelExceptionFilter), reinterpret_cast<ULONG_PTR>(structured_exception_handler));
|
||||||
|
return g_HookSetUnhandledExceptionFilter->call_original(structured_exception_handler);
|
||||||
|
});
|
||||||
|
SetUnhandledExceptionFilter(structured_exception_handler);
|
||||||
|
|
||||||
g_veh_do_full_dump = doFullDump;
|
g_veh_do_full_dump = doFullDump;
|
||||||
g_time_start = std::chrono::system_clock::now();
|
g_time_start = std::chrono::system_clock::now();
|
||||||
|
|
@ -355,6 +374,8 @@ bool veh::remove_handler()
|
||||||
if (g_veh_handle && RemoveVectoredExceptionHandler(g_veh_handle) != 0)
|
if (g_veh_handle && RemoveVectoredExceptionHandler(g_veh_handle) != 0)
|
||||||
{
|
{
|
||||||
g_veh_handle = nullptr;
|
g_veh_handle = nullptr;
|
||||||
|
g_HookSetUnhandledExceptionFilter.reset();
|
||||||
|
SetUnhandledExceptionFilter(nullptr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -513,50 +513,6 @@ void xivfixes::backup_userdata_save(bool bApply) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void xivfixes::clr_failfast_hijack(bool bApply)
|
|
||||||
{
|
|
||||||
static const char* LogTag = "[xivfixes:clr_failfast_hijack]";
|
|
||||||
static std::optional<hooks::import_hook<decltype(RaiseFailFastException)>> s_HookClrFatalError;
|
|
||||||
static std::optional<hooks::import_hook<decltype(SetUnhandledExceptionFilter)>> s_HookSetUnhandledExceptionFilter;
|
|
||||||
|
|
||||||
if (bApply)
|
|
||||||
{
|
|
||||||
if (!g_startInfo.BootEnabledGameFixes.contains("clr_failfast_hijack")) {
|
|
||||||
logging::I("{} Turned off via environment variable.", LogTag);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_HookClrFatalError.emplace("kernel32.dll!RaiseFailFastException (import, backup_userdata_save)", "kernel32.dll", "RaiseFailFastException", 0);
|
|
||||||
s_HookSetUnhandledExceptionFilter.emplace("kernel32.dll!SetUnhandledExceptionFilter (lpTopLevelExceptionFilter)", "kernel32.dll", "SetUnhandledExceptionFilter", 0);
|
|
||||||
|
|
||||||
s_HookClrFatalError->set_detour([](PEXCEPTION_RECORD pExceptionRecord,
|
|
||||||
_In_opt_ PCONTEXT pContextRecord,
|
|
||||||
_In_ DWORD dwFlags)
|
|
||||||
{
|
|
||||||
MessageBoxW(nullptr, L"An error in a Dalamud plugin was detected and the game cannot continue.\n\nPlease take a screenshot of this error message and let us know about it.", L"Dalamud", MB_OK | MB_ICONERROR);
|
|
||||||
|
|
||||||
return s_HookClrFatalError->call_original(pExceptionRecord, pContextRecord, dwFlags);
|
|
||||||
});
|
|
||||||
|
|
||||||
s_HookSetUnhandledExceptionFilter->set_detour([](LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) -> LPTOP_LEVEL_EXCEPTION_FILTER
|
|
||||||
{
|
|
||||||
logging::I("{} SetUnhandledExceptionFilter", LogTag);
|
|
||||||
return nullptr;
|
|
||||||
});
|
|
||||||
|
|
||||||
logging::I("{} Enable", LogTag);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (s_HookClrFatalError) {
|
|
||||||
logging::I("{} Disable ClrFatalError", LogTag);
|
|
||||||
s_HookClrFatalError.reset();
|
|
||||||
s_HookSetUnhandledExceptionFilter.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void xivfixes::prevent_icmphandle_crashes(bool bApply) {
|
void xivfixes::prevent_icmphandle_crashes(bool bApply) {
|
||||||
static const char* LogTag = "[xivfixes:prevent_icmphandle_crashes]";
|
static const char* LogTag = "[xivfixes:prevent_icmphandle_crashes]";
|
||||||
|
|
||||||
|
|
@ -598,7 +554,6 @@ void xivfixes::apply_all(bool bApply) {
|
||||||
{ "disable_game_openprocess_access_check", &disable_game_openprocess_access_check },
|
{ "disable_game_openprocess_access_check", &disable_game_openprocess_access_check },
|
||||||
{ "redirect_openprocess", &redirect_openprocess },
|
{ "redirect_openprocess", &redirect_openprocess },
|
||||||
{ "backup_userdata_save", &backup_userdata_save },
|
{ "backup_userdata_save", &backup_userdata_save },
|
||||||
{ "clr_failfast_hijack", &clr_failfast_hijack },
|
|
||||||
{ "prevent_icmphandle_crashes", &prevent_icmphandle_crashes }
|
{ "prevent_icmphandle_crashes", &prevent_icmphandle_crashes }
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ namespace xivfixes {
|
||||||
void disable_game_openprocess_access_check(bool bApply);
|
void disable_game_openprocess_access_check(bool bApply);
|
||||||
void redirect_openprocess(bool bApply);
|
void redirect_openprocess(bool bApply);
|
||||||
void backup_userdata_save(bool bApply);
|
void backup_userdata_save(bool bApply);
|
||||||
void clr_failfast_hijack(bool bApply);
|
|
||||||
void prevent_icmphandle_crashes(bool bApply);
|
void prevent_icmphandle_crashes(bool bApply);
|
||||||
|
|
||||||
void apply_all(bool bApply);
|
void apply_all(bool bApply);
|
||||||
|
|
|
||||||
|
|
@ -394,7 +394,10 @@ namespace Dalamud.Injector
|
||||||
startInfo.BootShowConsole = args.Contains("--console");
|
startInfo.BootShowConsole = args.Contains("--console");
|
||||||
startInfo.BootEnableEtw = args.Contains("--etw");
|
startInfo.BootEnableEtw = args.Contains("--etw");
|
||||||
startInfo.BootLogPath = GetLogPath(startInfo.LogPath, "dalamud.boot", startInfo.LogName);
|
startInfo.BootLogPath = GetLogPath(startInfo.LogPath, "dalamud.boot", startInfo.LogName);
|
||||||
startInfo.BootEnabledGameFixes = new List<string> { "prevent_devicechange_crashes", "disable_game_openprocess_access_check", "redirect_openprocess", "backup_userdata_save", "prevent_icmphandle_crashes" };
|
startInfo.BootEnabledGameFixes = new List<string> {
|
||||||
|
"prevent_devicechange_crashes", "disable_game_openprocess_access_check",
|
||||||
|
"redirect_openprocess", "backup_userdata_save", "prevent_icmphandle_crashes",
|
||||||
|
};
|
||||||
startInfo.BootDotnetOpenProcessHookMode = 0;
|
startInfo.BootDotnetOpenProcessHookMode = 0;
|
||||||
startInfo.BootWaitMessageBox |= args.Contains("--msgbox1") ? 1 : 0;
|
startInfo.BootWaitMessageBox |= args.Contains("--msgbox1") ? 1 : 0;
|
||||||
startInfo.BootWaitMessageBox |= args.Contains("--msgbox2") ? 2 : 0;
|
startInfo.BootWaitMessageBox |= args.Contains("--msgbox2") ? 2 : 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue