|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1993-1999 Microsoft Corporation
Module Name:
stndr.hxx
Abstract:
Contains routines for the generation of the new NDR format strings for structure types, and the new NDR marshalling and unmarshalling calls.
Notes:
History:
DKays Oct-1993 Created. ----------------------------------------------------------------------------*/
#include "becls.hxx"
#pragma hdrstop
void CG_STRUCT::GenNdrFormat( CCB * pCCB ) /*++
Routine Description :
Generates the format string description for a simple, conformant, or conformant varying structure.
Arguments :
pCCB - pointer to the code control block.
--*/ { FORMAT_STRING * pFormatString; CG_NDR * pOldCGNodeContext; CG_NDR * pConformantArray;
if ( GetFormatStringOffset() != -1 ) return;
//
// Check if this structure is "complex".
//
if ( IsComplexStruct() ) { GenNdrFormatComplex( pCCB ); return; }
//
// Check if the structure is "hard".
//
if ( IsHardStruct() ) { GenNdrFormatHard( pCCB ); return; }
Unroll();
//
// Temporarily set the format string offset to 0 in case this structure
// has pointers to it's own type.
//
SetFormatStringOffset( 0 ); SetInitialOffset( 0 );
CG_FIELD *pOldRegionField = NULL; #if defined(NDR64_ON_DCE_HACK)
if ( NULL != dynamic_cast<CG_REGION*>( this ) ) { pOldRegionField = pCCB->StartRegion(); } else #endif
pOldCGNodeContext = pCCB->SetCGNodeContext( this );
pFormatString = pCCB->GetFormatString();
//
// Search the fields of the structure for embedded structures and generate
// the format string for these.
//
CG_ITERATOR Iterator; CG_FIELD * pField; CG_NDR * pMember;
GetMembers( Iterator );
while ( ITERATOR_GETNEXT( Iterator, pField ) ) { CG_NDR * pOldPlaceholder;
pOldPlaceholder = pCCB->SetLastPlaceholderClass( pField );
pMember = (CG_NDR *) pField->GetChild();
//
// If there is a structure or array member then generate
// it's format string. We don't have to check for a union, because
// that will make the struct CG_COMPLEX_STRUCT.
//
if ( pMember->IsStruct() || pMember->IsArray() ) pMember->GenNdrFormat( pCCB );
pCCB->SetLastPlaceholderClass( pOldPlaceholder ); }
//
// If this is a conformant (varying) struct then generate the array's
// description.
//
if ( GetCGID() == ID_CG_CONF_STRUCT || GetCGID() == ID_CG_CONF_VAR_STRUCT ) { CG_NDR * pOldPlaceholder;
pOldPlaceholder = pCCB->SetLastPlaceholderClass( (CG_NDR *) ((CG_CONFORMANT_STRUCT *)this)->GetConformantField() );
// Get the conformant array CG class.
pConformantArray = (CG_NDR *) ((CG_CONFORMANT_STRUCT *)this)->GetConformantArray();
// Generate the format string for the array.
pConformantArray->GenNdrFormat( pCCB );
pCCB->SetLastPlaceholderClass( pOldPlaceholder ); }
//
// If there are pointers in the structure then before you can start
// generating the format string for the structure, you must generate
// the format string for all of the pointees.
//
if ( HasPointer() ) { GenNdrStructurePointees( pCCB ); }
SetFormatStringOffset( pFormatString->GetCurrentOffset() ); SetInitialOffset( pFormatString->GetCurrentOffset() );
switch ( GetCGID() ) { case ID_CG_STRUCT : pFormatString->PushFormatChar( HasPointer() ? FC_PSTRUCT : FC_STRUCT ); break;
case ID_CG_CONF_STRUCT : pFormatString->PushFormatChar( HasPointer() ? FC_CPSTRUCT : FC_CSTRUCT ); break;
case ID_CG_CONF_VAR_STRUCT : pFormatString->PushFormatChar( FC_CVSTRUCT ); break; }
// Set the alignment.
pFormatString->PushByte( GetWireAlignment() - 1 );
// Set the structure memory size.
pFormatString->PushShort( (short)GetMemorySize() );
//
// If this is a conformant array then push the offset to the conformant
// array's description.
//
if ( GetCGID() == ID_CG_CONF_STRUCT || GetCGID() == ID_CG_CONF_VAR_STRUCT ) { // Set the offset to the array description.
pFormatString->PushShortOffset( pConformantArray->GetFormatStringOffset() - pFormatString->GetCurrentOffset() ); }
// Generate the pointer layout if needed.
if ( HasPointer() ) { GenNdrStructurePointerLayout( pCCB, FALSE, FALSE ); }
// Now generate the layout.
GenNdrStructureLayout( pCCB );
//
// Now we have to fix up the offset for any recursive pointer to this
// structure.
//
GenNdrPointerFixUp( pCCB, this );
#if defined(NDR64_ON_DCE_HACK)
if ( NULL != dynamic_cast<CG_REGION*>( this ) ) { pCCB->EndRegion(pOldRegionField); } else #endif
pCCB->SetCGNodeContext( pOldCGNodeContext );
SetFormatStringEndOffset( pFormatString->GetCurrentOffset() ); pFormatString->OptimizeFragment( this ); SetInitialOffset( GetFormatStringOffset() );
FixupEmbeddedComplex( pCCB );
if ( GetDuplicatingComplex() ) GetDuplicatingComplex()->FixupEmbeddedComplex( pCCB ); }
void CG_STRUCT::GenNdrFormatHard( CCB * pCCB ) /*++
Routine Description :
Generates the format string description for a packed structure. The description has the same format as for a complex struct.
Arguments :
pCCB - pointer to the code control block.
--*/ { FORMAT_STRING * pFormatString; CG_NDR * pOldCGNodeContext; CG_NDR * pUnion; CG_FIELD * pFinalField; long CopySize; long MemoryIncrement;
if ( GetFormatStringOffset() != -1 ) return;
//
// Temporarily set the format string offset to 0 in case this structure
// has pointers to it's own type.
//
SetFormatStringOffset( 0 ); SetInitialOffset( 0 );
pOldCGNodeContext = pCCB->SetCGNodeContext( this );
pFormatString = pCCB->GetFormatString();
//
// Search the fields of the structure for embedded structures and generate
// the format string for these.
//
CG_ITERATOR Iterator; CG_FIELD * pField; CG_NDR * pMember; CG_NDR * pOldPlaceholder;
GetMembers( Iterator );
pOldPlaceholder = pCCB->GetLastPlaceholderClass();
while ( ITERATOR_GETNEXT( Iterator, pField ) ) { pMember = (CG_NDR *) pField->GetChild();
//
// If there is an embedded structure, array, or union then generate
// it's format string.
//
if ( pMember->IsStruct() || pMember->IsArray() || pMember->IsUnion() ) { pCCB->SetLastPlaceholderClass( pField ); pMember->GenNdrFormat( pCCB ); } }
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
SetFormatStringOffset( pFormatString->GetCurrentOffset() ); SetInitialOffset( pFormatString->GetCurrentOffset() );
pFinalField = GetFinalField();
//
// See if we have a union.
//
if ( pFinalField->GetChild()->IsUnion() ) pUnion = (CG_NDR *) pFinalField->GetChild(); else pUnion = 0;
//
// Determine the copy size and memory increment for the copy.
//
if ( pUnion ) { CG_STRUCT * pStruct;
pStruct = this; CopySize = 0;
for ( ;; ) { pStruct->GetMembers( Iterator );
while ( ITERATOR_GETNEXT( Iterator, pField ) ) ;
CopySize += pField->GetWireOffset();
pMember = (CG_NDR *) pField->GetChild();
if ( pMember->IsStruct() ) { pStruct = (CG_STRUCT *) pMember; continue; } else break; }
MemoryIncrement = GetMemorySize() - pUnion->GetMemorySize(); } else { CopySize = GetWireSize(); MemoryIncrement = GetMemorySize(); }
//
// Format string generation.
//
pFormatString->PushFormatChar( FC_HARD_STRUCT );
// The alignment.
pFormatString->PushByte( GetWireAlignment() - 1 );
// The structure's memory size.
pFormatString->PushShort( (short)GetMemorySize() );
// Reserved for future use.
pFormatString->PushLong( 0 );
//
// Offset to enum in struct.
//
if ( GetNumberOfEnum16s() == 1 ) pFormatString->PushShort( GetEnum16Offset() ); else pFormatString->PushShort( (short) -1 );
//
// Copy size and memory increment.
//
pFormatString->PushShort( CopySize ); pFormatString->PushShort( MemoryIncrement );
//
// Offset to union's format string description.
//
if ( pUnion ) { pOldPlaceholder = pCCB->GetLastPlaceholderClass(); pCCB->SetLastPlaceholderClass( pFinalField );
pFormatString->PushShort( (short) (pUnion->GetFormatStringOffset() - pFormatString->GetCurrentOffset()) );
pCCB->SetLastPlaceholderClass( pOldPlaceholder ); } else pFormatString->PushShort( (short) 0 );
// Now generate the layout.
GenNdrStructureLayout( pCCB );
//
// Now we have to fix up the offset for any recursive pointer to this
// structure.
//
GenNdrPointerFixUp( pCCB, this );
pCCB->SetCGNodeContext( pOldCGNodeContext );
SetFormatStringEndOffset( pFormatString->GetCurrentOffset() ); pFormatString->OptimizeFragment( this ); SetInitialOffset( GetFormatStringOffset() );
FixupEmbeddedComplex( pCCB ); }
void CG_STRUCT::GenNdrFormatComplex( CCB * pCCB ) /*++
Routine Description :
Generates the format string description for a packed structure. The description has the same format as for a complex struct.
Arguments :
pCCB - pointer to the code control block.
--*/ { CG_CLASS * pConfField; CG_COMPLEX_STRUCT * pComplex;
if ( (GetCGID() == ID_CG_CONF_STRUCT) || (GetCGID() == ID_CG_CONF_VAR_STRUCT) ) pConfField = ((CG_CONFORMANT_STRUCT *)this)->GetConformantField(); else pConfField = 0;
//
// Do the old duplication trick.
//
pComplex = new CG_COMPLEX_STRUCT( this, pConfField );
SetDuplicatingComplex( pComplex );
//
// Now temporarily set our format string offset to 0 to handle recursive
// definitions.
//
SetFormatStringOffset( 0 ); SetInitialOffset( 0 ); //
// This call will set our format string offset correctly.
//
pComplex->GenNdrFormat( pCCB );
// Don't delete since the expression evaluator might need this.
// delete( pComplex );
}
bool IsEnum16UnionAlignBug( CG_STRUCT *pStruct ) {
// Comment from old hack wacked on stub.
// The NT 3.50 stubs had a problem with union alignment that affects
// structs with 16b enum and a union as the only other thing.
// The old, incorrect alignment was 2 (code 1), the correct alignment is 4 (code 3).
// All the compilers since NT 3.51, i.e. MIDL 2.0.102 generate correct code,
// however we needed to introduce the wrong alignment into newly compiled stubs
// to get interoperability with the released dhcp client and server binaries.
if ( 4 != pStruct->GetWireAlignment()) return false;
CG_ITERATOR StructElements; pStruct->GetMembers( StructElements );
ITERATOR_INIT( StructElements ); size_t Elements = ITERATOR_GETCOUNT( StructElements );
if ( 2 != Elements ) return false;
ITERATOR_INIT( StructElements ); CG_FIELD *pField1 = NULL; ITERATOR_GETNEXT( StructElements, pField1 ); MIDL_ASSERT( NULL != pField1);
// Is the first field a enum16?
CG_ENUM *pEnum = dynamic_cast<CG_ENUM*>( pField1->GetChild() ); if ( ( NULL == pEnum ) || pEnum->IsEnumLong() ) return false;
// Is the second field a union
CG_FIELD *pField2 = NULL; ITERATOR_GETNEXT( StructElements, pField2 ); MIDL_ASSERT( NULL != pField2 );
if ( ! pField2->GetChild()->IsUnion()) return false;
// Ok. We have a 2 field structure were the first field is an enum16 and the second field is
// and union.
return true; }
void CG_COMPLEX_STRUCT::GenNdrFormat( CCB * pCCB ) /*++
Routine Description :
Generates the format string description for a complex structure.
Arguments :
pCCB - pointer to the code control block.
--*/ { FORMAT_STRING * pFormatString; CG_NDR * pOldCGNodeContext; CG_NDR * pConformantArray; long PointerLayoutOffset;
if ( GetFormatStringOffset() != -1 ) return;
pFormatString = pCCB->GetFormatString();
//
// Temporarily set the format string offset to 0 in case this structure
// has pointers to it's own type.
//
SetFormatStringOffset( 0 ); SetInitialOffset( 0 );
pOldCGNodeContext = pCCB->SetCGNodeContext( this );
//
// Search the fields of the structure for imbeded structures, arrays, and
// and unions and generate the format string for these.
//
CG_ITERATOR Iterator; CG_FIELD * pField; CG_NDR * pMember;
GetMembers( Iterator );
while ( ITERATOR_GETNEXT( Iterator, pField ) ) { pMember = (CG_NDR *) pField->GetChild();
//
// If the field is anything other than a base type or a
// non-interface pointer then generate it's description.
//
if ( ! pMember->IsSimpleType() && ! ( pMember->IsPointer() && !pMember->IsInterfacePointer() ) && (pMember->GetCGID() != ID_CG_IGN_PTR) || pMember->GetRangeAttribute() ) { CG_NDR * pOldPlaceholder;
pOldPlaceholder = pCCB->SetLastPlaceholderClass( pField );
pMember->GenNdrFormat( pCCB );
pCCB->SetLastPlaceholderClass( pOldPlaceholder ); } }
// Generate pointee format strings.
GenNdrStructurePointees( pCCB );
// Generate conformant array description.
if ( ( pConformantArray = (CG_NDR *) GetConformantArray() ) != 0 ) { CG_NDR * pOldPlaceholder;
pOldPlaceholder = pCCB->SetLastPlaceholderClass( (CG_NDR *) GetConformantField() );
pConformantArray->GenNdrFormat( pCCB );
pCCB->SetLastPlaceholderClass( pOldPlaceholder ); }
// Now set the struct's format string offset.
SetFormatStringOffset( pFormatString->GetCurrentOffset() ); SetInitialOffset( pFormatString->GetCurrentOffset() );
//
// Set the duplicated struct's format string offset if we were duplicated.
//
if ( GetDuplicatedStruct() ) { GetDuplicatedStruct()->SetFormatStringOffset( GetFormatStringOffset() ); GetDuplicatedStruct()->SetInitialOffset( GetFormatStringOffset() ); }
pFormatString->PushFormatChar( FC_BOGUS_STRUCT );
WarnAboutEmbeddedComplexStruct();
//
// Set the wire alignment.
//
if ( pCommand->WireCompat( WIRE_COMPAT_ENUM16UNIONALIGN ) && IsEnum16UnionAlignBug(this) ) {
// Comment from old hack wacked on stub.
// The NT 3.50 stubs had a problem with union alignment that affects
// structs with 16b enum and a union as the only other thing.
// The old, incorrect alignment was 2 (code 1), the correct alignment is 4 (code 3).
// All the compilers since NT 3.51, i.e. MIDL 2.0.102 generate correct code,
// however we needed to introduce the wrong alignment into newly compiled stubs
// to get interoperability with the released dhcp client and server binaries.
pFormatString->AddComment( pFormatString->GetCurrentOffset(), "/* 3 */ /* enum16unionalign Bug Compatibility */" ); pFormatString->PushByte( 1 );
} else pFormatString->PushByte( GetWireAlignment() - 1 );
// Set the structure memory size.
pFormatString->PushShort( (short)GetMemorySize() );
// Array description.
if ( pConformantArray ) pFormatString->PushShortOffset( pConformantArray->GetFormatStringOffset() - pFormatString->GetCurrentOffset() ); else pFormatString->PushShort( (short) 0 );
//
// Remember where the offset_to_pointer_layout<> field will go and push
// some space for it.
//
PointerLayoutOffset = pFormatString->GetCurrentOffset();
pFormatString->PushShortOffset( 0 );
// Now generate the structure's layout.
GenNdrStructureLayout( pCCB );
//
// Now see if we have any plain pointer fields and if so generate a
// pointer layout. We can't use the HasAtLeastOnePointer() method
// because this tells us TRUE if we have any embedded arrays, structs,
// or unions which have pointers. For complex structs we're only
// interested in actual pointer fields.
//
GetMembers( Iterator );
//
// Fill in the offset_to_pointer_layout<2> field and generate a
// pointer_layout<> if we have any pointer fields. Interface pointers
// do not reside in the pointer layout.
//
while ( ITERATOR_GETNEXT( Iterator, pField ) ) if ( pField->GetChild()->IsPointer() && !pField->IsInterfacePointer() ) { // This is an internal offset within the struct descriptor, namely
// to the pointer layout field, not the offset to a type.
// Surprisingly, this code may produce an offset to an array etc.
// Hence, we push an offset to be backward compatible.
pFormatString->PushShortOffset( pFormatString->GetCurrentOffset() - PointerLayoutOffset, PointerLayoutOffset );
GenNdrStructurePointerLayout( pCCB );
break; }
pFormatString->Align();
//
// Now we have to fix up the offset for any recursive pointer to this
// structure.
//
GenNdrPointerFixUp( pCCB, GetDuplicatedStruct() ? GetDuplicatedStruct() : this );
pCCB->SetCGNodeContext( pOldCGNodeContext );
SetFormatStringEndOffset( pFormatString->GetCurrentOffset() ); pFormatString->OptimizeFragment( this ); SetInitialOffset( GetFormatStringOffset() ); if ( GetDuplicatedStruct() ) GetDuplicatedStruct()->SetFormatStringOffset( GetFormatStringOffset() );
FixupEmbeddedComplex( pCCB ); if ( GetDuplicatedStruct() ) GetDuplicatedStruct()->FixupEmbeddedComplex( pCCB );
// There is no call to the string optimizer here. If we wanted to put it in,
// the code should check if the optimization is possible or not by checking the
// result of GenNdrEmbeddedPointers via GenNdrStructurePointerLayout call.
}
void CG_COMPLEX_STRUCT::GenNdrStructurePointerLayout( CCB * pCCB ) /*++
Routine Description :
Generates the format string pointer layout section for a complex structure.
Arguments :
pCCB - pointer to the code control block.
--*/ { CG_ITERATOR Iterator; CG_FIELD * pField; CG_NDR * pMember;
GetMembers( Iterator );
while( ITERATOR_GETNEXT( Iterator, pField ) ) { CG_NDR * pOldPlaceholder; pOldPlaceholder = pCCB->SetLastPlaceholderClass( pField );
pMember = (CG_NDR *) pField->GetChild();
if ( pMember->IsPointer() && !pMember->IsInterfacePointer()) { CG_POINTER * pPointer;
pPointer = (CG_POINTER *) pMember;
// The pointer description.
pPointer->GenNdrFormatEmbedded( pCCB ); }
pCCB->SetLastPlaceholderClass( pOldPlaceholder ); } // while
}
//---------------------------------------------------------------------------
// Methods shared by all or most structure classes.
//---------------------------------------------------------------------------
void CG_STRUCT::GenNdrStructurePointerLayout( CCB * pCCB, BOOL fNoPP, BOOL fNoType ) /*++
Routine Description :
Generates the format string pointer layout section for a structure. This is the default routine for this used by the structure classes. Only CG_COMPLEX_STRUCT redefines this virtual method.
Arguments :
pCCB - pointer to the code control block. fNoPP - TRUE if no FC_PP or FC_END should be emitted fNoType - TRUE only the bare offset and description should be emitted for each pointer
--*/ { CG_ITERATOR Iterator; FORMAT_STRING * pFormatString; CG_FIELD * pField; CG_NDR * pMember; long ImbedingMemSize; long ImbedingBufSize;
pFormatString = pCCB->GetFormatString();
// Get/Save the current imbeding sizes.
ImbedingMemSize = pCCB->GetImbedingMemSize(); ImbedingBufSize = pCCB->GetImbedingBufSize();
if ( ! fNoPP ) { pFormatString->PushFormatChar( FC_PP ); pFormatString->PushFormatChar( FC_PAD ); }
GetMembers( Iterator );
while( ITERATOR_GETNEXT( Iterator, pField ) ) { CG_NDR * pOldPlaceholder; pOldPlaceholder = pCCB->SetLastPlaceholderClass( pField );
pMember = (CG_NDR *) pField->GetChild();
if ( pMember->IsPointer() && !pMember->IsInterfacePointer() ) { CG_POINTER * pPointer;
pPointer = (CG_POINTER *) pMember;
// Push the instance type.
if ( ! fNoType ) { pFormatString->PushFormatChar( FC_NO_REPEAT ); pFormatString->PushFormatChar( FC_PAD ); }
pFormatString->PushShort( (short) (ImbedingMemSize + pField->GetMemOffset())); pFormatString->PushShort( (short) (ImbedingBufSize + pField->GetWireOffset()));
// The actual pointer description.
pPointer->GenNdrFormatEmbedded( pCCB ); }
//
// Generate pointer descriptions for all embedded arrays and structs.
// We don't have to check for unions because that will make the struct
// complex.
//
if ( pMember->IsArray() ) { CG_NDR * pNdr = (CG_NDR *) pMember->GetChild();
//
// For arrays we set the imbeded memory size equal to the
// size of the whole imbededing structure.
//
pCCB->SetImbedingMemSize( ImbedingMemSize + GetMemorySize() ); pCCB->SetImbedingBufSize( ImbedingBufSize + GetWireSize() );
if ( (pNdr->IsPointer() && !pNdr->IsInterfacePointer() ) || ( pNdr->IsStruct() && ((CG_COMP *)pNdr)->HasPointer() ) ) ((CG_ARRAY *)pMember)->GenNdrFormatArrayPointerLayout( pCCB, TRUE ); }
if ( pMember->IsStruct() ) if ( ((CG_STRUCT *)pMember)->HasPointer() ) { //
// For embedded structs we add the embedded struct's offset to
// the value of the current embeddeding size.
//
pCCB->SetImbedingMemSize( ImbedingMemSize + pField->GetMemOffset() ); pCCB->SetImbedingBufSize( ImbedingBufSize + pField->GetWireOffset() );
((CG_STRUCT *)pMember)->GenNdrStructurePointerLayout( pCCB, TRUE, fNoType ); }
pCCB->SetLastPlaceholderClass( pOldPlaceholder ); } // while
if ( ! fNoPP ) pFormatString->PushFormatChar( FC_END );
// Re-set the old imbeding sizes.
pCCB->SetImbedingMemSize( ImbedingMemSize ); pCCB->SetImbedingBufSize( ImbedingBufSize );
// There is no call to the string optimizer here. If we wanted to put it in,
// the code should check if the optimization is possible or not by checking the
// result of GenNdrEmbeddedPointers via GenNdrStructurePointerLayout call.
}
CG_FIELD * CG_STRUCT::GetPreviousField( CG_FIELD * pMarkerField ) /*++
Routine description:
Finds the field immediately preceding the given field.
Argument:
pMarkerField - the given field
Returns:
The preceding field or NULL if the given field is the first one. --*/ { CG_ITERATOR Iterator; CG_FIELD *pField, *pPreviousField = 0;
GetMembers( Iterator ); while( ITERATOR_GETNEXT( Iterator, pField ) ) { if ( pField == pMarkerField ) return( pPreviousField );
pPreviousField = pField; } return( 0 ); }
void CG_STRUCT::GenStructureMemPad( CCB * pCCB, unsigned long MemPad ) /*++
Routine Description :
Generates the format string for memory padding in a structure layout.
Arguments :
pCCB - pointer to the code control block. MemPad - Amount of required padding. --*/ { FORMAT_STRING * pFormatString = pCCB->GetFormatString(); MIDL_ASSERT( MemPad < 0xFFFF ); // structures must be less then 64k
switch( MemPad) { case 0: return; // No padding needed
case 1: pFormatString->PushFormatChar( FC_STRUCTPAD1 ); return; case 2: pFormatString->PushFormatChar( FC_STRUCTPAD2 ); return; case 3: pFormatString->PushFormatChar( FC_STRUCTPAD3 ); return; case 4: pFormatString->PushFormatChar( FC_STRUCTPAD4 ); return; case 5: pFormatString->PushFormatChar( FC_STRUCTPAD5 ); return; case 6: pFormatString->PushFormatChar( FC_STRUCTPAD6 ); return; case 7: pFormatString->PushFormatChar( FC_STRUCTPAD7 ); return; default:
// NDR60 Feature
// Pad an arbitrary amount
// FC_STRUCTPADN 0 <unsigned short>
pFormatString->Align(); pFormatString->PushFormatChar( FC_STRUCTPADN ); pFormatString->PushFormatChar( FC_ZERO ); pFormatString->PushShort( (short)MemPad );
pCommand->GetNdrVersionControl().SetHasStructPadN(); }
}
void CG_STRUCT::GenNdrStructureLayout( CCB * pCCB ) /*++
Routine Description :
Generates the format string layout section for a structure.
Arguments :
pCCB - pointer to the code control block.
--*/ { FORMAT_STRING * pFormatString = pCCB->GetFormatString();
CG_NDR * pOldPlaceholder = pCCB->GetLastPlaceholderClass();
CG_ITERATOR Iterator; GetMembers( Iterator );
CG_FIELD * pField; CG_FIELD * pPrevField = NULL; unsigned long BufferOffset = 0; bool fSawUnknownRepAs = false;
while( ITERATOR_GETNEXT( Iterator, pField ) ) { if ( fSawUnknownRepAs && !pField->HasEmbeddedUnknownRepAs() ) { switch ( pField->GetMemoryAlignment() ) { case 2: pFormatString->PushFormatChar( FC_ALIGNM2 ); break; case 4: pFormatString->PushFormatChar( FC_ALIGNM4 ); break; case 8: pFormatString->PushFormatChar( FC_ALIGNM8 ); break; } } else if ( !fSawUnknownRepAs && !pField->HasEmbeddedUnknownRepAs() ) { unsigned long MemPad = pField->GetMemOffset() - BufferOffset;
GenStructureMemPad( pCCB, MemPad );
BufferOffset += MemPad; }
pCCB->SetLastPlaceholderClass( pField ); CG_NDR *pMember = (CG_NDR *) pField->GetChild(); while ( pMember->GetCGID() == ID_CG_TYPEDEF ) { pMember = ( CG_NDR* )pMember->GetChild(); } // The ending conformat array is not included in the
// size of the structure.
// Note that this must be the last field.
if ( pMember->GetCGID() == ID_CG_CONF_ARRAY || pMember->GetCGID() == ID_CG_CONF_VAR_ARRAY || pMember->GetCGID() == ID_CG_CONF_STRING_ARRAY ) { break; }
// Generate an embedded complex for embedded things.
if ( pMember->IsStruct() || pMember->IsUnion() || pMember->IsArray() || pMember->IsXmitRepOrUserMarshal() || pMember->GetRangeAttribute() || pMember->IsInterfacePointer() ) { pFormatString->PushFormatChar( FC_EMBEDDED_COMPLEX );
if ( pField->HasEmbeddedUnknownRepAs() ) { pCCB->GetRepAsPadExprDict()->Register( pFormatString->GetCurrentOffset(), GetType(), pField->GetType()->GetSymName(), pPrevField ? pPrevField->GetType() : 0 );
pFormatString->PushByteWithPadMacro(); fSawUnknownRepAs = true; } else { pFormatString->PushByte( 0 ); //Padding is generated independently
}
if ( pMember->GetFormatStringOffset() == -1 || pMember->GetFormatStringOffset() == 0 ) { RegisterComplexEmbeddedForFixup( pMember, pFormatString->GetCurrentOffset() - GetInitialOffset() ); }
pFormatString->PushShortOffset( pMember->GetFormatStringOffset() - pFormatString->GetCurrentOffset() ); }
else if (pMember->IsPointer() || ( pMember->GetCGID() == ID_CG_IGN_PTR ) ) { if ( pMember->IsPointer() ) { if ( GetCGID() == ID_CG_COMPLEX_STRUCT ) pFormatString->PushFormatChar( FC_POINTER ); else { pFormatString->PushFormatChar( FC_LONG ); #if !defined(NDR64_ON_DCE_HACK )
MIDL_ASSERT( ! pCommand->Is64BitEnv() ); #endif
} } else pFormatString->PushFormatChar( FC_IGNORE );
} #if defined( NDR64_ON_DCE_HACK )
else if ( NULL != dynamic_cast<CG_PAD*>( pMember ) ) { pFormatString->PushFormatChar( FC_BUFFER_ALIGN ); pFormatString->PushByte( pMember->GetWireAlignment() - 1); } #endif
else { //
// Must be a CG_BASETYPE if we get here.
//
FORMAT_CHARACTER FormatChar = ((CG_BASETYPE *)pMember)->GetFormatChar(); pFormatString->PushFormatChar( FormatChar ); }
BufferOffset += pField->GetMemorySize(); pPrevField = pField; }
// Account for padding at the end of the structure.
MIDL_ASSERT( GetMemorySize() >= BufferOffset );
unsigned long EndingPad = GetMemorySize() - BufferOffset;
// End padding is only allow on complex struct.
MIDL_ASSERT( EndingPad ? ( (GetCGID() == ID_CG_COMPLEX_STRUCT) || IsComplexStruct() || IsHardStruct() ) : true );
GenStructureMemPad( pCCB, EndingPad );
//
// If the format string is on a short boundary right now then push
// a format character so that the format string will be properly aligned
// following the FC_END.
//
if ( ! (pFormatString->GetCurrentOffset() % 2) ) pFormatString->PushFormatChar( FC_PAD );
pFormatString->PushFormatChar( FC_END );
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
}
void CG_STRUCT::GenNdrStructurePointees( CCB * pCCB ) { CG_ITERATOR Iterator; FORMAT_STRING * pFormatString; CG_FIELD * pField; CG_NDR * pMember;
pFormatString = pCCB->GetFormatString();
GetMembers( Iterator );
//
// We only have to check for pointer fields here, because if the structure
// has a struct or array field which has pointers, this will be handled
// when we generate their format strings.
//
while( ITERATOR_GETNEXT( Iterator, pField ) ) { pMember = (CG_NDR *) pField->GetChild();
if ( pMember->IsPointer() && !pMember->IsInterfacePointer() ) { CG_NDR * pOldPlaceholder;
pOldPlaceholder = pCCB->SetLastPlaceholderClass( pField );
//
// Skip over an unattributed pointer to a simple type or string.
//
if ( ( ((CG_POINTER *)pMember)->IsPointerToBaseType() ) || ( pMember->GetCGID() == ID_CG_STRING_PTR ) ) { pCCB->SetLastPlaceholderClass( pOldPlaceholder ); continue; }
((CG_POINTER *)pMember)->GenNdrFormatPointee( pCCB );
pCCB->SetLastPlaceholderClass( pOldPlaceholder ); } } }
BOOL CG_STRUCT::ShouldFreeOffline() { return ( (GetCGID() == ID_CG_COMPLEX_STRUCT) || (GetCGID() == ID_CG_CONF_VAR_STRUCT) || HasPointer() || IsComplexStruct() || IsHardStruct() ); }
void CG_STRUCT::GenFreeInline( CCB* ) { }
void CG_NDR::GenNdrPointerFixUp( CCB * pCCB, CG_STRUCT * pStruct ) { CG_ITERATOR Iterator; CG_NDR * pMember; CG_NDR * pNdr; long Offset;
if ( ! IsStruct() && ! IsArray() && ! IsUnion() ) return;
if ( IsInFixUp() ) return;
SetFixUpLock( TRUE );
GetMembers( Iterator );
while ( ITERATOR_GETNEXT( Iterator, pMember ) ) { if ( IsStruct() ) { pNdr = (CG_NDR *) pMember->GetChild(); } else if ( IsUnion() ) { // member of union is a case, then case->field->ndr
if ( pMember->GetChild() && pMember->GetChild()->GetChild() ) pNdr = (CG_NDR *) pMember->GetChild()->GetChild(); else continue; } else // IsArray()
{ pNdr = pMember;
//
// See if the array's element is the structure we're looking for.
//
if ( pNdr == pStruct ) { Offset = ((CG_ARRAY *)this)->GetElementDescriptionOffset() + 2; pCCB->GetFormatString()->PushShortOffset( pStruct->GetFormatStringOffset() - Offset, Offset ); } }
if (pNdr->GetCGID() == ID_CG_TYPEDEF ) pNdr = (CG_NDR *)pNdr->GetChild();
if ( (pNdr->GetCGID() == ID_CG_PTR) || (pNdr->GetCGID() == ID_CG_SIZE_PTR) || (pNdr->GetCGID() == ID_CG_SIZE_LENGTH_PTR) ) { CG_POINTER * pPointer = (CG_POINTER *) pNdr;
//
// Check if we're ready for this guy yet.
//
if ( pPointer->GetFormatStringOffset() == -1 ) continue;
// Get the pointee.
switch ( pPointer->GetCGID() ) { case ID_CG_PTR : pNdr = (CG_NDR *) pPointer->GetChild(); break; case ID_CG_SIZE_PTR : pNdr = ((CG_SIZE_POINTER *)pPointer)->GetPointee(); break; case ID_CG_SIZE_LENGTH_PTR : pNdr = ((CG_SIZE_LENGTH_POINTER *)pPointer)->GetPointee(); break; } //
// If the pointer's pointee is the struct we're checking for,
// then patch up the pointer's offset_to_description<2> field.
//
if ( pNdr == pStruct ) { long PointerOffset;
//
// Get the offset in the format string where the
// offset_to_description<2> field of the pointer is.
//
PointerOffset = pPointer->GetFormatStringOffset() + 2; /*
printf( " **MIDL_fixup: Non-Reg Actually fixing %s at %d with %d (%d)\n", pNdr->GetSymName(), PointerOffset, pNdr->GetFormatStringOffset() - PointerOffset, pNdr->GetFormatStringOffset() ); */ pCCB->GetFormatString()->PushShortOffset( pStruct->GetFormatStringOffset() - PointerOffset, PointerOffset ); continue; } }
//
// This can happen sometimes because of structs which are promoted
// to complex because of padding.
//
if ( pNdr == this ) continue;
//
// Continue the chase if necessary.
//
if ( pNdr->IsStruct() || pNdr->IsUnion() || pNdr->IsArray() ) pNdr->GenNdrPointerFixUp( pCCB, pStruct ); }
SetFixUpLock( FALSE ); }
void CG_NDR::RegisterComplexEmbeddedForFixup( CG_NDR * pEmbeddedComplex, long RelativeOffset ) { if ( GetInitialOffset() == -1 ) printf( " Internal compiler problem with recursive embeddings\n" );
MIDL_ASSERT( GetInitialOffset() != -1 );
if ( pEmbeddedComplexFixupRegistry == NULL ) { pEmbeddedComplexFixupRegistry = new TREGISTRY; }
// printf( "MIDL_fixup: RegisterComplex %s\n", pEmbeddedComplex->GetSymName());
EMB_COMPLEX_FIXUP * pFixup = new EMB_COMPLEX_FIXUP;
pFixup->pEmbeddedNdr = pEmbeddedComplex; pFixup->RelativeOffset = RelativeOffset;
pEmbeddedComplexFixupRegistry->Register( (node_skl *)pFixup ); }
void CG_NDR::FixupEmbeddedComplex( CCB * pCCB ) { if ( IsInComplexFixup() ) return;
SetComplexFixupLock( TRUE );
// Go down first
CG_ITERATOR Iterator; CG_NDR * pField;
GetMembers( Iterator );
while ( ITERATOR_GETNEXT( Iterator, pField ) ) pField->FixupEmbeddedComplex( pCCB );
// Now fix up this level description.
if ( GetEmbeddedComplexFixupRegistry() ) { ITERATOR FixupList; EMB_COMPLEX_FIXUP * pFixup; long FixAtOffset; FORMAT_STRING * pFormatString = pCCB->GetFormatString(); GetListOfEmbeddedComplex( FixupList ); while ( ITERATOR_GETNEXT( FixupList, pFixup ) ) { FixAtOffset = GetFormatStringOffset() + pFixup->RelativeOffset; pFormatString->PushShortOffset( pFixup->pEmbeddedNdr->GetFormatStringOffset() - FixAtOffset, FixAtOffset ); /*
printf( " MIDL_fixup: Reg-Cmplx Actually fixing at %d with %d\n", FixAtOffset, pFixup->pEmbeddedNdr->GetFormatStringOffset() - FixAtOffset ); */ } }
// Due to duplication, the list may be at the duplicating node.
if ( IsStruct() ) { CG_COMPLEX_STRUCT * pDuping = ((CG_STRUCT *)this)->GetDuplicatingComplex(); if ( pDuping ) pDuping->FixupEmbeddedComplex( pCCB ); }
SetComplexFixupLock( FALSE ); }
// All these different ways of fixing recursive pointers need to be cleaned up.
// The RecPointer registry seems to be the best solution in that it fixes
// the pointers once per compilation while complex embed fixup calls walk the
// tree several times recursively.
// Also, the reason the below registry is different from previously introduced
// EmbeddedComplex fixup registry is that the emb cplx fixup registry uses
// a relative pointer when fixing up while the bug we are trying to address now
// affects standalone pointers where absolute offset is appropriate.
// The basic scheme with "struct _S**" field shows up in VARIANT and LPSAFEARRAY.
// Rkk, May, 1999.
void CCB::RegisterRecPointerForFixup( CG_NDR * pNdr, long AbsoluteOffset ) { if ( pRecPointerFixupRegistry == NULL ) { pRecPointerFixupRegistry = new TREGISTRY; }
POINTER_FIXUP * pFixup = new POINTER_FIXUP;
// printf( "MIDL_fixup: Registering for %s at %d\n", pNdr->GetSymName(), AbsoluteOffset);
pFixup->pNdr = pNdr; pFixup->AbsoluteOffset = AbsoluteOffset; pFixup->fFixed = false; pRecPointerFixupRegistry->Register( (node_skl *)pFixup ); }
void CCB::FixupRecPointers() { if ( GetRecPointerFixupRegistry() ) { ITERATOR FixupList; POINTER_FIXUP * pFixup; long FixAtOffset; FORMAT_STRING * pFormatString = GetFormatString(); GetListOfRecPointerFixups( FixupList ); while ( ITERATOR_GETNEXT( FixupList, pFixup ) ) { FixAtOffset = pFixup->AbsoluteOffset; if ( ! pFixup->fFixed ) { long Recorded = pFormatString->GetFormatShort(FixAtOffset) + FixAtOffset; long NdrOffset = pFixup->pNdr->GetFormatStringOffset();
if ( 0 == Recorded && 0 != NdrOffset || -1 == Recorded && -1 != NdrOffset ) { /*
printf( " MIDL_fixup: Actually fixing %s at %d with %d (%d)\n", pFixup->pNdr->GetSymName(), FixAtOffset, NdrOffset - FixAtOffset, NdrOffset ); */ pFormatString->PushShortOffset( NdrOffset - FixAtOffset, FixAtOffset );
pFixup->fFixed = true; } /*
else if ( 0 != Recorded && -1 != Recorded ) { printf( " MIDL_fixup: %s at %d was already fixed to %d (%d)\n", pFixup->pNdr->GetSymName(), FixAtOffset, NdrOffset - FixAtOffset, NdrOffset );
pFixup->fFixed = true; } else { printf( " MIDL_fixup: %s at %d has not been fixed to %d (%d)\n", pFixup->pNdr->GetSymName(), FixAtOffset, NdrOffset - FixAtOffset, NdrOffset ); } */ } // if ! fixed
} // while
} }
long CG_STRUCT::FixedBufferSize( CCB * pCCB ) { CG_ITERATOR Iterator; CG_FIELD * pField; CG_NDR * pNdr; CG_NDR * pOldPlaceholder; long TotalBufferSize; long BufSize;
//
// Check for recursion.
//
if ( IsInFixedBufferSize() ) return -1;
if ( (GetCGID() == ID_CG_CONF_STRUCT) || (GetCGID() == ID_CG_CONF_VAR_STRUCT) || (GetCGID() == ID_CG_COMPLEX_STRUCT) || IsComplexStruct() ) return -1;
if ( IsHardStruct() ) { if ( GetNumberOfUnions() == 0 ) return MAX_WIRE_ALIGNMENT + GetWireSize(); else return -1; }
SetInFixedBufferSize( TRUE );
MIDL_ASSERT( GetCGID() == ID_CG_STRUCT );
pOldPlaceholder = pCCB->SetLastPlaceholderClass( this );
GetMembers( Iterator );
TotalBufferSize = MAX_WIRE_ALIGNMENT + GetWireSize();
while ( ITERATOR_GETNEXT( Iterator, pField ) ) { pNdr = (CG_NDR *) pField->GetChild();
// skip these nodes to get to the transmitted element type.
if ( pNdr->IsXmitRepOrUserMarshal() ) pNdr = (CG_NDR *)pNdr->GetChild();
if ( pNdr->IsStruct() || pNdr->IsArray() || pNdr->IsPointer() ) { BufSize = pNdr->FixedBufferSize( pCCB );
if ( BufSize == -1 ) { SetInFixedBufferSize( FALSE ); return -1; }
//
// First subtract the basic size of this thing from the struct's
// size and then add back the value it returned.
//
TotalBufferSize -= pNdr->GetWireSize(); TotalBufferSize += BufSize; } }
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
SetInFixedBufferSize( FALSE );
// Success!
return TotalBufferSize; }
|