C++ 覆盖Direct3D接口?

C++ 覆盖Direct3D接口?,c++,interface,overriding,virtual,direct3d,C++,Interface,Overriding,Virtual,Direct3d,我的项目启动了一个目标进程,向其中注入了一个库,用于钩住Direct3D函数。我在过去成功地完成了这项工作,但我决定将库重写为更接近Direct3D接口规范的库。这里的想法是创建一组我自己的1:1包装类,每个类继承一个DirectX接口(即,classCD3D8:IDirect3D8,classCD3DDevice8:IDirect3DDevice8等等)。由于每个底层DirectX COM接口的所有成员都是纯虚拟方法,我想我可以轻松地重写它们 因此,当我的库钩住Direct3DCreate8时

我的项目启动了一个目标进程,向其中注入了一个库,用于钩住Direct3D函数。我在过去成功地完成了这项工作,但我决定将库重写为更接近Direct3D接口规范的库。这里的想法是创建一组我自己的1:1包装类,每个类继承一个DirectX接口(即,
classCD3D8:IDirect3D8
classCD3DDevice8:IDirect3DDevice8
等等)。由于每个底层DirectX COM接口的所有成员都是纯虚拟方法,我想我可以轻松地重写它们

因此,当我的库钩住
Direct3DCreate8
时,我返回指向我的
CDirect3D8
的指针,而不是标准的
IDirect3D8
。然后我的库使用指向hook方法15的指针的虚拟表,即
IDirect3D8::CreateDevice
。调用后,我返回一个指向
CDirect3DDevice8
的指针,而不是
IDirect3DDevice8
。除了注入的应用程序没有调用任何重写的函数外,所有函数看起来都很好!不知何故,该应用程序似乎在调用原始界面函数,而不是我自己的。我是不是遗漏了一些概念?例如,我是否需要手动将虚拟表指针重新映射到自定义包装器类中的指针

以下是我到目前为止得到的信息(仅显示d3d8):

D3D.h

#pragma一次
#定义STDM(方法)COM\u DECLSPEC\u nothresult STDMETHODCALLTYPE方法
#定义STDM_(类型、方法)COM_DECLSPEC_NOTHROW类型STDMETHODCALLTYPE方法
模板
CD3D类:公共IDirect3D8
{
公众:
CD3D();
~CD3D();
/***未知方法***/
STDM(查询接口)(本文件无效**ppvObj);
STDM_uong(ULONG,AddRef)(本);
STDM_uong(发布)(本);
/***IDirect3D8方法***/
STDM(寄存器软件设备)(此uvoid*p初始化功能);
STDM_Ut(UINT,GetAdapterCount)(本);
STDM(GetAdapterIdentifier)(此接口适配器、DWORD标志、D3DAAPTER标识8*Pidentier);
STDM(UINT,GetAdapterModeCount)(此UINT适配器);
STDM(EnumAdapterModes)(此单元适配器,单元模式,D3DDISPLAYMODE*pMode);
STDM(GetAdapterDisplayMode)(此单元适配器,D3DDISPLAYMODE*pMode);
STDM(CheckDeviceType)(此单元适配器,D3DDEVTYPE CheckType,D3DFORMAT DisplayFormat,D3DFORMAT BackBufferFormat,布尔窗口);
STDM(CheckDeviceFormat)(此单元适配器、D3DDEVTYPE设备类型、D3DFORMAT适配器性能、DWORD用法、D3DRESOURCETYPE RType、D3DFORMAT CheckFormat);
STDM(CheckDeviceMultiSampleType)(此单元适配器、D3DDEVTYPE设备类型、D3DFORMAT表面格式、布尔窗口、D3DMMultiSampleType多采样类型);
STDM(CheckDepthStencilMatch)(此单元适配器、D3DDEVTYPE设备类型、D3DFORMAT AdapterPerformat、D3DFORMAT RenderTargetFormat、D3DFORMAT DepthStencilFormat);
STDM(GetDeviceCaps)(此单元适配器,D3DDEVTYPE设备类型,D3DCAPS8*pCaps);
STDM(HMONITOR,GetAdapterMonitor)(此单元适配器);
STDM(CreateDevice)(此单元适配器、D3DDEVTYPE设备类型、HWND hFocusWindow、DWORD行为标志、D3D呈现参数*PPresentation参数、IDirect3DDevice8**PPresentedDeviceInterface);
};

