openDecal/Native/Inject/DirectDrawHook.cpp
erik d1442e3747 Initial commit: Complete open-source Decal rebuild
All 5 phases of the open-source Decal rebuild:

Phase 1: 14 decompiled .NET projects (Interop.*, Adapter, FileService, DecalUtil)
Phase 2: 10 native DLLs rewritten as C# COM servers with matching GUIDs
  - DecalDat, DHS, SpellFilter, DecalInput, DecalNet, DecalFilters
  - Decal.Core, DecalControls, DecalRender, D3DService
Phase 3: C++ shims for Inject.DLL (D3D9 hooking) and LauncherHook.DLL
Phase 4: DenAgent WinForms tray application
Phase 5: WiX installer and build script

25 C# projects building with 0 errors.
Native C++ projects require VS 2022 + Windows SDK (x86).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:27:56 +01:00

284 lines
8.1 KiB
C++

// DirectDrawHook.cpp : Implementation of CDirectDrawHook
#include "stdafx.h"
#include "Inject.h"
#include "DirectDrawHook.h"
#include "MaterialHook.h"
#include "DirectDrawSurfaceHook.h"
#include "Manager.h"
/////////////////////////////////////////////////////////////////////////////
// CDirectDrawHook
void CDirectDrawHook::setObject( IDirectDraw *pDD )
{
m_pDD = pDD;
m_pDD->QueryInterface( IID_IDirectDraw2, reinterpret_cast< void ** >( &m_pDD2 ) );
m_pDD->QueryInterface( IID_IDirectDraw4, reinterpret_cast< void ** >( &m_pDD4 ) );
m_pDD->QueryInterface( IID_IDirect3D, reinterpret_cast< void ** >( &m_pD3D ) );
m_pDD->QueryInterface( IID_IDirect3D2, reinterpret_cast< void ** >( &m_pD3D2 ) );
m_pDD->QueryInterface( IID_IDirect3D3, reinterpret_cast< void ** >( &m_pD3D3 ) );
cManager::_p->setDirectDraw( m_pDD4, m_pD3D3, NULL);
}
STDMETHODIMP CDirectDrawHook::SetCooperativeLevel(HWND p1, DWORD p2)
{
cManager::_p->setWindow( p1 );
return m_pDD->SetCooperativeLevel( p1, p2 );
}
STDMETHODIMP CDirectDrawHook::SetDisplayMode(DWORD p1, DWORD p2, DWORD p3)
{
return m_pDD->SetDisplayMode( p1, p2, p3 );
}
HRESULT (__stdcall *pfnOldLock)(IDirectDrawSurface4 *pDDS, LPRECT rc, LPDDSURFACEDESC2 *pddesc, DWORD dwFlags, HANDLE hEvent);
HRESULT (__stdcall *pfnOldUnlock)(IDirectDrawSurface4 *pDDS, LPRECT rc);
HRESULT __stdcall myLock (IDirectDrawSurface4 *pDDS, LPRECT rc, LPDDSURFACEDESC2 *pddesc, DWORD dwFlags, HANDLE hEvent)
{
HRESULT hRes = pfnOldLock(pDDS, rc, pddesc, dwFlags, hEvent);
//if(rc==NULL)
cManager::_p->m_lpSurface = (*pddesc)->lpSurface;
return hRes;
}
HRESULT __stdcall myUnlock ( IDirectDrawSurface4 *pDDS, LPRECT rc)
{
if(rc==NULL)
{
cManager::_p->draw2D();
//WaitForSingleObject(cManager::_p->m_hDrawSync, INFINITE);
//ResetEvent(cManager::_p->m_hDrawSync);
cManager::_p->m_lpSurface = NULL;
}
// EnterCriticalSection(&cs);
HRESULT hRes = pfnOldUnlock(pDDS, rc);
// LeaveCriticalSection(&cs);
//MessageBox(0, _bstr_t(" left: ") + _bstr_t((long)rc->left) + _bstr_t(" top: ") + _bstr_t((long)rc->top) + _bstr_t(" right: ") + _bstr_t((long)rc->right) + _bstr_t(" bottom: ") + _bstr_t((long)rc->bottom), "Asd", 0);
return hRes;
}
STDMETHODIMP CDirectDrawHook::CreateSurface(LPDDSURFACEDESC2 p1, LPDIRECTDRAWSURFACE4 FAR *ppDDS, IUnknown FAR *p3)
{
static long sc = 0;
//static bool bGotPrimary=false;
//static DWORD dwCaps=-1;
//I have no idea if this serves any purpose anymore, but its causing freezing on software clients. 'Removed' for now.
#if 0
if(cManager::_p->getSoftwareMode())// && (!bGotPrimary))
{
CComPtr< IDirectDrawSurface4 > pDDS;
HRESULT hRes = m_pDD4->CreateSurface( p1, &pDDS, p3 );
if( FAILED( hRes ) )
return hRes;
pDDS->QueryInterface(IID_IDirectDrawSurface4, reinterpret_cast< void ** >(ppDDS));
// Get the configured width from the registry
/* DWORD dwConfiguredWidth;
{
RECT rc;
::GetClientRect( cManager::_p->m_hMain, &rc );
dwConfiguredWidth = rc.right - rc.left;
}*/
/*if( p1->dwWidth < ( dwConfiguredWidth - 330 ) )
{
}
*/
if(p1->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
{
//MessageBox(0, _bstr_t("Width: ") + _bstr_t((long)p1->dwWidth) + _bstr_t(" Height: ") + _bstr_t((long)p1->dwHeight), "asd", 0);
sc++;
/*if(dwCaps!=-1)
if(dwCaps!=p1->ddsCaps.dwCaps)
MessageBox(0, "Diff", "asd", 0);*/
// dwCaps = p1->ddsCaps.dwCaps;
//if(/*(((sc%2)==0) && (bGotPrimary)) || */(sc==3) || (sc==4))
{
/*if(sc==1)
InitializeCriticalSection(&cs);*/
/*if(bGotPrimary)
{
if(m_pDDS4.p!=NULL)
{
HRESULT (__stdcall *&pfnUnlockPrev)(IDirectDrawSurface4 *pDDS, LPRECT rc) = reinterpret_cast< HRESULT (__stdcall**)(IDirectDrawSurface4 *pDDS, LPRECT rc) > ( *reinterpret_cast< DWORD * > ( m_pDDS4.p ) )[ 32 ];
pfnUnlockPrev = pfnOldUnlock;
}
}*/
//EnterCriticalSection(&cs);
if(sc==1)
{
HRESULT (__stdcall *&pfnLock)(IDirectDrawSurface4 *, LPRECT, LPDDSURFACEDESC2, DWORD, HANDLE) = reinterpret_cast< HRESULT (__stdcall**)(IDirectDrawSurface4 *, LPRECT, LPDDSURFACEDESC2, DWORD, HANDLE) > ( *reinterpret_cast< DWORD * > ( pDDS.p ) )[ 25 ];
HRESULT (__stdcall *&pfnUnlock)(IDirectDrawSurface4 *, LPRECT) = reinterpret_cast< HRESULT (__stdcall**)(IDirectDrawSurface4 *, LPRECT) > ( *reinterpret_cast< DWORD * > ( pDDS.p ) )[ 32 ];
pfnOldUnlock = *pfnUnlock;
pfnUnlock = myUnlock;
cManager::_p->setDirectDraw(m_pDD4, NULL, pDDS);
cManager::_p->setSurface(NULL);
}
//bGotPrimary=true;
//m_pDDS4 = pDDS;
//LeaveCriticalSection(&cs);
}
}
return hRes;
}
else
#endif
return m_pDD4->CreateSurface(p1, ppDDS, p3);
}
STDMETHODIMP CDirectDrawHook::SetDisplayMode(DWORD p1, DWORD p2, DWORD p3, DWORD p4, DWORD p5)
{
return m_pDD2->SetDisplayMode( p1, p2, p3, p4, p5 );
}
STDMETHODIMP CDirectDrawHook::CreateMaterial(LPDIRECT3DMATERIAL *p1,IUnknown *p2)
{
CComPtr< IDirect3DMaterial > pMat;
HRESULT hRes = m_pD3D->CreateMaterial( &pMat, p2 );
if( FAILED( hRes ) )
return hRes;
CComObject< CMaterialHook > *pHook;
CComObject< CMaterialHook >::CreateInstance( &pHook );
pHook->setObject( pMat, m_pDevice2, m_pDevice3 );
pHook->QueryInterface( IID_IDirect3DMaterial, reinterpret_cast< void ** >( p1 ) );
return hRes;
}
STDMETHODIMP CDirectDrawHook::CreateMaterial(LPDIRECT3DMATERIAL2*p1,IUnknown*p2)
{
CComPtr< IDirect3DMaterial2 > pMat;
HRESULT hRes = m_pD3D2->CreateMaterial( &pMat, p2 );
if( FAILED( hRes ) )
return hRes;
CComObject< CMaterialHook > *pHook;
CComObject< CMaterialHook >::CreateInstance( &pHook );
pHook->setObject( pMat, m_pDevice2, m_pDevice3 );
pHook->QueryInterface( IID_IDirect3DMaterial2, reinterpret_cast< void ** >( p1 ) );
return hRes;
}
STDMETHODIMP CDirectDrawHook::CreateMaterial(LPDIRECT3DMATERIAL3*p1,LPUNKNOWN p2)
{
CComPtr< IDirect3DMaterial3 > pMat;
HRESULT hRes = m_pD3D3->CreateMaterial( &pMat, p2 );
if( FAILED( hRes ) )
return hRes;
CComObject< CMaterialHook > *pHook;
CComObject< CMaterialHook >::CreateInstance( &pHook );
pHook->setObject( pMat, m_pDevice2, m_pDevice3 );
pHook->QueryInterface( IID_IDirect3DMaterial3, reinterpret_cast< void ** >( p1 ) );
return hRes;
}
STDMETHODIMP CDirectDrawHook::CreateDevice( REFCLSID cls,LPDIRECTDRAWSURFACE pDDS,LPDIRECT3DDEVICE2 *ppD3D )
{
CComPtr< IDirect3DDevice2 > pD3D;
HRESULT hRes = m_pD3D2->CreateDevice( cls, pDDS, &pD3D );
if( FAILED( hRes ) )
{
//::MessageBox (NULL, "2COULDN'T CreateDevice IN D3D HOOK", "ERROR", MB_OK);
return hRes;
}
CComObject< CDirect3DHook > *pHook;
CComObject< CDirect3DHook >::CreateInstance( &pHook );
pHook->setObject( pD3D );
pHook->QueryInterface( IID_IDirect3DDevice2, reinterpret_cast< void ** >( ppD3D ) );
m_pDevice2 = *ppD3D;
return hRes;
}
STDMETHODIMP CDirectDrawHook::CreateDevice(REFCLSID cls,LPDIRECTDRAWSURFACE4 pDDS,LPDIRECT3DDEVICE3* ppD3D,LPUNKNOWN pUnk)
{
CComPtr< IDirect3DDevice3 > pD3D;
HRESULT hRes = m_pD3D3->CreateDevice( cls, pDDS, &pD3D, pUnk );
if( FAILED( hRes ) )
{
//::MessageBox (NULL, "3COULDN'T CreateDevice IN D3D HOOK", "ERROR", MB_OK);
return hRes;
}
// Ok, figure out if this is the "primary" 3d device
DDSURFACEDESC2 ddsd;
ddsd.dwSize = sizeof( DDSURFACEDESC2 );
pDDS->GetSurfaceDesc( &ddsd );
// Get the configured width from the registry
DWORD dwConfiguredWidth;
{
RECT rc;
::GetClientRect( cManager::_p->m_hMain, &rc );
dwConfiguredWidth = rc.right - rc.left;
}
if( ddsd.dwWidth < ( dwConfiguredWidth - 330 ) )
{
// This is a secondary 3ddevice - do not hook it
return pD3D->QueryInterface( IID_IDirect3DDevice3, reinterpret_cast< void ** >( ppD3D ) );
}
// Ok, we're past the wrong device, get to the right device
cManager::_p->setSurface( pD3D );
CComObject< CDirect3DHook > *pHook;
CComObject< CDirect3DHook >::CreateInstance( &pHook );
pHook->setObject( pD3D );
pHook->QueryInterface( IID_IDirect3DDevice3, reinterpret_cast< void ** >( ppD3D ) );
m_pDevice3 = *ppD3D;
return hRes;
}