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>
363 lines
8.1 KiB
C++
363 lines
8.1 KiB
C++
// MessageImpl.h
|
|
// Declaration of helper classes for implementing the IMessageMembers interface
|
|
|
|
#ifndef __MESSAGEIMPL_H
|
|
#define __MESSAGEIMPL_H
|
|
|
|
#include "Message.h"
|
|
|
|
template< class ImplT >
|
|
class ATL_NO_VTABLE IMessageIteratorImpl
|
|
: public IDispatchImpl< IMessageIterator, &__uuidof( IMessageIterator ), &LIBID_DecalNet >
|
|
{
|
|
public:
|
|
enum { eEndIndex = 0xFFFFFFFF };
|
|
|
|
cMessage *getSource();
|
|
DWORD getStartIndex();
|
|
DWORD getEndIndex();
|
|
|
|
DWORD m_dwIterator;
|
|
long m_nIndex;
|
|
|
|
void init()
|
|
{
|
|
m_nIndex = -1;
|
|
}
|
|
|
|
DWORD getNextIndex( DWORD dwIndex )
|
|
{
|
|
DWORD dwNextIndex = dwIndex + ( static_cast< ImplT * >( this )->getSource()->m_fields.begin() + dwIndex )->m_nOwns;
|
|
if( dwNextIndex == static_cast< ImplT * >( this )->getEndIndex() )
|
|
return eEndIndex;
|
|
return dwNextIndex;
|
|
}
|
|
|
|
DWORD getNextIndex()
|
|
{
|
|
if( m_nIndex == -1 )
|
|
{
|
|
DWORD dwIndex = static_cast< ImplT * >( this )->getStartIndex();
|
|
if ( dwIndex == static_cast< ImplT * >( this )->getEndIndex () )
|
|
// This was 0 size
|
|
return eEndIndex;
|
|
|
|
return dwIndex;
|
|
}
|
|
|
|
return static_cast< ImplT * >( this )->getNextIndex( m_dwIterator );
|
|
}
|
|
|
|
HRESULT advanceToIndex( long nIndex )
|
|
{
|
|
if( nIndex <= m_nIndex )
|
|
{
|
|
_ASSERT( FALSE );
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
int nCurIndex = m_nIndex;
|
|
for( DWORD dwIterator = static_cast< ImplT * >( this )->getNextIndex(); dwIterator != eEndIndex; dwIterator = static_cast< ImplT * >( this )->getNextIndex( dwIterator ) )
|
|
{
|
|
// Reset the counter
|
|
++ nCurIndex;
|
|
if( nCurIndex == nIndex )
|
|
{
|
|
m_dwIterator = dwIterator;
|
|
m_nIndex = nCurIndex;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
// The advance went off the edge
|
|
m_dwIterator = eEndIndex;
|
|
return S_FALSE;
|
|
}
|
|
|
|
HRESULT advanceToName( BSTR strName )
|
|
{
|
|
int nIndex = m_nIndex;
|
|
for( DWORD dwIterator = static_cast< ImplT * >( this )->getNextIndex(); dwIterator != eEndIndex; dwIterator = static_cast< ImplT * >( this )->getNextIndex( dwIterator ) )
|
|
{
|
|
++ nIndex;
|
|
if( ::VarBstrCmp( strName, ( static_cast< ImplT * >( this )->getSource()->m_fields.begin() + dwIterator )->m_pSchema->m_strName, LOCALE_USER_DEFAULT, 0 ) == VARCMP_EQ )
|
|
{
|
|
// We've found the field
|
|
m_nIndex = nIndex;
|
|
m_dwIterator = dwIterator;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
HRESULT advanceNext()
|
|
{
|
|
m_dwIterator = static_cast< ImplT * >( this )->getNextIndex();
|
|
if( m_dwIterator == eEndIndex )
|
|
return S_FALSE;
|
|
|
|
++ m_nIndex;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHOD(get_Current)(VARIANT *pData)
|
|
{
|
|
if( pData == NULL )
|
|
{
|
|
_ASSERT( FALSE );
|
|
return E_POINTER;
|
|
}
|
|
|
|
if( m_dwIterator == eEndIndex )
|
|
{
|
|
pData->vt = VT_NULL;
|
|
return E_FAIL;
|
|
}
|
|
|
|
cMessage::cFieldList::iterator i = static_cast< ImplT * >( this )->getSource()->m_fields.begin() + m_dwIterator;
|
|
i->m_pSchema->getValue( static_cast< ImplT * >( this )->getSource(), i, pData );
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHOD(get_MemberName)( BSTR *pstrName )
|
|
{
|
|
if( pstrName == NULL )
|
|
{
|
|
_ASSERT( FALSE );
|
|
return E_POINTER;
|
|
}
|
|
|
|
if( m_dwIterator == eEndIndex )
|
|
return E_FAIL;
|
|
|
|
cMessage::cFieldList::iterator i = static_cast< ImplT * >( this )->getSource()->m_fields.begin() + m_dwIterator;
|
|
*pstrName = SysAllocString( i->m_pSchema->m_strName );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHOD(get_Index)( long *pnIndex )
|
|
{
|
|
if( pnIndex == NULL )
|
|
{
|
|
_ASSERT( FALSE );
|
|
return E_POINTER;
|
|
}
|
|
|
|
if( m_dwIterator == eEndIndex )
|
|
return E_FAIL;
|
|
|
|
*pnIndex = m_nIndex;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHOD(get_Next)( VARIANT vIndex, LPVARIANT pvValue )
|
|
{
|
|
if( pvValue == NULL )
|
|
{
|
|
_ASSERT( FALSE );
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hRes;
|
|
if( vIndex.vt == VT_ERROR )
|
|
// Error value indicates the optional value was not filled
|
|
hRes = advanceNext();
|
|
else if( vIndex.vt == VT_BSTR )
|
|
hRes = advanceToName( vIndex.bstrVal );
|
|
else
|
|
{
|
|
// Try and convert it to a long
|
|
HRESULT hResConv = ::VariantChangeType( &vIndex, &vIndex, 0, VT_I4 );
|
|
if( FAILED( hResConv ) )
|
|
{
|
|
_ASSERT( FALSE );
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
hRes = advanceToIndex( vIndex.lVal );
|
|
}
|
|
|
|
if( hRes == S_FALSE )
|
|
{
|
|
pvValue->vt = VT_NULL;
|
|
return hRes;
|
|
}
|
|
|
|
cMessage::cFieldList::iterator i = static_cast< ImplT * >( this )->getSource()->m_fields.begin() + m_dwIterator;
|
|
i->m_pSchema->getValue( static_cast< ImplT * >( this )->getSource(), i, pvValue );
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHOD(get_NextString)(BSTR Name, BSTR *pValue)
|
|
{
|
|
VARIANT v;
|
|
v.vt = VT_BSTR;
|
|
v.bstrVal = Name;
|
|
|
|
VARIANT vOut;
|
|
HRESULT hRes = get_Next( v, &vOut );
|
|
|
|
if( hRes == S_FALSE )
|
|
return E_FAIL;
|
|
|
|
if( vOut.vt != VT_BSTR )
|
|
{
|
|
_ASSERT( FALSE );
|
|
return E_FAIL;
|
|
}
|
|
|
|
*pValue = vOut.bstrVal;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHOD(get_NextInt)(BSTR Name, long *pValue)
|
|
{
|
|
VARIANT v;
|
|
v.vt = VT_BSTR;
|
|
v.bstrVal = Name;
|
|
|
|
VARIANT vOut;
|
|
HRESULT hRes = get_Next( v, &vOut );
|
|
|
|
if( hRes == S_FALSE )
|
|
return E_FAIL;
|
|
|
|
if( vOut.vt == VT_I4 )
|
|
*pValue = vOut.lVal;
|
|
else if( vOut.vt == VT_I2 )
|
|
*pValue = vOut.iVal;
|
|
else if ( vOut.vt == VT_UI1 )
|
|
*pValue = vOut.bVal;
|
|
else
|
|
{
|
|
_ASSERT( FALSE );
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHOD(get_NextFloat)(BSTR Name, float *pValue)
|
|
{
|
|
VARIANT v;
|
|
v.vt = VT_BSTR;
|
|
v.bstrVal = Name;
|
|
|
|
VARIANT vOut;
|
|
HRESULT hRes = get_Next( v, &vOut );
|
|
|
|
if( hRes == S_FALSE )
|
|
return E_FAIL;
|
|
|
|
if( vOut.vt == VT_R4 )
|
|
*pValue = vOut.fltVal;
|
|
else if( vOut.vt == VT_R8 )
|
|
*pValue = static_cast< float >( vOut.dblVal );
|
|
else
|
|
{
|
|
_ASSERT( FALSE );
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHOD(get_NextObject)(BSTR Name, IMessageIterator **pValue)
|
|
{
|
|
VARIANT v;
|
|
v.vt = VT_BSTR;
|
|
v.bstrVal = Name;
|
|
|
|
VARIANT vOut;
|
|
HRESULT hRes = get_Next( v, &vOut );
|
|
|
|
if( hRes == S_FALSE )
|
|
return E_FAIL;
|
|
|
|
if( vOut.vt != VT_DISPATCH )
|
|
{
|
|
_ASSERT( FALSE );
|
|
return E_FAIL;
|
|
}
|
|
|
|
return vOut.pdispVal->QueryInterface ( pValue );
|
|
}
|
|
|
|
STDMETHOD(get_NextObjectIndex)(IMessageIterator **pValue)
|
|
{
|
|
VARIANT v;
|
|
v.vt = VT_ERROR;
|
|
|
|
CComVariant vOut;
|
|
HRESULT hRes = get_Next( v, &vOut );
|
|
|
|
if( hRes == S_FALSE )
|
|
return E_FAIL;
|
|
|
|
if( vOut.vt != VT_DISPATCH )
|
|
{
|
|
_ASSERT( FALSE );
|
|
return E_FAIL;
|
|
}
|
|
|
|
return vOut.pdispVal->QueryInterface ( pValue );
|
|
}
|
|
|
|
STDMETHOD(Reset)()
|
|
{
|
|
m_nIndex = -1;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHOD(get_Message)(IMessage **ppMessage)
|
|
{
|
|
if( ppMessage == NULL )
|
|
{
|
|
_ASSERT( FALSE );
|
|
return E_POINTER;
|
|
}
|
|
|
|
static_cast< ImplT * >( this )->getSource()->QueryInterface( IID_IMessage, reinterpret_cast< void ** >( ppMessage ) );
|
|
|
|
return S_OK;
|
|
}
|
|
};
|
|
|
|
class IMessageIteratorSublistImpl
|
|
: public IMessageIteratorImpl< IMessageIteratorSublistImpl >
|
|
{
|
|
public:
|
|
cMessage *m_pSource;
|
|
DWORD m_dwStartIndex,
|
|
m_dwEndIndex;
|
|
|
|
cMessage *getSource()
|
|
{
|
|
return m_pSource;
|
|
}
|
|
|
|
DWORD getStartIndex()
|
|
{
|
|
return m_dwStartIndex;
|
|
}
|
|
|
|
DWORD getEndIndex()
|
|
{
|
|
return m_dwEndIndex;
|
|
}
|
|
|
|
void init( cMessage *pMessage, DWORD dwStructIndex )
|
|
{
|
|
m_pSource = pMessage;
|
|
m_dwStartIndex = dwStructIndex + 1;
|
|
m_dwEndIndex = dwStructIndex + ( m_pSource->m_fields.begin() + dwStructIndex )->m_nOwns;
|
|
|
|
IMessageIteratorImpl< IMessageIteratorSublistImpl >::init();
|
|
}
|
|
};
|
|
|
|
#endif
|