// Direct3DHook.h : Declaration of the CDirect3DHook

#ifndef __DIRECT3DHOOK_H_
#define __DIRECT3DHOOK_H_

#include "resource.h"       // main symbols

/////////////////////////////////////////////////////////////////////////////
// CDirect3DHook
class ATL_NO_VTABLE CDirect3DHook : 
	public CComObjectRootEx<CComMultiThreadModel>,
   public IDirect3DDevice,
   public IDirect3DDevice2,
   public IDirect3DDevice3
{
public:
	CDirect3DHook()
	{
	}

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CDirect3DHook)
   COM_INTERFACE_ENTRY_IID( IID_IDirect3DDevice, IDirect3DDevice )
   COM_INTERFACE_ENTRY_IID( IID_IDirect3DDevice2, IDirect3DDevice2 )
   COM_INTERFACE_ENTRY_IID( IID_IDirect3DDevice3, IDirect3DDevice3 )
END_COM_MAP()

   CComPtr< IDirect3DDevice > m_pDevice;
   CComPtr< IDirect3DDevice2 > m_pDevice2;
   CComPtr< IDirect3DDevice3 > m_pDevice3;

   void setObject( IUnknown *pDevice );

// IDirect3DHook
public:
   // Functions from IDirect3DDevice

    STDMETHOD(Initialize)(LPDIRECT3D p1,LPGUID p2,LPD3DDEVICEDESC p3)
    {
       return m_pDevice->Initialize( p1, p2, p3 );
    }

    STDMETHOD(GetCaps)(LPD3DDEVICEDESC p1,LPD3DDEVICEDESC p2)
    {
       return m_pDevice->GetCaps( p1, p2 );
    }

    STDMETHOD(SwapTextureHandles)(LPDIRECT3DTEXTURE p1,LPDIRECT3DTEXTURE p2)
    {
       return m_pDevice->SwapTextureHandles( p1, p2 );
    }

    STDMETHOD(CreateExecuteBuffer)(LPD3DEXECUTEBUFFERDESC p1,LPDIRECT3DEXECUTEBUFFER*p2,IUnknown*p3)
    {
       return m_pDevice->CreateExecuteBuffer( p1, p2, p3 );
    }

    STDMETHOD(GetStats)(LPD3DSTATS p1)
    {
       return m_pDevice->GetStats( p1 );
    }

    STDMETHOD(Execute)(LPDIRECT3DEXECUTEBUFFER p1,LPDIRECT3DVIEWPORT p2,DWORD p3)
    {
       return m_pDevice->Execute( p1, p2, p3 );
    }

    STDMETHOD(AddViewport)(LPDIRECT3DVIEWPORT p1)
    {
       return m_pDevice->AddViewport( p1 );
    }

    STDMETHOD(DeleteViewport)(LPDIRECT3DVIEWPORT p1)
    {
       return m_pDevice->DeleteViewport( p1 );
    }

    STDMETHOD(NextViewport)(LPDIRECT3DVIEWPORT p1,LPDIRECT3DVIEWPORT*p2,DWORD p3)
    {
       return m_pDevice->NextViewport( p1, p2, p3 );
    }

    STDMETHOD(Pick)(LPDIRECT3DEXECUTEBUFFER p1,LPDIRECT3DVIEWPORT p2,DWORD p3,LPD3DRECT p4)
    {
       return m_pDevice->Pick( p1, p2, p3, p4 );
    }

    STDMETHOD(GetPickRecords)(LPDWORD p1,LPD3DPICKRECORD p2)
    {
       return m_pDevice->GetPickRecords( p1, p2 );
    }

    STDMETHOD(EnumTextureFormats)(LPD3DENUMTEXTUREFORMATSCALLBACK p1,LPVOID p2)
    {
       return m_pDevice->EnumTextureFormats( p1, p2 );
    }

    STDMETHOD(CreateMatrix)(LPD3DMATRIXHANDLE p1)
    {
       return m_pDevice->CreateMatrix( p1 );
    }

    STDMETHOD(SetMatrix)(D3DMATRIXHANDLE p1,const LPD3DMATRIX p2)
    {
       return m_pDevice->SetMatrix( p1, p2 );
    }

    STDMETHOD(GetMatrix)(D3DMATRIXHANDLE p1,LPD3DMATRIX p2)
    {
       return m_pDevice->GetMatrix( p1, p2 );
    }

    STDMETHOD(DeleteMatrix)(D3DMATRIXHANDLE p1)
    {
       return m_pDevice->DeleteMatrix( p1 );
    }

    STDMETHOD(BeginScene)();

    STDMETHOD(EndScene)();

    STDMETHOD(GetDirect3D)(LPDIRECT3D*p1)
    {
       return m_pDevice->GetDirect3D( p1 );
    }

    // Functions from IDirect3DDevice2
    STDMETHOD(SwapTextureHandles)(LPDIRECT3DTEXTURE2 p1,LPDIRECT3DTEXTURE2 p2)
    {
       return m_pDevice2->SwapTextureHandles( p1, p2 );
    }

    STDMETHOD(AddViewport)(LPDIRECT3DVIEWPORT2 p1)
    {
       return m_pDevice2->AddViewport( p1 );
    }

    STDMETHOD(DeleteViewport)(LPDIRECT3DVIEWPORT2 p1)
    {
       return m_pDevice2->DeleteViewport( p1 );
    }

    STDMETHOD(NextViewport)(LPDIRECT3DVIEWPORT2 p1,LPDIRECT3DVIEWPORT2*p2,DWORD p3)
    {
       return m_pDevice2->NextViewport( p1, p2, p3 );
    }

    STDMETHOD(GetDirect3D)(LPDIRECT3D2*p1)
    {
       return m_pDevice2->GetDirect3D( p1 );
    }

    STDMETHOD(SetCurrentViewport)(LPDIRECT3DVIEWPORT2 p1)
    {
       return m_pDevice2->SetCurrentViewport( p1 );
    }

    STDMETHOD(GetCurrentViewport)(LPDIRECT3DVIEWPORT2 *p1)
    {
       return m_pDevice2->GetCurrentViewport( p1 );
    }

    STDMETHOD(SetRenderTarget)(LPDIRECTDRAWSURFACE p1,DWORD p2)
    {
       return m_pDevice2->SetRenderTarget( p1, p2 );
    }

    STDMETHOD(GetRenderTarget)(LPDIRECTDRAWSURFACE *p1)
    {
       return m_pDevice2->GetRenderTarget( p1 );
    }

    STDMETHOD(Begin)(D3DPRIMITIVETYPE p1,D3DVERTEXTYPE p2,DWORD p3)
    {
       return m_pDevice2->Begin( p1, p2, p3 );
    }

    STDMETHOD(BeginIndexed)(D3DPRIMITIVETYPE p1,D3DVERTEXTYPE p2,LPVOID p3,DWORD p4,DWORD p5)
    {
       return m_pDevice2->BeginIndexed( p1, p2, p3, p4, p5 );
    }

    STDMETHOD(Vertex)(LPVOID p1)
    {
       return m_pDevice2->Vertex( p1 );
    }

    STDMETHOD(Index)(WORD p1)
    {
       return m_pDevice2->Index( p1 );
    }

    STDMETHOD(End)(DWORD p1)
    {
       return m_pDevice2->End( p1 );
    }

    STDMETHOD(GetRenderState)(D3DRENDERSTATETYPE p1,LPDWORD p2)
    {
       return m_pDevice2->GetRenderState( p1, p2 );
    }

    STDMETHOD(SetRenderState)(D3DRENDERSTATETYPE p1,DWORD p2)
    {
       return m_pDevice2->SetRenderState( p1, p2 );
    }

    STDMETHOD(GetLightState)(D3DLIGHTSTATETYPE p1,LPDWORD p2)
    {
       return m_pDevice2->GetLightState( p1, p2 );
    }

    STDMETHOD(SetLightState)(D3DLIGHTSTATETYPE p1,DWORD p2)
    {
       return m_pDevice2->SetLightState( p1, p2 );
    }

    STDMETHOD(SetTransform)(D3DTRANSFORMSTATETYPE p1,LPD3DMATRIX p2)
    {
       return m_pDevice2->SetTransform( p1, p2 );
    }

    STDMETHOD(GetTransform)(D3DTRANSFORMSTATETYPE p1,LPD3DMATRIX p2)
    {
       return m_pDevice2->GetTransform( p1, p2 );
    }

    STDMETHOD(MultiplyTransform)(D3DTRANSFORMSTATETYPE p1,LPD3DMATRIX p2)
    {
       return m_pDevice2->MultiplyTransform( p1, p2 );
    }

    STDMETHOD(DrawPrimitive)(D3DPRIMITIVETYPE p1,D3DVERTEXTYPE p2,LPVOID p3,DWORD p4,DWORD p5)
    {
       return m_pDevice2->DrawPrimitive( p1, p2, p3, p4, p5 );
    }

    STDMETHOD(DrawIndexedPrimitive)(D3DPRIMITIVETYPE p1,D3DVERTEXTYPE p2,LPVOID p3,DWORD p4,LPWORD p5, DWORD p6, DWORD p7)
    {
       return m_pDevice2->DrawIndexedPrimitive( p1, p2, p3, p4, p5, p6, p7 );
    }

    STDMETHOD(SetClipStatus)(LPD3DCLIPSTATUS p1)
    {
       return m_pDevice2->SetClipStatus( p1 );
    }

    STDMETHOD(GetClipStatus)(LPD3DCLIPSTATUS p1)
    {
       return m_pDevice2->GetClipStatus( p1 );
    }

    // Functions from IDirect3DDevice3
    STDMETHOD(AddViewport)(LPDIRECT3DVIEWPORT3 p1)
    {
       return m_pDevice3->AddViewport( p1 );
    }

    STDMETHOD(DeleteViewport)(LPDIRECT3DVIEWPORT3 p1)
    {
       return m_pDevice3->DeleteViewport( p1 );
    }

    STDMETHOD(NextViewport)(LPDIRECT3DVIEWPORT3 p1,LPDIRECT3DVIEWPORT3*p2,DWORD p3)
    {
       return m_pDevice3->NextViewport( p1, p2, p3 );
    }

    STDMETHOD(EnumTextureFormats)(LPD3DENUMPIXELFORMATSCALLBACK p1,LPVOID p2)
    {
       return m_pDevice3->EnumTextureFormats( p1, p2 );
    }

    STDMETHOD(GetDirect3D)(LPDIRECT3D3* p1)
    {
       return m_pDevice3->GetDirect3D( p1 );
    }

    STDMETHOD(SetCurrentViewport)(LPDIRECT3DVIEWPORT3 p1)
    {
       return m_pDevice3->SetCurrentViewport( p1 );
    }

    STDMETHOD(GetCurrentViewport)(LPDIRECT3DVIEWPORT3 *p1)
    {
       return m_pDevice3->GetCurrentViewport( p1 );
    }

    STDMETHOD(SetRenderTarget)(LPDIRECTDRAWSURFACE4 p1,DWORD p2)
    {
       return m_pDevice3->SetRenderTarget( p1, p2 );
    }

    STDMETHOD(GetRenderTarget)(LPDIRECTDRAWSURFACE4 *p1)
    {
       return m_pDevice3->GetRenderTarget( p1 );
    }

    STDMETHOD(Begin)(D3DPRIMITIVETYPE p1,DWORD p2,DWORD p3)
    {
       return m_pDevice3->Begin( p1, p2, p3 );
    }

    STDMETHOD(BeginIndexed)(D3DPRIMITIVETYPE p1,DWORD p2,LPVOID p3,DWORD p4,DWORD p5)
    {
       return m_pDevice3->BeginIndexed( p1, p2, p3, p4, p5 );
    }

    STDMETHOD(DrawPrimitive)(D3DPRIMITIVETYPE p1,DWORD p2,LPVOID p3,DWORD p4,DWORD p5)
    {
       return m_pDevice3->DrawPrimitive( p1, p2, p3, p4, p5 );
    }

    STDMETHOD(DrawIndexedPrimitive)(D3DPRIMITIVETYPE p1,DWORD p2,LPVOID p3,DWORD p4,LPWORD p5,DWORD p6,DWORD p7)
    {
       return m_pDevice3->DrawIndexedPrimitive( p1, p2, p3, p4, p5, p6, p7 );
    }

    STDMETHOD(DrawPrimitiveStrided)(D3DPRIMITIVETYPE p1,DWORD p2,LPD3DDRAWPRIMITIVESTRIDEDDATA p3,DWORD p4,DWORD p5)
    {
       return m_pDevice3->DrawPrimitiveStrided( p1, p2, p3, p4, p5 );
    }

    STDMETHOD(DrawIndexedPrimitiveStrided)(D3DPRIMITIVETYPE p1,DWORD p2,LPD3DDRAWPRIMITIVESTRIDEDDATA p3,DWORD p4 ,LPWORD p5,DWORD p6,DWORD p7)
    {
       return m_pDevice3->DrawIndexedPrimitiveStrided( p1, p2, p3, p4, p5, p6, p7 );
    }

    STDMETHOD(DrawPrimitiveVB)(D3DPRIMITIVETYPE p1,LPDIRECT3DVERTEXBUFFER p2,DWORD p3,DWORD p4,DWORD p5)
    {
       return m_pDevice3->DrawPrimitiveVB( p1, p2, p3, p4, p5 );
    }

    STDMETHOD(DrawIndexedPrimitiveVB)(D3DPRIMITIVETYPE p1,LPDIRECT3DVERTEXBUFFER p2,LPWORD p3,DWORD p4,DWORD p5)
    {
       return m_pDevice3->DrawIndexedPrimitiveVB( p1, p2, p3, p4, p5 );
    }

    STDMETHOD(ComputeSphereVisibility)(LPD3DVECTOR p1,LPD3DVALUE p2,DWORD p3,DWORD p4,LPDWORD p5)
    {
       return m_pDevice3->ComputeSphereVisibility( p1, p2, p3, p4, p5 );
    }

    STDMETHOD(GetTexture)(DWORD p1,LPDIRECT3DTEXTURE2 *p2)
    {
       return m_pDevice3->GetTexture( p1, p2 );
    }

    STDMETHOD(SetTexture)(DWORD p1,LPDIRECT3DTEXTURE2 p2)
    {
       return m_pDevice3->SetTexture( p1, p2 );
    }

    STDMETHOD(GetTextureStageState)(DWORD p1,D3DTEXTURESTAGESTATETYPE p2,LPDWORD p3)
    {
       return m_pDevice3->GetTextureStageState( p1, p2, p3 );
    }

    STDMETHOD(SetTextureStageState)(DWORD p1,D3DTEXTURESTAGESTATETYPE p2,DWORD p3)
    {
       return m_pDevice3->SetTextureStageState( p1, p2, p3 );
    }

    STDMETHOD(ValidateDevice)(LPDWORD p1)
    {
       return m_pDevice3->ValidateDevice( p1 );
    }
};

#endif //__DIRECT3DHOOK_H_
