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:
parent
1a7319dbee
commit
68d3c75c95
@ -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<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)
|
||||
{
|
||||
if (!IsWindowVisible(hwnd))
|
||||
@ -157,7 +119,6 @@ namespace
|
||||
namespace CompatGdi
|
||||
{
|
||||
CRITICAL_SECTION g_gdiCriticalSection;
|
||||
std::unordered_map<void*, const char*> 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);
|
||||
|
@ -2,17 +2,8 @@
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#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
|
||||
{
|
||||
class GdiScopedThreadLock
|
||||
@ -26,27 +17,10 @@ namespace CompatGdi
|
||||
};
|
||||
|
||||
extern CRITICAL_SECTION g_gdiCriticalSection;
|
||||
extern std::unordered_map<void*, const char*> g_funcNames;
|
||||
|
||||
bool beginGdiRendering();
|
||||
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 installHooks();
|
||||
void invalidate(const RECT* rect);
|
||||
|
@ -3,11 +3,11 @@
|
||||
|
||||
#include <oleacc.h>
|
||||
#include <Windows.h>
|
||||
#include <detours.h>
|
||||
|
||||
#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,
|
||||
|
@ -1,13 +1,16 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include "CompatGdi.h"
|
||||
#include "CompatGdiDc.h"
|
||||
#include "CompatGdiDcFunctions.h"
|
||||
#include "DDrawLog.h"
|
||||
#include "Hook.h"
|
||||
#include "RealPrimarySurface.h"
|
||||
|
||||
#include <detours.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::unordered_map<void*, const char*> g_funcNames;
|
||||
|
||||
BOOL WINAPI PolyPatBlt(HDC, DWORD, DWORD, DWORD, DWORD) { return FALSE; }
|
||||
|
||||
template <typename Result, typename... Params>
|
||||
@ -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<OrigFuncPtr, origFunc>()(params...);
|
||||
Result result = Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(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<OrigFuncPtr, origFunc>()(replaceDc(params)...);
|
||||
Result result = Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(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<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)
|
||||
{
|
||||
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<decltype(&func), &func>( \
|
||||
#module, #func, getCompatGdiDcFuncPtr<decltype(&func), &func>(&func))
|
||||
hookGdiDcFunction<decltype(&func), &func>(#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();
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,8 @@
|
||||
#include "CompatGdiPaintHandlers.h"
|
||||
#include "CompatGdiScrollBar.h"
|
||||
#include "CompatGdiTitleBar.h"
|
||||
|
||||
#include <detours.h>
|
||||
#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();
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "CompatGdi.h"
|
||||
#include "CompatGdiScrollFunctions.h"
|
||||
|
||||
#include <detours.h>
|
||||
#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)
|
||||
|
@ -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
|
||||
|
@ -2,5 +2,5 @@
|
||||
|
||||
namespace Compat
|
||||
{
|
||||
std::map<void*, DetouredMethodInfo> detouredMethods;
|
||||
std::map<void*, HookedMethodInfo> g_hookedMethods;
|
||||
}
|
||||
|
@ -1,25 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <detours.h>
|
||||
|
||||
#include "DDrawLog.h"
|
||||
#include "DDrawVtableVisitor.h"
|
||||
#include "Hook.h"
|
||||
|
||||
template <typename Interface>
|
||||
using Vtable = typename std::remove_pointer<decltype(Interface::lpVtbl)>::type;
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
@ -28,7 +24,7 @@ namespace Compat
|
||||
std::map<void*, void*>& vtablePtrToCompatVtable;
|
||||
};
|
||||
|
||||
extern std::map<void*, DetouredMethodInfo> detouredMethods;
|
||||
extern std::map<void*, HookedMethodInfo> g_hookedMethods;
|
||||
}
|
||||
|
||||
template <typename CompatInterface, typename Interface>
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,6 +168,7 @@
|
||||
<ClInclude Include="DirectDrawSurfaceVtblVisitor.h" />
|
||||
<ClInclude Include="DirectDrawVtblVisitor.h" />
|
||||
<ClInclude Include="DDrawLog.h" />
|
||||
<ClInclude Include="Hook.h" />
|
||||
<ClInclude Include="IReleaseNotifier.h" />
|
||||
<ClInclude Include="RealPrimarySurface.h" />
|
||||
</ItemGroup>
|
||||
@ -189,6 +190,7 @@
|
||||
<ClCompile Include="DllMain.cpp" />
|
||||
<ClCompile Include="CompatPrimarySurface.cpp" />
|
||||
<ClCompile Include="DDrawProcs.cpp" />
|
||||
<ClCompile Include="Hook.cpp" />
|
||||
<ClCompile Include="IReleaseNotifier.cpp" />
|
||||
<ClCompile Include="RealPrimarySurface.cpp" />
|
||||
<ClCompile Include="CompatGdiDc.cpp" />
|
||||
|
@ -93,6 +93,9 @@
|
||||
<ClInclude Include="CompatGdiPaintHandlers.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Hook.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="DllMain.cpp">
|
||||
@ -158,6 +161,9 @@
|
||||
<ClCompile Include="CompatGdiPaintHandlers.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Hook.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="DDrawCompat.def">
|
||||
|
83
DDrawCompat/Hook.cpp
Normal file
83
DDrawCompat/Hook.cpp
Normal 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
29
DDrawCompat/Hook.h
Normal 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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user