From 064d0cebbc4a15de9acbadfe1f69b33da532d7fd Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 3 May 2026 21:38:31 +0300 Subject: [PATCH] update --- include/omath/hooks/hooks_manager.hpp | 16 ++---- source/hooks/hooks_manager.cpp | 81 ++++++++------------------- 2 files changed, 28 insertions(+), 69 deletions(-) diff --git a/include/omath/hooks/hooks_manager.hpp b/include/omath/hooks/hooks_manager.hpp index 99aeffe..c0c47fd 100644 --- a/include/omath/hooks/hooks_manager.hpp +++ b/include/omath/hooks/hooks_manager.hpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #ifndef WIN32_LEAN_AND_MEAN @@ -24,11 +23,11 @@ namespace omath::hooks { HooksManager() = default; public: - using present_callback = std::function; - using resize_buffers_callback = std::function; + using present_callback = std::function; + using resize_buffers_callback = std::function; using execute_command_lists_callback = std::function; // Return nullopt to pass the message to the original WndProc; return a value to intercept it. - using wnd_proc_callback = std::function(HWND, UINT, WPARAM, LPARAM)>; + using wnd_proc_callback = std::function(HWND, UINT, WPARAM, LPARAM)>; [[nodiscard]] static HooksManager& get(); HooksManager(const HooksManager&) = delete; @@ -48,8 +47,6 @@ namespace omath::hooks void set_on_wnd_proc(wnd_proc_callback callback); private: - [[nodiscard]] bool build_vtable(); - static HRESULT __stdcall present_detour(IDXGISwapChain* p_swap_chain, UINT sync_interval, UINT flags); static HRESULT __stdcall resize_buffers_detour(IDXGISwapChain* p_swap_chain, UINT buffer_count, UINT width, UINT height, DXGI_FORMAT new_format, @@ -64,7 +61,6 @@ namespace omath::hooks bool m_is_dx12_hooked = false; bool m_is_wnd_proc_hooked = false; - std::vector m_vtable; HWND m_hooked_hwnd = nullptr; WNDPROC m_original_wndproc = nullptr; @@ -72,10 +68,10 @@ namespace omath::hooks safetyhook::InlineHook m_resize_buffers_hook; safetyhook::InlineHook m_execute_command_lists_hook; - present_callback m_present_cb; - resize_buffers_callback m_resize_buffers_cb; + present_callback m_present_cb; + resize_buffers_callback m_resize_buffers_cb; execute_command_lists_callback m_execute_command_lists_cb; - wnd_proc_callback m_wnd_proc_cb; + wnd_proc_callback m_wnd_proc_cb; }; } diff --git a/source/hooks/hooks_manager.cpp b/source/hooks/hooks_manager.cpp index 24e608c..af8f331 100644 --- a/source/hooks/hooks_manager.cpp +++ b/source/hooks/hooks_manager.cpp @@ -1,7 +1,6 @@ #include "omath/hooks/hooks_manager.hpp" #ifdef OMATH_ENABLE_HOOKING -#include namespace { @@ -32,26 +31,10 @@ namespace [[nodiscard]] bool valid() const { return m_window_handle != nullptr; } }; - // Method counts per interface (vtable slots including inherited ones) - constexpr std::size_t k_device_methods = 44; - constexpr std::size_t k_command_queue_methods = 19; - constexpr std::size_t k_command_allocator_methods = 9; - constexpr std::size_t k_command_list_methods = 60; - constexpr std::size_t k_swap_chain_methods = 18; - constexpr std::size_t k_total_methods = k_device_methods + k_command_queue_methods + - k_command_allocator_methods + k_command_list_methods + - k_swap_chain_methods; // 150 - - // Base offsets in the combined table - constexpr std::size_t k_cmd_queue_base = k_device_methods; // 44 - constexpr std::size_t k_swap_chain_base = k_device_methods + k_command_queue_methods + - k_command_allocator_methods + k_command_list_methods; // 132 - - // IDXGISwapChain vtable: Present=8, ResizeBuffers=13 (from IUnknown base) - // ID3D12CommandQueue vtable: ExecuteCommandLists=8 (from IUnknown base) - constexpr std::size_t k_present_index = k_swap_chain_base + 8; // 140 - constexpr std::size_t k_resize_buffers_index = k_swap_chain_base + 13; // 145 - constexpr std::size_t k_execute_cmd_lists_index = k_cmd_queue_base + 8; // 52 + void* vtable_fn(void* com_obj, std::size_t index) + { + return (*reinterpret_cast(com_obj))[index]; + } } // namespace namespace omath::hooks @@ -68,8 +51,12 @@ namespace omath::hooks unhook_dx12(); } - bool HooksManager::build_vtable() + bool HooksManager::hook_dx12() { + std::unique_lock lock(m_mutex); + if (m_is_dx12_hooked) + return true; + const DummyWindow window; if (!window.valid()) return false; @@ -170,18 +157,19 @@ namespace omath::hooks return false; } - m_vtable.resize(k_total_methods); + // Read the 3 needed vtable slots directly — these addresses live in the DLL, + // not in the objects, so they remain valid after the objects are released. + m_present_hook = safetyhook::create_inline( + vtable_fn(swap_chain, 8), // IDXGISwapChain::Present + reinterpret_cast(&present_detour)); - const auto copy_vtable = [](uintptr_t* dst, void* com_obj, std::size_t count) - { - std::memcpy(dst, *reinterpret_cast(com_obj), count * sizeof(uintptr_t)); - }; + m_resize_buffers_hook = safetyhook::create_inline( + vtable_fn(swap_chain, 13), // IDXGISwapChain::ResizeBuffers + reinterpret_cast(&resize_buffers_detour)); - copy_vtable(m_vtable.data(), device, k_device_methods); - copy_vtable(m_vtable.data() + k_device_methods, command_queue, k_command_queue_methods); - copy_vtable(m_vtable.data() + k_device_methods + k_command_queue_methods, command_allocator, k_command_allocator_methods); - copy_vtable(m_vtable.data() + k_device_methods + k_command_queue_methods + k_command_allocator_methods, command_list, k_command_list_methods); - copy_vtable(m_vtable.data() + k_swap_chain_base, swap_chain, k_swap_chain_methods); + m_execute_command_lists_hook = safetyhook::create_inline( + vtable_fn(command_queue, 8), // ID3D12CommandQueue::ExecuteCommandLists + reinterpret_cast(&execute_command_lists_detour)); swap_chain->Release(); command_list->Release(); @@ -190,30 +178,6 @@ namespace omath::hooks device->Release(); factory->Release(); - return true; - } - - bool HooksManager::hook_dx12() - { - std::unique_lock lock(m_mutex); - if (m_is_dx12_hooked) - return true; - - if (!build_vtable()) - return false; - - m_present_hook = safetyhook::create_inline( - reinterpret_cast(m_vtable[k_present_index]), - reinterpret_cast(&present_detour)); - - m_resize_buffers_hook = safetyhook::create_inline( - reinterpret_cast(m_vtable[k_resize_buffers_index]), - reinterpret_cast(&resize_buffers_detour)); - - m_execute_command_lists_hook = safetyhook::create_inline( - reinterpret_cast(m_vtable[k_execute_cmd_lists_index]), - reinterpret_cast(&execute_command_lists_detour)); - if (!m_present_hook || !m_resize_buffers_hook || !m_execute_command_lists_hook) { m_present_hook = {}; @@ -232,7 +196,6 @@ namespace omath::hooks m_present_hook = {}; m_resize_buffers_hook = {}; m_execute_command_lists_hook = {}; - m_vtable.clear(); m_is_dx12_hooked = false; } @@ -265,8 +228,8 @@ namespace omath::hooks if (!prev) return false; - m_hooked_hwnd = hwnd; - m_original_wndproc = prev; + m_hooked_hwnd = hwnd; + m_original_wndproc = prev; m_is_wnd_proc_hooked = true; return true; }