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

Extended hooking to IDirect3D interfaces

This commit is contained in:
narzoul 2016-06-08 23:23:25 +02:00
parent 923912d3af
commit 691b10bff8
9 changed files with 311 additions and 99 deletions

View File

@ -0,0 +1,11 @@
#include "CompatDirect3d.h"
template <typename TDirect3d>
void CompatDirect3d<TDirect3d>::setCompatVtable(Vtable<TDirect3d>& /*vtable*/)
{
}
template CompatDirect3d<IDirect3D>;
template CompatDirect3d<IDirect3D2>;
template CompatDirect3d<IDirect3D3>;
template CompatDirect3d<IDirect3D7>;

View File

@ -0,0 +1,11 @@
#pragma once
#include "CompatVtable.h"
#include "Direct3dVtblVisitor.h"
template <typename TDirect3d>
class CompatDirect3d : public CompatVtable<CompatDirect3d<TDirect3d>, TDirect3d>
{
public:
static void setCompatVtable(Vtable<TDirect3d>& vtable);
};

View File

@ -1,7 +1,11 @@
#pragma once
#define CINTERFACE
#include <type_traits>
#include <d3d.h>
#include "CompatVtable.h"
namespace Compat
@ -12,6 +16,20 @@ namespace Compat
typedef Intf Type;
};
template <typename SrcIntf, typename DestIntf>
struct IsConvertible : std::integral_constant<bool,
std::is_same<typename GetBaseIntf<SrcIntf>::Type, typename GetBaseIntf<DestIntf>::Type>::value>
{
};
template<> struct IsConvertible<IDirect3D, IDirect3D7> : std::false_type {};
template<> struct IsConvertible<IDirect3D2, IDirect3D7> : std::false_type {};
template<> struct IsConvertible<IDirect3D3, IDirect3D7> : std::false_type {};
template<> struct IsConvertible<IDirect3D7, IDirect3D> : std::false_type {};
template<> struct IsConvertible<IDirect3D7, IDirect3D2> : std::false_type {};
template<> struct IsConvertible<IDirect3D7, IDirect3D3> : std::false_type {};
#define DEFINE_BASE_INTF(Intf, BaseIntf) \
template<> struct GetBaseIntf<Intf> { 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 <typename Intf>
@ -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 <typename Intf>
@ -71,9 +99,7 @@ namespace Compat
}
template <typename NewIntf, typename OrigIntf>
std::enable_if_t<std::is_same<
typename GetBaseIntf<NewIntf>::Type,
typename GetBaseIntf<OrigIntf>::Type>::value>
std::enable_if_t<IsConvertible<OrigIntf, NewIntf>::value>
queryInterface(OrigIntf& origIntf, NewIntf*& newIntf)
{
CompatVtableBase<OrigIntf>::getOrigVtable(origIntf).QueryInterface(

View File

@ -145,6 +145,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="CompatActivateAppHandler.h" />
<ClInclude Include="CompatDirect3d.h" />
<ClInclude Include="CompatDirectDrawPalette.h" />
<ClInclude Include="CompatDisplayMode.h" />
<ClInclude Include="CompatFontSmoothing.h" />
@ -166,6 +167,7 @@
<ClInclude Include="CompatRegistry.h" />
<ClInclude Include="CompatWeakPtr.h" />
<ClInclude Include="Config.h" />
<ClInclude Include="DDrawHooks.h" />
<ClInclude Include="DDrawProcs.h" />
<ClInclude Include="CompatDirectDraw.h" />
<ClInclude Include="CompatPrimarySurface.h" />
@ -175,6 +177,7 @@
<ClInclude Include="CompatDirectDrawSurface.h" />
<ClInclude Include="DDrawVtableVisitor.h" />
<ClInclude Include="CompatVtable.h" />
<ClInclude Include="Direct3dVtblVisitor.h" />
<ClInclude Include="DirectDrawPaletteVtblVisitor.h" />
<ClInclude Include="DirectDrawSurfaceVtblVisitor.h" />
<ClInclude Include="DirectDrawVtblVisitor.h" />
@ -187,6 +190,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="CompatActivateAppHandler.cpp" />
<ClCompile Include="CompatDirect3d.cpp" />
<ClCompile Include="CompatDirectDraw.cpp" />
<ClCompile Include="CompatDirectDrawPalette.cpp" />
<ClCompile Include="CompatDirectDrawSurface.cpp" />
@ -204,6 +208,7 @@
<ClCompile Include="CompatHooks.cpp" />
<ClCompile Include="CompatPaletteConverter.cpp" />
<ClCompile Include="CompatRegistry.cpp" />
<ClCompile Include="DDrawHooks.cpp" />
<ClCompile Include="DDrawLog.cpp" />
<ClCompile Include="DllMain.cpp" />
<ClCompile Include="CompatPrimarySurface.cpp" />

View File

@ -135,6 +135,15 @@
<ClInclude Include="CompatHooks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Direct3dVtblVisitor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CompatDirect3d.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DDrawHooks.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="DllMain.cpp">
@ -224,6 +233,12 @@
<ClCompile Include="CompatHooks.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CompatDirect3d.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DDrawHooks.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="DDrawCompat.def">

148
DDrawCompat/DDrawHooks.cpp Normal file
View File

@ -0,0 +1,148 @@
#define CINTERFACE
#include <d3d.h>
#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 <typename CompatInterface>
void hookVtable(const CompatPtr<typename CompatInterface::Interface>& intf);
template <typename TDirect3d, typename TDirectDraw>
CompatPtr<TDirect3d> createDirect3d(CompatRef<TDirectDraw> dd)
{
CompatPtr<TDirect3d> d3d;
HRESULT result = dd->QueryInterface(&dd, Compat::getIntfId<TDirect3d>(),
reinterpret_cast<void**>(&d3d.getRef()));
if (FAILED(result))
{
Compat::Log() << "Failed to create a Direct3D object for hooking: " << result;
}
return d3d;
}
void hookDirect3d(CompatRef<IDirectDraw> dd)
{
CompatPtr<IDirect3D> d3d(createDirect3d<IDirect3D>(dd));
if (d3d)
{
hookVtable<CompatDirect3d<IDirect3D>>(d3d);
hookVtable<CompatDirect3d<IDirect3D2>>(d3d);
hookVtable<CompatDirect3d<IDirect3D3>>(d3d);
}
}
void hookDirect3d7(CompatRef<IDirectDraw7> dd)
{
CompatPtr<IDirect3D7> d3d(createDirect3d<IDirect3D7>(dd));
if (d3d)
{
hookVtable<CompatDirect3d<IDirect3D7>>(d3d);
}
}
void hookDirectDraw(CompatRef<IDirectDraw7> dd)
{
CompatDirectDraw<IDirectDraw7>::s_origVtable = *(&dd)->lpVtbl;
CompatPtr<IDirectDraw7> dd7(&dd);
hookVtable<CompatDirectDraw<IDirectDraw>>(dd7);
hookVtable<CompatDirectDraw<IDirectDraw2>>(dd7);
hookVtable<CompatDirectDraw<IDirectDraw4>>(dd7);
hookVtable<CompatDirectDraw<IDirectDraw7>>(dd7);
dd7.detach();
}
void hookDirectDrawPalette(CompatRef<IDirectDraw7> dd)
{
PALETTEENTRY paletteEntries[2] = {};
CompatPtr<IDirectDrawPalette> 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<IDirectDraw7> 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<IDirectDrawSurface7> surface;
HRESULT result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr);
if (SUCCEEDED(result))
{
CompatDirectDrawSurface<IDirectDrawSurface7>::s_origVtable = *surface.get()->lpVtbl;
hookVtable<CompatDirectDrawSurface<IDirectDrawSurface>>(surface);
hookVtable<CompatDirectDrawSurface<IDirectDrawSurface2>>(surface);
hookVtable<CompatDirectDrawSurface<IDirectDrawSurface3>>(surface);
hookVtable<CompatDirectDrawSurface<IDirectDrawSurface4>>(surface);
hookVtable<CompatDirectDrawSurface<IDirectDrawSurface7>>(surface);
}
else
{
Compat::Log() << "Failed to create a DirectDraw surface for hooking: " << result;
}
}
template <typename CompatInterface>
void hookVtable(const CompatPtr<typename CompatInterface::Interface>& intf)
{
CompatInterface::hookVtable(*intf);
}
}
namespace DDrawHooks
{
void installHooks()
{
CompatPtr<IDirectDraw> 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();
}
}

