From 37c43c673e0f1b2e5a78949b0ec3c59661168490 Mon Sep 17 00:00:00 2001 From: muhopensores Date: Mon, 2 Jan 2023 14:22:49 +0300 Subject: [PATCH] minhook fixes --- dependencies/minhook/include/MinHook.h | 3 ++- dependencies/minhook/src/hook.c | 18 +++++++++++++++++- src/ModFramework.cpp | 23 ++++++++++++++++++++++- src/utility/FunctionHook.cpp | 10 +++++++--- src/utility/FunctionHook.hpp | 2 ++ 5 files changed, 50 insertions(+), 6 deletions(-) diff --git a/dependencies/minhook/include/MinHook.h b/dependencies/minhook/include/MinHook.h index 15c0a87..fcdbd70 100644 --- a/dependencies/minhook/include/MinHook.h +++ b/dependencies/minhook/include/MinHook.h @@ -1,4 +1,4 @@ -/* +/* * MinHook - The Minimalistic API Hooking Library for x64/x86 * Copyright (C) 2009-2017 Tsuda Kageyu. * All rights reserved. @@ -180,6 +180,7 @@ extern "C" { // Translates the MH_STATUS to its name as a string. const char * WINAPI MH_StatusToString(MH_STATUS status); + void WINAPI MH_SetSkipLocking(BOOL b); #ifdef __cplusplus } #endif diff --git a/dependencies/minhook/src/hook.c b/dependencies/minhook/src/hook.c index ce65e57..3eba7cd 100644 --- a/dependencies/minhook/src/hook.c +++ b/dependencies/minhook/src/hook.c @@ -91,7 +91,7 @@ volatile LONG g_isLocked = FALSE; // Private heap handle. If not NULL, this library is initialized. HANDLE g_hHeap = NULL; - +static BOOL g_skipLocks = FALSE; // Hook entries. struct { @@ -100,7 +100,14 @@ struct UINT size; // Actual number of data items } g_hooks; + + //------------------------------------------------------------------------- +// NOTE(edit): hacks to avoid deadlocks when we already froze threads from outside +void WINAPI MH_SetSkipLocking(BOOL b) { + g_skipLocks = b; +} + //------------------------------------------------------------------------- // Returns INVALID_HOOK_POS if not found. static UINT FindHookEntry(LPVOID pTarget) { @@ -306,6 +313,10 @@ static VOID EnumerateThreads(PFROZEN_THREADS pThreads) //------------------------------------------------------------------------- static VOID Freeze(PFROZEN_THREADS pThreads, UINT pos, UINT action) { + // NOTE(edit): deadlock hack + if (g_skipLocks) { + return; + } pThreads->pItems = NULL; pThreads->capacity = 0; pThreads->size = 0; @@ -330,6 +341,10 @@ static VOID Freeze(PFROZEN_THREADS pThreads, UINT pos, UINT action) //------------------------------------------------------------------------- static VOID Unfreeze(PFROZEN_THREADS pThreads) { + // NOTE(edit): deadlock hack + if (g_skipLocks) { + return; + } if (pThreads->pItems != NULL) { UINT i; @@ -435,6 +450,7 @@ static MH_STATUS EnableAllHooksLL(BOOL enable) //------------------------------------------------------------------------- static VOID EnterSpinLock(VOID) { + SIZE_T spinCount = 0; // Wait until the flag is FALSE. diff --git a/src/ModFramework.cpp b/src/ModFramework.cpp index 5d37f86..0f13e31 100644 --- a/src/ModFramework.cpp +++ b/src/ModFramework.cpp @@ -40,8 +40,10 @@ ModFramework::ModFramework() #endif // WARNING(): i hacked on init for time critical stuff here // TimeCritical init stuff +#if 0 std::thread init_thread([this]() { m_mods = std::make_unique(); + FunctionHook::set_mh_skip_locks(TRUE); auto threads = utils::SuspendAllOtherThreads(); m_mods->load_time_critical_mods(); auto e = m_mods->on_initialize(); @@ -55,10 +57,29 @@ ModFramework::ModFramework() } } utils::ResumeThreads(threads); + FunctionHook::set_mh_skip_locks(FALSE); }); init_thread.detach(); - std::this_thread::sleep_for(std::chrono::seconds(1)); +#else + m_mods = std::make_unique(); + FunctionHook::set_mh_skip_locks(TRUE); + auto threads = utils::SuspendAllOtherThreads(); + m_mods->load_time_critical_mods(); + auto e = m_mods->on_initialize(); + + if (e) { + if (e->empty()) { + m_error = "An unknown error has occurred."; + } + else { + m_error = *e; + } + } + utils::ResumeThreads(threads); + FunctionHook::set_mh_skip_locks(FALSE); +#endif + /*std::this_thread::sleep_for(std::chrono::seconds(1));*/ m_d3d9_hook = std::make_unique(); diff --git a/src/utility/FunctionHook.cpp b/src/utility/FunctionHook.cpp index 48e6e5a..6c31773 100644 --- a/src/utility/FunctionHook.cpp +++ b/src/utility/FunctionHook.cpp @@ -6,7 +6,7 @@ using namespace std; -bool g_isMinHookInitialized{ false }; +bool g_is_min_hook_initialized{ false }; FunctionHook::FunctionHook(Address target, Address destination) : m_target{ 0 }, @@ -16,8 +16,8 @@ FunctionHook::FunctionHook(Address target, Address destination) spdlog::info("Attempting to hook {:p}->{:p}", target.ptr(), destination.ptr()); // Initialize MinHook if it hasn't been already. - if (!g_isMinHookInitialized && MH_Initialize() == MH_OK) { - g_isMinHookInitialized = true; + if (!g_is_min_hook_initialized && MH_Initialize() == MH_OK) { + g_is_min_hook_initialized = true; } // Create the hook. Call create afterwards to prevent race conditions accessing FunctionHook before it leaves its constructor. @@ -65,6 +65,10 @@ bool FunctionHook::disable() { return true; } +void FunctionHook::set_mh_skip_locks(BOOL b) { + MH_SetSkipLocking(b); +} + bool FunctionHook::remove() { // Don't try to remove invalid hooks. if (m_original == 0) { diff --git a/src/utility/FunctionHook.hpp b/src/utility/FunctionHook.hpp index a1cfb72..5266c6a 100644 --- a/src/utility/FunctionHook.hpp +++ b/src/utility/FunctionHook.hpp @@ -33,6 +33,8 @@ class FunctionHook { return m_original != 0; } + static void set_mh_skip_locks(BOOL b); + FunctionHook& operator=(const FunctionHook& other) = delete; FunctionHook& operator=(FunctionHook&& other) = delete;