From b2c92f31da861b3ca209a39ea314122d59f462d8 Mon Sep 17 00:00:00 2001 From: narzoul Date: Sat, 20 Mar 2021 16:16:39 +0100 Subject: [PATCH] Use variable templates and auto template parameters --- DDrawCompat/Common/Hook.h | 23 +++----- DDrawCompat/Common/VtableHookVisitor.h | 23 ++++---- DDrawCompat/DDrawCompat.vcxproj | 7 ++- DDrawCompat/DDrawCompat.vcxproj.filters | 3 -- DDrawCompat/Direct3d/Types.h | 55 ------------------- DDrawCompat/Dll/DllMain.cpp | 41 ++++---------- DDrawCompat/Gdi/DcFunctions.cpp | 65 ++++++++-------------- DDrawCompat/Gdi/Icon.cpp | 72 ++++++++++--------------- DDrawCompat/Gdi/User32WndProcs.cpp | 29 ++++------ DDrawCompat/Win32/WaitFunctions.cpp | 6 +-- 10 files changed, 94 insertions(+), 230 deletions(-) delete mode 100644 DDrawCompat/Direct3d/Types.h diff --git a/DDrawCompat/Common/Hook.h b/DDrawCompat/Common/Hook.h index 6a5b75c..72be52e 100644 --- a/DDrawCompat/Common/Hook.h +++ b/DDrawCompat/Common/Hook.h @@ -4,26 +4,20 @@ #include -#define CALL_ORIG_FUNC(func) Compat::getOrigFuncPtr() +#define CALL_ORIG_FUNC(func) Compat::g_origFuncPtr<&func> #define HOOK_FUNCTION(module, func, newFunc) \ - Compat::hookFunction(#module, #func, &newFunc) + Compat::hookFunction<&func>(#module, #func, &newFunc) #define HOOK_SHIM_FUNCTION(func, newFunc) \ - Compat::hookFunction( \ - reinterpret_cast(Compat::getOrigFuncPtr()), newFunc, #func); - + Compat::hookFunction(reinterpret_cast(Compat::g_origFuncPtr<&func>), newFunc, #func) namespace Compat { std::string funcPtrToStr(void* funcPtr); HMODULE getModuleHandleFromAddress(void* address); - template - OrigFuncPtr& getOrigFuncPtr() - { - static OrigFuncPtr origFuncPtr = origFunc; - return origFuncPtr; - } + template + decltype(origFunc) g_origFuncPtr = origFunc; FARPROC getProcAddress(HMODULE module, const char* procName); void hookFunction(void*& origFuncPtr, void* newFuncPtr, const char* funcName); @@ -31,11 +25,10 @@ namespace Compat void hookFunction(const char* moduleName, const char* funcName, void*& origFuncPtr, void* newFuncPtr); void hookIatFunction(HMODULE module, const char* funcName, void* newFuncPtr); - template - void hookFunction(const char* moduleName, const char* funcName, OrigFuncPtr newFuncPtr) + template + void hookFunction(const char* moduleName, const char* funcName, decltype(origFunc) newFuncPtr) { - hookFunction(moduleName, funcName, - reinterpret_cast(getOrigFuncPtr()), newFuncPtr); + hookFunction(moduleName, funcName, reinterpret_cast(g_origFuncPtr), newFuncPtr); } void removeShim(HMODULE module, const char* funcName); diff --git a/DDrawCompat/Common/VtableHookVisitor.h b/DDrawCompat/Common/VtableHookVisitor.h index 13251d9..f77b66f 100644 --- a/DDrawCompat/Common/VtableHookVisitor.h +++ b/DDrawCompat/Common/VtableHookVisitor.h @@ -57,8 +57,8 @@ public: if (m_vtable.*memberPtr) { #ifdef DEBUGLOGS - getFuncName() = s_vtableTypeName + "::" + funcName; - Compat::Log() << "Hooking function: " << getFuncName() + s_funcName = s_vtableTypeName + "::" + funcName; + Compat::Log() << "Hooking function: " << s_funcName << " (" << Compat::funcPtrToStr(m_vtable.*memberPtr) << ')'; #endif m_vtable.*memberPtr = &hookFunc; @@ -67,13 +67,6 @@ public: } private: - template - static std::string& getFuncName() - { - static std::string funcName; - return funcName; - } - static std::string getVtableTypeName() { std::string name = typeid(Vtable).name(); @@ -87,10 +80,7 @@ private: template static Result STDMETHODCALLTYPE hookFunc(FirstParam firstParam, Params... params) { -#ifdef DEBUGLOGS - const char* funcName = getFuncName().c_str(); -#endif - LOG_FUNC(funcName, firstParam, params...); + LOG_FUNC(s_funcName.c_str(), firstParam, params...); [[maybe_unused]] Lock lock; constexpr auto compatFunc = getCompatFunc(); if constexpr (std::is_void_v) @@ -105,10 +95,17 @@ private: Vtable& m_vtable; + template + static std::string s_funcName; + static std::string s_vtableTypeName; }; #ifdef DEBUGLOGS +template +template +std::string VtableHookVisitor::s_funcName; + template std::string VtableHookVisitor::s_vtableTypeName(getVtableTypeName()); #endif diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index 711aeea..d716825 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -87,7 +87,7 @@ stdcpp17 - dxguid.lib;detours.lib;msimg32.lib;oleacc.lib;psapi.lib;uxtheme.lib;dwmapi.lib;winmm.lib;%(AdditionalDependencies) + dxguid.lib;detours.lib;msimg32.lib;oleacc.lib;uxtheme.lib;dwmapi.lib;winmm.lib;%(AdditionalDependencies) DebugFull true $(IntDir)$(TargetName).lib @@ -105,7 +105,7 @@ stdcpp17 - dxguid.lib;detours.lib;msimg32.lib;oleacc.lib;psapi.lib;uxtheme.lib;dwmapi.lib;winmm.lib;%(AdditionalDependencies) + dxguid.lib;detours.lib;msimg32.lib;oleacc.lib;uxtheme.lib;dwmapi.lib;winmm.lib;%(AdditionalDependencies) DebugFull true $(IntDir)$(TargetName).lib @@ -123,7 +123,7 @@ stdcpp17 - dxguid.lib;detours.lib;msimg32.lib;oleacc.lib;psapi.lib;uxtheme.lib;dwmapi.lib;winmm.lib;%(AdditionalDependencies) + dxguid.lib;detours.lib;msimg32.lib;oleacc.lib;uxtheme.lib;dwmapi.lib;winmm.lib;%(AdditionalDependencies) DebugFull true $(IntDir)$(TargetName).lib @@ -199,7 +199,6 @@ - diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 01b97b6..f050508 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -135,9 +135,6 @@ Header Files\Direct3d - - Header Files\Direct3d - Header Files\Direct3d diff --git a/DDrawCompat/Direct3d/Types.h b/DDrawCompat/Direct3d/Types.h deleted file mode 100644 index 3399c92..0000000 --- a/DDrawCompat/Direct3d/Types.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include - -namespace Direct3d -{ - struct Types1 - { - typedef IDirect3D TDirect3d; - typedef IDirect3D3 TDirect3dHighest; - typedef IDirect3DDevice TDirect3dDevice; - typedef D3DDEVICEDESC TD3dDeviceDesc; - typedef LPD3DENUMDEVICESCALLBACK TD3dEnumDevicesCallback; - }; - - struct Types2 - { - typedef IDirect3D2 TDirect3d; - typedef IDirect3D3 TDirect3dHighest; - typedef IDirect3DDevice2 TDirect3dDevice; - typedef D3DDEVICEDESC TD3dDeviceDesc; - typedef LPD3DENUMDEVICESCALLBACK TD3dEnumDevicesCallback; - }; - - struct Types3 - { - typedef IDirect3D3 TDirect3d; - typedef IDirect3D3 TDirect3dHighest; - typedef IDirect3DDevice3 TDirect3dDevice; - typedef D3DDEVICEDESC TD3dDeviceDesc; - typedef LPD3DENUMDEVICESCALLBACK TD3dEnumDevicesCallback; - }; - - struct Types7 - { - typedef IDirect3D7 TDirect3d; - typedef IDirect3D7 TDirect3dHighest; - typedef IDirect3DDevice7 TDirect3dDevice; - typedef D3DDEVICEDESC7 TD3dDeviceDesc; - typedef LPD3DENUMDEVICESCALLBACK7 TD3dEnumDevicesCallback; - }; - - template - struct Types; - - template <> struct Types : Types1 {}; - template <> struct Types : Types2 {}; - template <> struct Types : Types3 {}; - template <> struct Types : Types7 {}; - - template <> struct Types : Types1 {}; - template <> struct Types : Types2 {}; - template <> struct Types : Types3 {}; - template <> struct Types : Types7 {}; -} diff --git a/DDrawCompat/Dll/DllMain.cpp b/DDrawCompat/Dll/DllMain.cpp index 4395476..99a8719 100644 --- a/DDrawCompat/Dll/DllMain.cpp +++ b/DDrawCompat/Dll/DllMain.cpp @@ -1,8 +1,6 @@ #include -#include #include -#include #include #include #include @@ -73,17 +71,6 @@ namespace return path; } - std::vector getProcessModules(HANDLE process) - { - std::vector modules(10000); - DWORD bytesNeeded = 0; - if (EnumProcessModules(process, modules.data(), modules.size(), &bytesNeeded)) - { - modules.resize(bytesNeeded / sizeof(modules[0])); - } - return modules; - } - std::string getSystemDirectory() { char path[MAX_PATH] = {}; @@ -140,28 +127,20 @@ namespace } } - bool isEqualPath(const std::string& p1, const std::string& p2) + bool isEqual(const std::string& p1, const std::string& p2) { - return 0 == _strcmpi(p1.c_str(), p2.c_str()); + return 0 == _stricmp(p1.c_str(), p2.c_str()); } bool isOtherDDrawWrapperLoaded() { - auto currentDllPath = getModulePath(Dll::g_currentModule); - auto systemDirectory = getSystemDirectory(); - auto processModules = getProcessModules(GetCurrentProcess()); - for (HMODULE module : processModules) - { - auto path = getModulePath(module); - auto fileName = getFileName(path); - if ((isEqualPath(fileName, "ddraw.dll") || isEqualPath(fileName, "dciman32.dll")) && - !isEqualPath(path, currentDllPath) && - !isEqualPath(getDirName(path), systemDirectory)) - { - return true; - } - } - return false; + const auto currentDllPath = getModulePath(Dll::g_currentModule); + const auto currentDllDir = getDirName(currentDllPath); + const auto ddrawDllPath = currentDllDir + "\\ddraw.dll"; + const auto dciman32DllPath = currentDllDir + "\\dciman32.dll"; + + return (!isEqual(currentDllPath, ddrawDllPath) && GetModuleHandle(ddrawDllPath.c_str())) || + (!isEqual(currentDllPath, dciman32DllPath) && GetModuleHandle(dciman32DllPath.c_str())); } void printEnvironmentVariable(const char* var) @@ -237,7 +216,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) Compat::Log() << "Loading DDrawCompat " << (lpvReserved ? "statically" : "dynamically") << " from " << currentDllPath; auto systemDirectory = getSystemDirectory(); - if (isEqualPath(getDirName(currentDllPath), systemDirectory)) + if (isEqual(getDirName(currentDllPath), systemDirectory)) { Compat::Log() << "DDrawCompat cannot be installed in the Windows system directory"; return FALSE; diff --git a/DDrawCompat/Gdi/DcFunctions.cpp b/DDrawCompat/Gdi/DcFunctions.cpp index 6756958..40f7fa6 100644 --- a/DDrawCompat/Gdi/DcFunctions.cpp +++ b/DDrawCompat/Gdi/DcFunctions.cpp @@ -1,5 +1,3 @@ -#include - #include #include #include @@ -13,11 +11,13 @@ namespace { - std::unordered_map g_funcNames; + template + const char* g_funcName = nullptr; + thread_local UINT g_disableDibRedirection = 0; #define CREATE_DC_FUNC_ATTRIBUTE(attribute) \ - template \ + template \ bool attribute() \ { \ return false; \ @@ -25,7 +25,7 @@ namespace #define SET_DC_FUNC_ATTRIBUTE(attribute, func) \ template <> \ - bool attribute() \ + bool attribute<&func>() \ { \ return true; \ } @@ -53,9 +53,6 @@ namespace BOOL WINAPI GdiDrawStream(HDC, DWORD, DWORD) { return FALSE; } BOOL WINAPI PolyPatBlt(HDC, DWORD, DWORD, DWORD, DWORD) { return FALSE; } - template - using FuncPtr = Result(WINAPI *)(Params...); - bool hasDisplayDcArg(HDC dc) { return Gdi::isDisplayDc(dc); @@ -94,18 +91,16 @@ namespace return Gdi::CompatDc(dc); } - template + template Result WINAPI compatGdiDcFunc(HDC hdc, Params... params) { -#ifdef DEBUGLOGS - LOG_FUNC(g_funcNames[origFunc], hdc, params...); -#endif + LOG_FUNC(g_funcName, hdc, params...); if (hasDisplayDcArg(hdc, params...)) { - Gdi::CompatDc compatDc(hdc, isReadOnly()); - Result result = Compat::getOrigFuncPtr()(compatDc, replaceDc(params)...); - if (isPositionUpdated() && result) + Gdi::CompatDc compatDc(hdc, isReadOnly()); + Result result = Compat::g_origFuncPtr(compatDc, replaceDc(params)...); + if (isPositionUpdated() && result) { POINT currentPos = {}; GetCurrentPositionEx(compatDc, ¤tPos); @@ -114,11 +109,11 @@ namespace return LOG_RESULT(result); } - return LOG_RESULT(Compat::getOrigFuncPtr()(hdc, params...)); + return LOG_RESULT(Compat::g_origFuncPtr(hdc, params...)); } template <> - BOOL WINAPI compatGdiDcFunc( + BOOL WINAPI compatGdiDcFunc<&ExtTextOutW>( HDC hdc, int x, int y, UINT options, const RECT* lprect, LPCWSTR lpString, UINT c, const INT* lpDx) { LOG_FUNC("ExtTextOutW", hdc, x, y, options, lprect, lpString, c, lpDx); @@ -164,11 +159,11 @@ namespace return LOG_RESULT(TRUE); } - template + template Result WINAPI compatGdiTextDcFunc(HDC dc, Params... params) { Gdi::Font::Mapper fontMapper(dc); - return compatGdiDcFunc(dc, params...); + return compatGdiDcFunc(dc, params...); } HBITMAP WINAPI createCompatibleBitmap(HDC hdc, int cx, int cy) @@ -222,38 +217,24 @@ namespace return LOG_RESULT(CALL_ORIG_FUNC(DrawCaption)(hwnd, hdc, lprect, flags)); } - template - OrigFuncPtr getCompatGdiDcFuncPtr(FuncPtr) - { - return &compatGdiDcFunc; - } - - template - OrigFuncPtr getCompatGdiTextDcFuncPtr(FuncPtr) - { - return &compatGdiTextDcFunc; - } - - template + template void hookGdiDcFunction(const char* moduleName, const char* funcName) { #ifdef DEBUGLOGS - g_funcNames[origFunc] = funcName; + g_funcName = funcName; #endif - Compat::hookFunction( - moduleName, funcName, getCompatGdiDcFuncPtr(origFunc)); + Compat::hookFunction(moduleName, funcName, &compatGdiDcFunc); } - template + template void hookGdiTextDcFunction(const char* moduleName, const char* funcName) { #ifdef DEBUGLOGS - g_funcNames[origFunc] = funcName; + g_funcName = funcName; #endif - Compat::hookFunction( - moduleName, funcName, getCompatGdiTextDcFuncPtr(origFunc)); + Compat::hookFunction(moduleName, funcName, &compatGdiTextDcFunc); } HWND WINAPI windowFromDc(HDC dc) @@ -263,11 +244,11 @@ namespace } #define HOOK_GDI_DC_FUNCTION(module, func) \ - hookGdiDcFunction(#module, #func) + hookGdiDcFunction<&func>(#module, #func) #define HOOK_GDI_TEXT_DC_FUNCTION(module, func) \ - HOOK_GDI_DC_FUNCTION(module, func##A); \ - HOOK_GDI_DC_FUNCTION(module, func##W) + hookGdiTextDcFunction<&func##A>(#module, #func"A"); \ + hookGdiTextDcFunction<&func##W>(#module, #func"W") namespace Gdi { diff --git a/DDrawCompat/Gdi/Icon.cpp b/DDrawCompat/Gdi/Icon.cpp index 8bf5331..e8adbd8 100644 --- a/DDrawCompat/Gdi/Icon.cpp +++ b/DDrawCompat/Gdi/Icon.cpp @@ -1,5 +1,3 @@ -#include - #include #include #include @@ -7,71 +5,57 @@ namespace { - std::map g_funcNames; + template + const char* g_funcName = nullptr; - template - using FuncPtr = Result(WINAPI*)(Params...); - - template - struct EnableDibRedirection + template + bool isDibRedirectionEnabled(Params...) { - bool operator()(Params...) { return false; } - }; + return false; + } - template - struct EnableDibRedirection + template <> + bool isDibRedirectionEnabled<&CopyImage>(HANDLE, UINT type, int, int, UINT) { - bool operator()(HANDLE, UINT type, int, int, UINT) - { - return IMAGE_CURSOR != type && IMAGE_ICON != type; - } - }; + return IMAGE_CURSOR != type && IMAGE_ICON != type; + } - struct EnableDibRedirectionLoadImage + template <> + bool isDibRedirectionEnabled<&LoadImageA>(HINSTANCE, LPCSTR, UINT type, int, int, UINT) { - template - bool operator()(HINSTANCE, String, UINT type, int, int, UINT) - { - return IMAGE_CURSOR != type && IMAGE_ICON != type; - } - }; + return IMAGE_CURSOR != type && IMAGE_ICON != type; + } - template - struct EnableDibRedirection : EnableDibRedirectionLoadImage {}; - template - struct EnableDibRedirection : EnableDibRedirectionLoadImage {}; + template <> + bool isDibRedirectionEnabled<&LoadImageW>(HINSTANCE, LPCWSTR, UINT type, int, int, UINT) + { + return IMAGE_CURSOR != type && IMAGE_ICON != type; + } - template + template Result WINAPI iconFunc(Params... params) { - LOG_FUNC(g_funcNames[origFunc], params...); + LOG_FUNC(g_funcName, params...); - if (EnableDibRedirection()(params...)) + if (isDibRedirectionEnabled(params...)) { - return LOG_RESULT(Compat::getOrigFuncPtr()(params...)); + return LOG_RESULT(Compat::g_origFuncPtr(params...)); } Gdi::DcFunctions::disableDibRedirection(true); - Result result = Compat::getOrigFuncPtr()(params...); + Result result = Compat::g_origFuncPtr(params...); Gdi::DcFunctions::disableDibRedirection(false); return LOG_RESULT(result); } - template - OrigFuncPtr getIconFuncPtr(FuncPtr) - { - return &iconFunc; - } - - template + template void hookIconFunc(const char* moduleName, const char* funcName) { #ifdef DEBUGLOGS - g_funcNames[origFunc] = funcName; + g_funcName = funcName; #endif - Compat::hookFunction( - moduleName, funcName, getIconFuncPtr(origFunc)); + Compat::hookFunction(moduleName, funcName, &iconFunc); } template @@ -130,7 +114,7 @@ namespace } } -#define HOOK_ICON_FUNCTION(module, func) hookIconFunc(#module, #func) +#define HOOK_ICON_FUNCTION(module, func) hookIconFunc<&func>(#module, #func) namespace Gdi { diff --git a/DDrawCompat/Gdi/User32WndProcs.cpp b/DDrawCompat/Gdi/User32WndProcs.cpp index e9a473e..8171965 100644 --- a/DDrawCompat/Gdi/User32WndProcs.cpp +++ b/DDrawCompat/Gdi/User32WndProcs.cpp @@ -1,5 +1,3 @@ -#include - #include #include #include @@ -40,6 +38,11 @@ namespace bool isUnicode; }; + template + User32WndProc g_user32WndProcA = {}; + template + User32WndProc g_user32WndProcW = {}; + LRESULT defPaintProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC origWndProc); LRESULT defPaintProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC origWndProc, const char* origWndProcName); @@ -218,20 +221,6 @@ namespace return defPaintProc(hwnd, msg, wParam, lParam, origWndProc); } - template - User32WndProc& getUser32WndProcA() - { - static User32WndProc user32WndProcA = {}; - return user32WndProcA; - } - - template - User32WndProc& getUser32WndProcW() - { - static User32WndProc user32WndProcW = {}; - return user32WndProcW; - } - void hookUser32WndProc(User32WndProc& user32WndProc, WNDPROC newWndProc, const std::string& procName, const std::string& className, bool isUnicode) { @@ -270,14 +259,14 @@ namespace template void hookUser32WndProcA(const std::string& className, const std::string& procName) { - hookUser32WndProc(getUser32WndProcA(), user32WndProcA, + hookUser32WndProc(g_user32WndProcA, user32WndProcA, procName + 'A', className, false); } template void hookUser32WndProcW(const std::string& className, const std::string& procName) { - hookUser32WndProc(getUser32WndProcW(), user32WndProcW, + hookUser32WndProc(g_user32WndProcW, user32WndProcW, procName + 'W', className, true); } @@ -465,14 +454,14 @@ namespace template LRESULT CALLBACK user32WndProcA(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - auto& wp = getUser32WndProcA(); + auto& wp = g_user32WndProcA; return user32WndProc(hwnd, uMsg, wParam, lParam, wp.procName, wndProcHook, wp.oldWndProcTrampoline); } template LRESULT CALLBACK user32WndProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - auto& wp = getUser32WndProcW(); + auto& wp = g_user32WndProcW; return user32WndProc(hwnd, uMsg, wParam, lParam, wp.procName, wndProcHook, wp.oldWndProcTrampoline); } } diff --git a/DDrawCompat/Win32/WaitFunctions.cpp b/DDrawCompat/Win32/WaitFunctions.cpp index 431a35a..9d29472 100644 --- a/DDrawCompat/Win32/WaitFunctions.cpp +++ b/DDrawCompat/Win32/WaitFunctions.cpp @@ -19,16 +19,16 @@ namespace } } - template + template Result WINAPI mitigatedBusyWaitingFunc(Params... params) { mitigateBusyWaiting(); - return Compat::getOrigFuncPtr()(params...); + return Compat::g_origFuncPtr(params...); } } #define MITIGATE_BUSY_WAITING(module, func) \ - Compat::hookFunction(#module, #func, &mitigatedBusyWaitingFunc) + Compat::hookFunction<&func>(#module, #func, &mitigatedBusyWaitingFunc<&func>) namespace Win32 {