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>
152 lines
4 KiB
C++
152 lines
4 KiB
C++
// DatService.cpp : Implementation of cDatService
|
|
#include "stdafx.h"
|
|
#include "DecalDat.h"
|
|
#include "DatService.h"
|
|
|
|
#include "DatLibrary.h"
|
|
|
|
#include <ApiHook.h>
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// cDatService
|
|
|
|
HANDLE WINAPI CreateFileF( LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
|
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile )
|
|
{
|
|
dwShareMode |= FILE_SHARE_READ | FILE_SHARE_WRITE;
|
|
return cDatService::g_fn_CreateFile( lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
|
|
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile );
|
|
}
|
|
|
|
static cHookDescriptor _hooks[] = {
|
|
{ eByName, _T( "kernel32.dll" ), _T( "CreateFileA" ), 0, reinterpret_cast< DWORD >( CreateFileF ), 0 },
|
|
};
|
|
|
|
cDatService::cFileFilter *cDatService::getFilter( LPTSTR szFilter, int nLength )
|
|
{
|
|
std::string strFilter( szFilter, nLength );
|
|
|
|
for( cFileFilterList::iterator i = m_filters.begin(); i != m_filters.end(); ++ i )
|
|
{
|
|
if( strFilter == i->m_strName )
|
|
return &(*(i));
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
HRESULT cDatService::createFilter( cDatService::cFileFilter *pFilter, REFIID iid, LPVOID *ppvItf )
|
|
{
|
|
static _bstr_t _strFilter( _T( "FileFilters" ) );
|
|
|
|
CComPtr< IDecalEnum > pEnumFilter;
|
|
if( m_pDecal->get_Configuration( _strFilter, pFilter->m_clsid, &pEnumFilter ) != S_OK )
|
|
return E_FAIL;
|
|
|
|
return pEnumFilter->CreateInstance( iid, ppvItf );
|
|
}
|
|
|
|
HRESULT cDatService::onInitialize()
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
static _bstr_t _strPortal( _T( "%ac%\\portal.dat" ) ),
|
|
_strCell( _T( "%ac%\\cell.dat" ) );
|
|
|
|
if( g_p == NULL )
|
|
{
|
|
hookFunctions( _hooks, 1, true );
|
|
g_fn_CreateFile = reinterpret_cast< fn_CreateFile >( _hooks[ 0 ].m_pOldFunction );
|
|
g_p = this;
|
|
}
|
|
|
|
CComObject< cDatLibrary > *pComCell, *pComPortal;
|
|
CComObject< cDatLibrary >::CreateInstance( &pComCell );
|
|
CComObject< cDatLibrary >::CreateInstance( &pComPortal );
|
|
|
|
pComCell->AddRef();
|
|
pComPortal->AddRef();
|
|
|
|
m_pCell = pComCell;
|
|
m_pPortal = pComPortal;
|
|
|
|
m_pCell->load( this, _strCell, eCell, 256 );
|
|
m_pPortal->load( this, _strPortal, ePortal, 1024 );
|
|
|
|
// Load the list of filters
|
|
static _bstr_t _strFilter( _T( "FileFilters" ) ),
|
|
_strPrefix( _T( "Prefix" ) ),
|
|
_strCache( _T( "Cache" ) );
|
|
CComPtr< IDecalEnum > pEnum;
|
|
|
|
m_pDecal->get_Configuration( _strFilter, GUID_NULL, &pEnum );
|
|
|
|
while( pEnum->Next() == S_OK )
|
|
{
|
|
CComVariant vPrefix, vCache;
|
|
cFileFilter;
|
|
|
|
cFileFilter ff;
|
|
pEnum->get_ComClass( &ff.m_clsid );
|
|
|
|
HRESULT hRes = pEnum->get_Property( _strPrefix, &vPrefix );
|
|
if( !SUCCEEDED( hRes ) || vPrefix.vt != VT_BSTR )
|
|
{
|
|
_ASSERT( FALSE );
|
|
continue;
|
|
}
|
|
|
|
hRes = pEnum->get_Property( _strCache, &vCache );
|
|
if( !SUCCEEDED( hRes ) || vCache.vt != VT_I4 )
|
|
{
|
|
_ASSERT( FALSE );
|
|
continue;
|
|
}
|
|
|
|
ff.m_bCache = !!vCache.lVal;
|
|
|
|
LPTSTR szPrefix = OLE2T( vPrefix.bstrVal );
|
|
::_tcslwr( szPrefix );
|
|
ff.m_strName = szPrefix;
|
|
|
|
m_filters.push_back( ff );
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void cDatService::onTerminate()
|
|
{
|
|
m_cache.clear();
|
|
m_filters.clear();
|
|
|
|
if( g_p == this )
|
|
{
|
|
hookFunctions( _hooks, 1, false );
|
|
g_p = NULL;
|
|
}
|
|
|
|
m_pCell->Release();
|
|
m_pPortal->Release();
|
|
|
|
m_pCell = NULL;
|
|
m_pPortal = NULL;
|
|
}
|
|
|
|
cDatService *cDatService::g_p = NULL;
|
|
cDatService::fn_CreateFile cDatService::g_fn_CreateFile = NULL;
|
|
|
|
STDMETHODIMP cDatService::Lookup( BSTR strName, IUnknown **ppItf )
|
|
{
|
|
static _bstr_t _strPortal( _T( "portal" ) ),
|
|
_strCell( _T( "cell" ) );
|
|
|
|
if( ::VarBstrCmp( strName, _strPortal, 0, NORM_IGNORECASE ) == VARCMP_EQ )
|
|
return m_pPortal->QueryInterface( IID_IUnknown, reinterpret_cast< void ** >( ppItf ) );
|
|
|
|
if( ::VarBstrCmp( strName, _strCell, 0, NORM_IGNORECASE ) == VARCMP_EQ )
|
|
return m_pCell->QueryInterface( IID_IUnknown, reinterpret_cast< void ** >( ppItf ) );
|
|
|
|
// None of the above
|
|
return E_INVALIDARG;
|
|
}
|