D3D.cpp

#包括“stdafx.h”
#定义STDIMP(iface,method,…)COM_DECLSPEC_nothresult STDMETHODCALLTYPE CD3D::method(u_VA_ARGS_u)
#定义STDIMP(iface,type,method,…)COM\u DECLSPEC\u NOTHROW type STDMETHODCALLTYPE CD3D::method(\uu VA\u ARGS\uu)
#定义STDIMP8(方法,…)STDIMP(IDirect3D8,方法,_VA_参数)
#定义STDIMP8(类型、方法等)STDIMP(IDirect3D8、类型、方法、参数)
CD3D::CD3D()
{
}
CD3D::~CD3D()
{
}
STDIMP8(查询接口,此\uRefID riid,无效**ppvObj){
返回查询接口(riid、ppvObj);
}
STDIMP8(ULONG、AddRef、THIS){
返回AddRef();
}
STDIMP8_ULONG,发布,本){
返回释放();
}
STDIMP8(寄存器软件设备,此uvoid*p初始化函数){
返回寄存器SoftwareDevice(PiInitializeFunction);
}
STDIMP8_Ut(UINT,GetAdapterCount,THIS){
返回GetAdapterCount();
}
STDIMP8(GetAdapterIdentifier、此单元适配器、DWORD标志、D3DAAPTER标识8*Pidentier){
返回GetAdapterIdentifier(适配器、标志、Pidentier);
}
STDIMP8(UINT,GetAdapterModeCount,此UINT适配器){
返回GetAdapterModeCount(适配器);
}
STDIMP8(枚举适配器模式、此单元适配器、单元模式、D3DDISPLAYMODE*pMode){
返回EnumAdapterModes(适配器、模式、pMode);
}
STDIMP8(GetAdapterDisplayMode,此单元适配器,D3DDISPLAYMODE*pMode){
返回GetAdapterDisplayMode(适配器,pMode);
}
STDIMP8(CheckDeviceType,此单元适配器,D3DDEVTYPE CheckType,D3DFORMAT DisplayFormat,D3DFORMAT BackBufferFormat,布尔窗口){
返回CheckDeviceType(适配器、CheckType、DisplayFormat、BackBufferFormat、窗口化);
}
STDIMP8(检查设备格式、此单元适配器、D3DDEVTYPE设备类型、D3DFORMAT适配器性能、DWORD用法、D3DRESOURCETYPE RType、D3DFORMAT检查格式){
返回CheckDeviceFormat(适配器、设备类型、AdapterFormat、用法、RType、CheckFormat);
}
STDIMP8(检查设备多采样类型、此单元适配器、D3DDEVTYPE设备类型、D3D格式表面格式、布尔窗口、D3D多采样类型多采样类型){
返回CheckDeviceMultiSampleType(适配器、设备类型、表面格式、窗口、多采样类型);
}
STDIMP8(检查深度模板匹配、此单元适配器、D3DDEVTYPE设备类型、D3DFORMAT AdapterPerformat、D3DFORMAT RenderTargetFormat、D3DFORMAT深度模板格式){
返回CheckDepthStencilMatch(适配器、设备类型、AdapterPerformat、RenderTargetFormat、DepthStencilFormat);
}
STDIMP8(GetDeviceCaps,此单元适配器,D3DDEVTYPE DeviceType,D3DCAPS8*pCaps){
返回GetDeviceCaps(适配器、设备类型、pCaps);
}
STDIMP8(HMONITOR、GetAdapterMonitor、THIS_uuint适配器){
返回GetAdapterMonitor(适配器);
}
STDIMP8(CreateDevice,此单元适配器,D3DDEVTYPE设备类型,
#pragma once


#define STDM(method)        COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE method
#define STDM_(type,method)  COM_DECLSPEC_NOTHROW type STDMETHODCALLTYPE method

template<class IDirect3D8>
class CD3D : public IDirect3D8
{
public:
    CD3D();
    ~CD3D();

    /*** IUnknown methods ***/
    STDM(QueryInterface)(THIS_ REFIID riid, void** ppvObj);
    STDM_(ULONG,AddRef)(THIS);
    STDM_(ULONG,Release)(THIS);

    /*** IDirect3D8 methods ***/
    STDM(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction);
    STDM_(UINT, GetAdapterCount)(THIS);
    STDM(GetAdapterIdentifier)(THIS_ UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER8* pIdentifier);
    STDM_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter);
    STDM(EnumAdapterModes)(THIS_ UINT Adapter,UINT Mode,D3DDISPLAYMODE* pMode);
    STDM(GetAdapterDisplayMode)(THIS_ UINT Adapter,D3DDISPLAYMODE* pMode);
    STDM(CheckDeviceType)(THIS_ UINT Adapter,D3DDEVTYPE CheckType,D3DFORMAT DisplayFormat,D3DFORMAT BackBufferFormat,BOOL Windowed);
    STDM(CheckDeviceFormat)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat);
    STDM(CheckDeviceMultiSampleType)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType);
    STDM(CheckDepthStencilMatch)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat);
    STDM(GetDeviceCaps)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS8* pCaps);
    STDM_(HMONITOR, GetAdapterMonitor)(THIS_ UINT Adapter);
    STDM(CreateDevice)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice8** ppReturnedDeviceInterface);
};
#include "stdafx.h"


