1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Extracted function hooking to its own unit

This commit is contained in:
narzoul 2016-03-21 22:51:56 +01:00
parent 1a7319dbee
commit 68d3c75c95
15 changed files with 193 additions and 148 deletions

View File

@ -23,44 +23,6 @@ namespace
bool g_isPaletteUsed = false; bool g_isPaletteUsed = false;
PALETTEENTRY g_usedPaletteEntries[256] = {}; PALETTEENTRY g_usedPaletteEntries[256] = {};
FARPROC getProcAddress(HMODULE module, const char* procName)
{
if (!module || !procName)
{
return nullptr;
}
PIMAGE_DOS_HEADER dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(module);
if (IMAGE_DOS_SIGNATURE != dosHeader->e_magic) {
return nullptr;
}
char* moduleBase = reinterpret_cast<char*>(module);
PIMAGE_NT_HEADERS ntHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(
reinterpret_cast<char*>(dosHeader) + dosHeader->e_lfanew);
if (IMAGE_NT_SIGNATURE != ntHeader->Signature)
{
return nullptr;
}
PIMAGE_EXPORT_DIRECTORY exportDir = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(
moduleBase + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
DWORD* rvaOfNames = reinterpret_cast<DWORD*>(moduleBase + exportDir->AddressOfNames);
for (DWORD i = 0; i < exportDir->NumberOfNames; ++i)
{
if (0 == strcmp(procName, moduleBase + rvaOfNames[i]))
{
WORD* nameOrds = reinterpret_cast<WORD*>(moduleBase + exportDir->AddressOfNameOrdinals);
DWORD* rvaOfFunctions = reinterpret_cast<DWORD*>(moduleBase + exportDir->AddressOfFunctions);
return reinterpret_cast<FARPROC>(moduleBase + rvaOfFunctions[nameOrds[i]]);
}
}
return nullptr;
}
BOOL CALLBACK invalidateWindow(HWND hwnd, LPARAM lParam) BOOL CALLBACK invalidateWindow(HWND hwnd, LPARAM lParam)
{ {
if (!IsWindowVisible(hwnd)) if (!IsWindowVisible(hwnd))
@ -157,7 +119,6 @@ namespace
namespace CompatGdi namespace CompatGdi
{ {
CRITICAL_SECTION g_gdiCriticalSection; CRITICAL_SECTION g_gdiCriticalSection;
std::unordered_map<void*, const char*> g_funcNames;
GdiScopedThreadLock::GdiScopedThreadLock() : m_isLocked(true) 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) void hookWndProc(LPCSTR className, WNDPROC &oldWndProc, WNDPROC newWndProc)
{ {
HWND hwnd = CreateWindow(className, nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, 0); HWND hwnd = CreateWindow(className, nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, 0);

View File

@ -2,17 +2,8 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <unordered_map>
#include <Windows.h> #include <Windows.h>
#include "DDrawLog.h"
#define CALL_ORIG_GDI(func) CompatGdi::getOrigFuncPtr<decltype(&func), &func>()
#define HOOK_GDI_FUNCTION(module, func, newFunc) \
CompatGdi::hookGdiFunction<decltype(&func), &func>(#module, #func, &newFunc)
namespace CompatGdi namespace CompatGdi
{ {
class GdiScopedThreadLock class GdiScopedThreadLock
@ -26,27 +17,10 @@ namespace CompatGdi
}; };
extern CRITICAL_SECTION g_gdiCriticalSection; extern CRITICAL_SECTION g_gdiCriticalSection;
extern std::unordered_map<void*, const char*> g_funcNames;
bool beginGdiRendering(); bool beginGdiRendering();
void endGdiRendering(); void endGdiRendering();
template <typename OrigFuncPtr, OrigFuncPtr origFunc>
OrigFuncPtr& getOrigFuncPtr()
{
static OrigFuncPtr origFuncPtr = origFunc;
return origFuncPtr;
}
void hookGdiFunction(const char* moduleName, const char* funcName, void*& origFuncPtr, void* newFuncPtr);
template <typename OrigFuncPtr, OrigFuncPtr origFunc>
void hookGdiFunction(const char* moduleName, const char* funcName, OrigFuncPtr newFuncPtr)
{
hookGdiFunction(moduleName, funcName,
reinterpret_cast<void*&>(getOrigFuncPtr<OrigFuncPtr, origFunc>()), newFuncPtr);
}
void hookWndProc(LPCSTR className, WNDPROC &oldWndProc, WNDPROC newWndProc); void hookWndProc(LPCSTR className, WNDPROC &oldWndProc, WNDPROC newWndProc);
void installHooks(); void installHooks();
void invalidate(const RECT* rect); void invalidate(const RECT* rect);

View File

@ -3,11 +3,11 @@
#include <oleacc.h> #include <oleacc.h>
#include <Windows.h> #include <Windows.h>
#include <detours.h>
#include "CompatGdi.h" #include "CompatGdi.h"
#include "CompatGdiCaret.h" #include "CompatGdiCaret.h"
#include "CompatGdiDc.h" #include "CompatGdiDc.h"
#include "Hook.h"
namespace namespace
{ {
@ -144,7 +144,7 @@ namespace
BOOL WINAPI createCaret(HWND hWnd, HBITMAP hBitmap, int nWidth, int nHeight) 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) if (result)
{ {
CaretScopedThreadLock caretLock; CaretScopedThreadLock caretLock;
@ -161,7 +161,7 @@ namespace
BOOL WINAPI hideCaret(HWND hWnd) BOOL WINAPI hideCaret(HWND hWnd)
{ {
BOOL result = CALL_ORIG_GDI(HideCaret)(hWnd); BOOL result = CALL_ORIG_FUNC(HideCaret)(hWnd);
if (result) if (result)
{ {
CaretScopedThreadLock caretLock; CaretScopedThreadLock caretLock;
@ -176,7 +176,7 @@ namespace
BOOL WINAPI showCaret(HWND hWnd) BOOL WINAPI showCaret(HWND hWnd)
{ {
if (!CALL_ORIG_GDI(ShowCaret)(hWnd)) if (!CALL_ORIG_FUNC(ShowCaret)(hWnd))
{ {
return FALSE; return FALSE;
} }
@ -213,11 +213,11 @@ namespace CompatGdiCaret
{ {
InitializeCriticalSection(&g_caretCriticalSection); InitializeCriticalSection(&g_caretCriticalSection);
DetourTransactionBegin(); Compat::beginHookTransaction();
HOOK_GDI_FUNCTION(user32, CreateCaret, createCaret); HOOK_FUNCTION(user32, CreateCaret, createCaret);
HOOK_GDI_FUNCTION(user32, HideCaret, hideCaret); HOOK_FUNCTION(user32, HideCaret, hideCaret);
HOOK_GDI_FUNCTION(user32, ShowCaret, showCaret); HOOK_FUNCTION(user32, ShowCaret, showCaret);
DetourTransactionCommit(); Compat::endHookTransaction();
const DWORD threadId = GetCurrentThreadId(); const DWORD threadId = GetCurrentThreadId();
SetWinEventHook(EVENT_OBJECT_DESTROY, EVENT_OBJECT_DESTROY, SetWinEventHook(EVENT_OBJECT_DESTROY, EVENT_OBJECT_DESTROY,

View File

@ -1,13 +1,16 @@
#include <unordered_map>
#include "CompatGdi.h" #include "CompatGdi.h"
#include "CompatGdiDc.h" #include "CompatGdiDc.h"
#include "CompatGdiDcFunctions.h" #include "CompatGdiDcFunctions.h"
#include "DDrawLog.h" #include "DDrawLog.h"
#include "Hook.h"
#include "RealPrimarySurface.h" #include "RealPrimarySurface.h"
#include <detours.h>
namespace namespace
{ {
std::unordered_map<void*, const char*> g_funcNames;
BOOL WINAPI PolyPatBlt(HDC, DWORD, DWORD, DWORD, DWORD) { return FALSE; } BOOL WINAPI PolyPatBlt(HDC, DWORD, DWORD, DWORD, DWORD) { return FALSE; }
template <typename Result, typename... Params> template <typename Result, typename... Params>
@ -61,12 +64,12 @@ namespace
Result WINAPI compatGdiDcFunc(Params... params) Result WINAPI compatGdiDcFunc(Params... params)
{ {
#ifdef _DEBUG #ifdef _DEBUG
Compat::LogEnter(CompatGdi::g_funcNames[origFunc], params...); Compat::LogEnter(g_funcNames[origFunc], params...);
#endif #endif
if (!hasDisplayDcArg(params...) || !CompatGdi::beginGdiRendering()) if (!hasDisplayDcArg(params...) || !CompatGdi::beginGdiRendering())
{ {
Result result = CompatGdi::getOrigFuncPtr<OrigFuncPtr, origFunc>()(params...); Result result = Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(params...);
#ifdef _DEBUG #ifdef _DEBUG
if (!hasDisplayDcArg(params...)) if (!hasDisplayDcArg(params...))
@ -81,18 +84,18 @@ namespace
{ {
Compat::Log() << "Skipping redirection since the primary surface could not be locked"; 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 #endif
return result; return result;
} }
Result result = CompatGdi::getOrigFuncPtr<OrigFuncPtr, origFunc>()(replaceDc(params)...); Result result = Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(replaceDc(params)...);
releaseDc(params...); releaseDc(params...);
CompatGdi::endGdiRendering(); CompatGdi::endGdiRendering();
#ifdef _DEBUG #ifdef _DEBUG
Compat::LogLeave(CompatGdi::g_funcNames[origFunc], params...) << result; Compat::LogLeave(g_funcNames[origFunc], params...) << result;
#endif #endif
return result; return result;
@ -104,15 +107,25 @@ namespace
return &compatGdiDcFunc<OrigFuncPtr, origFunc, Result, Params...>; return &compatGdiDcFunc<OrigFuncPtr, origFunc, Result, Params...>;
} }
template <typename OrigFuncPtr, OrigFuncPtr origFunc>
void hookGdiDcFunction(const char* moduleName, const char* funcName)
{
#ifdef _DEBUG
g_funcNames[origFunc] = funcName;
#endif
Compat::hookFunction<OrigFuncPtr, origFunc>(
moduleName, funcName, getCompatGdiDcFuncPtr<OrigFuncPtr, origFunc>(origFunc));
}
HWND WINAPI windowFromDc(HDC dc) 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) \ #define HOOK_GDI_DC_FUNCTION(module, func) \
CompatGdi::hookGdiFunction<decltype(&func), &func>( \ hookGdiDcFunction<decltype(&func), &func>(#module, #func)
#module, #func, getCompatGdiDcFuncPtr<decltype(&func), &func>(&func))
#define HOOK_GDI_TEXT_DC_FUNCTION(module, func) \ #define HOOK_GDI_TEXT_DC_FUNCTION(module, func) \
HOOK_GDI_DC_FUNCTION(module, func##A); \ HOOK_GDI_DC_FUNCTION(module, func##A); \
@ -122,7 +135,7 @@ namespace CompatGdiDcFunctions
{ {
void installHooks() void installHooks()
{ {
DetourTransactionBegin(); Compat::beginHookTransaction();
// Bitmap functions // Bitmap functions
HOOK_GDI_DC_FUNCTION(msimg32, AlphaBlend); HOOK_GDI_DC_FUNCTION(msimg32, AlphaBlend);
@ -154,7 +167,7 @@ namespace CompatGdiDcFunctions
// Device context functions // Device context functions
HOOK_GDI_DC_FUNCTION(gdi32, CreateCompatibleDC); HOOK_GDI_DC_FUNCTION(gdi32, CreateCompatibleDC);
HOOK_GDI_DC_FUNCTION(gdi32, DrawEscape); HOOK_GDI_DC_FUNCTION(gdi32, DrawEscape);
HOOK_GDI_FUNCTION(user32, WindowFromDC, windowFromDc); HOOK_FUNCTION(user32, WindowFromDC, windowFromDc);
// Filled shape functions // Filled shape functions
HOOK_GDI_DC_FUNCTION(gdi32, Chord); HOOK_GDI_DC_FUNCTION(gdi32, Chord);
@ -213,6 +226,6 @@ namespace CompatGdiDcFunctions
// Undocumented functions // Undocumented functions
HOOK_GDI_DC_FUNCTION(gdi32, PolyPatBlt); HOOK_GDI_DC_FUNCTION(gdi32, PolyPatBlt);
DetourTransactionCommit(); Compat::endHookTransaction();
} }
} }

View File

@ -3,8 +3,8 @@
#include "CompatGdiPaintHandlers.h" #include "CompatGdiPaintHandlers.h"
#include "CompatGdiScrollBar.h" #include "CompatGdiScrollBar.h"
#include "CompatGdiTitleBar.h" #include "CompatGdiTitleBar.h"
#include "DDrawLog.h"
#include <detours.h> #include "Hook.h"
namespace namespace
{ {
@ -25,12 +25,12 @@ namespace
LRESULT WINAPI defDlgProcA(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) 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) 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( LRESULT WINAPI defWindowProc(
@ -70,12 +70,12 @@ namespace
LRESULT WINAPI defWindowProcA(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 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) 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) 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("#32768", g_origMenuWndProc, &menuWndProc);
CompatGdi::hookWndProc("ScrollBar", g_origScrollBarWndProc, &scrollBarWndProc); CompatGdi::hookWndProc("ScrollBar", g_origScrollBarWndProc, &scrollBarWndProc);
DetourTransactionBegin(); Compat::beginHookTransaction();
HOOK_GDI_FUNCTION(user32, DefWindowProcA, defWindowProcA); HOOK_FUNCTION(user32, DefWindowProcA, defWindowProcA);
HOOK_GDI_FUNCTION(user32, DefWindowProcW, defWindowProcW); HOOK_FUNCTION(user32, DefWindowProcW, defWindowProcW);
HOOK_GDI_FUNCTION(user32, DefDlgProcA, defDlgProcA); HOOK_FUNCTION(user32, DefDlgProcA, defDlgProcA);
HOOK_GDI_FUNCTION(user32, DefDlgProcW, defDlgProcW); HOOK_FUNCTION(user32, DefDlgProcW, defDlgProcW);
DetourTransactionCommit(); Compat::endHookTransaction();
} }
} }

View File

@ -1,5 +1,6 @@
#include "CompatGdi.h" #include "CompatGdi.h"
#include "CompatGdiScrollBar.h" #include "CompatGdiScrollBar.h"
#include "Hook.h"
namespace namespace
{ {
@ -72,7 +73,7 @@ namespace CompatGdi
} }
RECT rect = sbci.rect; 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 void ScrollBar::drawHorizArrows() const

View File

@ -1,7 +1,6 @@
#include "CompatGdi.h" #include "CompatGdi.h"
#include "CompatGdiScrollFunctions.h" #include "CompatGdiScrollFunctions.h"
#include "Hook.h"
#include <detours.h>
namespace namespace
{ {
@ -12,7 +11,7 @@ namespace
_In_ const RECT *lpRect, _In_ const RECT *lpRect,
_In_ const RECT *lpClipRect) _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); CompatGdiScrollFunctions::updateScrolledWindow(hWnd);
return result; return result;
} }
@ -27,7 +26,7 @@ namespace
_Out_ LPRECT prcUpdate, _Out_ LPRECT prcUpdate,
_In_ UINT flags) _In_ UINT flags)
{ {
int result = CALL_ORIG_GDI(ScrollWindowEx)( int result = CALL_ORIG_FUNC(ScrollWindowEx)(
hWnd, dx, dy, prcScroll, prcClip, hrgnUpdate, prcUpdate, flags); hWnd, dx, dy, prcScroll, prcClip, hrgnUpdate, prcUpdate, flags);
CompatGdiScrollFunctions::updateScrolledWindow(hWnd); CompatGdiScrollFunctions::updateScrolledWindow(hWnd);
return result; return result;
@ -38,10 +37,10 @@ namespace CompatGdiScrollFunctions
{ {
void installHooks() void installHooks()
{ {
DetourTransactionBegin(); Compat::beginHookTransaction();
HOOK_GDI_FUNCTION(user32, ScrollWindow, scrollWindow); HOOK_FUNCTION(user32, ScrollWindow, scrollWindow);
HOOK_GDI_FUNCTION(user32, ScrollWindowEx, scrollWindowEx); HOOK_FUNCTION(user32, ScrollWindowEx, scrollWindowEx);
DetourTransactionCommit(); Compat::endHookTransaction();
} }
void updateScrolledWindow(HWND hwnd) void updateScrolledWindow(HWND hwnd)

View File

@ -1,5 +1,6 @@
#include "CompatGdi.h" #include "CompatGdi.h"
#include "CompatGdiTitleBar.h" #include "CompatGdiTitleBar.h"
#include "Hook.h"
namespace namespace
{ {
@ -99,7 +100,7 @@ namespace CompatGdi
flags |= DC_SMALLCAP; 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 void TitleBar::drawButton(std::size_t tbiIndex, UINT dfcState) const
@ -120,7 +121,7 @@ namespace CompatGdi
} }
RECT rect = m_tbi.rgrect[tbiIndex]; 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 void TitleBar::excludeFromClipRegion() const

View File

@ -2,5 +2,5 @@
namespace Compat namespace Compat
{ {
std::map<void*, DetouredMethodInfo> detouredMethods; std::map<void*, HookedMethodInfo> g_hookedMethods;
} }

View File

@ -1,25 +1,21 @@
#pragma once #pragma once
#define WIN32_LEAN_AND_MEAN
#include <map> #include <map>
#include <string> #include <string>
#include <vector> #include <vector>
#include <Windows.h>
#include <detours.h>
#include "DDrawLog.h" #include "DDrawLog.h"
#include "DDrawVtableVisitor.h" #include "DDrawVtableVisitor.h"
#include "Hook.h"
template <typename Interface> template <typename Interface>
using Vtable = typename std::remove_pointer<decltype(Interface::lpVtbl)>::type; using Vtable = typename std::remove_pointer<decltype(Interface::lpVtbl)>::type;
namespace Compat namespace Compat
{ {
struct DetouredMethodInfo struct HookedMethodInfo
{ {
DetouredMethodInfo(void*& updatedOrigMethodPtr, std::map<void*, void*>& vtablePtrToCompatVtable) HookedMethodInfo(void*& updatedOrigMethodPtr, std::map<void*, void*>& vtablePtrToCompatVtable)
: updatedOrigMethodPtr(updatedOrigMethodPtr), vtablePtrToCompatVtable(vtablePtrToCompatVtable) : updatedOrigMethodPtr(updatedOrigMethodPtr), vtablePtrToCompatVtable(vtablePtrToCompatVtable)
{ {
} }
@ -28,7 +24,7 @@ namespace Compat
std::map<void*, void*>& vtablePtrToCompatVtable; std::map<void*, void*>& vtablePtrToCompatVtable;
}; };
extern std::map<void*, DetouredMethodInfo> detouredMethods; extern std::map<void*, HookedMethodInfo> g_hookedMethods;
} }
template <typename CompatInterface, typename Interface> template <typename CompatInterface, typename Interface>
@ -107,8 +103,8 @@ private:
void hookMethod(void*& origMethodPtr, void* newMethodPtr) void hookMethod(void*& origMethodPtr, void* newMethodPtr)
{ {
auto it = Compat::detouredMethods.find(origMethodPtr); auto it = Compat::g_hookedMethods.find(origMethodPtr);
if (it != Compat::detouredMethods.end()) if (it != Compat::g_hookedMethods.end())
{ {
origMethodPtr = it->second.updatedOrigMethodPtr; origMethodPtr = it->second.updatedOrigMethodPtr;
it->second.vtablePtrToCompatVtable[s_vtablePtr] = &s_compatVtable; it->second.vtablePtrToCompatVtable[s_vtablePtr] = &s_compatVtable;
@ -116,11 +112,11 @@ private:
else else
{ {
s_vtablePtrToCompatVtable[s_vtablePtr] = &s_compatVtable; s_vtablePtrToCompatVtable[s_vtablePtr] = &s_compatVtable;
Compat::detouredMethods.emplace(origMethodPtr, Compat::g_hookedMethods.emplace(origMethodPtr,
Compat::DetouredMethodInfo(origMethodPtr, s_vtablePtrToCompatVtable)); Compat::HookedMethodInfo(origMethodPtr, s_vtablePtrToCompatVtable));
DetourTransactionBegin(); Compat::beginHookTransaction();
DetourAttach(&origMethodPtr, newMethodPtr); Compat::hookFunction(origMethodPtr, newMethodPtr);
DetourTransactionCommit(); Compat::endHookTransaction();
} }
} }

View File

@ -168,6 +168,7 @@
<ClInclude Include="DirectDrawSurfaceVtblVisitor.h" /> <ClInclude Include="DirectDrawSurfaceVtblVisitor.h" />
<ClInclude Include="DirectDrawVtblVisitor.h" /> <ClInclude Include="DirectDrawVtblVisitor.h" />
<ClInclude Include="DDrawLog.h" /> <ClInclude Include="DDrawLog.h" />
<ClInclude Include="Hook.h" />
<ClInclude Include="IReleaseNotifier.h" /> <ClInclude Include="IReleaseNotifier.h" />
<ClInclude Include="RealPrimarySurface.h" /> <ClInclude Include="RealPrimarySurface.h" />
</ItemGroup> </ItemGroup>
@ -189,6 +190,7 @@
<ClCompile Include="DllMain.cpp" /> <ClCompile Include="DllMain.cpp" />
<ClCompile Include="CompatPrimarySurface.cpp" /> <ClCompile Include="CompatPrimarySurface.cpp" />
<ClCompile Include="DDrawProcs.cpp" /> <ClCompile Include="DDrawProcs.cpp" />
<ClCompile Include="Hook.cpp" />
<ClCompile Include="IReleaseNotifier.cpp" /> <ClCompile Include="IReleaseNotifier.cpp" />
<ClCompile Include="RealPrimarySurface.cpp" /> <ClCompile Include="RealPrimarySurface.cpp" />
<ClCompile Include="CompatGdiDc.cpp" /> <ClCompile Include="CompatGdiDc.cpp" />

View File

@ -93,6 +93,9 @@
<ClInclude Include="CompatGdiPaintHandlers.h"> <ClInclude Include="CompatGdiPaintHandlers.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Hook.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="DllMain.cpp"> <ClCompile Include="DllMain.cpp">
@ -158,6 +161,9 @@
<ClCompile Include="CompatGdiPaintHandlers.cpp"> <ClCompile Include="CompatGdiPaintHandlers.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Hook.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="DDrawCompat.def"> <None Include="DDrawCompat.def">

83
DDrawCompat/Hook.cpp Normal file
View File

@ -0,0 +1,83 @@
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <detours.h>
#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<PIMAGE_DOS_HEADER>(module);
if (IMAGE_DOS_SIGNATURE != dosHeader->e_magic) {
return nullptr;
}
char* moduleBase = reinterpret_cast<char*>(module);
PIMAGE_NT_HEADERS ntHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(
reinterpret_cast<char*>(dosHeader) + dosHeader->e_lfanew);
if (IMAGE_NT_SIGNATURE != ntHeader->Signature)
{
return nullptr;
}
PIMAGE_EXPORT_DIRECTORY exportDir = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(
moduleBase + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
DWORD* rvaOfNames = reinterpret_cast<DWORD*>(moduleBase + exportDir->AddressOfNames);
for (DWORD i = 0; i < exportDir->NumberOfNames; ++i)
{
if (0 == strcmp(procName, moduleBase + rvaOfNames[i]))
{
WORD* nameOrds = reinterpret_cast<WORD*>(moduleBase + exportDir->AddressOfNameOrdinals);
DWORD* rvaOfFunctions = reinterpret_cast<DWORD*>(moduleBase + exportDir->AddressOfFunctions);
return reinterpret_cast<FARPROC>(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;
}
}
}

29
DDrawCompat/Hook.h Normal file
View File

@ -0,0 +1,29 @@
#pragma once
#define CALL_ORIG_FUNC(func) Compat::getOrigFuncPtr<decltype(&func), &func>()
#define HOOK_FUNCTION(module, func, newFunc) \
Compat::hookFunction<decltype(&func), &func>(#module, #func, &newFunc)
namespace Compat
{
void beginHookTransaction();
void endHookTransaction();
template <typename OrigFuncPtr, OrigFuncPtr origFunc>
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 <typename OrigFuncPtr, OrigFuncPtr origFunc>
void hookFunction(const char* moduleName, const char* funcName, OrigFuncPtr newFuncPtr)
{
hookFunction(moduleName, funcName,
reinterpret_cast<void*&>(getOrigFuncPtr<OrigFuncPtr, origFunc>()), newFuncPtr);
}
}

View File

@ -7,6 +7,7 @@
#include "Config.h" #include "Config.h"
#include "DDrawProcs.h" #include "DDrawProcs.h"
#include "DDrawTypes.h" #include "DDrawTypes.h"
#include "Hook.h"
#include "IReleaseNotifier.h" #include "IReleaseNotifier.h"
#include "RealPrimarySurface.h" #include "RealPrimarySurface.h"
@ -55,7 +56,7 @@ namespace
HDC converterDc = nullptr; HDC converterDc = nullptr;
origVtable.GetDC(g_paletteConverterSurface, &converterDc); 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, RealPrimarySurface::s_surfaceDesc.dwWidth, RealPrimarySurface::s_surfaceDesc.dwHeight,
converterDc, 0, 0, SRCCOPY); converterDc, 0, 0, SRCCOPY);