openDecal/Native/DecalDat/DatLibrary.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

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 ) );
}