#define STDIMP(iface, method, ...) COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE CD3D<iface>::method(__VA_ARGS__)
#define STDIMP_(iface, type, method, ...) COM_DECLSPEC_NOTHROW type STDMETHODCALLTYPE CD3D<iface>::method(__VA_ARGS__)
#define STDIMP8(method, ...) STDIMP(IDirect3D8, method, __VA_ARGS__)
#define STDIMP8_(type, method, ...)  STDIMP_(IDirect3D8, type, method, __VA_ARGS__)


CD3D<IDirect3D8>::CD3D()
{
}

CD3D<IDirect3D8>::~CD3D()
{
}

STDIMP8(QueryInterface, THIS_ REFIID riid, void** ppvObj) {
    return QueryInterface( riid, ppvObj );
}

STDIMP8_(ULONG, AddRef, THIS) {
    return AddRef();
}

STDIMP8_(ULONG, Release, THIS) {
    return Release();
}

STDIMP8(RegisterSoftwareDevice, THIS_ void* pInitializeFunction) {
    return RegisterSoftwareDevice( pInitializeFunction );
}

STDIMP8_(UINT, GetAdapterCount, THIS) {
    return GetAdapterCount();
}

STDIMP8(GetAdapterIdentifier, THIS_ UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER8* pIdentifier) {
    return GetAdapterIdentifier( Adapter, Flags, pIdentifier );
}

STDIMP8_(UINT, GetAdapterModeCount, THIS_ UINT Adapter) {
    return GetAdapterModeCount( Adapter );
}

STDIMP8(EnumAdapterModes, THIS_ UINT Adapter, UINT Mode, D3DDISPLAYMODE* pMode) {
    return EnumAdapterModes( Adapter, Mode, pMode );
}

STDIMP8(GetAdapterDisplayMode, THIS_ UINT Adapter, D3DDISPLAYMODE* pMode) {
    return GetAdapterDisplayMode( Adapter, pMode );
}

STDIMP8(CheckDeviceType, THIS_ UINT Adapter, D3DDEVTYPE CheckType, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL Windowed) {
    return CheckDeviceType( Adapter, CheckType, DisplayFormat, BackBufferFormat, Windowed );
}

STDIMP8(CheckDeviceFormat, THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) {
    return CheckDeviceFormat( Adapter, DeviceType, AdapterFormat, Usage, RType, CheckFormat );
}

STDIMP8(CheckDeviceMultiSampleType, THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType) {
    return CheckDeviceMultiSampleType( Adapter, DeviceType, SurfaceFormat, Windowed, MultiSampleType );
}

