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>
This commit is contained in:
commit
d1442e3747
1382 changed files with 170725 additions and 0 deletions
727
Native/DecalNet/MessageParsers.cpp
Normal file
727
Native/DecalNet/MessageParsers.cpp
Normal file
|
|
@ -0,0 +1,727 @@
|
|||
// MessageParsers.cpp
|
||||
// Implementation of parsers and runtime objects for parsing message data
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "DecalNet.h"
|
||||
|
||||
#include "MessageParsers.h"
|
||||
#include "MessageLoaders.h"
|
||||
|
||||
#include "MessageStruct.h"
|
||||
#include "MessageVector.h"
|
||||
|
||||
class cStructElement
|
||||
: public cMessage::cMessageElement
|
||||
{
|
||||
public:
|
||||
cMessage::cElementList m_members;
|
||||
|
||||
virtual bool load( cMessage::cLoadContext &context )
|
||||
{
|
||||
// Walk through the list of members and have them load
|
||||
int nIndex = context.addField( this, NULL );
|
||||
|
||||
for( cMessage::cElementList::iterator i = m_members.begin(); i != m_members.end(); ++ i )
|
||||
{
|
||||
if( !i->get()->load( cMessage::cLoadContext( &context ) ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update the field count
|
||||
context.groupField( nIndex );
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void getValue( cMessage *pMessage, cMessage::cFieldList::iterator i, LPVARIANT pDest )
|
||||
{
|
||||
if( i->m_pDisp.p == NULL )
|
||||
{
|
||||
// Create the vector object
|
||||
CComObject< cMessageStructIter > *pVecDisp;
|
||||
CComObject< cMessageStructIter >::CreateInstance( &pVecDisp );
|
||||
|
||||
pVecDisp->init( pMessage, ( i - pMessage->m_fields.begin() ) );
|
||||
i->m_pDisp = pVecDisp;
|
||||
}
|
||||
else
|
||||
i->m_pDisp->Reset();
|
||||
|
||||
pDest->vt = VT_DISPATCH;
|
||||
i->m_pDisp->QueryInterface ( IID_IMessageMember, reinterpret_cast< LPVOID * > ( &pDest->pdispVal ) );
|
||||
}
|
||||
};
|
||||
|
||||
class cFieldParser
|
||||
: public cElementParser
|
||||
{
|
||||
public:
|
||||
class cFieldElement
|
||||
: public cMessage::cMessageElement
|
||||
{
|
||||
public:
|
||||
cFieldLoader *m_pLoader;
|
||||
|
||||
virtual bool load( cMessage::cLoadContext &context )
|
||||
{
|
||||
if( !m_pLoader->testValue( context.getMessage()->m_pEndCrack, context.getMessage()->m_pEndData ) )
|
||||
{
|
||||
// The element failed, this will usually indicate bad schema
|
||||
_ASSERTE( FALSE );
|
||||
return false;
|
||||
}
|
||||
|
||||
context.addField( this, context.getMessage()->m_pEndCrack );
|
||||
context.getMessage()->m_pEndCrack = reinterpret_cast< BYTE * >( m_pLoader->skip( context.getMessage()->m_pEndCrack ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void getValue( cMessage *, cMessage::cFieldList::iterator i, LPVARIANT pDest )
|
||||
{
|
||||
m_pLoader->getValue( i->m_pvData, pDest );
|
||||
}
|
||||
|
||||
virtual long getNumber( cMessage::cFieldList::iterator i )
|
||||
{
|
||||
return m_pLoader->getNumber( i->m_pvData );
|
||||
}
|
||||
};
|
||||
|
||||
// Strings
|
||||
static _bstr_t g_strType;
|
||||
static _bstr_t g_strName;
|
||||
|
||||
virtual cMessage::cMessageElement *parse( cContext &context, MSXML::IXMLDOMElementPtr &pElement )
|
||||
{
|
||||
// Locate the data type in the list
|
||||
_variant_t strDataType = pElement->getAttribute( g_strType );
|
||||
|
||||
if( strDataType.vt != VT_BSTR )
|
||||
{
|
||||
// Schema error
|
||||
_ASSERTE( strDataType.vt == VT_BSTR );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_bstr_t bstrDataType = strDataType;
|
||||
|
||||
cFieldLoader *pField = cFieldLoader::lookup( bstrDataType );
|
||||
if( pField == NULL )
|
||||
return parseStruct( context, pElement, bstrDataType );
|
||||
|
||||
_variant_t strName = pElement->getAttribute( g_strName );
|
||||
|
||||
if( strName.vt != VT_BSTR )
|
||||
{
|
||||
_ASSERTE( strName.vt == VT_BSTR );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cFieldElement *pFieldElement = new cFieldElement;
|
||||
|
||||
pFieldElement->m_strName = strName;
|
||||
pFieldElement->m_pLoader = pField;
|
||||
return pFieldElement;
|
||||
}
|
||||
|
||||
cMessage::cMessageElement *parseStruct( cContext &context, MSXML::IXMLDOMElementPtr &pElement, const _bstr_t &strType )
|
||||
{
|
||||
// Locate the data type in the list
|
||||
_variant_t strName = pElement->getAttribute( cFieldParser::g_strName );
|
||||
|
||||
if( strName.vt != VT_BSTR )
|
||||
{
|
||||
// Schema error
|
||||
_ASSERTE( strName.vt == VT_BSTR );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// We have the field name, now look up data type schema
|
||||
USES_CONVERSION;
|
||||
|
||||
TCHAR szQuery[ 255 ];
|
||||
::_stprintf( szQuery, _T( "/schema/datatypes/type[@name='%s']" ),
|
||||
OLE2T( strType ) );
|
||||
|
||||
MSXML::IXMLDOMElementPtr pStruct = pElement->ownerDocument->selectSingleNode( szQuery );
|
||||
if( pStruct.GetInterfacePtr() == NULL )
|
||||
{
|
||||
// Could not cross reference the structure
|
||||
_ASSERTE( pStruct.GetInterfacePtr() != NULL );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VSBridge::auto_ptr< cStructElement > pStructElement( new cStructElement() );
|
||||
pStructElement->m_strName = strName;
|
||||
if( context.parseChildren( pStructElement->m_members, pStruct ) )
|
||||
return pStructElement.release();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
_bstr_t cFieldParser::g_strType( _T( "type" ) );
|
||||
_bstr_t cFieldParser::g_strName( _T( "name" ) );
|
||||
|
||||
class cMaskParser
|
||||
: public cElementParser
|
||||
{
|
||||
public:
|
||||
class cMaskElement
|
||||
: public cMessage::cMessageElement
|
||||
{
|
||||
public:
|
||||
cMessage::cMessageElement *m_pValue;
|
||||
|
||||
class cMask
|
||||
{
|
||||
public:
|
||||
DWORD m_dwValue;
|
||||
DWORD m_dwFirstChild,
|
||||
m_dwLastChild;
|
||||
};
|
||||
|
||||
typedef std::vector< cMask > cMaskMap;
|
||||
|
||||
cMaskMap m_masks;
|
||||
cMessage::cElementList m_members;
|
||||
|
||||
virtual bool load( cMessage::cLoadContext &context )
|
||||
{
|
||||
// First, look for our value element in the message
|
||||
cMessage::cFieldList::iterator iField = context.lookupField( m_pValue );
|
||||
if( iField == context.getMessage()->m_fields.end() )
|
||||
{
|
||||
// Could not find a mask source - most likely a bad name of some kind
|
||||
_ASSERTE( FALSE );
|
||||
return false;
|
||||
}
|
||||
|
||||
_ASSERT( iField->m_pSchema == m_pValue );
|
||||
|
||||
long nMaskValue = iField->m_pSchema->getNumber( iField );
|
||||
|
||||
// Walk through the mask values and load all of the fields in range
|
||||
for( cMaskMap::iterator i = m_masks.begin(); i != m_masks.end(); ++ i )
|
||||
{
|
||||
if( ( nMaskValue & i->m_dwValue ) == 0 )
|
||||
continue;
|
||||
|
||||
// This is a valid mask load up all teh fields in range
|
||||
cMessage::cElementList::iterator m_end = m_members.begin() + i->m_dwLastChild;
|
||||
for( cMessage::cElementList::iterator j = m_members.begin() + i->m_dwFirstChild; j != m_end; ++ j )
|
||||
{
|
||||
if( !j->get()->load( context ) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void getValue( cMessage *, cMessage::cFieldList::iterator, LPVARIANT )
|
||||
{
|
||||
// This element should never insert itself into the message list
|
||||
_ASSERTE( FALSE );
|
||||
}
|
||||
};
|
||||
|
||||
static _bstr_t g_strMask;
|
||||
static _bstr_t g_strValue;
|
||||
|
||||
virtual cMessage::cMessageElement *parse( cContext &context, MSXML::IXMLDOMElementPtr &pElement )
|
||||
{
|
||||
_variant_t vName = pElement->getAttribute( cFieldParser::g_strName );
|
||||
if( vName.vt != VT_BSTR )
|
||||
{
|
||||
// It must have the name field
|
||||
_ASSERTE( vName.vt == VT_BSTR );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Find a matching element in the schema
|
||||
cMessage::cMessageElement *pName = context.findElement( vName.bstrVal );
|
||||
if( pName == NULL )
|
||||
{
|
||||
// The mask field was not found
|
||||
_ASSERTE( pName != NULL );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create the mask element
|
||||
VSBridge::auto_ptr< cMaskElement > pMaskElement( new cMaskElement );
|
||||
pMaskElement->m_pValue = pName;
|
||||
|
||||
// Walk through each of the mask values
|
||||
USES_CONVERSION;
|
||||
|
||||
MSXML::IXMLDOMNodeListPtr pMaskList = pElement->selectNodes( g_strMask );
|
||||
for( MSXML::IXMLDOMElementPtr pMask = pMaskList->nextNode(); pMask.GetInterfacePtr() != NULL; pMask = pMaskList->nextNode() )
|
||||
{
|
||||
_variant_t vValue = pMask->getAttribute( g_strValue );
|
||||
if( vValue.vt != VT_BSTR )
|
||||
{
|
||||
_ASSERTE( vName.vt == VT_BSTR );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Make sure it has the 'hex' prefix
|
||||
if( vValue.bstrVal[ 0 ] != OLESTR( '0' ) )
|
||||
{
|
||||
_ASSERTE( vValue.bstrVal[ 0 ] == OLESTR( '0' ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( vValue.bstrVal[ 1 ] != OLESTR( 'x' ) )
|
||||
{
|
||||
_ASSERTE( vValue.bstrVal[ 1 ] == OLESTR( 'x' ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Attempt to convert the remaining number
|
||||
long nMaskValue;
|
||||
if( ::_stscanf( OLE2T( vValue.bstrVal + 2 ), _T( "%X" ), &nMaskValue ) != 1 )
|
||||
{
|
||||
// Could not convert value
|
||||
_ASSERTE( FALSE );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
long nStartOffset = pMaskElement->m_members.size();
|
||||
context.parseChildren( pMaskElement->m_members, pMask );
|
||||
|
||||
cMaskElement::cMask mask = { nMaskValue, nStartOffset, pMaskElement->m_members.size() };
|
||||
pMaskElement->m_masks.push_back( mask );
|
||||
}
|
||||
|
||||
return pMaskElement.release();
|
||||
}
|
||||
};
|
||||
|
||||
_bstr_t cMaskParser::g_strMask( _T( "mask" ) );
|
||||
_bstr_t cMaskParser::g_strValue( _T( "value" ) );
|
||||
|
||||
class cAlignParser
|
||||
: public cElementParser
|
||||
{
|
||||
public:
|
||||
class cAlignElement
|
||||
: public cMessage::cMessageElement
|
||||
{
|
||||
public:
|
||||
cFieldLoader *m_pLoader;
|
||||
|
||||
virtual bool load( cMessage::cLoadContext &context )
|
||||
{
|
||||
void *pAlign = m_pLoader->align( context.getMessage()->m_pEndCrack, context.getMessage()->m_pStartCrack );
|
||||
if( pAlign > context.getMessage()->m_pEndData )
|
||||
{
|
||||
_ASSERTE( FALSE );
|
||||
return false;
|
||||
}
|
||||
|
||||
context.getMessage()->m_pEndCrack = reinterpret_cast< BYTE * >( pAlign );
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void getValue( cMessage *, cMessage::cFieldList::iterator i, LPVARIANT pDest )
|
||||
{
|
||||
// This should never associate itself with a field
|
||||
_ASSERTE( FALSE );
|
||||
}
|
||||
};
|
||||
|
||||
virtual cMessage::cMessageElement *parse( cContext &context, MSXML::IXMLDOMElementPtr &pElement )
|
||||
{
|
||||
// Locate the data type in the list
|
||||
_variant_t strDataType = pElement->getAttribute( cFieldParser::g_strType );
|
||||
|
||||
if( strDataType.vt != VT_BSTR )
|
||||
{
|
||||
// Schema error
|
||||
_ASSERTE( strDataType.vt == VT_BSTR );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_bstr_t bstrDataType = strDataType;
|
||||
|
||||
cFieldLoader *pField = cFieldLoader::lookup( bstrDataType );
|
||||
if( pField == NULL )
|
||||
{
|
||||
_ASSERTE( FALSE );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cAlignElement *pAlignElement = new cAlignElement;
|
||||
|
||||
pAlignElement->m_pLoader = pField;
|
||||
return pAlignElement;
|
||||
}
|
||||
};
|
||||
|
||||
class cVectorParser
|
||||
: public cElementParser
|
||||
{
|
||||
public:
|
||||
class cVectorElement
|
||||
: public cMessage::cMessageElement
|
||||
{
|
||||
public:
|
||||
cMessage::cMessageElement *m_pLength;
|
||||
VSBridge::auto_ptr< cMessage::cMessageElement > m_pStruct;
|
||||
int m_nSkip;
|
||||
|
||||
DWORD m_dwMask;
|
||||
|
||||
virtual bool load( cMessage::cLoadContext &context )
|
||||
{
|
||||
// First, look for our value element in the message
|
||||
cMessage::cFieldList::iterator iField = context.lookupField( m_pLength );
|
||||
if( iField == context.getMessage()->m_fields.end() )
|
||||
{
|
||||
// Could not find a mask source - most likely a bad name of some kind
|
||||
_ASSERTE( FALSE );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_ASSERT( iField->m_pSchema == m_pLength );
|
||||
|
||||
long nLength = iField->m_pSchema->getNumber( iField ) - m_nSkip;
|
||||
|
||||
if (m_dwMask != 0)
|
||||
{
|
||||
DWORD dwTemp = (DWORD) nLength & m_dwMask;
|
||||
DWORD dwTempMask = m_dwMask;
|
||||
|
||||
// Shift the length field right as far as we can.
|
||||
while (! (dwTempMask & 0x1))
|
||||
{
|
||||
dwTempMask >>= 1;
|
||||
dwTemp >>= 1;
|
||||
}
|
||||
|
||||
nLength = (long) dwTemp;
|
||||
}
|
||||
|
||||
// Insert a record for ourself
|
||||
DWORD dwIndex = context.addField( this, NULL );
|
||||
|
||||
for( int i = 0; i < nLength; ++ i )
|
||||
{
|
||||
// Insert a record for the current struct
|
||||
if( !m_pStruct->load( cMessage::cLoadContext( &context ) ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update the used field count
|
||||
context.groupField( dwIndex );
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void getValue( cMessage *pMessage, cMessage::cFieldList::iterator i, LPVARIANT pDest )
|
||||
{
|
||||
if( i->m_pDisp.p == NULL )
|
||||
{
|
||||
// Create the vector object
|
||||
CComObject< cMessageVectorIter > *pVecDisp;
|
||||
CComObject< cMessageVectorIter >::CreateInstance( &pVecDisp );
|
||||
|
||||
pVecDisp->init( pMessage, ( i - pMessage->m_fields.begin() ) );
|
||||
i->m_pDisp = pVecDisp;
|
||||
}
|
||||
else
|
||||
i->m_pDisp->Reset();
|
||||
|
||||
pDest->vt = VT_DISPATCH;
|
||||
i->m_pDisp->QueryInterface ( IID_IMessageMember, reinterpret_cast< LPVOID * > ( &pDest->pdispVal ) );
|
||||
}
|
||||
};
|
||||
|
||||
static _bstr_t g_strLength,
|
||||
g_strSkip,
|
||||
g_strMask;
|
||||
|
||||
virtual cMessage::cMessageElement *parse( cContext &context, MSXML::IXMLDOMElementPtr &pElement )
|
||||
{
|
||||
_variant_t vName = pElement->getAttribute( cFieldParser::g_strName );
|
||||
if( vName.vt != VT_BSTR )
|
||||
{
|
||||
// It must have the name field
|
||||
_ASSERTE( vName.vt == VT_BSTR );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_variant_t vLength = pElement->getAttribute( g_strLength ),
|
||||
vSkip = pElement->getAttribute( g_strSkip ),
|
||||
vMask = pElement->getAttribute( g_strMask );
|
||||
|
||||
if( vLength.vt != VT_BSTR )
|
||||
{
|
||||
// It must have the name field
|
||||
_ASSERTE( vLength.vt == VT_BSTR );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
long nSkip = 0;
|
||||
if( vSkip.vt != VT_NULL )
|
||||
{
|
||||
try
|
||||
{
|
||||
nSkip = vSkip;
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
// Failed to make the conversion
|
||||
_ASSERT( FALSE );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD dwMask = 0;
|
||||
if( vMask.vt != VT_NULL )
|
||||
{
|
||||
dwMask = ::wcstoul (vMask.bstrVal, NULL, 16);
|
||||
}
|
||||
|
||||
cMessage::cMessageElement *pLength = context.findElement( vLength.bstrVal );
|
||||
if( pLength == NULL )
|
||||
{
|
||||
// The mask field was not found
|
||||
_ASSERTE( pLength != NULL );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VSBridge::auto_ptr< cStructElement > pStructElement( new cStructElement );
|
||||
|
||||
if( !context.parseChildren( pStructElement->m_members, pElement ) )
|
||||
return NULL;
|
||||
|
||||
cVectorElement *pVector = new cVectorElement;
|
||||
pVector->m_strName = vName;
|
||||
pVector->m_pLength = pLength;
|
||||
pVector->m_nSkip = nSkip;
|
||||
pVector->m_dwMask = dwMask;
|
||||
pVector->m_pStruct = VSBridge::auto_ptr< cMessage::cMessageElement >( pStructElement.release() );
|
||||
|
||||
return pVector;
|
||||
}
|
||||
};
|
||||
|
||||
_bstr_t cVectorParser::g_strLength( _T( "length" ) );
|
||||
_bstr_t cVectorParser::g_strSkip( _T( "skip" ) );
|
||||
_bstr_t cVectorParser::g_strMask( _T( "mask" ) );
|
||||
|
||||
class cSwitchParser
|
||||
: public cElementParser
|
||||
{
|
||||
public:
|
||||
class cSwitchElement
|
||||
: public cMessage::cMessageElement
|
||||
{
|
||||
public:
|
||||
cMessage::cMessageElement *m_pValue;
|
||||
|
||||
class cCase
|
||||
{
|
||||
public:
|
||||
DWORD m_dwValue;
|
||||
DWORD m_dwFirstChild,
|
||||
m_dwLastChild;
|
||||
};
|
||||
|
||||
typedef std::vector< cCase > cCaseMap;
|
||||
|
||||
cCaseMap m_cases;
|
||||
cMessage::cElementList m_members;
|
||||
|
||||
virtual bool load( cMessage::cLoadContext &context )
|
||||
{
|
||||
// First, look for our value element in the message
|
||||
cMessage::cFieldList::iterator iField = context.lookupField( m_pValue );
|
||||
if( iField == context.getMessage()->m_fields.end() )
|
||||
{
|
||||
// Could not find a mask source - most likely a bad name of some kind
|
||||
_ASSERTE( FALSE );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_ASSERT( iField->m_pSchema == m_pValue );
|
||||
|
||||
long nCaseValue = iField->m_pSchema->getNumber( iField );
|
||||
|
||||
// Walk through the mask values and load all of the fields in range
|
||||
for( cCaseMap::iterator i = m_cases.begin(); i != m_cases.end(); ++ i )
|
||||
{
|
||||
if( nCaseValue != i->m_dwValue )
|
||||
continue;
|
||||
|
||||
// This is a valid mask load up all teh fields in range
|
||||
cMessage::cElementList::iterator m_end = m_members.begin() + i->m_dwLastChild;
|
||||
for( cMessage::cElementList::iterator j = m_members.begin() + i->m_dwFirstChild; j != m_end; ++ j )
|
||||
{
|
||||
if( !j->get()->load( context ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
// For now we short circuit cases
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void getValue( cMessage *, cMessage::cFieldList::iterator, LPVARIANT )
|
||||
{
|
||||
// This element should never insert itself into the message list
|
||||
_ASSERTE( FALSE );
|
||||
}
|
||||
};
|
||||
|
||||
static _bstr_t g_strCase;
|
||||
|
||||
virtual cMessage::cMessageElement *parse( cContext &context, MSXML::IXMLDOMElementPtr &pElement )
|
||||
{
|
||||
_variant_t vName = pElement->getAttribute( cFieldParser::g_strName );
|
||||
if( vName.vt != VT_BSTR )
|
||||
{
|
||||
// It must have the name field
|
||||
_ASSERTE( vName.vt == VT_BSTR );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Find a matching element in the schema
|
||||
cMessage::cMessageElement *pName = context.findElement( vName.bstrVal );
|
||||
if( pName == NULL )
|
||||
{
|
||||
// The mask field was not found
|
||||
_ASSERTE( pName != NULL );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create the mask element
|
||||
VSBridge::auto_ptr< cSwitchElement > pSwitchElement( new cSwitchElement );
|
||||
pSwitchElement->m_pValue = pName;
|
||||
|
||||
// Walk through each of the mask values
|
||||
USES_CONVERSION;
|
||||
|
||||
MSXML::IXMLDOMNodeListPtr pCaseList = pElement->selectNodes( g_strCase );
|
||||
for( MSXML::IXMLDOMElementPtr pCase = pCaseList->nextNode(); pCase.GetInterfacePtr() != NULL; pCase = pCaseList->nextNode() )
|
||||
{
|
||||
_variant_t vValue = pCase->getAttribute( cMaskParser::g_strValue );
|
||||
if( vValue.vt != VT_BSTR )
|
||||
{
|
||||
_ASSERTE( vName.vt == VT_BSTR );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Make sure it has the 'hex' prefix
|
||||
if( vValue.bstrVal[ 0 ] != OLESTR( '0' ) )
|
||||
{
|
||||
_ASSERTE( vValue.bstrVal[ 0 ] == OLESTR( '0' ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( vValue.bstrVal[ 1 ] != OLESTR( 'x' ) )
|
||||
{
|
||||
_ASSERTE( vValue.bstrVal[ 1 ] == OLESTR( 'x' ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Attempt to convert the remaining number
|
||||
long nCaseValue;
|
||||
if( ::_stscanf( OLE2T( vValue.bstrVal + 2 ), _T( "%X" ), &nCaseValue ) != 1 )
|
||||
{
|
||||
// Could not convert value
|
||||
_ASSERTE( FALSE );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
long nStartOffset = pSwitchElement->m_members.size();
|
||||
context.parseChildren( pSwitchElement->m_members, pCase );
|
||||
|
||||
cSwitchElement::cCase _case = { nCaseValue, nStartOffset, pSwitchElement->m_members.size() };
|
||||
pSwitchElement->m_cases.push_back( _case );
|
||||
}
|
||||
|
||||
return pSwitchElement.release();
|
||||
}
|
||||
};
|
||||
|
||||
_bstr_t cSwitchParser::g_strCase( _T( "case" ) );
|
||||
|
||||
cMessage::cMessageElement *cElementParser::cContext::findElement( const _bstr_t &strElement )
|
||||
{
|
||||
for( cContext *pContext = this; pContext != NULL; pContext = pContext->m_pParent )
|
||||
{
|
||||
for( cMessage::cElementList::iterator i = m_pElements->begin() + m_dwStartOffset; i != m_pElements->end(); ++ i )
|
||||
{
|
||||
if( i->get()->m_strName == strElement )
|
||||
return i->get();
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool cElementParser::cContext::parseChildren( MSXML::IXMLDOMElementPtr &pElement )
|
||||
{
|
||||
MSXML::IXMLDOMNodeListPtr pChildList = pElement->selectNodes( g_strAll );
|
||||
for( MSXML::IXMLDOMElementPtr pChild = pChildList->nextNode(); pChild.GetInterfacePtr() != NULL; pChild = pChildList->nextNode() )
|
||||
{
|
||||
_bstr_t strElementName = pChild->tagName;
|
||||
cElementParser *pParser = cElementParser::lookup( strElementName );
|
||||
if( pParser == NULL )
|
||||
{
|
||||
// Could not find a parse for this element type
|
||||
_ASSERTE( FALSE );
|
||||
return false;
|
||||
}
|
||||
|
||||
cMessage::cMessageElement *pElement = pParser->parse( *this, pChild );
|
||||
if( pElement == NULL )
|
||||
return false;
|
||||
|
||||
m_pElements->push_back( cMessage::cElementList::value_type( pElement ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_bstr_t cElementParser::cContext::g_strAll( _T( "*" ) );
|
||||
|
||||
bool cElementParser::cContext::parseChildren( cMessage::cElementList &elements, MSXML::IXMLDOMElementPtr &pElement )
|
||||
{
|
||||
cContext c( &elements, this );
|
||||
return c.parseChildren( pElement );
|
||||
}
|
||||
|
||||
cElementParser *cElementParser::lookup( const _bstr_t &strElement )
|
||||
{
|
||||
cElementParserMap::iterator i = g_parsers.find( strElement );
|
||||
if( i == g_parsers.end() )
|
||||
return NULL;
|
||||
|
||||
return i->second.get();
|
||||
}
|
||||
|
||||
void cElementParser::init()
|
||||
{
|
||||
addParser( _T( "field" ), new cFieldParser );
|
||||
addParser( _T( "maskmap" ), new cMaskParser );
|
||||
addParser( _T( "vector" ), new cVectorParser );
|
||||
addParser( _T( "switch" ), new cSwitchParser );
|
||||
addParser( _T( "align" ), new cAlignParser );
|
||||
}
|
||||
|
||||
void cElementParser::term()
|
||||
{
|
||||
g_parsers.clear();
|
||||
}
|
||||
|
||||
void cElementParser::addParser( LPCTSTR szName, cElementParser *pParser )
|
||||
{
|
||||
g_parsers.insert( cElementParserMap::value_type( szName, VSBridge::auto_ptr< cElementParser >( pParser ) ) );
|
||||
}
|
||||
|
||||
cElementParser::cElementParserMap cElementParser::g_parsers;
|
||||
Loading…
Add table
Add a link
Reference in a new issue