From 68d3c75c95a9e0102204aabff10bded7453aae27 Mon Sep 17 00:00:00 2001 From: narzoul Date: Mon, 21 Mar 2016 22:51:56 +0100 Subject: [PATCH] Extracted function hooking to its own unit --- DDrawCompat/CompatGdi.cpp | 60 ----------------- DDrawCompat/CompatGdi.h | 26 -------- DDrawCompat/CompatGdiCaret.cpp | 18 ++--- DDrawCompat/CompatGdiDcFunctions.cpp | 39 +++++++---- DDrawCompat/CompatGdiPaintHandlers.cpp | 24 +++---- DDrawCompat/CompatGdiScrollBar.cpp | 3 +- DDrawCompat/CompatGdiScrollFunctions.cpp | 15 ++--- DDrawCompat/CompatGdiTitleBar.cpp | 5 +- DDrawCompat/CompatVtable.cpp | 2 +- DDrawCompat/CompatVtable.h | 26 ++++---- DDrawCompat/DDrawCompat.vcxproj | 2 + DDrawCompat/DDrawCompat.vcxproj.filters | 6 ++ DDrawCompat/Hook.cpp | 83 ++++++++++++++++++++++++ DDrawCompat/Hook.h | 29 +++++++++ DDrawCompat/RealPrimarySurface.cpp | 3 +- 15 files changed, 193 insertions(+), 148 deletions(-) create mode 100644 DDrawCompat/Hook.cpp create mode 100644 DDrawCompat/Hook.h diff --git a/DDrawCompat/CompatGdi.cpp b/DDrawCompat/CompatGdi.cpp index 584f5ae..77cab06 100644 --- a/DDrawCompat/CompatGdi.cpp +++ b/DDrawCompat/CompatGdi.cpp @@ -23,44 +23,6 @@ namespace bool g_isPaletteUsed = false; PALETTEENTRY g_usedPaletteEntries[256] = {}; - FARPROC getProcAddress(HMODULE module, const char* procName) - { - if (!module || !procName) - { - return nullptr; - } - - PIMAGE_DOS_HEADER dosHeader = reinterpret_cast(module); - if (IMAGE_DOS_SIGNATURE != dosHeader->e_magic) { - return nullptr; - } - char* moduleBase = reinterpret_cast(module); - - PIMAGE_NT_HEADERS ntHeader = reinterpret_cast( - reinterpret_cast(dosHeader) + dosHeader->e_lfanew); - if (IMAGE_NT_SIGNATURE != ntHeader->Signature) - { - return nullptr; - } - - PIMAGE_EXPORT_DIRECTORY exportDir = reinterpret_cast( - moduleBase + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); - - DWORD* rvaOfNames = reinterpret_cast(moduleBase + exportDir->AddressOfNames); - - for (DWORD i = 0; i < exportDir->NumberOfNames; ++i) - { - if (0 == strcmp(procName, moduleBase + rvaOfNames[i])) - { - WORD* nameOrds = reinterpret_cast(moduleBase + exportDir->AddressOfNameOrdinals); - DWORD* rvaOfFunctions = reinterpret_cast(moduleBase + exportDir->AddressOfFunctions); - return reinterpret_cast(moduleBase + rvaOfFunctions[nameOrds[i]]); - } - } - - return nullptr; - } - BOOL CALLBACK invalidateWindow(HWND hwnd, LPARAM lParam) { if (!IsWindowVisible(hwnd)) @@ -157,7 +119,6 @@ namespace namespace CompatGdi { CRITICAL_SECTION g_gdiCriticalSection; - std::unordered_map g_funcNames; GdiScopedThreadLock::GdiScopedThreadLock() : m_isLocked(true) { @@ -252,27 +213,6 @@ namespace CompatGdi } } - void hookGdiFunction(const char* moduleName, const char* funcName, void*& origFuncPtr, void* newFuncPtr) - { -#ifdef _DEBUG - g_funcNames[origFuncPtr] = funcName; -#endif - - FARPROC procAddr = getProcAddress(GetModuleHandle(moduleName), funcName); - if (!procAddr) - { - Compat::Log() << "Failed to load the address of a GDI function: " << funcName; - return; - } - - origFuncPtr = procAddr; - if (NO_ERROR != DetourAttach(&origFuncPtr, newFuncPtr)) - { - Compat::Log() << "Failed to hook a GDI function: " << funcName; - return; - } - } - void hookWndProc(LPCSTR className, WNDPROC &oldWndProc, WNDPROC newWndProc) { HWND hwnd = CreateWindow(className, nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, 0); diff --git a/DDrawCompat/CompatGdi.h b/DDrawCompat/CompatGdi.h index 6e5b6aa..690a79e 100644 --- a/DDrawCompat/CompatGdi.h +++ b/DDrawCompat/CompatGdi.h @@ -2,17 +2,8 @@ #define WIN32_LEAN_AND_MEAN -#include - #include -#include "DDrawLog.h" - -#define CALL_ORIG_GDI(func) CompatGdi::getOrigFuncPtr() - -#define HOOK_GDI_FUNCTION(module, func, newFunc) \ - CompatGdi::hookGdiFunction(#module, #func, &newFunc) - namespace CompatGdi { class GdiScopedThreadLock @@ -26,27 +17,10 @@ namespace CompatGdi }; extern CRITICAL_SECTION g_gdiCriticalSection; - extern std::unordered_map g_funcNames; bool beginGdiRendering(); void endGdiRendering(); - template - OrigFuncPtr& getOrigFuncPtr() - { - static OrigFuncPtr origFuncPtr = origFunc; - return origFuncPtr; - } - - void hookGdiFunction(const char* moduleName, const char* funcName, void*& origFuncPtr, void* newFuncPtr); - - template - void hookGdiFunction(const char* moduleName, const char* funcName, OrigFuncPtr newFuncPtr) - { - hookGdiFunction(moduleName, funcName, - reinterpret_cast(getOrigFuncPtr()), newFuncPtr); - } - void hookWndProc(LPCSTR className, WNDPROC &oldWndProc, WNDPROC newWndProc); void installHooks(); void invalidate(const RECT* rect); diff --git a/DDrawCompat/CompatGdiCaret.cpp b/DDrawCompat/CompatGdiCaret.cpp index 9842e32..9735dff 100644 --- a/DDrawCompat/CompatGdiCaret.cpp +++ b/DDrawCompat/CompatGdiCaret.cpp @@ -3,11 +3,11 @@ #include #include -#include #include "CompatGdi.h" #include "CompatGdiCaret.h" #include "CompatGdiDc.h" +#include "Hook.h" namespace { @@ -144,7 +144,7 @@ namespace BOOL WINAPI createCaret(HWND hWnd, HBITMAP hBitmap, int nWidth, int nHeight) { - BOOL result = CALL_ORIG_GDI(CreateCaret)(hWnd, hBitmap, nWidth, nHeight); + BOOL result = CALL_ORIG_FUNC(CreateCaret)(hWnd, hBitmap, nWidth, nHeight); if (result) { CaretScopedThreadLock caretLock; @@ -161,7 +161,7 @@ namespace BOOL WINAPI hideCaret(HWND hWnd) { - BOOL result = CALL_ORIG_GDI(HideCaret)(hWnd); + BOOL result = CALL_ORIG_FUNC(HideCaret)(hWnd); if (result) { CaretScopedThreadLock caretLock; @@ -176,7 +176,7 @@ namespace BOOL WINAPI showCaret(HWND hWnd) { - if (!CALL_ORIG_GDI(ShowCaret)(hWnd)) + if (!CALL_ORIG_FUNC(ShowCaret)(hWnd)) { return FALSE; } @@ -213,11 +213,11 @@ namespace CompatGdiCaret { InitializeCriticalSection(&g_caretCriticalSection); - DetourTransactionBegin(); - HOOK_GDI_FUNCTION(user32, CreateCaret, createCaret); - HOOK_GDI_FUNCTION(user32, HideCaret, hideCaret); - HOOK_GDI_FUNCTION(user32, ShowCaret, showCaret); - DetourTransactionCommit(); + Compat::beginHookTransaction(); + HOOK_FUNCTION(user32, CreateCaret, createCaret); + HOOK_FUNCTION(user32, HideCaret, hideCaret); + HOOK_FUNCTION(user32, ShowCaret, showCaret); + Compat::endHookTransaction(); const DWORD threadId = GetCurrentThreadId(); SetWinEventHook(EVENT_OBJECT_DESTROY, EVENT_OBJECT_DESTROY, diff --git a/DDrawCompat/CompatGdiDcFunctions.cpp b/DDrawCompat/CompatGdiDcFunctions.cpp index 415a2d2..4aac1a1 100644 --- a/DDrawCompat/CompatGdiDcFunctions.cpp +++ b/DDrawCompat/CompatGdiDcFunctions.cpp @@ -1,13 +1,16 @@ +#include + #include "CompatGdi.h" #include "CompatGdiDc.h" #include "CompatGdiDcFunctions.h" #include "DDrawLog.h" +#include "Hook.h" #include "RealPrimarySurface.h" -#include - namespace { + std::unordered_map g_funcNames; + BOOL WINAPI PolyPatBlt(HDC, DWORD, DWORD, DWORD, DWORD) { return FALSE; } template @@ -61,12 +64,12 @@ namespace Result WINAPI compatGdiDcFunc(Params... params) { #ifdef _DEBUG - Compat::LogEnter(CompatGdi::g_funcNames[origFunc], params...); + Compat::LogEnter(g_funcNames[origFunc], params...); #endif if (!hasDisplayDcArg(params...) || !CompatGdi::beginGdiRendering()) { - Result result = CompatGdi::getOrigFuncPtr()(params...); + Result result = Compat::getOrigFuncPtr()(params...); #ifdef _DEBUG if (!hasDisplayDcArg(params...)) @@ -81,18 +84,18 @@ namespace { Compat::Log() << "Skipping redirection since the primary surface could not be locked"; } - Compat::LogLeave(CompatGdi::g_funcNames[origFunc], params...) << result; + Compat::LogLeave(g_funcNames[origFunc], params...) << result; #endif return result; } - Result result = CompatGdi::getOrigFuncPtr()(replaceDc(params)...); + Result result = Compat::getOrigFuncPtr()(replaceDc(params)...); releaseDc(params...); CompatGdi::endGdiRendering(); #ifdef _DEBUG - Compat::LogLeave(CompatGdi::g_funcNames[origFunc], params...) << result; + Compat::LogLeave(g_funcNames[origFunc], params...) << result; #endif return result; @@ -104,15 +107,25 @@ namespace return &compatGdiDcFunc; } + template + void hookGdiDcFunction(const char* moduleName, const char* funcName) + { +#ifdef _DEBUG + g_funcNames[origFunc] = funcName; +#endif + + Compat::hookFunction( + moduleName, funcName, getCompatGdiDcFuncPtr(origFunc)); + } + HWND WINAPI windowFromDc(HDC dc) { - return CALL_ORIG_GDI(WindowFromDC)(CompatGdiDc::getOrigDc(dc)); + return CALL_ORIG_FUNC(WindowFromDC)(CompatGdiDc::getOrigDc(dc)); } } #define HOOK_GDI_DC_FUNCTION(module, func) \ - CompatGdi::hookGdiFunction( \ - #module, #func, getCompatGdiDcFuncPtr(&func)) + hookGdiDcFunction(#module, #func) #define HOOK_GDI_TEXT_DC_FUNCTION(module, func) \ HOOK_GDI_DC_FUNCTION(module, func##A); \ @@ -122,7 +135,7 @@ namespace CompatGdiDcFunctions { void installHooks() { - DetourTransactionBegin(); + Compat::beginHookTransaction(); // Bitmap functions HOOK_GDI_DC_FUNCTION(msimg32, AlphaBlend); @@ -154,7 +167,7 @@ namespace CompatGdiDcFunctions // Device context functions HOOK_GDI_DC_FUNCTION(gdi32, CreateCompatibleDC); HOOK_GDI_DC_FUNCTION(gdi32, DrawEscape); - HOOK_GDI_FUNCTION(user32, WindowFromDC, windowFromDc); + HOOK_FUNCTION(user32, WindowFromDC, windowFromDc); // Filled shape functions HOOK_GDI_DC_FUNCTION(gdi32, Chord); @@ -213,6 +226,6 @@ namespace CompatGdiDcFunctions // Undocumented functions HOOK_GDI_DC_FUNCTION(gdi32, PolyPatBlt); - DetourTransactionCommit(); + Compat::endHookTransaction(); } } diff --git a/DDrawCompat/CompatGdiPaintHandlers.cpp b/DDrawCompat/CompatGdiPaintHandlers.cpp index d8b76bd..45ff652 100644 --- a/DDrawCompat/CompatGdiPaintHandlers.cpp +++ b/DDrawCompat/CompatGdiPaintHandlers.cpp @@ -3,8 +3,8 @@ #include "CompatGdiPaintHandlers.h" #include "CompatGdiScrollBar.h" #include "CompatGdiTitleBar.h" - -#include +#include "DDrawLog.h" +#include "Hook.h" namespace { @@ -25,12 +25,12 @@ namespace LRESULT WINAPI defDlgProcA(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) { - return defWindowProc(hdlg, msg, wParam, lParam, CALL_ORIG_GDI(DefDlgProcA), "defDlgProcA"); + return defWindowProc(hdlg, msg, wParam, lParam, CALL_ORIG_FUNC(DefDlgProcA), "defDlgProcA"); } LRESULT WINAPI defDlgProcW(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) { - return defWindowProc(hdlg, msg, wParam, lParam, CALL_ORIG_GDI(DefDlgProcW), "defDlgProcW"); + return defWindowProc(hdlg, msg, wParam, lParam, CALL_ORIG_FUNC(DefDlgProcW), "defDlgProcW"); } LRESULT WINAPI defWindowProc( @@ -70,12 +70,12 @@ namespace LRESULT WINAPI defWindowProcA(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - return defWindowProc(hwnd, msg, wParam, lParam, CALL_ORIG_GDI(DefWindowProcA), "defWindowProcA"); + return defWindowProc(hwnd, msg, wParam, lParam, CALL_ORIG_FUNC(DefWindowProcA), "defWindowProcA"); } LRESULT WINAPI defWindowProcW(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - return defWindowProc(hwnd, msg, wParam, lParam, CALL_ORIG_GDI(DefWindowProcW), "defWindowProcW"); + return defWindowProc(hwnd, msg, wParam, lParam, CALL_ORIG_FUNC(DefWindowProcW), "defWindowProcW"); } LRESULT WINAPI editWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) @@ -294,11 +294,11 @@ namespace CompatGdiPaintHandlers CompatGdi::hookWndProc("#32768", g_origMenuWndProc, &menuWndProc); CompatGdi::hookWndProc("ScrollBar", g_origScrollBarWndProc, &scrollBarWndProc); - DetourTransactionBegin(); - HOOK_GDI_FUNCTION(user32, DefWindowProcA, defWindowProcA); - HOOK_GDI_FUNCTION(user32, DefWindowProcW, defWindowProcW); - HOOK_GDI_FUNCTION(user32, DefDlgProcA, defDlgProcA); - HOOK_GDI_FUNCTION(user32, DefDlgProcW, defDlgProcW); - DetourTransactionCommit(); + Compat::beginHookTransaction(); + HOOK_FUNCTION(user32, DefWindowProcA, defWindowProcA); + HOOK_FUNCTION(user32, DefWindowProcW, defWindowProcW); + HOOK_FUNCTION(user32, DefDlgProcA, defDlgProcA); + HOOK_FUNCTION(user32, DefDlgProcW, defDlgProcW); + Compat::endHookTransaction(); } } diff --git a/DDrawCompat/CompatGdiScrollBar.cpp b/DDrawCompat/CompatGdiScrollBar.cpp index 0b949b0..a7cc5af 100644 --- a/DDrawCompat/CompatGdiScrollBar.cpp +++ b/DDrawCompat/CompatGdiScrollBar.cpp @@ -1,5 +1,6 @@ #include "CompatGdi.h" #include "CompatGdiScrollBar.h" +#include "Hook.h" namespace { @@ -72,7 +73,7 @@ namespace CompatGdi } RECT rect = sbci.rect; - CALL_ORIG_GDI(DrawFrameControl)(m_compatDc, &rect, DFC_SCROLL, dfcState | stateFlags); + CALL_ORIG_FUNC(DrawFrameControl)(m_compatDc, &rect, DFC_SCROLL, dfcState | stateFlags); } void ScrollBar::drawHorizArrows() const diff --git a/DDrawCompat/CompatGdiScrollFunctions.cpp b/DDrawCompat/CompatGdiScrollFunctions.cpp index b3e1016..4c2536d 100644 --- a/DDrawCompat/CompatGdiScrollFunctions.cpp +++ b/DDrawCompat/CompatGdiScrollFunctions.cpp @@ -1,7 +1,6 @@ #include "CompatGdi.h" #include "CompatGdiScrollFunctions.h" - -#include +#include "Hook.h" namespace { @@ -12,7 +11,7 @@ namespace _In_ const RECT *lpRect, _In_ const RECT *lpClipRect) { - BOOL result = CALL_ORIG_GDI(ScrollWindow)(hWnd, XAmount, YAmount, lpRect, lpClipRect); + BOOL result = CALL_ORIG_FUNC(ScrollWindow)(hWnd, XAmount, YAmount, lpRect, lpClipRect); CompatGdiScrollFunctions::updateScrolledWindow(hWnd); return result; } @@ -27,7 +26,7 @@ namespace _Out_ LPRECT prcUpdate, _In_ UINT flags) { - int result = CALL_ORIG_GDI(ScrollWindowEx)( + int result = CALL_ORIG_FUNC(ScrollWindowEx)( hWnd, dx, dy, prcScroll, prcClip, hrgnUpdate, prcUpdate, flags); CompatGdiScrollFunctions::updateScrolledWindow(hWnd); return result; @@ -38,10 +37,10 @@ namespace CompatGdiScrollFunctions { void installHooks() { - DetourTransactionBegin(); - HOOK_GDI_FUNCTION(user32, ScrollWindow, scrollWindow); - HOOK_GDI_FUNCTION(user32, ScrollWindowEx, scrollWindowEx); - DetourTransactionCommit(); + Compat::beginHookTransaction(); + HOOK_FUNCTION(user32, ScrollWindow, scrollWindow); + HOOK_FUNCTION(user32, ScrollWindowEx, scrollWindowEx); + Compat::endHookTransaction(); } void updateScrolledWindow(HWND hwnd) diff --git a/DDrawCompat/CompatGdiTitleBar.cpp b/DDrawCompat/CompatGdiTitleBar.cpp index b674e88..461dbd9 100644 --- a/DDrawCompat/CompatGdiTitleBar.cpp +++ b/DDrawCompat/CompatGdiTitleBar.cpp @@ -1,5 +1,6 @@ #include "CompatGdi.h" #include "CompatGdiTitleBar.h" +#include "Hook.h" namespace { @@ -99,7 +100,7 @@ namespace CompatGdi flags |= DC_SMALLCAP; } - CALL_ORIG_GDI(DrawCaption)(m_hwnd, m_compatDc, &m_tbi.rcTitleBar, flags); + CALL_ORIG_FUNC(DrawCaption)(m_hwnd, m_compatDc, &m_tbi.rcTitleBar, flags); } void TitleBar::drawButton(std::size_t tbiIndex, UINT dfcState) const @@ -120,7 +121,7 @@ namespace CompatGdi } RECT rect = m_tbi.rgrect[tbiIndex]; - CALL_ORIG_GDI(DrawFrameControl)(m_compatDc, &rect, DFC_CAPTION, dfcState | stateFlags); + CALL_ORIG_FUNC(DrawFrameControl)(m_compatDc, &rect, DFC_CAPTION, dfcState | stateFlags); } void TitleBar::excludeFromClipRegion() const diff --git a/DDrawCompat/CompatVtable.cpp b/DDrawCompat/CompatVtable.cpp index 1cc4233..c70ee3d 100644 --- a/DDrawCompat/CompatVtable.cpp +++ b/DDrawCompat/CompatVtable.cpp @@ -2,5 +2,5 @@ namespace Compat { - std::map detouredMethods; + std::map g_hookedMethods; } diff --git a/DDrawCompat/CompatVtable.h b/DDrawCompat/CompatVtable.h index f34de6b..f1fabad 100644 --- a/DDrawCompat/CompatVtable.h +++ b/DDrawCompat/CompatVtable.h @@ -1,25 +1,21 @@ #pragma once -#define WIN32_LEAN_AND_MEAN - #include #include #include -#include -#include - #include "DDrawLog.h" #include "DDrawVtableVisitor.h" +#include "Hook.h" template using Vtable = typename std::remove_pointer::type; namespace Compat { - struct DetouredMethodInfo + struct HookedMethodInfo { - DetouredMethodInfo(void*& updatedOrigMethodPtr, std::map& vtablePtrToCompatVtable) + HookedMethodInfo(void*& updatedOrigMethodPtr, std::map& vtablePtrToCompatVtable) : updatedOrigMethodPtr(updatedOrigMethodPtr), vtablePtrToCompatVtable(vtablePtrToCompatVtable) { } @@ -28,7 +24,7 @@ namespace Compat std::map& vtablePtrToCompatVtable; }; - extern std::map detouredMethods; + extern std::map g_hookedMethods; } template @@ -107,8 +103,8 @@ private: void hookMethod(void*& origMethodPtr, void* newMethodPtr) { - auto it = Compat::detouredMethods.find(origMethodPtr); - if (it != Compat::detouredMethods.end()) + auto it = Compat::g_hookedMethods.find(origMethodPtr); + if (it != Compat::g_hookedMethods.end()) { origMethodPtr = it->second.updatedOrigMethodPtr; it->second.vtablePtrToCompatVtable[s_vtablePtr] = &s_compatVtable; @@ -116,11 +112,11 @@ private: else { s_vtablePtrToCompatVtable[s_vtablePtr] = &s_compatVtable; - Compat::detouredMethods.emplace(origMethodPtr, - Compat::DetouredMethodInfo(origMethodPtr, s_vtablePtrToCompatVtable)); - DetourTransactionBegin(); - DetourAttach(&origMethodPtr, newMethodPtr); - DetourTransactionCommit(); + Compat::g_hookedMethods.emplace(origMethodPtr, + Compat::HookedMethodInfo(origMethodPtr, s_vtablePtrToCompatVtable)); + Compat::beginHookTransaction(); + Compat::hookFunction(origMethodPtr, newMethodPtr); + Compat::endHookTransaction(); } } diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index 4dcaed4..f40baa4 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -168,6 +168,7 @@ + @@ -189,6 +190,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index dd2c1ae..a1420c1 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -93,6 +93,9 @@ Header Files + + Header Files + @@ -158,6 +161,9 @@ Source Files + + Source Files + diff --git a/DDrawCompat/Hook.cpp b/DDrawCompat/Hook.cpp new file mode 100644 index 0000000..0aaecd4 --- /dev/null +++ b/DDrawCompat/Hook.cpp @@ -0,0 +1,83 @@ +#define WIN32_LEAN_AND_MEAN + +#include +#include + +#include "DDrawLog.h" +#include "Hook.h" + +namespace +{ + FARPROC getProcAddress(HMODULE module, const char* procName) + { + if (!module || !procName) + { + return nullptr; + } + + PIMAGE_DOS_HEADER dosHeader = reinterpret_cast(module); + if (IMAGE_DOS_SIGNATURE != dosHeader->e_magic) { + return nullptr; + } + char* moduleBase = reinterpret_cast(module); + + PIMAGE_NT_HEADERS ntHeader = reinterpret_cast( + reinterpret_cast(dosHeader) + dosHeader->e_lfanew); + if (IMAGE_NT_SIGNATURE != ntHeader->Signature) + { + return nullptr; + } + + PIMAGE_EXPORT_DIRECTORY exportDir = reinterpret_cast( + moduleBase + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); + + DWORD* rvaOfNames = reinterpret_cast(moduleBase + exportDir->AddressOfNames); + + for (DWORD i = 0; i < exportDir->NumberOfNames; ++i) + { + if (0 == strcmp(procName, moduleBase + rvaOfNames[i])) + { + WORD* nameOrds = reinterpret_cast(moduleBase + exportDir->AddressOfNameOrdinals); + DWORD* rvaOfFunctions = reinterpret_cast(moduleBase + exportDir->AddressOfFunctions); + return reinterpret_cast(moduleBase + rvaOfFunctions[nameOrds[i]]); + } + } + + return nullptr; + } +} + +namespace Compat +{ + void beginHookTransaction() + { + DetourTransactionBegin(); + } + + void endHookTransaction() + { + DetourTransactionCommit(); + } + + void hookFunction(void*& origFuncPtr, void* newFuncPtr) + { + DetourAttach(&origFuncPtr, newFuncPtr); + } + + void hookFunction(const char* moduleName, const char* funcName, void*& origFuncPtr, void* newFuncPtr) + { + FARPROC procAddr = getProcAddress(GetModuleHandle(moduleName), funcName); + if (!procAddr) + { + Compat::Log() << "Failed to load the address of a function: " << funcName; + return; + } + + origFuncPtr = procAddr; + if (NO_ERROR != DetourAttach(&origFuncPtr, newFuncPtr)) + { + Compat::Log() << "Failed to hook a function: " << funcName; + return; + } + } +} \ No newline at end of file diff --git a/DDrawCompat/Hook.h b/DDrawCompat/Hook.h new file mode 100644 index 0000000..2d41e2e --- /dev/null +++ b/DDrawCompat/Hook.h @@ -0,0 +1,29 @@ +#pragma once + +#define CALL_ORIG_FUNC(func) Compat::getOrigFuncPtr() + +#define HOOK_FUNCTION(module, func, newFunc) \ + Compat::hookFunction(#module, #func, &newFunc) + +namespace Compat +{ + void beginHookTransaction(); + void endHookTransaction(); + + template + OrigFuncPtr& getOrigFuncPtr() + { + static OrigFuncPtr origFuncPtr = origFunc; + return origFuncPtr; + } + + void hookFunction(void*& origFuncPtr, void* newFuncPtr); + void hookFunction(const char* moduleName, const char* funcName, void*& origFuncPtr, void* newFuncPtr); + + template + void hookFunction(const char* moduleName, const char* funcName, OrigFuncPtr newFuncPtr) + { + hookFunction(moduleName, funcName, + reinterpret_cast(getOrigFuncPtr()), newFuncPtr); + } +} diff --git a/DDrawCompat/RealPrimarySurface.cpp b/DDrawCompat/RealPrimarySurface.cpp index 1461728..039d429 100644 --- a/DDrawCompat/RealPrimarySurface.cpp +++ b/DDrawCompat/RealPrimarySurface.cpp @@ -7,6 +7,7 @@ #include "Config.h" #include "DDrawProcs.h" #include "DDrawTypes.h" +#include "Hook.h" #include "IReleaseNotifier.h" #include "RealPrimarySurface.h" @@ -55,7 +56,7 @@ namespace HDC converterDc = nullptr; origVtable.GetDC(g_paletteConverterSurface, &converterDc); - result = TRUE == CALL_ORIG_GDI(BitBlt)(destDc, 0, 0, + result = TRUE == CALL_ORIG_FUNC(BitBlt)(destDc, 0, 0, RealPrimarySurface::s_surfaceDesc.dwWidth, RealPrimarySurface::s_surfaceDesc.dwHeight, converterDc, 0, 0, SRCCOPY);