STDIMP8(CheckDepthStencilMatch, THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) {
    return CheckDepthStencilMatch( Adapter, DeviceType, AdapterFormat, RenderTargetFormat, DepthStencilFormat );
}

STDIMP8(GetDeviceCaps, THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS8* pCaps) {
    return GetDeviceCaps( Adapter, DeviceType, pCaps );
}

STDIMP8_(HMONITOR, GetAdapterMonitor, THIS_ UINT Adapter) {
    return GetAdapterMonitor( Adapter );
}

STDIMP8(CreateDevice, THIS_ UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice8** ppReturnedDeviceInterface) {
    return CreateDevice( Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface );
}
#include <detours.h>
#include "D3D.h"

typedef HMODULE (WINAPI * HookLoadLibraryA)( LPCSTR lpFileName );
typedef IDirect3D8 *(WINAPI * HookDirect3DCreate8)( UINT SdkVersion );
typedef HRESULT (WINAPI * HookCreateDevice8)( IDirect3DDevice8* pInterface, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice8** ppReturnedDeviceInterface );
HookLoadLibraryA RealLoadLibraryA;
HookDirect3DCreate8 RealDirect3DCreate8;
HookCreateDevice8 RealCreateDevice8;
//...
CD3D<IDirect3D8> *m_d3d8;
CD3DDevice<IDirect3D8> *m_d3dDev8;
//...
RealLoadLibraryA = (HookLoadLibraryA)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)RealLoadLibraryA, FakeLoadLibraryA);
DetourTransactionCommit();
//...

VOID VirtualHook( PVOID pInterface, PVOID pHookProc, PVOID pOldProc, int iIndex )
{
    // Hook a procedure within an interface's virtual table
    PDWORD pVtable = (PDWORD)*((PDWORD)pInterface);
    DWORD lpflOldProtect;

    VirtualProtect( (PVOID)&pVtable[iIndex], sizeof(DWORD), PAGE_READWRITE, &lpflOldProtect );
    if( pOldProc ) *(DWORD*)pOldProc = pVtable[iIndex];
    pVtable[iIndex] = (DWORD)pHookProc;
    VirtualProtect( pVtable, sizeof(DWORD), lpflOldProtect, &lpflOldProtect );
}

HRESULT WINAPI FakeCreateDevice8( IDirect3DDevice8* pInterface, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice8** ppReturnedDeviceInterface )
{
    HRESULT ret = RealCreateDevice8( pInterface, Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface );
    // Save the registers
    __asm pushad
    if(*ppReturnedDeviceInterface != NULL)
        m_d3dDev8 = reinterpret_cast<CD3DDevice<IDirect3D8> *>(*ppReturnedDeviceInterface);
    // Restore the registers
    __asm popad
    return ret;
}

IDirect3D8 *WINAPI FakeDirect3DCreate8( UINT SdkVersion )
{
    m_d3d8 = reinterpret_cast<CD3D<IDirect3D8> *>(RealDirect3DCreate8( SdkVersion ));
    if( m_d3d8 ) {
        // Hook CreateDevice (vftable index #15)
        VirtualHook( m_d3d8, &FakeCreateDevice8, &RealCreateDevice8, 15 );
    }
    return m_d3d8;
}

HMODULE WINAPI FakeLoadLibraryA( LPCSTR lpFileName )
{
    CStringA strFileName( lpFileName );
    int i = strFileName.ReverseFind('\\');
    if(i != -1) strFileName = strFileName.Right(i + 1);
    if( strFileName.CompareNoCase("d3d8.dll") == 0 )
    {
        // Hook Direct3DCreate8
        HMODULE m_hD3D = RealLoadLibraryA( lpFileName );
        RealDirect3DCreate8 = (HookDirect3DCreate8)GetProcAddress(m_hD3D, "Direct3DCreate8");
        DetourTransactionBegin();
        DetourUpdateThread( GetCurrentThread() );
        DetourAttach(&(PVOID&)RealDirect3DCreate8, FakeDirect3DCreate8);
        DetourTransactionCommit();
        return m_hD3D;
    }
}
STDIMP8_(ULONG, AddRef, THIS) {
    return realObject->AddRef();
}