mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1490 lines
36 KiB
1490 lines
36 KiB
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
Copyright (c) 1993 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 );
|
|
|
|
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( CvtAlignPropertyToAlign(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 );
|
|
|
|
pCCB->SetCGNodeContext( pOldCGNodeContext );
|
|
|
|
SetFormatStringEndOffset( pFormatString->GetCurrentOffset() );
|
|
SetFormatStringOffset( 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( CvtAlignPropertyToAlign(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() );
|
|
SetFormatStringOffset( 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 );
|
|
}
|
|
|
|
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->GetCGID() != ID_CG_INTERFACE_PTR) ) &&
|
|
(pMember->GetCGID() != ID_CG_IGN_PTR) )
|
|
{
|
|
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() )
|
|
{
|
|
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 );
|
|
|
|
//
|
|
// Set the wire alignment.
|
|
//
|
|
pFormatString->PushByte( CvtAlignPropertyToAlign(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->GetCGID() != ID_CG_INTERFACE_PTR )
|
|
{
|
|
pFormatString->PushShort(
|
|
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() );
|
|
SetFormatStringOffset( pFormatString->OptimizeFragment( this ) );
|
|
SetInitialOffset( GetFormatStringOffset() );
|
|
if ( GetDuplicatedStruct() )
|
|
GetDuplicatedStruct()->SetFormatStringOffset( GetFormatStringOffset() );
|
|
|
|
FixupEmbeddedComplex( pCCB );
|
|
if ( GetDuplicatedStruct() )
|
|
GetDuplicatedStruct()->FixupEmbeddedComplex( pCCB );
|
|
}
|
|
|
|
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->GetCGID() != ID_CG_INTERFACE_PTR )
|
|
{
|
|
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->GetCGID() != ID_CG_INTERFACE_PTR) )
|
|
{
|
|
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->GetCGID() != ID_CG_INTERFACE_PTR))
|
|
||
|
|
( 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 );
|
|
}
|
|
|
|
|
|
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::GenNdrStructureLayout( CCB * pCCB )
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
Generates the format string layout section for a structure.
|
|
This is the default routines for this used by the structure classes.
|
|
Only CG_COMPLEX_STRUCT redefines this virtual method.
|
|
|
|
Arguments :
|
|
|
|
pCCB - pointer to the code control block.
|
|
|
|
--*/
|
|
{
|
|
CG_NDR * pOldPlaceholder;
|
|
CG_ITERATOR Iterator;
|
|
FORMAT_STRING * pFormatString;
|
|
CG_FIELD * pField;
|
|
CG_FIELD * pFieldPrev;
|
|
long MemoryAlign;
|
|
long BufferAlign;
|
|
long LastFieldEnd;
|
|
long FieldSize;
|
|
|
|
//
|
|
// This table is used for computing the next known memory alignment
|
|
// given the current memory alignment and the number of bytes in memory
|
|
// of the current field. It is indexed by a [<current alignment>],
|
|
// [<field size> % 8] pair. Note that the valid values for the current
|
|
// alignment are 1, 2, 4, and 8.
|
|
//
|
|
static long NextAlign[9][8] =
|
|
{
|
|
-1, -1, -1, -1, -1, -1, -1, -1,
|
|
1, 2, 1, 2, 1, 2, 1, 2,
|
|
2, 1, 2, 1, 2, 1, 2, 1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, // Invalid
|
|
4, 1, 2, 1, 4, 1, 2, 1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, // Invalid
|
|
-1, -1, -1, -1, -1, -1, -1, -1, // Invalid
|
|
-1, -1, -1, -1, -1, -1, -1, -1, // Invalid
|
|
8, 1, 2, 1, 4, 1, 2, 1
|
|
};
|
|
|
|
#define NEXT_ALIGN( CurrentAlign, MemorySize ) \
|
|
NextAlign[ CurrentAlign ][ (MemorySize) % 8 ]
|
|
|
|
#define GET_ALIGN( Align, Zp ) \
|
|
(((Align - 1) & (Zp - 1)) + 1)
|
|
|
|
pFormatString = pCCB->GetFormatString();
|
|
|
|
pOldPlaceholder = pCCB->GetLastPlaceholderClass();
|
|
|
|
//
|
|
// These keep track of the best know current alignment of the memory
|
|
// and buffer pointers.
|
|
//
|
|
MemoryAlign = 8;
|
|
BufferAlign = 0; // Currently unused.
|
|
|
|
GetMembers( Iterator );
|
|
|
|
for ( LastFieldEnd = 0, FieldSize = 0, pFieldPrev = 0;
|
|
ITERATOR_GETNEXT( Iterator, pField );
|
|
LastFieldEnd = pField->GetMemOffset() + FieldSize, pFieldPrev = pField
|
|
)
|
|
{
|
|
CG_NDR * pMember;
|
|
FORMAT_CHARACTER FormatChar;
|
|
long MemPad;
|
|
|
|
pCCB->SetLastPlaceholderClass( pField );
|
|
|
|
pMember = (CG_NDR *) pField->GetChild();
|
|
|
|
if ( pMember->GetCGID() == ID_CG_CONF_ARRAY ||
|
|
pMember->GetCGID() == ID_CG_CONF_VAR_ARRAY ||
|
|
pMember->GetCGID() == ID_CG_CONF_STRING_ARRAY )
|
|
{
|
|
pField = pFieldPrev;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// First check if we can align as usual or if we have to pad.
|
|
//
|
|
|
|
if ( pField->HasEmbeddedUnknownRepAs() )
|
|
{
|
|
// Embedded unknown represent as type means that the alignment
|
|
// of the embedding object (struct, array, ..) is unknown.
|
|
// So, padding will be generated as a (text) expression.
|
|
|
|
pFormatString->PushFormatChar( FC_EMBEDDED_COMPLEX );
|
|
|
|
unsigned long MacroOffset = pFormatString->GetCurrentOffset();
|
|
CG_FIELD * pPrevField = GetPreviousField( pField );
|
|
|
|
pCCB->GetRepAsPadExprDict()
|
|
->Register( MacroOffset,
|
|
GetType(),
|
|
pField->GetType()->GetSymName(),
|
|
pPrevField ? pPrevField->GetType()
|
|
: 0 );
|
|
|
|
pFormatString->PushByteWithPadMacro();
|
|
|
|
if ( pMember->GetFormatStringOffset() == 0 )
|
|
{
|
|
RegisterComplexEmbeddedForFixup(
|
|
pMember,
|
|
pFormatString->GetCurrentOffset() - GetInitialOffset() );
|
|
}
|
|
|
|
pFormatString->PushShortOffset( (short)
|
|
(pMember->GetFormatStringOffset() -
|
|
pFormatString->GetCurrentOffset()) );
|
|
|
|
// Cheat.
|
|
if ( pField->GetSibling() )
|
|
{
|
|
FieldSize = ((CG_FIELD *)pField->GetSibling())->GetMemOffset() -
|
|
pField->GetMemOffset();
|
|
}
|
|
|
|
//
|
|
// Alignment now becomes 1.
|
|
//
|
|
MemoryAlign = 1;
|
|
|
|
continue;
|
|
}
|
|
|
|
MemPad = pField->GetMemOffset() - LastFieldEnd;
|
|
|
|
if ( (pMember->GetCGID() == ID_CG_CONF_ARRAY) ||
|
|
(pMember->GetCGID() == ID_CG_CONF_VAR_ARRAY) ||
|
|
(pMember->GetCGID() == ID_CG_CONF_STRING_ARRAY) )
|
|
{
|
|
FieldSize = 0;
|
|
continue;
|
|
}
|
|
|
|
if ( pMember->IsStruct() ||
|
|
pMember->IsUnion() ||
|
|
pMember->IsArray() ||
|
|
pMember->IsXmitRepOrUserMarshal() ||
|
|
pMember->GetCGID() == ID_CG_INTERFACE_PTR )
|
|
{
|
|
pFormatString->PushFormatChar( FC_EMBEDDED_COMPLEX );
|
|
pFormatString->PushByte( (char) MemPad );
|
|
|
|
// if embedded complex member has an offset zero, it
|
|
// almost certainly means that it is in a recursion
|
|
// that is not resolved yet.
|
|
// I am not sure if -1 can happen.
|
|
|
|
if ( pMember->GetFormatStringOffset() == 0 ||
|
|
pMember->GetFormatStringOffset() == -1 )
|
|
{
|
|
RegisterComplexEmbeddedForFixup(
|
|
pMember,
|
|
pFormatString->GetCurrentOffset() - GetInitialOffset() );
|
|
}
|
|
|
|
pFormatString->PushShortOffset( pMember->GetFormatStringOffset() -
|
|
pFormatString->GetCurrentOffset() );
|
|
|
|
MemoryAlign = NEXT_ALIGN( MemoryAlign,
|
|
MemPad + pMember->GetMemorySize() );
|
|
|
|
FieldSize = pMember->GetMemorySize();
|
|
continue;
|
|
}
|
|
|
|
if ( pMember->IsPointer() ||
|
|
(pMember->GetCGID() == ID_CG_IGN_PTR) )
|
|
{
|
|
if ( MemoryAlign < GET_ALIGN(4,GetZp()) )
|
|
{
|
|
switch ( GET_ALIGN(4,GetZp()) )
|
|
{
|
|
case 2 :
|
|
pFormatString->PushFormatChar( FC_ALIGNM2 );
|
|
break;
|
|
case 4 :
|
|
pFormatString->PushFormatChar( FC_ALIGNM4 );
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
MemoryAlign = 4;
|
|
|
|
if ( pMember->IsPointer() )
|
|
{
|
|
if ( GetCGID() == ID_CG_COMPLEX_STRUCT )
|
|
pFormatString->PushFormatChar( FC_POINTER );
|
|
else
|
|
pFormatString->PushFormatChar( FC_LONG );
|
|
}
|
|
else
|
|
pFormatString->PushFormatChar( FC_IGNORE );
|
|
|
|
FieldSize = sizeof(void *);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Must be a CG_BASETYPE if we get here.
|
|
//
|
|
if ( MemoryAlign < GET_ALIGN(pMember->GetMemoryAlignment(),GetZp()) )
|
|
{
|
|
switch ( GET_ALIGN(pMember->GetMemoryAlignment(),GetZp()) )
|
|
{
|
|
case 2 :
|
|
pFormatString->PushFormatChar( FC_ALIGNM2 );
|
|
break;
|
|
case 4 :
|
|
pFormatString->PushFormatChar( FC_ALIGNM4 );
|
|
break;
|
|
case 8 :
|
|
pFormatString->PushFormatChar( FC_ALIGNM8 );
|
|
break;
|
|
default :
|
|
assert(0);
|
|
}
|
|
|
|
MemoryAlign = pMember->GetMemoryAlignment();
|
|
}
|
|
else
|
|
MemoryAlign = NEXT_ALIGN( MemoryAlign, pMember->GetMemorySize() );
|
|
|
|
FormatChar = ((CG_BASETYPE *)pMember)->GetFormatChar();
|
|
|
|
pFormatString->PushFormatChar( FormatChar );
|
|
|
|
FieldSize = pMember->GetMemorySize();
|
|
|
|
} // while field iterator
|
|
|
|
//
|
|
// We have to check for padding at the end of the structure.
|
|
//
|
|
|
|
long Pad = 0;
|
|
|
|
if ( pField )
|
|
{
|
|
CG_NDR * pNdr = (CG_NDR *) pField->GetChild();
|
|
|
|
Pad = GetMemorySize() -
|
|
(pField->GetMemOffset() + pNdr->GetMemorySize());
|
|
|
|
if ( Pad )
|
|
{
|
|
assert( (GetCGID() == ID_CG_COMPLEX_STRUCT) ||
|
|
IsComplexStruct() || IsHardStruct() );
|
|
}
|
|
}
|
|
|
|
switch ( Pad )
|
|
{
|
|
case 0 :
|
|
break;
|
|
case 1 :
|
|
pFormatString->PushFormatChar( FC_STRUCTPAD1 );
|
|
break;
|
|
case 2 :
|
|
pFormatString->PushFormatChar( FC_STRUCTPAD2 );
|
|
break;
|
|
case 3 :
|
|
pFormatString->PushFormatChar( FC_STRUCTPAD3 );
|
|
break;
|
|
case 4 :
|
|
pFormatString->PushFormatChar( FC_STRUCTPAD4 );
|
|
break;
|
|
case 5 :
|
|
pFormatString->PushFormatChar( FC_STRUCTPAD5 );
|
|
break;
|
|
case 6 :
|
|
pFormatString->PushFormatChar( FC_STRUCTPAD6 );
|
|
break;
|
|
case 7 :
|
|
pFormatString->PushFormatChar( FC_STRUCTPAD7 );
|
|
break;
|
|
default :
|
|
assert( ! "Struct has end padding >= 8" );
|
|
}
|
|
|
|
//
|
|
// 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->GetCGID() != ID_CG_INTERFACE_PTR) )
|
|
{
|
|
CG_NDR * pOldPlaceholder;
|
|
|
|
pOldPlaceholder = pCCB->SetLastPlaceholderClass( pField );
|
|
|
|
//
|
|
// Skip over an unattributed pointer to a simple type or string.
|
|
//
|
|
if ( ( pMember->GetCGID() == ID_CG_PTR &&
|
|
((CG_NDR *)pMember->GetChild())->IsSimpleType() ) ||
|
|
( 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 * pCCB )
|
|
{
|
|
}
|
|
|
|
void
|
|
CG_NDR::GenNdrPointerFixUp( CCB * pCCB, CG_STRUCT * pStruct )
|
|
{
|
|
CG_ITERATOR Iterator;
|
|
CG_NDR * pMember;
|
|
CG_NDR * pNdr;
|
|
long Offset;
|
|
|
|
if ( ! IsStruct() && ! IsArray() )
|
|
return;
|
|
|
|
if ( IsInFixUp() )
|
|
return;
|
|
|
|
SetFixUpLock( TRUE );
|
|
|
|
GetMembers( Iterator );
|
|
|
|
while ( ITERATOR_GETNEXT( Iterator, pMember ) )
|
|
{
|
|
if ( IsStruct() )
|
|
{
|
|
pNdr = (CG_NDR *) pMember->GetChild();
|
|
}
|
|
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()->PushShort(
|
|
pStruct->GetFormatStringOffset() - Offset,
|
|
Offset );
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
pCCB->GetFormatString()->PushShort(
|
|
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" );
|
|
|
|
assert( GetInitialOffset() != -1 );
|
|
|
|
if ( pEmbeddedComplexFixupRegistry == NULL )
|
|
{
|
|
pEmbeddedComplexFixupRegistry = new TREGISTRY;
|
|
}
|
|
|
|
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->PushShort(
|
|
pFixup->pEmbeddedNdr->GetFormatStringOffset() - FixAtOffset,
|
|
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 );
|
|
}
|
|
|
|
void
|
|
CG_STRUCT::SetNextNdrAlignment( CCB * pCCB )
|
|
{
|
|
if ( ! HasPointer() && ! IsComplexStruct() && ! IsHardStruct() )
|
|
{
|
|
pCCB->SetNextNdrAlignment( GetWireSize() );
|
|
}
|
|
else
|
|
{
|
|
pCCB->SetNdrAlignment( NDR_ALWC1 );
|
|
}
|
|
}
|
|
|
|
void
|
|
CG_CONFORMANT_STRUCT::SetNextNdrAlignment( CCB * pCCB )
|
|
{
|
|
if ( HasPointer() )
|
|
{
|
|
pCCB->SetNdrAlignment( NDR_ALWC1 );
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Has no pointers.
|
|
//
|
|
|
|
pCCB->SetNdrAlignment( NDR_ALWC4 );
|
|
|
|
pCCB->SetNextNdrAlignment( GetWireSize() );
|
|
|
|
pCCB->NdrAlignmentAction( GetConformantArray()->GetWireAlignment() );
|
|
|
|
((CG_NDR *)GetConformantArray()->GetChild())->SetNextNdrAlignment( pCCB );
|
|
}
|
|
|
|
void
|
|
CG_CONFORMANT_VARYING_STRUCT::SetNextNdrAlignment( CCB * pCCB )
|
|
{
|
|
if ( HasPointer() )
|
|
{
|
|
pCCB->SetNdrAlignment( NDR_ALWC1 );
|
|
return;
|
|
}
|
|
|
|
pCCB->SetNdrAlignment( NDR_ALWC4 );
|
|
|
|
pCCB->NdrAlignmentAction( GetConformantArray()->GetWireAlignment() );
|
|
|
|
((CG_NDR *)GetConformantArray()->GetChild())->SetNextNdrAlignment( pCCB );
|
|
}
|
|
|
|
void
|
|
CG_COMPLEX_STRUCT::SetNextNdrAlignment( CCB * pCCB )
|
|
{
|
|
pCCB->SetNdrAlignment( NDR_ALWC1 );
|
|
}
|
|
|
|
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 8 + GetWireSize();
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
SetInFixedBufferSize( TRUE );
|
|
|
|
assert( GetCGID() == ID_CG_STRUCT );
|
|
|
|
pOldPlaceholder = pCCB->SetLastPlaceholderClass( this );
|
|
|
|
GetMembers( Iterator );
|
|
|
|
TotalBufferSize = 8 + 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;
|
|
}
|
|
|