7
DDrawCompat/DDrawHooks.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
namespace DDrawHooks
{
void installHooks();
void uninstallHooks();
}

View File

@ -0,0 +1,77 @@
#pragma once
#define CINTERFACE
#include <d3d.h>
#include "DDrawVtableVisitor.h"
template <>
struct DDrawVtableForEach<IDirect3DVtbl>
{
template <typename Vtable, typename Visitor>
static void forEach(Visitor& visitor)
{
DDrawVtableForEach<IUnknownVtbl>::forEach<Vtable>(visitor);
DD_VISIT(Initialize);
DD_VISIT(EnumDevices);
DD_VISIT(CreateLight);
DD_VISIT(CreateMaterial);
DD_VISIT(CreateViewport);
DD_VISIT(FindDevice);
}
};
template <>
struct DDrawVtableForEach<IDirect3D2Vtbl>
{
template <typename Vtable, typename Visitor>
static void forEach(Visitor& visitor)
{
DDrawVtableForEach<IUnknownVtbl>::forEach<Vtable>(visitor);
DD_VISIT(EnumDevices);
DD_VISIT(CreateLight);
DD_VISIT(CreateMaterial);
DD_VISIT(CreateViewport);
DD_VISIT(FindDevice);
DD_VISIT(CreateDevice);
}
};
template <>
struct DDrawVtableForEach<IDirect3D3Vtbl>
{
template <typename Vtable, typename Visitor>
static void forEach(Visitor& visitor)
{
DDrawVtableForEach<IUnknownVtbl>::forEach<Vtable>(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<IDirect3D7Vtbl>
{
template <typename Vtable, typename Visitor>
static void forEach(Visitor& visitor)
{
DDrawVtableForEach<IUnknownVtbl>::forEach<Vtable>(visitor);
DD_VISIT(EnumDevices);
DD_VISIT(CreateDevice);
DD_VISIT(CreateVertexBuffer);
DD_VISIT(EnumZBufferFormats);
DD_VISIT(EvictManagedTextures);
}
};

View File

@ -5,20 +5,13 @@
#include <Windows.h>
#include <Uxtheme.h>
#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 <typename CompatInterface>
void hookVtable(const GUID& guid, IUnknown& unk)
{
typename CompatInterface::Interface* intf = nullptr;
if (SUCCEEDED(unk.lpVtbl->QueryInterface(&unk, guid, reinterpret_cast<LPVOID*>(&intf))))
{
CompatInterface::hookVtable(*intf);
intf->lpVtbl->Release(intf);
}
}
template <typename CompatInterface>
void hookVtable(const CompatPtr<typename CompatInterface::Interface>& intf)
{
CompatInterface::hookVtable(*intf);
}
void hookDirectDraw(CompatRef<IDirectDraw7> dd)
{
CompatDirectDraw<IDirectDraw7>::s_origVtable = *(&dd)->lpVtbl;
CompatPtr<IDirectDraw7> dd7(&dd);
hookVtable<CompatDirectDraw<IDirectDraw>>(dd7);
hookVtable<CompatDirectDraw<IDirectDraw2>>(dd7);
hookVtable<CompatDirectDraw<IDirectDraw4>>(dd7);
hookVtable<CompatDirectDraw<IDirectDraw7>>(dd7);
dd7.detach();
}
void hookDirectDrawSurface(CompatRef<IDirectDraw7> 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<IDirectDrawSurface7> surface;
HRESULT result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr);
if (SUCCEEDED(result))
{
CompatDirectDrawSurface<IDirectDrawSurface7>::s_origVtable = *surface.get()->lpVtbl;
hookVtable<CompatDirectDrawSurface<IDirectDrawSurface>>(surface);
hookVtable<CompatDirectDrawSurface<IDirectDrawSurface2>>(surface);
hookVtable<CompatDirectDrawSurface<IDirectDrawSurface3>>(surface);
hookVtable<CompatDirectDrawSurface<IDirectDrawSurface4>>(surface);
hookVtable<CompatDirectDrawSurface<IDirectDrawSurface7>>(surface);
}
else
{
Compat::Log() << "Failed to create a DirectDraw surface for hooking: " << result;
}
}
void hookDirectDrawPalette(CompatRef<IDirectDraw7> dd)
{
PALETTEENTRY paletteEntries[2] = {};
CompatPtr<IDirectDrawPalette> 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);