diff --git a/plugins/win-capture/funchook.c b/plugins/win-capture/funchook.c deleted file mode 100644 index 2535158da..000000000 --- a/plugins/win-capture/funchook.c +++ /dev/null @@ -1,285 +0,0 @@ -#include -#include -#include "funchook.h" - -#define JMP_64_SIZE 14 -#define JMP_32_SIZE 5 - -#define X86_NOP 0x90 -#define X86_JMP_NEG_5 0xF9EB - -static inline void fix_permissions(void *addr, size_t size) -{ - DWORD protect_val; - VirtualProtect(addr, size, PAGE_EXECUTE_READWRITE, &protect_val); -} - -void hook_init(struct func_hook *hook, void *func_addr, void *hook_addr, - const char *name) -{ - memset(hook, 0, sizeof(*hook)); - - hook->func_addr = (uintptr_t)func_addr; - hook->hook_addr = (uintptr_t)hook_addr; - hook->name = name; - - fix_permissions((void *)(hook->func_addr - JMP_32_SIZE), - JMP_64_SIZE + JMP_32_SIZE); - - memcpy(hook->unhook_data, func_addr, JMP_64_SIZE); -} - -static inline size_t patch_size(struct func_hook *hook) -{ - return hook->is_64bit_jump ? JMP_64_SIZE : JMP_32_SIZE; -} - -static const uint8_t longjmp64[6] = {0xFF, 0x25, 0x00, 0x00, 0x00, 0x00}; - -static inline void rehook64(struct func_hook *hook) -{ - uint8_t data[JMP_64_SIZE]; - uintptr_t *ptr_loc = (uintptr_t *)((uint8_t *)data + sizeof(longjmp64)); - - fix_permissions((void *)hook->func_addr, JMP_64_SIZE); - - memcpy(data, (void *)hook->func_addr, JMP_64_SIZE); - memcpy(data, longjmp64, sizeof(longjmp64)); - *ptr_loc = hook->hook_addr; - - hook->call_addr = (void *)hook->func_addr; - hook->type = HOOKTYPE_FORWARD_OVERWRITE; - hook->hooked = true; - - memcpy((void *)hook->func_addr, data, JMP_64_SIZE); -} - -static inline void hook_reverse_new(struct func_hook *hook, uint8_t *p) -{ - hook->call_addr = (void *)(hook->func_addr + 2); - hook->type = HOOKTYPE_REVERSE_CHAIN; - hook->hooked = true; - - p[0] = 0xE9; - *((uint32_t *)&p[1]) = (uint32_t)(hook->hook_addr - hook->func_addr); - *((uint16_t *)&p[5]) = X86_JMP_NEG_5; -} - -static inline void hook_reverse_chain(struct func_hook *hook, uint8_t *p) -{ - if (hook->type != HOOKTYPE_FORWARD_OVERWRITE) - return; - - hook->call_addr = (void *)(hook->func_addr + *((int32_t *)&p[1])); - hook->type = HOOKTYPE_REVERSE_CHAIN; - hook->hooked = true; - - *((uint32_t *)&p[1]) = (uint32_t)(hook->hook_addr - hook->func_addr); -} - -static inline void hook_forward_chain(struct func_hook *hook, uint8_t *p, - intptr_t offset) -{ - int32_t cur_offset = *(int32_t *)&p[6]; - - if (hook->type != HOOKTYPE_FORWARD_OVERWRITE) - return; - - hook->call_addr = (void *)(hook->func_addr + JMP_32_SIZE + cur_offset); - hook->type = HOOKTYPE_FORWARD_CHAIN; - hook->hooked = true; - - *((int32_t *)&p[6]) = (int32_t)offset; -} - -static inline void hook_forward_overwrite(struct func_hook *hook, - intptr_t offset) -{ - uint8_t *ptr = (uint8_t *)hook->func_addr; - - hook->call_addr = (void *)hook->func_addr; - hook->type = HOOKTYPE_FORWARD_OVERWRITE; - hook->hooked = true; - - *(ptr++) = 0xE9; - *((int32_t *)ptr) = (int32_t)offset; -} - -static inline void rehook32(struct func_hook *hook, bool force, intptr_t offset) -{ - fix_permissions((void *)(hook->func_addr - JMP_32_SIZE), - JMP_32_SIZE * 2); - - if (force || !hook->started) { - uint8_t *p = (uint8_t *)hook->func_addr - JMP_32_SIZE; - size_t nop_count = 0; - - /* check for reverse chain hook availability */ - for (size_t i = 0; i < JMP_32_SIZE; i++) { - if (p[i] == X86_NOP) - nop_count++; - } - - if (nop_count == JMP_32_SIZE && p[5] == 0x8B && p[6] == 0xFF) { - hook_reverse_new(hook, p); - - } else if (p[0] == 0xE9 && - *(uint16_t *)&p[5] == X86_JMP_NEG_5) { - hook_reverse_chain(hook, p); - - } else if (p[5] == 0xE9) { - hook_forward_chain(hook, p, offset); - - } else if (hook->type != HOOKTYPE_FORWARD_OVERWRITE) { - hook->type = HOOKTYPE_FORWARD_OVERWRITE; - } - - hook->started = true; - } - - if (hook->type == HOOKTYPE_FORWARD_OVERWRITE) { - hook_forward_overwrite(hook, offset); - } -} - -/* - * Creates memory close to the target function, used to force the actual hook - * to use a 32bit jump instead of a 64bit jump, thus preventing the chance of - * overwriting adjacent functions, which can cause a crash. (by R1CH) - */ -static void setup_64bit_bounce(struct func_hook *hook, intptr_t *offset) -{ - MEMORY_BASIC_INFORMATION mbi; - uintptr_t address; - uintptr_t newdiff; - SYSTEM_INFO si; - bool success; - int pagesize; - int i; - - success = VirtualQueryEx(GetCurrentProcess(), - (const void *)hook->func_addr, &mbi, - sizeof(mbi)); - if (!success) - return; - - GetSystemInfo(&si); - pagesize = (int)si.dwAllocationGranularity; - - address = (uintptr_t)mbi.AllocationBase - pagesize; - for (i = 0; i < 256; i++, address -= pagesize) { - hook->bounce_addr = VirtualAlloc((LPVOID)address, pagesize, - MEM_RESERVE | MEM_COMMIT, - PAGE_EXECUTE_READWRITE); - if (hook->bounce_addr) - break; - } - - if (!hook->bounce_addr) { - address = (uintptr_t)mbi.AllocationBase + mbi.RegionSize + - pagesize; - for (i = 0; i < 256; i++, address += pagesize) { - hook->bounce_addr = - VirtualAlloc((LPVOID)address, pagesize, - MEM_RESERVE | MEM_COMMIT, - PAGE_EXECUTE_READWRITE); - if (hook->bounce_addr) - break; - } - } - - if (!hook->bounce_addr) - return; - - if ((hook->func_addr + 5) > (uintptr_t)hook->bounce_addr) - newdiff = hook->func_addr + 5 - (uintptr_t)hook->bounce_addr; - else - newdiff = (uintptr_t)hook->bounce_addr - hook->func_addr + 5; - - if (newdiff <= 0x7ffffff0) { - uint8_t *addr = (uint8_t *)hook->bounce_addr; - - FillMemory(hook->bounce_addr, pagesize, 0xCC); - - *(addr++) = 0xFF; - *(addr++) = 0x25; - *((uint32_t *)addr) = 0; - *((uint64_t *)(addr + 4)) = hook->hook_addr; - - hook->hook_addr = (uint64_t)hook->bounce_addr; - *offset = hook->hook_addr - hook->func_addr - JMP_32_SIZE; - hook->is_64bit_jump = false; - } -} - -void do_hook(struct func_hook *hook, bool force) -{ - intptr_t offset; - - if (!force && hook->hooked) - return; - - /* copy back the memory that was previously encountered to preserve - * the current hook and any newer hooks on top */ - if (hook->started && !force) { - uintptr_t addr; - size_t size; - - if (hook->type == HOOKTYPE_REVERSE_CHAIN) { - addr = hook->func_addr - JMP_32_SIZE; - size = JMP_32_SIZE; - } else { - addr = hook->func_addr; - size = patch_size(hook); - } - - memcpy((void *)addr, hook->rehook_data, size); - hook->hooked = true; - return; - } - - offset = hook->hook_addr - hook->func_addr - JMP_32_SIZE; - -#ifdef _WIN64 - hook->is_64bit_jump = (llabs(offset) >= 0x7fffffff); - - if (hook->is_64bit_jump) { - if (!hook->attempted_bounce) { - hook->attempted_bounce = true; - setup_64bit_bounce(hook, &offset); - } - - if (hook->is_64bit_jump) { - rehook64(hook); - return; - } - } -#endif - - rehook32(hook, force, offset); -} - -void unhook(struct func_hook *hook) -{ - uintptr_t addr; - size_t size; - - if (!hook->hooked) - return; - - if (hook->type == HOOKTYPE_REVERSE_CHAIN) { - size = JMP_32_SIZE; - addr = (hook->func_addr - JMP_32_SIZE); - } else { - size = patch_size(hook); - addr = hook->func_addr; - } - - fix_permissions((void *)addr, size); - memcpy(hook->rehook_data, (void *)addr, size); - - if (hook->type == HOOKTYPE_FORWARD_OVERWRITE) - memcpy((void *)hook->func_addr, hook->unhook_data, size); - - hook->hooked = false; -} diff --git a/plugins/win-capture/funchook.h b/plugins/win-capture/funchook.h deleted file mode 100644 index f97c44593..000000000 --- a/plugins/win-capture/funchook.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#else -#if defined(_MSC_VER) && !defined(inline) -#define inline __inline -#endif -#endif - -enum hook_type { - HOOKTYPE_FORWARD_OVERWRITE, - HOOKTYPE_FORWARD_CHAIN, - HOOKTYPE_REVERSE_CHAIN -}; - -struct func_hook { - void *call_addr; - - uintptr_t func_addr; /* function being hooked to */ - uintptr_t hook_addr; /* hook function itself */ - void *bounce_addr; - const char *name; - enum hook_type type; - bool is_64bit_jump; - bool hooked; - bool started; - bool attempted_bounce; - uint8_t unhook_data[14]; - uint8_t rehook_data[14]; -}; - -extern void hook_init(struct func_hook *hook, void *func_addr, void *hook_addr, - const char *name); -extern void hook_start(struct func_hook *hook); -extern void do_hook(struct func_hook *hook, bool force); -extern void unhook(struct func_hook *hook); - -static inline void rehook(struct func_hook *hook) -{ - do_hook(hook, false); -} - -static inline void force_rehook(struct func_hook *hook) -{ - do_hook(hook, true); -} - -#ifdef __cplusplus -} -#endif diff --git a/plugins/win-capture/graphics-hook-ver.h b/plugins/win-capture/graphics-hook-ver.h index a93bfde71..ade12980a 100644 --- a/plugins/win-capture/graphics-hook-ver.h +++ b/plugins/win-capture/graphics-hook-ver.h @@ -12,7 +12,7 @@ * THIS IS YOUR ONLY WARNING. */ #define HOOK_VER_MAJOR 1 -#define HOOK_VER_MINOR 6 +#define HOOK_VER_MINOR 7 #define HOOK_VER_PATCH 0 #define STRINGIFY(s) #s diff --git a/plugins/win-capture/graphics-hook/CMakeLists.txt b/plugins/win-capture/graphics-hook/CMakeLists.txt index ca42b6fc6..554bbc29b 100644 --- a/plugins/win-capture/graphics-hook/CMakeLists.txt +++ b/plugins/win-capture/graphics-hook/CMakeLists.txt @@ -17,14 +17,12 @@ set(graphics-hook_HEADERS ../graphics-hook-ver.h ../graphics-hook-info.h ../hook-helpers.h - ../funchook.h ../obfuscate.h gl-decs.h d3d9-patches.hpp) set(graphics-hook_SOURCES graphics-hook.c - ../funchook.c ../obfuscate.c gl-capture.c d3d8-capture.cpp diff --git a/plugins/win-capture/graphics-hook/d3d10-capture.cpp b/plugins/win-capture/graphics-hook/d3d10-capture.cpp index e627d43ea..932486316 100644 --- a/plugins/win-capture/graphics-hook/d3d10-capture.cpp +++ b/plugins/win-capture/graphics-hook/d3d10-capture.cpp @@ -3,7 +3,6 @@ #include "dxgi-helpers.hpp" #include "graphics-hook.h" -#include "../funchook.h" struct d3d10_data { ID3D10Device *device; /* do not release */ diff --git a/plugins/win-capture/graphics-hook/d3d11-capture.cpp b/plugins/win-capture/graphics-hook/d3d11-capture.cpp index a71517096..63b488721 100644 --- a/plugins/win-capture/graphics-hook/d3d11-capture.cpp +++ b/plugins/win-capture/graphics-hook/d3d11-capture.cpp @@ -3,7 +3,6 @@ #include "dxgi-helpers.hpp" #include "graphics-hook.h" -#include "../funchook.h" struct d3d11_data { ID3D11Device *device; /* do not release */ diff --git a/plugins/win-capture/graphics-hook/d3d8-capture.cpp b/plugins/win-capture/graphics-hook/d3d8-capture.cpp index 2f46d0c4c..e5a2b11b7 100644 --- a/plugins/win-capture/graphics-hook/d3d8-capture.cpp +++ b/plugins/win-capture/graphics-hook/d3d8-capture.cpp @@ -2,7 +2,8 @@ #include "../d3d8-api/d3d8.h" #include "graphics-hook.h" -#include "../funchook.h" + +#include typedef HRESULT(STDMETHODCALLTYPE *reset_t)(IDirect3DDevice8 *, D3DPRESENT_PARAMETERS *); @@ -10,8 +11,8 @@ typedef HRESULT(STDMETHODCALLTYPE *present_t)(IDirect3DDevice8 *, CONST RECT *, CONST RECT *, HWND, CONST RGNDATA *); -static struct func_hook present; -static struct func_hook reset; +reset_t RealReset = NULL; +present_t RealPresent = NULL; struct d3d8_data { HMODULE d3d8; @@ -250,17 +251,10 @@ static void d3d8_capture(IDirect3DDevice8 *device, static HRESULT STDMETHODCALLTYPE hook_reset(IDirect3DDevice8 *device, D3DPRESENT_PARAMETERS *parameters) { - HRESULT hr; - if (capture_active()) d3d8_free(); - unhook(&reset); - reset_t call = (reset_t)reset.call_addr; - hr = call(device, parameters); - rehook(&reset); - - return hr; + return RealReset(device, parameters); } static bool hooked_reset = false; @@ -269,11 +263,19 @@ static void setup_reset_hooks(IDirect3DDevice8 *device) { uintptr_t *vtable = *(uintptr_t **)device; - hook_init(&reset, (void *)vtable[14], (void *)hook_reset, - "IDirect3DDevice8::Reset"); - rehook(&reset); + DetourTransactionBegin(); - hooked_reset = true; + RealReset = (reset_t)vtable[14]; + DetourAttach((PVOID *)&RealReset, hook_reset); + + const LONG error = DetourTransactionCommit(); + const bool success = error == NO_ERROR; + if (success) { + hlog("Hooked IDirect3DDevice8::Reset"); + hooked_reset = true; + } else { + RealReset = nullptr; + } } static HRESULT STDMETHODCALLTYPE hook_present(IDirect3DDevice8 *device, @@ -283,7 +285,6 @@ static HRESULT STDMETHODCALLTYPE hook_present(IDirect3DDevice8 *device, CONST RGNDATA *dirty_region) { IDirect3DSurface8 *backbuffer; - HRESULT hr; if (!hooked_reset) setup_reset_hooks(device); @@ -294,12 +295,8 @@ static HRESULT STDMETHODCALLTYPE hook_present(IDirect3DDevice8 *device, backbuffer->Release(); } - unhook(&present); - present_t call = (present_t)present.call_addr; - hr = call(device, src_rect, dst_rect, override_window, dirty_region); - rehook(&present); - - return hr; + return RealPresent(device, src_rect, dst_rect, override_window, + dirty_region); } typedef IDirect3D8 *(WINAPI *d3d8create_t)(UINT); @@ -388,11 +385,20 @@ bool hook_d3d8(void) return true; } - hook_init(&present, present_addr, (void *)hook_present, - "IDirect3DDevice8::Present"); + DetourTransactionBegin(); - rehook(&present); + RealPresent = (present_t)present_addr; + DetourAttach((PVOID *)&RealPresent, hook_present); - hlog("Hooked D3D8"); - return true; + const LONG error = DetourTransactionCommit(); + const bool success = error == NO_ERROR; + if (success) { + hlog("Hooked IDirect3DDevice8::Present"); + hlog("Hooked D3D8"); + } else { + RealPresent = nullptr; + hlog("Failed to attach Detours hook: %ld", error); + } + + return success; } diff --git a/plugins/win-capture/graphics-hook/d3d9-capture.cpp b/plugins/win-capture/graphics-hook/d3d9-capture.cpp index 92b5eacc7..7ee411522 100644 --- a/plugins/win-capture/graphics-hook/d3d9-capture.cpp +++ b/plugins/win-capture/graphics-hook/d3d9-capture.cpp @@ -3,13 +3,14 @@ #include #include "graphics-hook.h" -#include "../funchook.h" #include "d3d9-patches.hpp" +#include + typedef HRESULT(STDMETHODCALLTYPE *present_t)(IDirect3DDevice9 *, CONST RECT *, CONST RECT *, HWND, CONST RGNDATA *); -typedef HRESULT(STDMETHODCALLTYPE *present_ex_t)(IDirect3DDevice9 *, +typedef HRESULT(STDMETHODCALLTYPE *present_ex_t)(IDirect3DDevice9Ex *, CONST RECT *, CONST RECT *, HWND, CONST RGNDATA *, DWORD); typedef HRESULT(STDMETHODCALLTYPE *present_swap_t)(IDirect3DSwapChain9 *, @@ -24,11 +25,11 @@ typedef HRESULT(STDMETHODCALLTYPE *reset_ex_t)(IDirect3DDevice9 *, typedef HRESULT(WINAPI *createfactory1_t)(REFIID, void **); -static struct func_hook present; -static struct func_hook present_ex; -static struct func_hook present_swap; -static struct func_hook reset; -static struct func_hook reset_ex; +present_t RealPresent = NULL; +present_ex_t RealPresentEx = NULL; +present_swap_t RealPresentSwap = NULL; +reset_t RealReset = NULL; +reset_ex_t RealResetEx = NULL; struct d3d9_data { HMODULE d3d9; @@ -641,17 +642,14 @@ static HRESULT STDMETHODCALLTYPE hook_present(IDirect3DDevice9 *device, CONST RGNDATA *dirty_region) { IDirect3DSurface9 *backbuffer = nullptr; - HRESULT hr; if (!hooked_reset) setup_reset_hooks(device); present_begin(device, backbuffer); - unhook(&present); - present_t call = (present_t)present.call_addr; - hr = call(device, src_rect, dst_rect, override_window, dirty_region); - rehook(&present); + const HRESULT hr = RealPresent(device, src_rect, dst_rect, + override_window, dirty_region); present_end(device, backbuffer); @@ -659,22 +657,18 @@ static HRESULT STDMETHODCALLTYPE hook_present(IDirect3DDevice9 *device, } static HRESULT STDMETHODCALLTYPE hook_present_ex( - IDirect3DDevice9 *device, CONST RECT *src_rect, CONST RECT *dst_rect, + IDirect3DDevice9Ex *device, CONST RECT *src_rect, CONST RECT *dst_rect, HWND override_window, CONST RGNDATA *dirty_region, DWORD flags) { IDirect3DSurface9 *backbuffer = nullptr; - HRESULT hr; if (!hooked_reset) setup_reset_hooks(device); present_begin(device, backbuffer); - unhook(&present_ex); - present_ex_t call = (present_ex_t)present_ex.call_addr; - hr = call(device, src_rect, dst_rect, override_window, dirty_region, - flags); - rehook(&present_ex); + const HRESULT hr = RealPresentEx(device, src_rect, dst_rect, + override_window, dirty_region, flags); present_end(device, backbuffer); @@ -687,12 +681,11 @@ static HRESULT STDMETHODCALLTYPE hook_present_swap( { IDirect3DSurface9 *backbuffer = nullptr; IDirect3DDevice9 *device = nullptr; - HRESULT hr; if (!present_recurse) { - hr = swap->GetDevice(&device); - if (SUCCEEDED(hr)) { - device->Release(); + IDirect3DDevice9 *temp; + if (SUCCEEDED(swap->GetDevice(&temp))) { + device = temp; } } @@ -703,14 +696,13 @@ static HRESULT STDMETHODCALLTYPE hook_present_swap( present_begin(device, backbuffer); } - unhook(&present_swap); - present_swap_t call = (present_swap_t)present_swap.call_addr; - hr = call(swap, src_rect, dst_rect, override_window, dirty_region, - flags); - rehook(&present_swap); + const HRESULT hr = RealPresentSwap( + swap, src_rect, dst_rect, override_window, dirty_region, flags); - if (device) + if (device) { present_end(device, backbuffer); + device->Release(); + } return hr; } @@ -718,34 +710,20 @@ static HRESULT STDMETHODCALLTYPE hook_present_swap( static HRESULT STDMETHODCALLTYPE hook_reset(IDirect3DDevice9 *device, D3DPRESENT_PARAMETERS *params) { - HRESULT hr; - if (capture_active()) d3d9_free(); - unhook(&reset); - reset_t call = (reset_t)reset.call_addr; - hr = call(device, params); - rehook(&reset); - - return hr; + return RealReset(device, params); } static HRESULT STDMETHODCALLTYPE hook_reset_ex(IDirect3DDevice9 *device, D3DPRESENT_PARAMETERS *params, D3DDISPLAYMODEEX *dmex) { - HRESULT hr; - if (capture_active()) d3d9_free(); - unhook(&reset_ex); - reset_ex_t call = (reset_ex_t)reset_ex.call_addr; - hr = call(device, params, dmex); - rehook(&reset_ex); - - return hr; + return RealResetEx(device, params, dmex); } static void setup_reset_hooks(IDirect3DDevice9 *device) @@ -754,21 +732,30 @@ static void setup_reset_hooks(IDirect3DDevice9 *device) uintptr_t *vtable = *(uintptr_t **)device; HRESULT hr; - hook_init(&reset, (void *)vtable[16], (void *)hook_reset, - "IDirect3DDevice9::Reset"); - rehook(&reset); + DetourTransactionBegin(); - hr = device->QueryInterface(__uuidof(IDirect3DDevice9Ex), - (void **)&d3d9ex); + RealReset = (reset_t)vtable[16]; + DetourAttach((PVOID *)&RealReset, hook_reset); + + hr = device->QueryInterface(IID_PPV_ARGS(&d3d9ex)); if (SUCCEEDED(hr)) { - hook_init(&reset_ex, (void *)vtable[132], (void *)hook_reset_ex, - "IDirect3DDevice9Ex::ResetEx"); - rehook(&reset_ex); + RealResetEx = (reset_ex_t)vtable[132]; + DetourAttach((PVOID *)&RealResetEx, hook_reset_ex); d3d9ex->Release(); } - hooked_reset = true; + const LONG error = DetourTransactionCommit(); + const bool success = error == NO_ERROR; + if (success) { + hlog("Hooked IDirect3DDevice9::Reset"); + if (RealResetEx) + hlog("Hooked IDirect3DDevice9Ex::ResetEx"); + hooked_reset = true; + } else { + RealReset = nullptr; + RealResetEx = nullptr; + } } typedef HRESULT(WINAPI *d3d9create_ex_t)(UINT, IDirect3D9Ex **); @@ -878,23 +865,37 @@ bool hook_d3d9(void) return true; } + DetourTransactionBegin(); + if (present_swap_addr) { - hook_init(&present_swap, present_swap_addr, - (void *)hook_present_swap, - "IDirect3DSwapChain9::Present"); - rehook(&present_swap); + RealPresentSwap = (present_swap_t)present_swap_addr; + DetourAttach((PVOID *)&RealPresentSwap, hook_present_swap); } if (present_ex_addr) { - hook_init(&present_ex, present_ex_addr, (void *)hook_present_ex, - "IDirect3DDevice9Ex::PresentEx"); - rehook(&present_ex); + RealPresentEx = (present_ex_t)present_ex_addr; + DetourAttach((PVOID *)&RealPresentEx, hook_present_ex); } if (present_addr) { - hook_init(&present, present_addr, (void *)hook_present, - "IDirect3DDevice9::Present"); - rehook(&present); + RealPresent = (present_t)present_addr; + DetourAttach((PVOID *)&RealPresent, hook_present); } - hlog("Hooked D3D9"); - return true; + const LONG error = DetourTransactionCommit(); + const bool success = error == NO_ERROR; + if (success) { + if (RealPresentSwap) + hlog("Hooked IDirect3DSwapChain9::Present"); + if (RealPresentEx) + hlog("Hooked IDirect3DDevice9Ex::PresentEx"); + if (RealPresent) + hlog("Hooked IDirect3DDevice9::Present"); + hlog("Hooked D3D9"); + } else { + RealPresentSwap = nullptr; + RealPresentEx = nullptr; + RealPresent = nullptr; + hlog("Failed to attach Detours hook: %ld", error); + } + + return success; } diff --git a/plugins/win-capture/graphics-hook/dxgi-capture.cpp b/plugins/win-capture/graphics-hook/dxgi-capture.cpp index 5e031529d..6f43c0d45 100644 --- a/plugins/win-capture/graphics-hook/dxgi-capture.cpp +++ b/plugins/win-capture/graphics-hook/dxgi-capture.cpp @@ -5,7 +5,8 @@ #include #include "graphics-hook.h" -#include "../funchook.h" + +#include #if COMPILE_D3D12_HOOK #include @@ -19,10 +20,10 @@ typedef HRESULT(STDMETHODCALLTYPE *present_t)(IDXGISwapChain *, UINT, UINT); typedef HRESULT(STDMETHODCALLTYPE *present1_t)(IDXGISwapChain1 *, UINT, UINT, const DXGI_PRESENT_PARAMETERS *); -static struct func_hook release; -static struct func_hook resize_buffers; -static struct func_hook present; -static struct func_hook present1; +release_t RealRelease = nullptr; +resize_buffers_t RealResizeBuffers = nullptr; +present_t RealPresent = nullptr; +present1_t RealPresent1 = nullptr; thread_local bool dxgi_presenting = false; struct ID3D12CommandQueue *dxgi_possible_swap_queues[8]{}; @@ -112,10 +113,7 @@ static bool setup_dxgi(IDXGISwapChain *swap) static ULONG STDMETHODCALLTYPE hook_release(IUnknown *unknown) { - unhook(&release); - release_t call = (release_t)release.call_addr; - ULONG refs = call(unknown); - rehook(&release); + const ULONG refs = RealRelease(unknown); hlog_verbose("Release callback: Refs=%lu", refs); if (unknown == data.swap && refs == 0) { @@ -155,11 +153,8 @@ static HRESULT STDMETHODCALLTYPE hook_resize_buffers(IDXGISwapChain *swap, data.free(); data.free = nullptr; - unhook(&resize_buffers); - resize_buffers_t call = (resize_buffers_t)resize_buffers.call_addr; - const HRESULT hr = - call(swap, buffer_count, width, height, format, flags); - rehook(&resize_buffers); + const HRESULT hr = RealResizeBuffers(swap, buffer_count, width, height, + format, flags); resize_buffers_called = true; @@ -229,10 +224,7 @@ static HRESULT STDMETHODCALLTYPE hook_present(IDXGISwapChain *swap, } dxgi_presenting = true; - unhook(&present); - present_t call = (present_t)present.call_addr; - const HRESULT hr = call(swap, sync_interval, flags); - rehook(&present); + const HRESULT hr = RealPresent(swap, sync_interval, flags); dxgi_presenting = false; dxgi_present_attempted = true; @@ -291,10 +283,7 @@ hook_present1(IDXGISwapChain1 *swap, UINT sync_interval, UINT flags, } dxgi_presenting = true; - unhook(&present1); - present1_t call = (present1_t)present1.call_addr; - const HRESULT hr = call(swap, sync_interval, flags, params); - rehook(&present1); + const HRESULT hr = RealPresent1(swap, sync_interval, flags, params); dxgi_presenting = false; dxgi_present_attempted = true; @@ -337,30 +326,41 @@ bool hook_dxgi(void) release_addr = get_offset_addr( dxgi_module, global_hook_info->offsets.dxgi2.release); - hook_init(&present, present_addr, (void *)hook_present, - "IDXGISwapChain::Present"); - hlog("Hooked IDXGISwapChain::Present"); - hook_init(&resize_buffers, resize_addr, (void *)hook_resize_buffers, - "IDXGISwapChain::ResizeBuffers"); - hlog("Hooked IDXGISwapChain::ResizeBuffers"); + DetourTransactionBegin(); + + RealPresent = (present_t)present_addr; + DetourAttach(&(PVOID &)RealPresent, hook_present); + + RealResizeBuffers = (resize_buffers_t)resize_addr; + DetourAttach(&(PVOID &)RealResizeBuffers, hook_resize_buffers); + if (present1_addr) { - hook_init(&present1, present1_addr, (void *)hook_present1, - "IDXGISwapChain1::Present1"); - hlog("Hooked IDXGISwapChain::Present1"); + RealPresent1 = (present1_t)present1_addr; + DetourAttach(&(PVOID &)RealPresent1, hook_present1); } + if (release_addr) { - hook_init(&release, release_addr, (void *)hook_release, - "IDXGISwapChain::Release"); - hlog("Hooked IDXGISwapChain::Release"); + RealRelease = (release_t)release_addr; + DetourAttach(&(PVOID &)RealRelease, hook_release); } - rehook(&resize_buffers); - rehook(&present); - if (present1_addr) - rehook(&present1); - if (release_addr) - rehook(&release); + const LONG error = DetourTransactionCommit(); + const bool success = error == NO_ERROR; + if (success) { + hlog("Hooked IDXGISwapChain::Present"); + hlog("Hooked IDXGISwapChain::ResizeBuffers"); + if (RealPresent1) + hlog("Hooked IDXGISwapChain1::Present1"); + if (RealRelease) + hlog("Hooked IDXGISwapChain::Release"); + hlog("Hooked DXGI"); + } else { + RealPresent = nullptr; + RealResizeBuffers = nullptr; + RealPresent1 = nullptr; + RealRelease = nullptr; + hlog("Failed to attach Detours hook: %ld", error); + } - hlog("Hooked DXGI"); - return true; + return success; } diff --git a/plugins/win-capture/graphics-hook/gl-capture.c b/plugins/win-capture/graphics-hook/gl-capture.c index a7ebd3962..657fc32a3 100644 --- a/plugins/win-capture/graphics-hook/gl-capture.c +++ b/plugins/win-capture/graphics-hook/gl-capture.c @@ -11,7 +11,8 @@ #include "gl-decs.h" #include "graphics-hook.h" -#include "../funchook.h" + +#include #define DUMMY_WINDOW_CLASS_NAME L"graphics_hook_gl_dummy_window" @@ -24,10 +25,15 @@ static const GUID GUID_IDXGIResource = /* clang-format on */ -static struct func_hook swap_buffers; -static struct func_hook wgl_swap_layer_buffers; -static struct func_hook wgl_swap_buffers; -static struct func_hook wgl_delete_context; +typedef BOOL(WINAPI *PFN_SwapBuffers)(HDC); +typedef BOOL(WINAPI *PFN_WglSwapLayerBuffers)(HDC, UINT); +typedef BOOL(WINAPI *PFN_WglSwapBuffers)(HDC); +typedef BOOL(WINAPI *PFN_WglDeleteContext)(HGLRC); + +PFN_SwapBuffers RealSwapBuffers = NULL; +PFN_WglSwapLayerBuffers RealWglSwapLayerBuffers = NULL; +PFN_WglSwapBuffers RealWglSwapBuffers = NULL; +PFN_WglDeleteContext RealWglDeleteContext = NULL; static bool darkest_dungeon_fix = false; static bool functions_initialized = false; @@ -780,14 +786,9 @@ static inline void gl_swap_end(HDC hdc) static BOOL WINAPI hook_swap_buffers(HDC hdc) { - BOOL ret; - gl_swap_begin(hdc); - unhook(&swap_buffers); - BOOL(WINAPI * call)(HDC) = swap_buffers.call_addr; - ret = call(hdc); - rehook(&swap_buffers); + const BOOL ret = RealSwapBuffers(hdc); gl_swap_end(hdc); @@ -796,14 +797,9 @@ static BOOL WINAPI hook_swap_buffers(HDC hdc) static BOOL WINAPI hook_wgl_swap_buffers(HDC hdc) { - BOOL ret; - gl_swap_begin(hdc); - unhook(&wgl_swap_buffers); - BOOL(WINAPI * call)(HDC) = wgl_swap_buffers.call_addr; - ret = call(hdc); - rehook(&wgl_swap_buffers); + const BOOL ret = RealWglSwapBuffers(hdc); gl_swap_end(hdc); @@ -812,14 +808,9 @@ static BOOL WINAPI hook_wgl_swap_buffers(HDC hdc) static BOOL WINAPI hook_wgl_swap_layer_buffers(HDC hdc, UINT planes) { - BOOL ret; - gl_swap_begin(hdc); - unhook(&wgl_swap_layer_buffers); - BOOL(WINAPI * call)(HDC, UINT) = wgl_swap_layer_buffers.call_addr; - ret = call(hdc, planes); - rehook(&wgl_swap_layer_buffers); + const BOOL ret = RealWglSwapLayerBuffers(hdc, planes); gl_swap_end(hdc); @@ -828,8 +819,6 @@ static BOOL WINAPI hook_wgl_swap_layer_buffers(HDC hdc, UINT planes) static BOOL WINAPI hook_wgl_delete_context(HGLRC hrc) { - BOOL ret; - if (capture_active() && functions_initialized) { HDC last_hdc = jimglGetCurrentDC(); HGLRC last_hrc = jimglGetCurrentContext(); @@ -839,12 +828,7 @@ static BOOL WINAPI hook_wgl_delete_context(HGLRC hrc) jimglMakeCurrent(last_hdc, last_hrc); } - unhook(&wgl_delete_context); - BOOL(WINAPI * call)(HGLRC) = wgl_delete_context.call_addr; - ret = call(hrc); - rehook(&wgl_delete_context); - - return ret; + return RealWglDeleteContext(hrc); } static bool gl_register_window(void) @@ -892,24 +876,44 @@ bool hook_gl(void) wgl_slb_proc = base_get_proc("wglSwapLayerBuffers"); wgl_sb_proc = base_get_proc("wglSwapBuffers"); - hook_init(&swap_buffers, SwapBuffers, hook_swap_buffers, "SwapBuffers"); + DetourTransactionBegin(); + + RealSwapBuffers = SwapBuffers; + DetourAttach((PVOID *)&RealSwapBuffers, hook_swap_buffers); if (wgl_dc_proc) { - hook_init(&wgl_delete_context, wgl_dc_proc, - hook_wgl_delete_context, "wglDeleteContext"); - rehook(&wgl_delete_context); + RealWglDeleteContext = (PFN_WglDeleteContext)wgl_dc_proc; + DetourAttach((PVOID *)&RealWglDeleteContext, + hook_wgl_delete_context); } if (wgl_slb_proc) { - hook_init(&wgl_swap_layer_buffers, wgl_slb_proc, - hook_wgl_swap_layer_buffers, "wglSwapLayerBuffers"); - rehook(&wgl_swap_layer_buffers); + RealWglSwapLayerBuffers = (PFN_WglSwapLayerBuffers)wgl_slb_proc; + DetourAttach((PVOID *)&RealWglSwapLayerBuffers, + hook_wgl_swap_layer_buffers); } if (wgl_sb_proc) { - hook_init(&wgl_swap_buffers, wgl_sb_proc, hook_wgl_swap_buffers, - "wglSwapBuffers"); - rehook(&wgl_swap_buffers); + RealWglSwapBuffers = (PFN_WglSwapBuffers)wgl_sb_proc; + DetourAttach((PVOID *)&RealWglSwapBuffers, + hook_wgl_swap_buffers); } - rehook(&swap_buffers); + const LONG error = DetourTransactionCommit(); + const bool success = error == NO_ERROR; + if (success) { + hlog("Hooked SwapBuffers"); + if (RealWglDeleteContext) + hlog("Hooked wglDeleteContext"); + if (RealWglSwapLayerBuffers) + hlog("Hooked wglSwapLayerBuffers"); + if (RealWglSwapBuffers) + hlog("Hooked wglSwapBuffers"); + hlog("Hooked GL"); + } else { + RealSwapBuffers = NULL; + RealWglDeleteContext = NULL; + RealWglSwapLayerBuffers = NULL; + RealWglSwapBuffers = NULL; + hlog("Failed to attach Detours hook: %ld", error); + } - return true; + return success; } diff --git a/plugins/win-capture/graphics-hook/graphics-hook.c b/plugins/win-capture/graphics-hook/graphics-hook.c index 12600243c..87ac4540d 100644 --- a/plugins/win-capture/graphics-hook/graphics-hook.c +++ b/plugins/win-capture/graphics-hook/graphics-hook.c @@ -4,7 +4,6 @@ #include "graphics-hook.h" #include "../graphics-hook-ver.h" #include "../obfuscate.h" -#include "../funchook.h" #define DEBUG_OUTPUT