From 033041bfecdb4903f048c8bbd66e0bbba7f4f0a9 Mon Sep 17 00:00:00 2001 From: praydog Date: Sat, 30 Mar 2024 20:27:33 -0700 Subject: [PATCH] Revert "FunctionHook: Update with proper RAII" This reverts commit fb427692cab879e2601a7131b43bb8c06b40db50. This was causing race conditions. --- shared/utility/FunctionHook.cpp | 42 +++++++++++++++++++++++++++++---- shared/utility/FunctionHook.hpp | 2 ++ src/DInputHook.cpp | 2 +- src/HookManager.cpp | 1 + src/mods/Hooks.cpp | 22 ++++++++--------- src/mods/Hooks.hpp | 4 ++-- src/mods/VR.cpp | 6 ++--- 7 files changed, 58 insertions(+), 21 deletions(-) diff --git a/shared/utility/FunctionHook.cpp b/shared/utility/FunctionHook.cpp index 9b007afbc..0b82cc0a9 100644 --- a/shared/utility/FunctionHook.cpp +++ b/shared/utility/FunctionHook.cpp @@ -1,4 +1,6 @@ #include +#include + #include #include "FunctionHook.hpp" @@ -12,6 +14,36 @@ FunctionHook::FunctionHook(Address target, Address destination) { spdlog::info("Attempting to hook {:p}->{:p}", target.ptr(), destination.ptr()); + // Create the hook. Call create afterwards to prevent race conditions accessing FunctionHook before it leaves its constructor. + /*if (auto status = MH_CreateHook(target.as(), destination.as(), (LPVOID*)&m_original); status == MH_OK) { + m_target = target; + m_destination = destination; + + spdlog::info("Hook init successful {:p}->{:p}", target.ptr(), destination.ptr()); + } + else { + spdlog::error("Failed to hook {:p}: {}", target.ptr(), MH_StatusToString(status)); + }*/ +} + +FunctionHook::~FunctionHook() { +} + +bool FunctionHook::create() { + if (m_target == 0 || m_destination == 0 ) { + spdlog::error("FunctionHook not initialized"); + return false; + } + + /*if (auto status = MH_EnableHook((LPVOID)m_target); status != MH_OK) { + m_original = 0; + m_destination = 0; + m_target = 0; + + spdlog::error("Failed to hook {:x}: {}", m_target, MH_StatusToString(status)); + return false; + }*/ + try { auto expect = safetyhook::InlineHook::create(safetyhook::Allocator::global(), m_target, m_destination); @@ -45,22 +77,24 @@ FunctionHook::FunctionHook(Address target, Address destination) }; spdlog::error("Failed to hook {:x}: {}", m_target, error); - return; + return false; } m_inline_hook = std::move(*expect); } catch (const std::exception& e) { spdlog::error("Failed to hook {:x}: {}", m_target, e.what()); + return false; } catch (...) { spdlog::error("Failed to hook {:x}: unknown exception", m_target); + return false; } if (m_inline_hook) { spdlog::info("Hooked {:x}->{:x}", m_target, m_destination); } else { spdlog::error("Failed to hook {:x}", m_target); + return false; } -} -FunctionHook::~FunctionHook() { -} + return true; +} \ No newline at end of file diff --git a/shared/utility/FunctionHook.hpp b/shared/utility/FunctionHook.hpp index 9813139b0..22487ba44 100644 --- a/shared/utility/FunctionHook.hpp +++ b/shared/utility/FunctionHook.hpp @@ -15,6 +15,8 @@ class FunctionHook { FunctionHook(Address target, Address destination); virtual ~FunctionHook(); + bool create(); + auto get_original() const { return m_inline_hook.trampoline().address(); } diff --git a/src/DInputHook.cpp b/src/DInputHook.cpp index 2e96dd093..875f1bcb8 100644 --- a/src/DInputHook.cpp +++ b/src/DInputHook.cpp @@ -81,7 +81,7 @@ bool DInputHook::hook() { // Hook them. m_get_device_state_hook = make_unique(get_device_state, (uintptr_t)&DInputHook::get_device_state); - return m_get_device_state_hook->is_valid(); + return m_get_device_state_hook->create(); } HRESULT DInputHook::get_device_state_internal(IDirectInputDevice* device, DWORD size, LPVOID data) { diff --git a/src/HookManager.cpp b/src/HookManager.cpp index 3090e7dd5..0b0d5d223 100644 --- a/src/HookManager.cpp +++ b/src/HookManager.cpp @@ -593,6 +593,7 @@ HookManager::HookId HookManager::add(sdk::REMethodDefinition* fn, HookManager::P create_jitted_facilitator(hook, fn, [&](){ fn_hook = std::make_unique(hook->target_fn, (void*)hook->facilitator_fn); + fn_hook->create(); return fn_hook->get_original(); }, [&]() { diff --git a/src/mods/Hooks.cpp b/src/mods/Hooks.cpp index 4cfd0e9c1..cb792f168 100644 --- a/src/mods/Hooks.cpp +++ b/src/mods/Hooks.cpp @@ -195,7 +195,7 @@ std::optional Hooks::hook_update_transform() { // Can be found by breakpointing RETransform's worldTransform m_update_transform_hook = std::make_unique(update_transform, &update_transform_hook); - if (!m_update_transform_hook->is_valid()) { + if (!m_update_transform_hook->create()) { //return "Failed to hook UpdateTransform"; spdlog::error("Failed to hook UpdateTransform"); return std::nullopt; // who cares @@ -231,7 +231,7 @@ std::optional Hooks::hook_update_camera_controller() { // Can be found by breakpointing camera controller's worldPosition m_update_camera_controller_hook = std::make_unique(update_camera_controller, &update_camera_controller_hook); - if (!m_update_camera_controller_hook->is_valid()) { + if (!m_update_camera_controller_hook->create()) { return "Failed to hook UpdateCameraController"; } #endif @@ -258,7 +258,7 @@ std::optional Hooks::hook_update_camera_controller2() { // Can be found by breakpointing camera controller's worldRotation m_update_camera_controller2_hook = std::make_unique(update_camera_controller2, &update_camera_controller2_hook); - if (!m_update_camera_controller2_hook->is_valid()) { + if (!m_update_camera_controller2_hook->create()) { return "Failed to hook Updatecamera_controller2"; } #endif @@ -306,7 +306,7 @@ std::optional Hooks::hook_gui_draw() { m_gui_draw_hook = std::make_unique(gui_draw, &gui_draw_hook); - if (!m_gui_draw_hook->is_valid()) { + if (!m_gui_draw_hook->create()) { return "Failed to hook GUI::draw"; } @@ -337,7 +337,7 @@ std::optional Hooks::hook_application_entry(std::string name, std:: hook = std::make_unique(func, hook_fn); - if (!hook->is_valid()) { + if (!hook->create()) { return "Failed to hook via::Application::" + name; } @@ -469,7 +469,7 @@ std::optional Hooks::hook_all_application_entries() { } /*for (auto& entry : m_application_entry_hooks) { - if (!entry.second->is_valid()) { + if (!entry.second->create()) { return "Failed to hook via::Application::" + std::string{entry.first}; } }*/ @@ -489,7 +489,7 @@ std::optional Hooks::hook_update_before_lock_scene() { m_update_before_lock_scene_hook = std::make_unique(update_before_lock_scene, &update_before_lock_scene_hook); - if (!m_update_before_lock_scene_hook->is_valid()) { + if (!m_update_before_lock_scene_hook->create()) { return "Failed to hook via::render::EntityRenderer::updateBeforeLockScene"; } @@ -532,7 +532,7 @@ std::optional Hooks::hook_lightshaft_draw() { m_lightshaft_draw_hook = std::make_unique((uintptr_t)draw, (uintptr_t)&lightshaft_draw_hook); - if (!m_lightshaft_draw_hook->is_valid()) { + if (!m_lightshaft_draw_hook->create()) { return "Failed to hook via::render::LightShaft::draw"; } #endif @@ -563,7 +563,7 @@ std::optional Hooks::hook_view_get_size() { // Hook the native function m_view_get_size_hook = std::make_unique(native_func, view_get_size_hook); - if (!m_view_get_size_hook->is_valid()) { + if (!m_view_get_size_hook->create()) { return "Hook init failed: via.SceneView.get_Size native function hook failed."; } @@ -593,7 +593,7 @@ std::optional Hooks::hook_camera_get_projection_matrix() { // Hook the native function m_camera_get_projection_matrix_hook = std::make_unique(native_func, camera_get_projection_matrix_hook); - if (!m_camera_get_projection_matrix_hook->is_valid()) { + if (!m_camera_get_projection_matrix_hook->create()) { return "Hook init failed: via.Camera.get_ProjectionMatrix native function hook failed."; } @@ -623,7 +623,7 @@ std::optional Hooks::hook_camera_get_view_matrix() { // Hook the native function m_camera_get_view_matrix_hook = std::make_unique(native_func, camera_get_view_matrix_hook); - if (!m_camera_get_view_matrix_hook->is_valid()) { + if (!m_camera_get_view_matrix_hook->create()) { return "Hook init failed: via.Camera.get_ViewMatrix native function hook failed."; } diff --git a/src/mods/Hooks.hpp b/src/mods/Hooks.hpp index 9546fb693..b1c05141d 100644 --- a/src/mods/Hooks.hpp +++ b/src/mods/Hooks.hpp @@ -47,12 +47,12 @@ class Hooks : public Mod { virtual bool hook_draw(Address target) { draw_hook = std::make_unique(target, &RenderLayerHook::draw); - return draw_hook->is_valid(); + return draw_hook->create(); } virtual bool hook_update(Address target) { update_hook = std::make_unique(target, &RenderLayerHook::update); - return update_hook->is_valid(); + return update_hook->create(); } operator RenderLayerHook&() { diff --git a/src/mods/VR.cpp b/src/mods/VR.cpp index f42e8a3c6..5115861d2 100644 --- a/src/mods/VR.cpp +++ b/src/mods/VR.cpp @@ -1126,7 +1126,7 @@ std::optional VR::hijack_input() { // Hook the native function g_input_hook = std::make_unique(func, inputsystem_update_hook); - if (!g_input_hook->is_valid()) { + if (!g_input_hook->create()) { return "VR init failed: InputSystem.update native function hook failed."; } #endif @@ -1157,7 +1157,7 @@ std::optional VR::hijack_camera() { // Hook the native function g_projection_matrix_hook2 = std::make_unique(native_func, gui_camera_get_projection_matrix_hook); - if (g_projection_matrix_hook2->is_valid()) { + if (g_projection_matrix_hook2->create()) { spdlog::info("Hooked via.gui.GUICamera.get_ProjectionMatrix"); } } else { @@ -1232,7 +1232,7 @@ std::optional VR::hijack_wwise_listeners() { g_wwise_listener_update_hook = std::make_unique(update_native, wwise_listener_update_hook); - if (!g_wwise_listener_update_hook->is_valid()) { + if (!g_wwise_listener_update_hook->create()) { return "VR init failed: via.wwise.WwiseListener update native function hook failed."; } #endif