From 691b10bff8f470d3a90c4429fa5eb8dcdf19b9cf Mon Sep 17 00:00:00 2001 From: narzoul Date: Wed, 8 Jun 2016 23:23:25 +0200 Subject: [PATCH] Extended hooking to IDirect3D interfaces --- DDrawCompat/CompatDirect3d.cpp | 11 ++ DDrawCompat/CompatDirect3d.h | 11 ++ DDrawCompat/CompatQueryInterface.h | 32 ++++- DDrawCompat/DDrawCompat.vcxproj | 5 + DDrawCompat/DDrawCompat.vcxproj.filters | 15 +++ DDrawCompat/DDrawHooks.cpp | 148 ++++++++++++++++++++++++ DDrawCompat/DDrawHooks.h | 7 ++ DDrawCompat/Direct3dVtblVisitor.h | 77 ++++++++++++ DDrawCompat/DllMain.cpp | 104 ++--------------- 9 files changed, 311 insertions(+), 99 deletions(-) create mode 100644 DDrawCompat/CompatDirect3d.cpp create mode 100644 DDrawCompat/CompatDirect3d.h create mode 100644 DDrawCompat/DDrawHooks.cpp create mode 100644 DDrawCompat/DDrawHooks.h create mode 100644 DDrawCompat/Direct3dVtblVisitor.h diff --git a/DDrawCompat/CompatDirect3d.cpp b/DDrawCompat/CompatDirect3d.cpp new file mode 100644 index 0000000..c15695f --- /dev/null +++ b/DDrawCompat/CompatDirect3d.cpp @@ -0,0 +1,11 @@ +#include "CompatDirect3d.h" + +template +void CompatDirect3d::setCompatVtable(Vtable& /*vtable*/) +{ +} + +template CompatDirect3d; +template CompatDirect3d; +template CompatDirect3d; +template CompatDirect3d; diff --git a/DDrawCompat/CompatDirect3d.h b/DDrawCompat/CompatDirect3d.h new file mode 100644 index 0000000..6cc80f2 --- /dev/null +++ b/DDrawCompat/CompatDirect3d.h @@ -0,0 +1,11 @@ +#pragma once + +#include "CompatVtable.h" +#include "Direct3dVtblVisitor.h" + +template +class CompatDirect3d : public CompatVtable, TDirect3d> +{ +public: + static void setCompatVtable(Vtable& vtable); +}; diff --git a/DDrawCompat/CompatQueryInterface.h b/DDrawCompat/CompatQueryInterface.h index 0fb9da3..3736c31 100644 --- a/DDrawCompat/CompatQueryInterface.h +++ b/DDrawCompat/CompatQueryInterface.h @@ -1,7 +1,11 @@ #pragma once +#define CINTERFACE + #include +#include + #include "CompatVtable.h" namespace Compat @@ -12,6 +16,20 @@ namespace Compat typedef Intf Type; }; + template + struct IsConvertible : std::integral_constant::Type, typename GetBaseIntf::Type>::value> + { + }; + + template<> struct IsConvertible : std::false_type {}; + template<> struct IsConvertible : std::false_type {}; + template<> struct IsConvertible : std::false_type {}; + + template<> struct IsConvertible : std::false_type {}; + template<> struct IsConvertible : std::false_type {}; + template<> struct IsConvertible : std::false_type {}; + #define DEFINE_BASE_INTF(Intf, BaseIntf) \ template<> struct GetBaseIntf { typedef BaseIntf Type; } @@ -23,6 +41,11 @@ namespace Compat DEFINE_BASE_INTF(IDirectDrawSurface4, IDirectDrawSurface); DEFINE_BASE_INTF(IDirectDrawSurface7, IDirectDrawSurface); + DEFINE_BASE_INTF(IDirect3D, IDirectDraw); + DEFINE_BASE_INTF(IDirect3D2, IDirectDraw); + DEFINE_BASE_INTF(IDirect3D3, IDirectDraw); + DEFINE_BASE_INTF(IDirect3D7, IDirectDraw); + #undef DEFINE_BASE_INTF template @@ -45,6 +68,11 @@ namespace Compat DEFINE_INTF_ID(IDirectDrawColorControl); DEFINE_INTF_ID(IDirectDrawGammaControl); + DEFINE_INTF_ID(IDirect3D); + DEFINE_INTF_ID(IDirect3D2); + DEFINE_INTF_ID(IDirect3D3); + DEFINE_INTF_ID(IDirect3D7); + #undef DEFINE_INTF_ID template @@ -71,9 +99,7 @@ namespace Compat } template - std::enable_if_t::Type, - typename GetBaseIntf::Type>::value> + std::enable_if_t::value> queryInterface(OrigIntf& origIntf, NewIntf*& newIntf) { CompatVtableBase::getOrigVtable(origIntf).QueryInterface( diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index 0ab3742..da85a62 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -145,6 +145,7 @@ + @@ -166,6 +167,7 @@ + @@ -175,6 +177,7 @@ + @@ -187,6 +190,7 @@ + @@ -204,6 +208,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 0f8d7b5..e01e369 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -135,6 +135,15 @@ Header Files + + Header Files + + + Header Files + + + Header Files + @@ -224,6 +233,12 @@ Source Files + + Source Files + + + Source Files + diff --git a/DDrawCompat/DDrawHooks.cpp b/DDrawCompat/DDrawHooks.cpp new file mode 100644 index 0000000..5e8d3b3 --- /dev/null +++ b/DDrawCompat/DDrawHooks.cpp @@ -0,0 +1,148 @@ +#define CINTERFACE + +#include + +#include "CompatActivateAppHandler.h" +#include "CompatDirect3d.h" +#include "CompatDirectDraw.h" +#include "CompatDirectDrawSurface.h" +#include "CompatDirectDrawPalette.h" +#include "CompatPtr.h" +#include "CompatRef.h" +#include "DDrawHooks.h" +#include "DDrawLog.h" +#include "DDrawProcs.h" +#include "DDrawRepository.h" +#include "RealPrimarySurface.h" + +namespace +{ + template + void hookVtable(const CompatPtr& intf); + + template + CompatPtr createDirect3d(CompatRef dd) + { + CompatPtr d3d; + HRESULT result = dd->QueryInterface(&dd, Compat::getIntfId(), + reinterpret_cast(&d3d.getRef())); + if (FAILED(result)) + { + Compat::Log() << "Failed to create a Direct3D object for hooking: " << result; + } + return d3d; + } + + void hookDirect3d(CompatRef dd) + { + CompatPtr d3d(createDirect3d(dd)); + if (d3d) + { + hookVtable>(d3d); + hookVtable>(d3d); + hookVtable>(d3d); + } + } + + void hookDirect3d7(CompatRef dd) + { + CompatPtr d3d(createDirect3d(dd)); + if (d3d) + { + hookVtable>(d3d); + } + } + + void hookDirectDraw(CompatRef dd) + { + CompatDirectDraw::s_origVtable = *(&dd)->lpVtbl; + CompatPtr dd7(&dd); + hookVtable>(dd7); + hookVtable>(dd7); + hookVtable>(dd7); + hookVtable>(dd7); + dd7.detach(); + } + + void hookDirectDrawPalette(CompatRef dd) + { + PALETTEENTRY paletteEntries[2] = {}; + CompatPtr palette; + HRESULT result = dd->CreatePalette(&dd, + DDPCAPS_1BIT, paletteEntries, &palette.getRef(), nullptr); + if (SUCCEEDED(result)) + { + CompatDirectDrawPalette::hookVtable(*palette); + } + else + { + Compat::Log() << "Failed to create a DirectDraw palette for hooking: " << result; + } + } + + void hookDirectDrawSurface(CompatRef dd) + { + DDSURFACEDESC2 desc = {}; + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; + desc.dwWidth = 1; + desc.dwHeight = 1; + desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + + CompatPtr surface; + HRESULT result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr); + if (SUCCEEDED(result)) + { + CompatDirectDrawSurface::s_origVtable = *surface.get()->lpVtbl; + hookVtable>(surface); + hookVtable>(surface); + hookVtable>(surface); + hookVtable>(surface); + hookVtable>(surface); + } + else + { + Compat::Log() << "Failed to create a DirectDraw surface for hooking: " << result; + } + } + + template + void hookVtable(const CompatPtr& intf) + { + CompatInterface::hookVtable(*intf); + } +} + +namespace DDrawHooks +{ + void installHooks() + { + CompatPtr dd; + CALL_ORIG_DDRAW(DirectDrawCreate, nullptr, &dd.getRef(), nullptr); + if (!dd) + { + Compat::Log() << "Failed to create a DirectDraw object for hooking"; + return; + } + + auto dd7(DDrawRepository::getDirectDraw()); + if (!dd7) + { + Compat::Log() << "Failed to create a DirectDraw7 object for hooking"; + return; + } + + hookDirectDraw(*dd7); + hookDirectDrawSurface(*dd7); + hookDirectDrawPalette(*dd7); + hookDirect3d(*dd); + hookDirect3d7(*dd7); + CompatActivateAppHandler::installHooks(); + } + + void uninstallHooks() + { + RealPrimarySurface::removeUpdateThread(); + CompatActivateAppHandler::uninstallHooks(); + } +} diff --git a/DDrawCompat/DDrawHooks.h b/DDrawCompat/DDrawHooks.h new file mode 100644 index 0000000..e28a467 --- /dev/null +++ b/DDrawCompat/DDrawHooks.h @@ -0,0 +1,7 @@ +#pragma once + +namespace DDrawHooks +{ + void installHooks(); + void uninstallHooks(); +} diff --git a/DDrawCompat/Direct3dVtblVisitor.h b/DDrawCompat/Direct3dVtblVisitor.h new file mode 100644 index 0000000..667ac7d --- /dev/null +++ b/DDrawCompat/Direct3dVtblVisitor.h @@ -0,0 +1,77 @@ +#pragma once + +#define CINTERFACE + +#include + +#include "DDrawVtableVisitor.h" + +template <> +struct DDrawVtableForEach +{ + template + static void forEach(Visitor& visitor) + { + DDrawVtableForEach::forEach(visitor); + + DD_VISIT(Initialize); + DD_VISIT(EnumDevices); + DD_VISIT(CreateLight); + DD_VISIT(CreateMaterial); + DD_VISIT(CreateViewport); + DD_VISIT(FindDevice); + } +}; + +template <> +struct DDrawVtableForEach +{ + template + static void forEach(Visitor& visitor) + { + DDrawVtableForEach::forEach(visitor); + + DD_VISIT(EnumDevices); + DD_VISIT(CreateLight); + DD_VISIT(CreateMaterial); + DD_VISIT(CreateViewport); + DD_VISIT(FindDevice); + DD_VISIT(CreateDevice); + } +}; + +template <> +struct DDrawVtableForEach +{ + template + static void forEach(Visitor& visitor) + { + DDrawVtableForEach::forEach(visitor); + + DD_VISIT(EnumDevices); + DD_VISIT(CreateLight); + DD_VISIT(CreateMaterial); + DD_VISIT(CreateViewport); + DD_VISIT(FindDevice); + DD_VISIT(CreateDevice); + DD_VISIT(CreateVertexBuffer); + DD_VISIT(EnumZBufferFormats); + DD_VISIT(EvictManagedTextures); + } +}; + +template <> +struct DDrawVtableForEach +{ + template + static void forEach(Visitor& visitor) + { + DDrawVtableForEach::forEach(visitor); + + DD_VISIT(EnumDevices); + DD_VISIT(CreateDevice); + DD_VISIT(CreateVertexBuffer); + DD_VISIT(EnumZBufferFormats); + DD_VISIT(EvictManagedTextures); + } +}; diff --git a/DDrawCompat/DllMain.cpp b/DDrawCompat/DllMain.cpp index 3eb5287..91c2310 100644 --- a/DDrawCompat/DllMain.cpp +++ b/DDrawCompat/DllMain.cpp @@ -5,20 +5,13 @@ #include #include -#include "CompatActivateAppHandler.h" -#include "CompatDirectDraw.h" -#include "CompatDirectDrawSurface.h" -#include "CompatDirectDrawPalette.h" #include "CompatDisplayMode.h" #include "CompatFontSmoothing.h" #include "CompatGdi.h" #include "CompatHooks.h" #include "CompatRegistry.h" -#include "CompatPtr.h" -#include "CompatVtable.h" +#include "DDrawHooks.h" #include "DDrawProcs.h" -#include "DDrawRepository.h" -#include "RealPrimarySurface.h" #include "Time.h" struct IDirectInput; @@ -28,98 +21,18 @@ namespace HMODULE g_origDDrawModule = nullptr; HMODULE g_origDInputModule = nullptr; - template - void hookVtable(const GUID& guid, IUnknown& unk) - { - typename CompatInterface::Interface* intf = nullptr; - if (SUCCEEDED(unk.lpVtbl->QueryInterface(&unk, guid, reinterpret_cast(&intf)))) - { - CompatInterface::hookVtable(*intf); - intf->lpVtbl->Release(intf); - } - } - - template - void hookVtable(const CompatPtr& intf) - { - CompatInterface::hookVtable(*intf); - } - - void hookDirectDraw(CompatRef dd) - { - CompatDirectDraw::s_origVtable = *(&dd)->lpVtbl; - CompatPtr dd7(&dd); - hookVtable>(dd7); - hookVtable>(dd7); - hookVtable>(dd7); - hookVtable>(dd7); - dd7.detach(); - } - - void hookDirectDrawSurface(CompatRef dd) - { - DDSURFACEDESC2 desc = {}; - desc.dwSize = sizeof(desc); - desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; - desc.dwWidth = 1; - desc.dwHeight = 1; - desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; - - CompatPtr surface; - HRESULT result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr); - if (SUCCEEDED(result)) - { - CompatDirectDrawSurface::s_origVtable = *surface.get()->lpVtbl; - hookVtable>(surface); - hookVtable>(surface); - hookVtable>(surface); - hookVtable>(surface); - hookVtable>(surface); - } - else - { - Compat::Log() << "Failed to create a DirectDraw surface for hooking: " << result; - } - } - - void hookDirectDrawPalette(CompatRef dd) - { - PALETTEENTRY paletteEntries[2] = {}; - CompatPtr palette; - HRESULT result = dd->CreatePalette(&dd, - DDPCAPS_1BIT, paletteEntries, &palette.getRef(), nullptr); - if (SUCCEEDED(result)) - { - CompatDirectDrawPalette::hookVtable(*palette); - } - else - { - Compat::Log() << "Failed to create a DirectDraw palette for hooking: " << result; - } - } - void installHooks() { static bool isAlreadyInstalled = false; if (!isAlreadyInstalled) { Compat::Log() << "Installing DirectDraw hooks"; - auto dd(DDrawRepository::getDirectDraw()); - if (dd) - { - hookDirectDraw(*dd); - hookDirectDrawSurface(*dd); - hookDirectDrawPalette(*dd); - CompatActivateAppHandler::installHooks(); - - Compat::Log() << "Installing GDI hooks"; - CompatGdi::installHooks(); - - Compat::Log() << "Installing registry hooks"; - CompatRegistry::installHooks(); - - Compat::Log() << "Finished installing hooks"; - } + DDrawHooks::installHooks(); + Compat::Log() << "Installing GDI hooks"; + CompatGdi::installHooks(); + Compat::Log() << "Installing registry hooks"; + CompatRegistry::installHooks(); + Compat::Log() << "Finished installing hooks"; isAlreadyInstalled = true; } } @@ -219,8 +132,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/) else if (fdwReason == DLL_PROCESS_DETACH) { Compat::Log() << "Detaching DDrawCompat"; - RealPrimarySurface::removeUpdateThread(); - CompatActivateAppHandler::uninstallHooks(); + DDrawHooks::uninstallHooks(); CompatGdi::uninstallHooks(); Compat::unhookAllFunctions(); FreeLibrary(g_origDInputModule);