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>
158 lines
3.9 KiB
C++
158 lines
3.9 KiB
C++
// DatLibrary.cpp : Implementation of cDatLibrary
|
|
#include "stdafx.h"
|
|
#include "DecalDat.h"
|
|
#include "DatLibrary.h"
|
|
|
|
#include "DatFile.h"
|
|
#include "DatService.h"
|
|
#include "DatStream.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// cDatLibrary
|
|
|
|
void cDatLibrary::load( cDatService *pService, BSTR strFilename, int nFileType, long nSectorSize )
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
// Convert the template path into a real path
|
|
m_pService = pService;
|
|
CComBSTR strPath;
|
|
pService->m_pDecal->MapPath( strFilename, &strPath );
|
|
m_nFileType = nFileType;
|
|
|
|
try
|
|
{
|
|
m_pFile = new cDatFile( OLE2T( strPath ), nSectorSize );
|
|
}
|
|
catch( ... )
|
|
{
|
|
}
|
|
}
|
|
|
|
HRESULT cDatLibrary::createFile( DWORD dwFile, REFIID iid, void **ppvItf )
|
|
{
|
|
CComObject< cDatStream > *pStream;
|
|
CComObject< cDatStream >::CreateInstance( &pStream );
|
|
CComPtr< IUnknown > pUnkStream = pStream;
|
|
|
|
try
|
|
{
|
|
pStream->m_pFile = new cDatFile::cFile( m_pFile->getFile( dwFile ) );
|
|
}
|
|
catch( ... )
|
|
{
|
|
delete pStream;
|
|
|
|
// File not found
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
return pStream->QueryInterface( iid, ppvItf );
|
|
}
|
|
|
|
STDMETHODIMP cDatLibrary::Lookup( BSTR strName, IUnknown **ppItf )
|
|
{
|
|
USES_CONVERSION;
|
|
LPTSTR szName = OLE2T( strName );
|
|
|
|
int nProtocol = ::_tcscspn( szName, _T( ":" ) );
|
|
if( szName[ nProtocol ] == _T( '\0' ) )
|
|
{
|
|
// Special case, no protocol creates a raw stream
|
|
DWORD dwFile;
|
|
if( ::_stscanf( szName, _T( "%X" ), &dwFile ) != 1 )
|
|
return E_INVALIDARG;
|
|
|
|
return get_Stream( dwFile, ppItf );
|
|
}
|
|
|
|
// We have a protocol name
|
|
szName[ nProtocol ] = _T( '\0' );
|
|
|
|
// Convert the hew file number
|
|
DWORD dwFile;
|
|
if( ::_stscanf( szName + nProtocol + 1, _T( "%X" ), &dwFile ) != 1 )
|
|
{
|
|
_ASSERT( FALSE );
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
return Open( CComBSTR( szName ), dwFile, ppItf );
|
|
}
|
|
|
|
STDMETHODIMP cDatLibrary::get_Stream(DWORD dwFile, LPUNKNOWN *pVal)
|
|
{
|
|
return createFile( dwFile, IID_IUnknown, reinterpret_cast< void ** >( pVal ) );
|
|
}
|
|
|
|
STDMETHODIMP cDatLibrary::Open(BSTR Protocol, DWORD File, LPUNKNOWN *pFile)
|
|
{
|
|
USES_CONVERSION;
|
|
LPTSTR szName = OLE2T( Protocol );
|
|
|
|
::_tcslwr( szName );
|
|
|
|
cDatService::cFileFilter *pFilter = m_pService->getFilter( szName, ::_tcslen( szName ) );
|
|
if( pFilter == NULL )
|
|
{
|
|
_ASSERT( FALSE );
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if( pFilter->m_bCache )
|
|
{
|
|
// Check the file cache for an existing verison
|
|
for( cDatService::cFileCacheList::iterator i = m_pService->m_cache.begin(); i != m_pService->m_cache.end(); ++ i )
|
|
{
|
|
if( i->m_dwFile == File &&
|
|
static_cast< int >( i->m_library ) == m_nFileType &&
|
|
i->m_pFilter == pFilter )
|
|
{
|
|
// Found our file, return victorious
|
|
return i->m_pFile->QueryInterface( pFile );
|
|
}
|
|
}
|
|
}
|
|
|
|
// No cache or not found in the cache, create the stream
|
|
CComPtr< IDatStream > pStream;
|
|
HRESULT hRes = createFile( File, IID_IDatStream, reinterpret_cast< void ** >( &pStream ) );
|
|
if( FAILED( hRes ) )
|
|
{
|
|
_ASSERT( FALSE );
|
|
return hRes;
|
|
}
|
|
|
|
// Lookin' good, create the filter
|
|
CComPtr< IFileFilter > pFileFilter;
|
|
hRes = m_pService->createFilter( pFilter, IID_IFileFilter, reinterpret_cast< void ** >( &pFileFilter ) );
|
|
|
|
if( FAILED( hRes ) )
|
|
{
|
|
_ASSERT( FALSE );
|
|
return hRes;
|
|
}
|
|
|
|
hRes = pFileFilter->Initialize( pStream );
|
|
|
|
if( FAILED( hRes ) )
|
|
{
|
|
_ASSERT( FALSE );
|
|
return hRes;
|
|
}
|
|
|
|
if( pFilter->m_bCache )
|
|
{
|
|
// Make a cache entry
|
|
cDatService::cFileCache fc;
|
|
|
|
fc.m_dwFile = File;
|
|
fc.m_library = static_cast< cDatService::eLibrary >( m_nFileType );
|
|
fc.m_pFilter = pFilter;
|
|
fc.m_pFile = pFileFilter;
|
|
|
|
m_pService->m_cache.push_back( fc );
|
|
}
|
|
|
|
return pFileFilter->QueryInterface( IID_IUnknown, reinterpret_cast< void ** >( pFile ) );
|
|
}
|