mirror of https://github.com/tongzx/nt5src
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.
3591 lines
114 KiB
3591 lines
114 KiB
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
Copyright (c) 1999-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ndr64.cxx
|
|
|
|
Abstract:
|
|
|
|
Routines for the ndr64 transfer syntax.
|
|
|
|
Notes:
|
|
|
|
|
|
History:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
|
|
#include "becls.hxx"
|
|
|
|
char * _SimpleTypeName[] = {
|
|
"",
|
|
"NDR64_FORMAT_UINT8",
|
|
"NDR64_FORMAT_UINT16",
|
|
"NDR64_FORMAT_UINT32",
|
|
"NDR64_FORMAT_UINT64"
|
|
};
|
|
|
|
// define the name table for the NDR64 format characters
|
|
#define NDR64_BEGIN_TABLE \
|
|
const char *pNDR64FormatCharNames[] = {
|
|
|
|
#define NDR64_TABLE_END \
|
|
};
|
|
|
|
#define NDR64_ZERO_ENTRY \
|
|
"FC64_ZERO"
|
|
|
|
#define NDR64_TABLE_ENTRY( number, tokenname, marshal, embeddedmarshall, unmarshall, embeddedunmarshal, buffersize, embeddedbuffersize, memsize, embeddedmemsize, free, embeddedfree, typeflags ) \
|
|
, #tokenname
|
|
|
|
#define NDR64_SIMPLE_TYPE_TABLE_ENTRY( number, tokenname, simpletypebuffersize, simpletypememorysize ) \
|
|
, #tokenname
|
|
|
|
#define NDR64_UNUSED_TABLE_ENTRY( number, tokenname ) \
|
|
, #tokenname
|
|
|
|
#define NDR64_UNUSED_TABLE_ENTRY_NOSYM( number ) \
|
|
, NULL
|
|
|
|
#include "tokntbl.h"
|
|
|
|
extern const pNDR64FormatCharNamesSize = (sizeof(pNDR64FormatCharNames) / sizeof(*pNDR64FormatCharNames));
|
|
|
|
C_ASSERT( (sizeof(pNDR64FormatCharNames) / sizeof(*pNDR64FormatCharNames)) == 256 );
|
|
#undef NDR64_BEGIN_TABLE
|
|
#undef NDR64_TABLE_END
|
|
#undef NDR64_ZERO_ENTRY
|
|
#undef NDR64_TABLE_ENTRY
|
|
#undef NDR64_SIMPLE_TYPE_TABLE_ENTRY
|
|
#undef NDR64_UNUSED_TABLE_ENTRY
|
|
#undef NDR64_UNUSED_TABLE_ENTRY_NOSYM
|
|
|
|
|
|
FormatFragment * GenExprFormatString(CCB *pCCB,
|
|
expr_node *pSizeExpr,
|
|
CompositeFormatFragment *FragmentList,
|
|
BOOL * IsEarly,
|
|
ulong * pExprLength );
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: FormatFragment::OutputDescription
|
|
//
|
|
// Synopsis: Output a description of this fragment
|
|
//
|
|
// Notes: The output is in the form of a C style comment.
|
|
// The decription is the name of the type that this fragment
|
|
// represents. If this fragment represents more than on type
|
|
// because of optimization then all the types will be output.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void FormatFragment::OutputDescription( ISTREAM *stream )
|
|
{
|
|
FormatFragment *frag = this;
|
|
bool first = true;
|
|
|
|
stream->WriteOnNewLine( "/* " );
|
|
|
|
do
|
|
{
|
|
if ( !first )
|
|
stream->Write(", ");
|
|
|
|
CG_CLASS *pClass = frag->GetCGNode();
|
|
const char *pName = NULL;
|
|
|
|
while ( NULL != pClass && pClass->IsPointer() )
|
|
{
|
|
stream->Write( "*" );
|
|
pClass = pClass->GetChild();
|
|
}
|
|
if ( NULL != pClass && NULL != pClass->GetType() )
|
|
{
|
|
pName = pClass->GetName();
|
|
if ( pName != NULL && pName[0] == '\0' )
|
|
pName = NULL;
|
|
}
|
|
if ( NULL == pName )
|
|
pName = frag->GetTypeName();
|
|
|
|
stream->Write( pName );
|
|
|
|
frag = frag->pNextOptimized;
|
|
first = false;
|
|
}
|
|
while ( NULL != frag );
|
|
|
|
stream->Write( " */" );
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: CompositeFormatFragment::IsEqualTo
|
|
//
|
|
// Synopsis: Compare two composite fragments
|
|
//
|
|
// Notes: This method compares two composite fragments. Two composite
|
|
// fragments are equal if and only if the elements of the composite
|
|
// are equal.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
bool CompositeFormatFragment::IsEqualTo( FormatFragment *candidate )
|
|
{
|
|
CompositeFormatFragment *pOther = (CompositeFormatFragment *)candidate;
|
|
|
|
FormatFragment *pCurrent = pHead;
|
|
FormatFragment *pCurrentOther = pOther->pHead;
|
|
|
|
while ( (pCurrent != NULL) &&
|
|
(pCurrentOther != NULL) )
|
|
{
|
|
|
|
const type_info &frag_type = typeid( *pCurrent );
|
|
const type_info &other_type = typeid( *pCurrentOther );
|
|
|
|
if ( frag_type != other_type )
|
|
return false;
|
|
|
|
if ( !pCurrent->IsEqualTo( pCurrentOther ) )
|
|
return false;
|
|
|
|
pCurrent = pCurrent->Next;
|
|
pCurrentOther = pCurrentOther->Next;
|
|
|
|
}
|
|
|
|
// Both lists must have the same length.
|
|
bool bResult = ( NULL == pCurrent ) && ( NULL == pCurrentOther );
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Class: CompositeFormatFragment::LookupFragment
|
|
//
|
|
// Synopsis: Find the fragment corresponding to a class
|
|
//
|
|
// Parameters: [pClass] -- The class
|
|
//
|
|
// Returns: NULL if the class has no fragment yet
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
FormatFragment * CompositeFormatFragment::LookupFragment( CG_CLASS *pClass )
|
|
{
|
|
FormatFragment *frag;
|
|
|
|
// Generic handles are a special case. They don't actually have any
|
|
// representation in the format info.
|
|
|
|
if ( ID_CG_GENERIC_HDL == pClass->GetCGID() )
|
|
pClass = pClass->GetChild();
|
|
|
|
for ( frag = pHead; NULL != frag; frag = frag->Next )
|
|
if ( frag->pClass == pClass )
|
|
return frag;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Class: CompositeFormatFragment::AddFragment
|
|
//
|
|
// Synopsis: Add a fragment to the list if it isn't already present
|
|
//
|
|
// Parameters: [frag] -- The fragment
|
|
//
|
|
// Returns: The id of the fragment
|
|
//
|
|
// Notes: Another way to think of this method is that it provides a
|
|
// mapping between CG_CLASS pointers and FormatInfoRef's.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
FormatInfoRef CompositeFormatFragment::AddFragment( FormatFragment *frag )
|
|
{
|
|
frag->Next = NULL;
|
|
frag->RefID = NextRefID;
|
|
frag->Prev = pTail;
|
|
frag->Parent = this;
|
|
|
|
if ( NULL == pTail )
|
|
pHead = frag;
|
|
else
|
|
pTail->Next = frag;
|
|
|
|
pTail = frag;
|
|
NextRefID = (FormatInfoRef) ((size_t) NextRefID + 1);
|
|
|
|
return frag->RefID;
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Class: CompositeFormatFragment::OutputFragmentType
|
|
//
|
|
// Synopsis: Output a type declaration for this composite
|
|
//
|
|
// Notes: It looks like:
|
|
//
|
|
// struct <name>
|
|
// {
|
|
// <frag1 type>,
|
|
// <frag2 type>
|
|
// ...
|
|
// }
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void CompositeFormatFragment::OutputFragmentType( CCB *pCCB )
|
|
{
|
|
|
|
ISTREAM *stream = pCCB->GetStream();
|
|
|
|
stream->WriteOnNewLine("struct ");
|
|
stream->Write( GetTypeName() );
|
|
stream->WriteOnNewLine("{");
|
|
stream->IndentInc();
|
|
|
|
FormatFragment *pCurrent = pHead;
|
|
|
|
for ( pCurrent = pHead; NULL != pCurrent; pCurrent = pCurrent->Next )
|
|
{
|
|
if ( pCurrent->WasOptimizedOut() )
|
|
{
|
|
// Only top-level stuff should be optimized
|
|
MIDL_ASSERT( NULL == GetParent() );
|
|
continue;
|
|
}
|
|
|
|
pCurrent->OutputFragmentType( pCCB );
|
|
stream->WriteFormat(" frag%d;", (size_t) pCurrent->GetRefID());
|
|
}
|
|
|
|
stream->IndentDec();
|
|
stream->WriteOnNewLine("}");
|
|
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Class: CompositeFormatFragment::OutputFragmentData
|
|
//
|
|
// Synopsis: Output the initializer data for this composite
|
|
//
|
|
// Notes: It looks like:
|
|
//
|
|
// {
|
|
// <frag1 data>,
|
|
// <frag2 type>
|
|
// ...
|
|
// }
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void CompositeFormatFragment::OutputFragmentData( CCB *pCCB )
|
|
{
|
|
|
|
ISTREAM *stream = pCCB->GetStream();
|
|
|
|
OutputStructDataStart( pCCB );
|
|
|
|
FormatFragment *pCurrent;
|
|
bool FirstFragment = true;
|
|
|
|
for ( pCurrent = pHead; NULL != pCurrent; pCurrent = pCurrent->Next )
|
|
{
|
|
if ( pCurrent->WasOptimizedOut() )
|
|
{
|
|
// Only top-level stuff should be optimized
|
|
MIDL_ASSERT( NULL == GetParent() );
|
|
continue;
|
|
}
|
|
|
|
if ( !FirstFragment )
|
|
stream->Write(",");
|
|
|
|
FirstFragment = false;
|
|
|
|
pCurrent->OutputFragmentData( pCCB );
|
|
|
|
}
|
|
|
|
OutputStructDataEnd( pCCB );
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Class: CompositeFormatFragment::OptimizeFragment
|
|
//
|
|
// Synopsis: Try to optimize out a fragment in the format string by
|
|
// checking to see if it is the same as some other fragment.
|
|
//
|
|
// Parameters: [frag] -- The fragment to optimize
|
|
//
|
|
// Returns: The final ID of the fragment
|
|
//
|
|
// Notes: Optimization can be suppressed by the user by specifiying
|
|
// -no_format_opt
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
FormatInfoRef CompositeFormatFragment::OptimizeFragment( FormatFragment *frag )
|
|
{
|
|
if ( pCommand->IsSwitchDefined( SWITCH_NO_FMT_OPT ) )
|
|
return frag->RefID;
|
|
|
|
// Only stuff in the root composite can be optimized
|
|
|
|
if ( ! dynamic_cast<RootFormatFragment *>(frag->GetParent()) )
|
|
return frag->RefID;
|
|
|
|
FormatFragment *candidate;
|
|
|
|
for ( candidate = pHead;
|
|
NULL != candidate && candidate != frag;
|
|
candidate = candidate->Next )
|
|
{
|
|
const type_info &frag_type = typeid( *frag );
|
|
const type_info &candidate_type = typeid( *candidate );
|
|
|
|
if ( frag_type != candidate_type )
|
|
continue;
|
|
|
|
if ( candidate->IsEqualTo( frag ) )
|
|
{
|
|
frag->RefID = candidate->RefID;
|
|
|
|
while ( NULL != candidate->pNextOptimized )
|
|
candidate = candidate->pNextOptimized;
|
|
|
|
candidate->pNextOptimized = frag;
|
|
frag->pPrevOptimized = candidate;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return frag->RefID;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: RootFormatFragement::Output
|
|
//
|
|
// Synopsis: Output a the whole ndr64 format structure
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void RootFormatFragment::Output( CCB *pCCB )
|
|
{
|
|
ISTREAM *stream = pCCB->GetStream();
|
|
|
|
stream->NewLine();
|
|
|
|
// REVIEW: Is this the right place to output these?
|
|
|
|
stream->WriteOnNewLine("#include \"ndr64types.h\"");
|
|
stream->WriteOnNewLine("#include \"pshpack8.h\"");
|
|
stream->NewLine();
|
|
|
|
FormatFragment *pCurrent;
|
|
|
|
for ( pCurrent = pTail; NULL != pCurrent; pCurrent = pCurrent->Prev )
|
|
{
|
|
if ( pCurrent->WasOptimizedOut() )
|
|
continue;
|
|
|
|
stream->NewLine();
|
|
stream->WriteOnNewLine("typedef ");
|
|
pCurrent->OutputFragmentType( pCCB );
|
|
stream->NewLine();
|
|
stream->WriteFormat("__midl_frag%d_t;", pCurrent->GetRefID() );
|
|
stream->NewLine();
|
|
stream->WriteFormat(
|
|
"extern const __midl_frag%d_t __midl_frag%d;",
|
|
pCurrent->GetRefID(),
|
|
pCurrent->GetRefID() );
|
|
}
|
|
|
|
for ( pCurrent = pTail; NULL != pCurrent; pCurrent = pCurrent->Prev )
|
|
{
|
|
if ( pCurrent->WasOptimizedOut() )
|
|
continue;
|
|
|
|
stream->NewLine( 2 );
|
|
stream->WriteFormat(
|
|
"static const __midl_frag%d_t __midl_frag%d =",
|
|
pCurrent->GetRefID(),
|
|
pCurrent->GetRefID() );
|
|
pCurrent->OutputFragmentData( pCCB );
|
|
stream->Write(";");
|
|
}
|
|
|
|
stream->NewLine( 2 );
|
|
stream->WriteOnNewLine("#include \"poppack.h\"");
|
|
stream->NewLine( 2 );
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::CreateInstance (static)
|
|
//
|
|
// Synopsis: Class factory for GenNdr64Format
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
GenNdr64Format * GenNdr64Format::CreateInstance( CCB *pCCB )
|
|
{
|
|
MIDL_ASSERT( pCommand->IsNDR64Run() );
|
|
|
|
CG_VISITOR_TEMPLATE<GenNdr64Format> *pVisitor = new CG_VISITOR_TEMPLATE<GenNdr64Format>;
|
|
|
|
GenNdr64Format *generator = pVisitor;
|
|
|
|
generator->pCCB = pCCB;
|
|
generator->pRoot = new RootFormatFragment;
|
|
generator->pCurrent = generator->pRoot;
|
|
generator->pVisitor = pVisitor;
|
|
|
|
// add a dummy entry at the beginning of format string to prevent
|
|
// an emptry structure being generated when there is only [local]
|
|
// interface in an .idl file.
|
|
MIDL_NDR_FORMAT_UINT32 * pDummy = new MIDL_NDR_FORMAT_UINT32;
|
|
pDummy->Data = 0;
|
|
|
|
generator->pRoot->AddFragment( pDummy );
|
|
|
|
return generator;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::ContinueGeneration
|
|
//
|
|
// Synopsis: Do generation for a sub-tree. This is typically called
|
|
// by a parent node to generate it's children so that it can
|
|
// get offsets to the child format string indices, etc.
|
|
//
|
|
// Parameters: pClass -- The subtree to generate from
|
|
// pCompositeFragment -- The composite to generate into
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
FormatInfoRef GenNdr64Format::ContinueGeneration(
|
|
CG_CLASS *pClass,
|
|
CompositeFormatFragment *pComposite )
|
|
{
|
|
CompositeFormatFragment *pOldCurrent = pCurrent;
|
|
|
|
// Some CG classes don't have children. Those classes should not be
|
|
// calling ContinueGeneration on thier non-existant children.
|
|
|
|
MIDL_ASSERT( NULL != pClass );
|
|
|
|
// Do this here to save from every visit function from doing it.
|
|
FormatFragment* pFrag = pComposite->LookupFragment( pClass );
|
|
if ( NULL != pFrag )
|
|
return pFrag->GetRefID();
|
|
|
|
if ( NULL != pComposite )
|
|
pCurrent = pComposite;
|
|
|
|
pClass->Visit( pVisitor );
|
|
|
|
FormatInfoRef NewFragmentID = pCurrent->LookupFragmentID( pClass );
|
|
|
|
pCurrent = pOldCurrent;
|
|
|
|
return NewFragmentID;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::Generate
|
|
//
|
|
// Synopsis: External routine called to generate the string for a type.
|
|
//
|
|
// Parameters: pClass -- Type to generate string for.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
FormatInfoRef GenNdr64Format::Generate( CG_CLASS *pClass )
|
|
{
|
|
return ContinueGeneration( pClass, GetRoot() );
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::Output
|
|
//
|
|
// Synopsis: External routine called to output the string.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::Output( )
|
|
{
|
|
GetRoot()->Output( pCCB );
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::ContinueGenerationInRoot
|
|
//
|
|
// Synopsis: Same as ContinueGeneration except switches to root.
|
|
//
|
|
// Parameters: pClass -- The subtree to generate from
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
inline FormatInfoRef GenNdr64Format::ContinueGenerationInRoot( CG_CLASS *pClass )
|
|
{
|
|
return ContinueGeneration( pClass, GetRoot() );
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::Visit( CG_CLASS )
|
|
//
|
|
// Synopsis: Default visitor that handles things that don't need any
|
|
// handling.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::Visit( CG_CLASS *pClass )
|
|
{
|
|
// Should only be called for these classes or drived ones
|
|
/*
|
|
assert(
|
|
NULL != dynamic_cast<CG_AUX *>(pClass)
|
|
);
|
|
*/
|
|
|
|
CG_ITERATOR Iterator;
|
|
CG_CLASS *pChild;
|
|
|
|
pClass->GetMembers( Iterator );
|
|
|
|
while ( ITERATOR_GETNEXT( Iterator, pChild ) )
|
|
ContinueGenerationInRoot( pChild );
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::Visit( CG_BASETYPE )
|
|
//
|
|
// Synopsis: Generate info for base types and ranges
|
|
//
|
|
// Notes: FC64_BYTE, FC64_CHAR, FC64_WCHAR, FC64_SMALL, FC64_USMALL,
|
|
// FC64_SHORT, FC64_USHORT, FC64_LONG, FC64_ULONG, FC64_HYPER, FC64_UHYPER,
|
|
// FC64_INT3264, FC64_UINT3264, FC64_FLOAT, FC64_DOUBLE,
|
|
// FC64_ERROR_STATUS_T
|
|
//
|
|
// (also, pending support elsewhere)
|
|
//
|
|
// FC64_INT128, FC64_UINT128, FC64_FLOAT128, FC64_FLOAT80
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::Visit( CG_BASETYPE *pClass )
|
|
{
|
|
if ( pClass->GetRangeAttribute() )
|
|
{
|
|
GenRangeFormat( pClass );
|
|
return;
|
|
}
|
|
|
|
MIDL_NDR64_FORMAT_CHAR *frag = new MIDL_NDR64_FORMAT_CHAR( pClass );
|
|
|
|
GetCurrent()->AddFragment( frag );
|
|
GetRoot()->OptimizeFragment( frag );
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::GenRangeFormat
|
|
//
|
|
// Synopsis: Ranges are a special case of base types so we can't
|
|
// distinguish between them polymorphically. The base type
|
|
// visitor method calls this if we have a range.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::GenRangeFormat( CG_BASETYPE *pRangeCG )
|
|
{
|
|
MIDL_NDR64_RANGE_FORMAT *format;
|
|
node_range_attr *range;
|
|
|
|
format = new MIDL_NDR64_RANGE_FORMAT( pRangeCG );
|
|
|
|
range = pRangeCG->GetRangeAttribute();
|
|
MIDL_ASSERT( NULL != range );
|
|
|
|
format->FormatCode = FC64_RANGE;
|
|
format->RangeType = (NDR64_FORMAT_CHAR)pRangeCG->GetNDR64FormatChar();
|
|
format->Reserved = 0;
|
|
format->MinValue = range->GetMinExpr()->GetValue();
|
|
format->MaxValue = range->GetMaxExpr()->GetValue();
|
|
|
|
GetCurrent()->AddFragment( format );
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::Visit( CG_ENCAPSULATED_STRUCT )
|
|
//
|
|
// Synopsis: Despite the name, this is for generating info for
|
|
// encapsulated unions
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::Visit( CG_ENCAPSULATED_STRUCT *pEncapUnion )
|
|
{
|
|
|
|
// A union is represented in the format info by a composite containing
|
|
// the union header follow by fragments representing the arm selector
|
|
|
|
CompositeFormatFragment *composite = new CompositeFormatFragment( pEncapUnion );
|
|
|
|
GetCurrent()->AddFragment( composite );
|
|
|
|
MIDL_NDR64_ENCAPSULATED_UNION *format;
|
|
|
|
format = new MIDL_NDR64_ENCAPSULATED_UNION( pEncapUnion );
|
|
|
|
composite->AddFragment( format );
|
|
|
|
CG_FIELD *pSwitchField = (CG_FIELD *) pEncapUnion->GetChild();
|
|
CG_BASETYPE *pSwitch = (CG_BASETYPE *) pSwitchField->GetChild();
|
|
CG_FIELD *pUnionField = (CG_FIELD *) pSwitchField->GetSibling();
|
|
CG_UNION *pUnion = (CG_UNION *) pUnionField->GetChild();
|
|
|
|
MIDL_ASSERT( NULL != dynamic_cast<CG_BASETYPE *>(pSwitch) );
|
|
MIDL_ASSERT( NULL != pUnion && NULL != dynamic_cast<CG_UNION *>(pUnion) );
|
|
|
|
format->FormatCode = FC64_ENCAPSULATED_UNION;
|
|
format->Alignment = ConvertAlignment( pEncapUnion->GetWireAlignment() );
|
|
format->Flags = 0;
|
|
format->SwitchType = (NDR64_FORMAT_CHAR)pSwitch->GetNDR64SignedFormatChar();
|
|
format->MemoryOffset = pUnionField->GetMemOffset()
|
|
- pSwitchField->GetMemOffset();
|
|
format->MemorySize = pEncapUnion->GetMemorySize();
|
|
format->Reserved = 0;
|
|
|
|
GenerateUnionArmSelector( pUnion, composite );
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::GenerateUnionArmSelector
|
|
//
|
|
// Synopsis: Generate info about union arms
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::GenerateUnionArmSelector(
|
|
CG_UNION *pUnion,
|
|
CompositeFormatFragment *FragmentList )
|
|
{
|
|
MIDL_NDR64_UNION_ARM_SELECTOR *header;
|
|
|
|
header = new MIDL_NDR64_UNION_ARM_SELECTOR;
|
|
|
|
header->Reserved1 = 0;
|
|
header->Alignment = ConvertAlignment( pUnion->GetWireAlignment() );
|
|
header->Reserved2 = 0;
|
|
header->Arms = (NDR64_UINT32) pUnion->GetNumberOfArms();
|
|
|
|
FragmentList->AddFragment( header );
|
|
|
|
// Generate the non-default arms
|
|
|
|
CG_ITERATOR Iterator;
|
|
CG_CASE *pCase;
|
|
CG_CASE *pDefaultCase = NULL;
|
|
NDR64_UINT16 ArmCount = 0;
|
|
|
|
pUnion->GetMembers( Iterator );
|
|
|
|
while ( ITERATOR_GETNEXT( Iterator, pCase ) )
|
|
{
|
|
// The default case is always put at the end
|
|
|
|
if ( ID_CG_DEFAULT_CASE == pCase->GetCGID() )
|
|
{
|
|
pDefaultCase = pCase;
|
|
continue;
|
|
}
|
|
|
|
MIDL_NDR64_UNION_ARM *arm = new MIDL_NDR64_UNION_ARM;
|
|
|
|
MIDL_ASSERT( NULL != pCase->GetExpr() );
|
|
|
|
arm->CaseValue = pCase->GetExpr()->GetValue();
|
|
|
|
// it's legal to have a case with no type
|
|
|
|
if ( NULL == pCase->GetChild() || NULL == pCase->GetChild()->GetChild() )
|
|
arm->Type = 0;
|
|
else
|
|
arm->Type = ContinueGenerationInRoot(
|
|
pCase->GetChild()->GetChild() );
|
|
|
|
arm->Reserved = 0;
|
|
FragmentList->AddFragment( arm );
|
|
++ArmCount;
|
|
}
|
|
|
|
MIDL_ASSERT( ArmCount == header->Arms );
|
|
|
|
// Generate the default
|
|
|
|
PNDR64_FORMAT Type;
|
|
|
|
if ( NULL == pDefaultCase )
|
|
Type = (PNDR64_FORMAT) -1;
|
|
else
|
|
{
|
|
CG_CLASS *pType = pDefaultCase->GetChild();
|
|
|
|
if ( NULL != pType )
|
|
pType = pType->GetChild();
|
|
|
|
if ( NULL == pType )
|
|
Type = 0;
|
|
else
|
|
Type = ContinueGenerationInRoot( pType );
|
|
}
|
|
|
|
FragmentList->AddFragment( new MIDL_NDR64_DEFAULT_CASE( Type ) );
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::Visit( CG_INTERFACE )
|
|
//
|
|
// Synopsis: Generate info for interfaces
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::Visit( CG_INTERFACE *pInterface )
|
|
{
|
|
CG_ITERATOR I;
|
|
CCB *pCCB = GetCCB();
|
|
CG_PROC *pProc;
|
|
|
|
pInterface->InitializeCCB( pCCB );
|
|
|
|
pCCB->SetImplicitHandleIDNode( 0 );
|
|
|
|
if( pInterface->GetMembers( I ) )
|
|
while ( ITERATOR_GETNEXT( I, pProc ) )
|
|
ContinueGenerationInRoot( pProc );
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::Visit( CG_PARAM )
|
|
//
|
|
// Synopsis: Generate info for parameters
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::Visit( CG_PARAM *pParam )
|
|
{
|
|
|
|
if ( GetCurrent()->HasClassFragment( pParam ) )
|
|
return;
|
|
|
|
NDR64_PARAM_FLAGS Attributes;
|
|
CG_NDR *pChild;
|
|
CG_NDR *pOldPlaceholder;
|
|
|
|
pChild = (CG_NDR *) pParam->GetChild();
|
|
|
|
if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
|
|
pChild = (CG_NDR *) pChild->GetChild();
|
|
|
|
// Ignore the following type of arguments that don't go on wire:
|
|
// - async handles
|
|
// - primitive handles
|
|
//
|
|
if ( pChild->GetCGID() == ID_CG_PRIMITIVE_HDL || ( (CG_PARAM*) pParam)->IsAsyncHandleParam() )
|
|
return;
|
|
|
|
pOldPlaceholder = pCCB->SetLastPlaceholderClass( pParam );
|
|
|
|
// Get the parameter attributes. The 32-bit PARAM_ATTRIBUTES structure
|
|
// is essentially the same as the NDR64_PARAM_FLAGS structure except
|
|
// the 64-bit structure has a single bit (UseCache) for the old
|
|
// ServerAllocSize field
|
|
|
|
PARAM_ATTRIBUTES *pattr = (PARAM_ATTRIBUTES *) &Attributes;
|
|
pChild->GetNdrParamAttributes( pCCB, pattr );
|
|
Attributes.UseCache = (NDR64_UINT16) ((pattr->ServerAllocSize) ? 1 : 0);
|
|
Attributes.Reserved = 0;
|
|
|
|
// For reasons not understood, GenNdrParamAttributes marks basetypes as
|
|
// not by value even if they are (unless they are ranges). Fix the
|
|
// insanity.
|
|
|
|
if ( pChild->IsSimpleType() )
|
|
Attributes.IsByValue = 1;
|
|
|
|
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
|
|
|
|
// Get the fragment of the pointee.
|
|
|
|
FormatFragment *pChildFragment;
|
|
|
|
pChildFragment = GetCurrent()->GetParent()->LookupFragment( pChild );
|
|
MIDL_ASSERT( NULL != pChildFragment );
|
|
|
|
// Fill in the parameter information
|
|
|
|
MIDL_NDR64_PARAM_FORMAT *format;
|
|
|
|
format = new MIDL_NDR64_PARAM_FORMAT( pParam );
|
|
|
|
format->Attributes = Attributes;
|
|
format->Reserved = 0;
|
|
|
|
pParam->GetStackOffsets( pCCB, &format->StackOffset );
|
|
|
|
// REVIEW: The reason why we have to test base types seperately is
|
|
// because of the inconsistent way things are stored. Consider
|
|
// a string pointer. It's format info is a simple ref to an
|
|
// string array - this can be intrepreted as a pointer to a block
|
|
// of memory. However, it's CG representation is just a pointer.
|
|
// The missing level of dereference causes the problem. In
|
|
// constrast a pointer to a single long is represented as a ref
|
|
// pointer to a long both in CG and in the format info.
|
|
|
|
if ( Attributes.IsBasetype
|
|
&& ( Attributes.IsByValue || Attributes.IsSimpleRef ) )
|
|
{
|
|
if ( Attributes.IsSimpleRef )
|
|
pChild = (CG_NDR *) pChild->GetChild();
|
|
|
|
format->Type = GetRoot()->LookupFragment( pChild )->GetRefID();
|
|
}
|
|
else
|
|
{
|
|
FormatFragment *pChildFragment = GetCurrent()->GetParent()->LookupFragment( pChild );
|
|
MIDL_ASSERT( NULL != pChildFragment );
|
|
|
|
// Is the parameter is a simple ref, we need to bypass the pointer
|
|
// in the format string.
|
|
if ( Attributes.IsSimpleRef )
|
|
{
|
|
MIDL_NDR64_POINTER_FORMAT* pPointerFrag =
|
|
dynamic_cast<MIDL_NDR64_POINTER_FORMAT*>(pChildFragment);
|
|
format->Type = pPointerFrag->Pointee;
|
|
}
|
|
else
|
|
{
|
|
format->Type = pChildFragment->GetRefID();
|
|
}
|
|
}
|
|
|
|
GetCurrent()->AddFragment( format );
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::Visit( CG_PROC )
|
|
//
|
|
// Synopsis: Generate info for interfaces
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::Visit( CG_PROC *pProc )
|
|
{
|
|
|
|
if ( GetCurrent()->HasClassFragment( pProc ) )
|
|
return;
|
|
|
|
CG_NDR * pOldCGNodeContext;
|
|
CG_ITERATOR Iterator;
|
|
CG_PARAM * pParam;
|
|
short ParamNum;
|
|
long ServerBufferSize;
|
|
long ClientBufferSize;
|
|
long BufSize;
|
|
BOOL fServerMustSize;
|
|
BOOL fClientMustSize;
|
|
|
|
// Make sure [call_as] targets are processed
|
|
|
|
CG_PROC *pCallAs = pProc->GetCallAsCG();
|
|
if (pCallAs)
|
|
ContinueGenerationInRoot( pCallAs );
|
|
|
|
CompositeFormatFragment *composite = new CompositeFormatFragment( pProc );
|
|
|
|
composite->SetParent( GetCurrent() );
|
|
GetCurrent()->AddFragment(composite);
|
|
|
|
MIDL_NDR64_PROC_FORMAT *format = new MIDL_NDR64_PROC_FORMAT( pProc );
|
|
|
|
composite->AddFragment( format );
|
|
|
|
pCCB->SetInObjectInterface( pProc->IsObject() );
|
|
|
|
pOldCGNodeContext = pCCB->SetCGNodeContext( pProc );
|
|
|
|
//
|
|
// If this procedure uses an explicit handle then set the
|
|
// NdrBindDescriptionOffset to 0 so that it will not try to output it's
|
|
// description when given the GenNdrParamOffLine method in the loop below.
|
|
// It's description must be part of the procedure description.
|
|
//
|
|
if ( pProc->GetHandleUsage() == HU_EXPLICIT )
|
|
{
|
|
CG_HANDLE * pHandle = pProc->GetHandleClassPtr();
|
|
|
|
pHandle->SetNdrBindDescriptionOffset( 0 );
|
|
|
|
if ( pHandle->GetCGID() == ID_CG_CONTEXT_HDL )
|
|
{
|
|
// The context handle directs the call.
|
|
((CG_CONTEXT_HANDLE *)pHandle)->SetCannotBeNull();
|
|
}
|
|
}
|
|
|
|
if ( !pProc->IsObject() && !pCCB->IsInCallback() )
|
|
{
|
|
if ( HU_IMPLICIT == pProc->GetHandleUsage() )
|
|
{
|
|
if ( pProc->IsGenericHandle() )
|
|
pCCB->RegisterGenericHandleType(
|
|
pProc->GetHandleClassPtr()->GetHandleType() );
|
|
}
|
|
}
|
|
|
|
pProc->GetMembers( Iterator );
|
|
|
|
ParamNum = 0;
|
|
|
|
ServerBufferSize = 0;
|
|
ClientBufferSize = 0;
|
|
|
|
fServerMustSize = FALSE;
|
|
fClientMustSize = FALSE;
|
|
|
|
pCCB->SetInterpreterOutSize( 0 );
|
|
|
|
while( ITERATOR_GETNEXT( Iterator, pParam ) )
|
|
{
|
|
CG_NDR * pChild;
|
|
CG_NDR * pOldPlaceholder;
|
|
|
|
pChild = (CG_NDR *) pParam->GetChild();
|
|
|
|
// Ignore the following type of arguments that don't go on wire:
|
|
// - async handles
|
|
// - primitive handles
|
|
//
|
|
if ( pChild->GetCGID() == ID_CG_PRIMITIVE_HDL || ( (CG_PARAM*) pParam)->IsAsyncHandleParam() )
|
|
continue;
|
|
|
|
pParam->SetParamNumber( ParamNum++ );
|
|
|
|
pCCB->SetCurrentParam( (CG_PARAM *) pParam );
|
|
pOldPlaceholder = pCCB->SetLastPlaceholderClass( pParam );
|
|
|
|
ContinueGenerationInRoot( pChild );
|
|
|
|
// A procedure's buffer size does not depend on pipe arguments
|
|
if (pChild->IsPipeOrPipeReference())
|
|
{
|
|
if (pChild->GetChild()->HasAFixedBufferSize())
|
|
pParam->SetInterpreterMustSize(FALSE);
|
|
else
|
|
// There must be a union in there somewhere
|
|
pParam->SetInterpreterMustSize(TRUE);
|
|
}
|
|
else
|
|
{
|
|
BufSize = pChild->FixedBufferSize( pCCB );
|
|
|
|
if ( BufSize != -1 )
|
|
{
|
|
//
|
|
// If either the client's or server's fixed buffer size gets too
|
|
// big then we force the parameter to be sized.
|
|
//
|
|
if ( (pParam->IsParamIn() &&
|
|
((ClientBufferSize + BufSize) >= 65356)) ||
|
|
(pParam->IsParamOut() &&
|
|
((ServerBufferSize + BufSize) >= 65356)) )
|
|
{
|
|
fClientMustSize = TRUE;
|
|
fServerMustSize = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pParam->SetInterpreterMustSize( FALSE );
|
|
|
|
if ( pParam->IsParamIn() )
|
|
ClientBufferSize += BufSize;
|
|
if ( pParam->IsParamOut() )
|
|
ServerBufferSize += BufSize;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pParam->IsParamIn() )
|
|
fClientMustSize = TRUE;
|
|
if ( pParam->IsParamOut() )
|
|
fServerMustSize = TRUE;
|
|
}
|
|
}
|
|
|
|
pCCB->SetCurrentParam( 0 );
|
|
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
|
|
}
|
|
|
|
//
|
|
// Generate the format string for the return type if needed.
|
|
//
|
|
if ( pProc->GetReturnType() )
|
|
{
|
|
CG_NDR * pChild;
|
|
CG_NDR * pOldPlaceholder;
|
|
|
|
pProc->GetReturnType()->SetParamNumber( ParamNum++ );
|
|
|
|
pChild = (CG_NDR *) pProc->GetReturnType()->GetChild();
|
|
|
|
pCCB->SetCurrentParam( pProc->GetReturnType() );
|
|
pOldPlaceholder = pCCB->SetLastPlaceholderClass( pProc->GetReturnType() );
|
|
|
|
ContinueGenerationInRoot( pChild );
|
|
|
|
BufSize = pChild->FixedBufferSize( pCCB );
|
|
|
|
if ( BufSize != -1 )
|
|
{
|
|
if ( (ServerBufferSize + BufSize) >= 65536 )
|
|
{
|
|
fServerMustSize = TRUE;
|
|
}
|
|
else
|
|
{
|
|
ServerBufferSize += BufSize;
|
|
pProc->GetReturnType()->SetInterpreterMustSize( FALSE );
|
|
}
|
|
}
|
|
else
|
|
fServerMustSize = TRUE;
|
|
|
|
pCCB->SetCurrentParam( 0 );
|
|
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
|
|
}
|
|
|
|
pCCB->SetCurrentParam( 0 );
|
|
|
|
//
|
|
// REVIEW: This routine really needs to be broken up a bit
|
|
//
|
|
|
|
// Figure out the handle type
|
|
|
|
if ( pProc->IsObject() )
|
|
format->Flags.HandleType = NDR64_FC_AUTO_HANDLE;
|
|
else if ( pCCB->IsInCallback() )
|
|
format->Flags.HandleType = NDR64_FC_CALLBACK_HANDLE;
|
|
else if ( HU_IMPLICIT != pProc->GetHandleUsage() )
|
|
format->Flags.HandleType = NDR64_FC_EXPLICIT_HANDLE;
|
|
else if ( pProc->IsAutoHandle() )
|
|
format->Flags.HandleType = NDR64_FC_AUTO_HANDLE;
|
|
else if ( pProc->IsPrimitiveHandle() )
|
|
format->Flags.HandleType = NDR64_FC_BIND_PRIMITIVE;
|
|
else if ( pProc->IsGenericHandle() )
|
|
format->Flags.HandleType = NDR64_FC_BIND_GENERIC;
|
|
|
|
// Set the proc flags
|
|
|
|
format->Flags.ProcType = 0; // REVIEW: ??
|
|
format->Flags.IsInterpreted = 1; // REVIEW: ??
|
|
format->Flags.IsObject = pProc->IsObject();
|
|
format->Flags.IsAsync = pProc->HasAsyncUUID(); // REVIEW: HasAsyncHandle?
|
|
format->Flags.IsEncode = pProc->HasEncode();
|
|
format->Flags.IsDecode = pProc->HasDecode();
|
|
format->Flags.UsesFullPtrPackage = pProc->HasFullPtr();
|
|
format->Flags.UsesRpcSmPackage = pProc->MustInvokeRpcSSAllocate();
|
|
format->Flags.HandlesExceptions = pProc->HasStatuses(); // REVIEW: ??
|
|
format->Flags.UsesPipes = pProc->HasPipes();
|
|
format->Flags.ServerMustSize = fServerMustSize;
|
|
format->Flags.ClientMustSize = fClientMustSize;
|
|
format->Flags.HasReturn = ( NULL != pProc->GetReturnType() );
|
|
format->Flags.HasComplexReturn = pProc->HasComplexReturnType();
|
|
format->Flags.ServerHasCorrelation = pProc->HasServerCorr();
|
|
format->Flags.ClientHasCorrelation = pProc->HasClientCorr();
|
|
format->Flags.HasNotify = pProc->HasNotify() || pProc->HasNotifyFlag();
|
|
format->Flags.HasOtherExtensions = 0; // Reset in GenExtendedProcInfo
|
|
format->Flags.Reserved = 0;
|
|
|
|
// Figure out the stack size. Note that stack size in the
|
|
// NDR64_PROC_FORMAT structure is meaningless outside of ndr since it is
|
|
// different for every processor
|
|
|
|
format->ia64StackSize = pProc->GetTotalStackSize( pCCB );
|
|
|
|
// Constant buffer sizes
|
|
|
|
format->ConstantClientBufferSize = ClientBufferSize;
|
|
format->ConstantServerBufferSize = ServerBufferSize;
|
|
|
|
|
|
// RpcFlags
|
|
//
|
|
// REVIEW: Async is not an operation type!
|
|
|
|
unsigned int opbits = pProc->GetOperationBits();
|
|
|
|
format->RpcFlags.Idempotent = (NDR64_UINT16) (opbits & OPERATION_IDEMPOTENT ? 1 : 0);
|
|
format->RpcFlags.Broadcast = (NDR64_UINT16) (opbits & OPERATION_BROADCAST ? 1 : 0);
|
|
format->RpcFlags.Maybe = (NDR64_UINT16) (opbits & OPERATION_MAYBE ? 1 : 0);
|
|
format->RpcFlags.Message = (NDR64_UINT16) (opbits & OPERATION_MESSAGE ? 1 : 0);
|
|
format->RpcFlags.InputSynchronous = (NDR64_UINT16) (opbits & OPERATION_INPUT_SYNC ? 1 : 0);
|
|
format->RpcFlags.Asynchronous = 0; // !!
|
|
format->RpcFlags.Reserved1 = 0;
|
|
format->RpcFlags.Reserved2 = 0;
|
|
format->RpcFlags.Reserved3 = 0;
|
|
|
|
// Miscellaneous
|
|
|
|
format->FloatDoubleMask = pProc->GetFloatArgMask( pCCB );
|
|
format->NumberOfParams = ParamNum;
|
|
format->ExtensionSize = 0; // Reset in GenExtendedProcInfo
|
|
|
|
// Generate the extended proc info if any
|
|
|
|
if ( format->Flags.HasNotify || pProc->GetHandleUsage() == HU_EXPLICIT )
|
|
GenExtendedProcInfo( composite );
|
|
|
|
// Now generate the parameter descriptors
|
|
|
|
ITERATOR_INIT( Iterator );
|
|
|
|
while ( ITERATOR_GETNEXT( Iterator, pParam ) )
|
|
ContinueGeneration( pParam, composite );
|
|
|
|
if ( pProc->HasReturn() )
|
|
ContinueGeneration( pProc->GetReturnType(), composite );
|
|
|
|
// REVIEW: Are procs optimized? If so be careful because the stack size
|
|
// field is set to 0 for all procs
|
|
// composite->OptimizeFragment( format );
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::GenExtendedProcInfo
|
|
//
|
|
// Synopsis: Generate info concerning explicit binding handles and
|
|
// [notify] procs.
|
|
//
|
|
// Parameters: [composite] -- The composite to add the info to
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::GenExtendedProcInfo( CompositeFormatFragment *composite )
|
|
{
|
|
// The proc info should be the first thing in the composite
|
|
MIDL_NDR64_PROC_FORMAT *procFormat;
|
|
CG_PROC *procCG;
|
|
MIDL_NDR64_BIND_AND_NOTIFY_EXTENSION *extension;
|
|
|
|
extension = new MIDL_NDR64_BIND_AND_NOTIFY_EXTENSION;
|
|
|
|
composite->AddFragment( extension );
|
|
|
|
procFormat = dynamic_cast<MIDL_NDR64_PROC_FORMAT *>(composite->GetFirstFragment());
|
|
MIDL_ASSERT( NULL != procFormat );
|
|
|
|
procCG = (CG_PROC *) procFormat->GetCGNode();
|
|
|
|
procFormat->Flags.HasOtherExtensions = 1; // REVIEW: ??
|
|
|
|
//
|
|
// explicit handles
|
|
//
|
|
|
|
if ( procCG->GetHandleUsage() == HU_EXPLICIT )
|
|
{
|
|
CG_HANDLE *pHandle = procCG->GetHandleClassPtr();
|
|
CG_PARAM *pParam = procCG->GetHandleUsagePtr();
|
|
CG_NDR *pOldPlaceholder;
|
|
|
|
pOldPlaceholder = pCCB->SetLastPlaceholderClass( pParam );
|
|
|
|
pHandle->GetNdrHandleInfo( pCCB, &extension->Binding );
|
|
pParam->GetStackOffsets( pCCB, &extension->StackOffsets );
|
|
|
|
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
|
|
}
|
|
else
|
|
{
|
|
// No explicit handle, zero out the handle info.
|
|
memset( &extension->Binding, 0, sizeof( extension->Binding ) );
|
|
memset( &extension->StackOffsets, 0, sizeof( extension->StackOffsets ) );
|
|
}
|
|
|
|
//
|
|
// [notify]
|
|
//
|
|
|
|
if ( procFormat->Flags.HasNotify )
|
|
extension->NotifyIndex = procCG->GetNotifyTableOffset( pCCB );
|
|
else
|
|
extension->NotifyIndex = 0;
|
|
|
|
// Update the extension size field.
|
|
|
|
procFormat->ExtensionSize = sizeof(NDR64_BIND_AND_NOTIFY_EXTENSION);
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::Visit( CG_POINTER )
|
|
//
|
|
// Synopsis: Generate info for simple pointer and add fragment to
|
|
// current composite fragment.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::Visit( CG_POINTER *pPointer )
|
|
{
|
|
MIDL_NDR64_POINTER_FORMAT *format;
|
|
|
|
format = new MIDL_NDR64_POINTER_FORMAT( pPointer );
|
|
|
|
// Get the type of the pointer (ref, etc) and any flags
|
|
|
|
pPointer->GetTypeAndFlags( pCCB, format );
|
|
|
|
CG_CLASS *pointee = pPointer->GetChild();
|
|
|
|
if ( format->Flags & FC_SIMPLE_POINTER )
|
|
{
|
|
|
|
// generic handles are represented as thier underlying type and
|
|
// otherwise pretty much ignored for our purposes.
|
|
|
|
if ( ID_CG_GENERIC_HDL == pointee->GetCGID() )
|
|
pointee = pointee->GetChild();
|
|
|
|
MIDL_ASSERT( NULL != dynamic_cast<CG_BASETYPE *> ( pointee ) );
|
|
|
|
}
|
|
|
|
GetCurrent()->AddFragment( format );
|
|
|
|
format->Reserved = 0;
|
|
|
|
format->Pointee = ContinueGenerationInRoot( pointee );
|
|
|
|
GetRoot()->OptimizeFragment( format );
|
|
}
|
|
|
|
|
|
MIDL_NDR64_POINTER_FORMAT* GenNdr64Format::GenQualifiedPtrHdr( CG_QUALIFIED_POINTER *pPointer )
|
|
{
|
|
MIDL_NDR64_POINTER_FORMAT* pHeader = new MIDL_NDR64_POINTER_FORMAT( pPointer );
|
|
pPointer->GetTypeAndFlags( pCCB, pHeader );
|
|
|
|
// Always use complex pointer struct
|
|
pHeader->Flags &= ~FC_SIMPLE_POINTER;
|
|
pHeader->Reserved = 0;
|
|
pHeader->Pointee = INVALID_FRAGMENT_ID;
|
|
|
|
return pHeader;
|
|
}
|
|
|
|
MIDL_NDR64_POINTER_FORMAT* GenNdr64Format::GenQualifiedArrayPtr( CG_ARRAY *pArray )
|
|
{
|
|
// Ref arrays do not need the pointer header.
|
|
if ( pArray->GetPtrType() == PTR_REF )
|
|
return NULL;
|
|
|
|
MIDL_NDR64_POINTER_FORMAT* pFragment = new MIDL_NDR64_POINTER_FORMAT( pArray );
|
|
switch ( pArray->GetPtrType() )
|
|
{
|
|
case PTR_UNKNOWN:
|
|
case PTR_REF:
|
|
MIDL_ASSERT(0);
|
|
break;
|
|
|
|
case PTR_UNIQUE:
|
|
pFragment->FormatCode = FC64_UP;
|
|
break;
|
|
|
|
case PTR_FULL:
|
|
pFragment->FormatCode = FC64_FP;
|
|
break;
|
|
|
|
default:
|
|
MIDL_ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
pFragment->Flags = 0;
|
|
pFragment->Reserved = 0;
|
|
|
|
return pFragment;
|
|
}
|
|
|
|
void GenNdr64Format::Visit( CG_STRING_POINTER *pPointer )
|
|
{
|
|
// REVIEW: This is essentially two routines distinguished by an if.
|
|
// Seperate them.
|
|
|
|
MIDL_NDR64_POINTER_FORMAT* pPointerHdr = GenQualifiedPtrHdr( pPointer );
|
|
GetCurrent()->AddFragment( pPointerHdr );
|
|
|
|
FormatFragment *pStringFrag = NULL;
|
|
|
|
if ( dynamic_cast<CG_SIZE_STRING_POINTER *>(pPointer) )
|
|
{
|
|
CG_CONF_ATTRIBUTE *pConfAttribute = dynamic_cast<CG_CONF_ATTRIBUTE*>( pPointer );
|
|
FormatFragment *pFrag = GenerateCorrelationDescriptor( pConfAttribute->GetSizeIsExpr() );
|
|
MIDL_NDR64_SIZED_CONFORMANT_STRING_FORMAT *pSizedConfFormat =
|
|
new MIDL_NDR64_SIZED_CONFORMANT_STRING_FORMAT( pPointer );
|
|
pStringFrag = pSizedConfFormat;
|
|
|
|
InitStringHeader( pPointer, &pSizedConfFormat->Header, true, true);
|
|
pSizedConfFormat->SizeDescription = (PNDR64_FORMAT)pFrag->GetRefID();
|
|
}
|
|
else
|
|
{
|
|
MIDL_NDR64_CONFORMANT_STRING_FORMAT *pConfFormat =
|
|
new MIDL_NDR64_CONFORMANT_STRING_FORMAT( pPointer );
|
|
pStringFrag = pConfFormat;
|
|
|
|
InitStringHeader( pPointer, &pConfFormat->Header, true, false);
|
|
}
|
|
GetRoot()->AddFragment( pStringFrag );
|
|
GetRoot()->OptimizeFragment( pStringFrag );
|
|
|
|
pPointerHdr->Pointee = pStringFrag->GetRefID();
|
|
|
|
GetRoot()->OptimizeFragment( pPointerHdr );
|
|
}
|
|
|
|
void GenNdr64Format::GenerateNonStringQualifiedPtr( CG_QUALIFIED_POINTER *pPointer )
|
|
{
|
|
MIDL_NDR64_POINTER_FORMAT *pPointerFrag = GenQualifiedPtrHdr( pPointer );
|
|
GetCurrent()->AddFragment( pPointerFrag );
|
|
|
|
FormatFragment *pArrayFrag = GenerateNonStringQualifiedArrayLayout( pPointer, GetRoot() );
|
|
pPointerFrag->Pointee = pArrayFrag->GetRefID();
|
|
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::GenInterfacePointer
|
|
//
|
|
// Synopsis: Generate info for interface pointers
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::GenInterfacePointer( CG_POINTER *pPointer, BOOL IsConstantIID )
|
|
{
|
|
MIDL_NDR64_POINTER_FORMAT *format;
|
|
|
|
format = new MIDL_NDR64_POINTER_FORMAT( pPointer );
|
|
|
|
// Generate the pointer node
|
|
|
|
pPointer->GetTypeAndFlags( pCCB, format );
|
|
|
|
format->FormatCode = FC64_IP; // GetTypeAndFlags doesn't emit FC64_IP
|
|
format->Reserved = 0;
|
|
|
|
GetCurrent()->AddFragment( format );
|
|
|
|
// generate the interface type node
|
|
|
|
if ( IsConstantIID )
|
|
{
|
|
|
|
CG_INTERFACE_POINTER *pInterface =
|
|
dynamic_cast<CG_INTERFACE_POINTER*>( pPointer );
|
|
|
|
MIDL_NDR64_CONSTANT_IID_FORMAT *iid;
|
|
|
|
iid = new MIDL_NDR64_CONSTANT_IID_FORMAT;
|
|
|
|
iid->FormatCode = FC64_IP;
|
|
iid->Flags.ConstantIID = 1;
|
|
iid->Flags.Reserved = 0;
|
|
iid->Reserved = 0;
|
|
|
|
node_guid * pGuid = (node_guid *) pInterface
|
|
->GetTheInterface()
|
|
->GetAttribute( ATTR_GUID );
|
|
|
|
pGuid->GetGuid( iid->Guid );
|
|
|
|
format->Pointee = GetRoot()->AddFragment( iid );
|
|
|
|
}
|
|
else
|
|
{
|
|
CG_IIDIS_INTERFACE_POINTER *piidInterface =
|
|
dynamic_cast<CG_IIDIS_INTERFACE_POINTER*>( pPointer );
|
|
|
|
FormatFragment *pIIDExpr = GenerateCorrelationDescriptor( piidInterface->GetIIDExpr() );
|
|
MIDL_NDR64_IID_FORMAT *iid = new MIDL_NDR64_IID_FORMAT;
|
|
|
|
iid->FormatCode = FC64_IP;
|
|
iid->Flags.ConstantIID = 0;
|
|
iid->Flags.Reserved = 0;
|
|
iid->Reserved = 0;
|
|
iid->IIDDescriptor = pIIDExpr->GetRefID();
|
|
|
|
format->Pointee = GetRoot()->AddFragment( iid );
|
|
}
|
|
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::Visit( CG_UNION )
|
|
//
|
|
// Synopsis: Generate info for unions
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::Visit( CG_UNION *pUnion )
|
|
{
|
|
|
|
// A union is represented in the format info by a composite containing
|
|
// the union header follow by fragments representing the arm selector
|
|
|
|
CompositeFormatFragment *composite = new CompositeFormatFragment( pUnion );
|
|
|
|
GetCurrent()->AddFragment( composite );
|
|
|
|
MIDL_NDR64_NON_ENCAPSULATED_UNION *format;
|
|
|
|
format = new MIDL_NDR64_NON_ENCAPSULATED_UNION( pUnion );
|
|
|
|
composite->AddFragment( format );
|
|
|
|
MIDL_ASSERT( dynamic_cast<CG_BASETYPE *> (pUnion->GetSwitchType()) );
|
|
|
|
NDR64_FORMAT_CHAR SwitchType = (NDR64_FORMAT_CHAR)
|
|
( (CG_BASETYPE *) pUnion->GetSwitchType() )
|
|
->GetNDR64SignedFormatChar();
|
|
|
|
// The alignment of a union is the max of the type alignment and the arm alignment.
|
|
unsigned short UnionArmAlignment = pUnion->GetWireAlignment();
|
|
unsigned short SwitchTypeAlignment =
|
|
( (CG_BASETYPE*) pUnion->GetSwitchType() )->GetWireAlignment() ;
|
|
unsigned short UnionAlignment = UnionArmAlignment > SwitchTypeAlignment ?
|
|
UnionArmAlignment : SwitchTypeAlignment;
|
|
|
|
format->FormatCode = FC64_NON_ENCAPSULATED_UNION;
|
|
format->Alignment = ConvertAlignment( UnionAlignment );
|
|
format->Flags = 0;
|
|
format->SwitchType = SwitchType;
|
|
format->MemorySize = pUnion->GetMemorySize();
|
|
format->Reserved = 0;
|
|
|
|
expr_node *pSwitchExpr = pUnion->GetNdr64SwitchIsExpr();
|
|
|
|
FormatFragment* pSwitchFormat = GenerateCorrelationDescriptor( pSwitchExpr );
|
|
format->Switch = (PNDR64_FORMAT)pSwitchFormat->GetRefID();
|
|
|
|
GenerateUnionArmSelector( pUnion, composite );
|
|
|
|
GetRoot()->OptimizeFragment( composite );
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::Visit( CG_CONTEXT_HANDLE )
|
|
//
|
|
// Synopsis: Generate info for context handles
|
|
//
|
|
// Notes: This is an an abreviated version of the same information in
|
|
// the proc descriptor.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::Visit( CG_CONTEXT_HANDLE *pHandle )
|
|
{
|
|
CG_PARAM * pBindParam = (CG_PARAM *) pCCB->GetLastPlaceholderClass();
|
|
CG_PROC * pProc = (CG_PROC *) pCCB->GetCGNodeContext();
|
|
|
|
MIDL_NDR64_CONTEXT_HANDLE_FORMAT *format;
|
|
|
|
format = new MIDL_NDR64_CONTEXT_HANDLE_FORMAT( pHandle );
|
|
|
|
format->FormatCode = FC64_BIND_CONTEXT;
|
|
|
|
//
|
|
// Register the rundown routine always, even if the context handle is
|
|
// not used as the binding paramter.
|
|
//
|
|
if ( pHandle->GetHandleType()->NodeKind() == NODE_DEF )
|
|
{
|
|
pCCB->RegisterContextHandleType( pHandle->GetHandleType() );
|
|
}
|
|
|
|
// Flags
|
|
|
|
unsigned char uFlags = pHandle->MakeExplicitHandleFlag( pBindParam );
|
|
|
|
format->ContextFlags.CannotBeNull = pHandle->GetCannotBeNull()
|
|
|| pBindParam->IsParamIn()
|
|
&& !pBindParam->IsParamOut();
|
|
|
|
format->ContextFlags.Serialize = (NDR64_UINT8) ( pHandle->HasSerialize() ? 1 : 0 );
|
|
format->ContextFlags.NoSerialize = (NDR64_UINT8) ( pHandle->HasNoSerialize() ? 1 : 0 );
|
|
format->ContextFlags.Strict = (NDR64_UINT8) ( pHandle->HasStrict() ? 1 : 0 );
|
|
format->ContextFlags.IsReturn = (NDR64_UINT8) ( ( uFlags & HANDLE_PARAM_IS_RETURN ) ? 1 : 0 );
|
|
format->ContextFlags.IsOut = (NDR64_UINT8) ( ( uFlags & HANDLE_PARAM_IS_OUT ) ? 1 : 0 );
|
|
format->ContextFlags.IsIn = (NDR64_UINT8) ( ( uFlags & HANDLE_PARAM_IS_IN ) ? 1 : 0 );
|
|
format->ContextFlags.IsViaPointer = (NDR64_UINT8) ( ( uFlags & HANDLE_PARAM_IS_VIA_PTR ) ? 1 : 0 );
|
|
|
|
// Routine index.
|
|
// IndexMgr keeps indexes 1..n, we use indexes 0..n-1
|
|
|
|
format->RundownRoutineIndex = (NDR64_UINT8)
|
|
( pCCB->LookupRundownRoutine( pHandle->GetRundownRtnName() ) - 1);
|
|
|
|
// Ordinal
|
|
|
|
format->Ordinal = (NDR64_UINT8) pProc->GetContextHandleCount();
|
|
pProc->SetContextHandleCount( (short) (format->Ordinal + 1) );
|
|
|
|
GetCurrent()->AddFragment( format );
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::Visit( CG_GENERIC_HANDLE )
|
|
//
|
|
// Synopsis: Generate info for generic handles
|
|
//
|
|
// Notes: Actually generic handles are represented by thier underlying
|
|
// type, not by any special "generic handle" type. Therefore
|
|
// there's nothing to generate. We do need a place to
|
|
// register the handle though.
|
|
//
|
|
// Review: Since we're not generating perhaps registering is better
|
|
// placed in some other phase?
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::Visit( CG_GENERIC_HANDLE *pHandle )
|
|
{
|
|
ContinueGenerationInRoot( pHandle->GetChild() );
|
|
|
|
MIDL_ASSERT( pCCB->GetCGNodeContext()->IsProc() );
|
|
|
|
CG_HANDLE *pBindingHandle = ((CG_PROC *)pCCB->GetCGNodeContext())
|
|
->GetHandleClassPtr();
|
|
|
|
if ( pBindingHandle == pHandle )
|
|
pCCB->RegisterGenericHandleType( pHandle->GetHandleType() );
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Pointer Layout Functions
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::GenSimplePtrLayout( CG_STRUCT, bool, ulong *)
|
|
//
|
|
// Synopsis: Generate a pointer layout for a block copyable structure.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
FormatFragment * GenNdr64Format::GenSimplePtrLayout( CG_STRUCT *pStruct,
|
|
bool bGenHeaderFooter,
|
|
ulong *pPtrInstances )
|
|
{
|
|
CompositeFormatFragment *pCompositeFormatFragment = NULL;
|
|
CCB *pCCB = GetCCB();
|
|
ulong NumberPointerInstances = 0;
|
|
|
|
CG_FIELD *pOldRegionField = NULL;
|
|
CG_NDR *pOldContext = NULL;
|
|
|
|
if ( dynamic_cast<CG_REGION*>( pStruct ) )
|
|
pOldRegionField = pCCB->StartRegion();
|
|
else
|
|
pOldContext = pCCB->SetCGNodeContext( pStruct );
|
|
|
|
CG_ITERATOR Iterator;
|
|
pStruct->GetMembers( Iterator );
|
|
|
|
CG_FIELD *pField;
|
|
ITERATOR_INIT( Iterator );
|
|
|
|
while ( ITERATOR_GETNEXT( Iterator, pField ) )
|
|
{
|
|
|
|
CG_NDR * pOldPlaceHolder = pCCB->SetLastPlaceholderClass( pField );
|
|
|
|
CG_CLASS *pMember = (CG_NDR *) pField->GetChild();
|
|
|
|
MIDL_ASSERT( !pMember->IsStruct() ); // Structure should have been unrolled.
|
|
|
|
if ( pMember->IsPointer() )
|
|
{
|
|
|
|
if ( NULL == pCompositeFormatFragment )
|
|
pCompositeFormatFragment = new CompositeFormatFragment();
|
|
|
|
if ( bGenHeaderFooter )
|
|
pCompositeFormatFragment->AddFragment(
|
|
new MIDL_NDR64_NO_REPEAT_FORMAT() );
|
|
|
|
pCompositeFormatFragment->AddFragment(
|
|
new MIDL_NDR64_POINTER_INSTANCE_HEADER_FORMAT( pField->GetMemOffset() ) );
|
|
|
|
ContinueGeneration( pMember, pCompositeFormatFragment );
|
|
|
|
NumberPointerInstances++;
|
|
}
|
|
|
|
// For now, arrays do not have pointers.
|
|
|
|
else if ( pMember->IsArray() )
|
|
{
|
|
FormatFragment *pPointerFragment = GenSimplePtrLayout( dynamic_cast<CG_ARRAY*>( pMember ),
|
|
false,
|
|
pField->GetMemOffset() );
|
|
|
|
if ( NULL != pPointerFragment )
|
|
{
|
|
|
|
if ( NULL == pCompositeFormatFragment )
|
|
pCompositeFormatFragment = new CompositeFormatFragment();
|
|
|
|
pCompositeFormatFragment->AddFragment( pPointerFragment );
|
|
|
|
}
|
|
}
|
|
|
|
pCCB->SetLastPlaceholderClass( pOldPlaceHolder );
|
|
}
|
|
|
|
if ( ( NULL != pCompositeFormatFragment ) &&
|
|
bGenHeaderFooter )
|
|
{
|
|
FormatFragment *pFormatFragment = new MIDL_NDR64_FORMAT_CHAR( FC64_END );
|
|
pCompositeFormatFragment->AddFragment( pFormatFragment );
|
|
}
|
|
|
|
if ( NULL != pPtrInstances )
|
|
{
|
|
*pPtrInstances = NumberPointerInstances;
|
|
}
|
|
|
|
if ( dynamic_cast<CG_REGION*>( pStruct ) )
|
|
pCCB->EndRegion( pOldRegionField );
|
|
else
|
|
pCCB->SetCGNodeContext( pOldContext );
|
|
|
|
return pCompositeFormatFragment;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::GenSimplePtrLayout( CG_ARRAY, bool, ulong *)
|
|
//
|
|
// Synopsis: Generate a pointer layout for a block copyable structure.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
FormatFragment * GenNdr64Format::GenSimplePtrLayout( CG_NDR *pArray,
|
|
bool bGenHeaderFooter,
|
|
ulong MemoryOffset )
|
|
{
|
|
|
|
CompositeFormatFragment *pArrayLayout = NULL;
|
|
CG_CLASS *pChild = pArray->GetChild();
|
|
FormatFragment* pChildLayout = NULL;
|
|
unsigned long NumberPointers = 0;
|
|
|
|
// Multidimensional arrays should be bogus
|
|
MIDL_ASSERT( !pChild->IsArray() );
|
|
|
|
if ( pChild->IsPointer() )
|
|
{
|
|
|
|
CompositeFormatFragment *pCompositeFormatFragment =
|
|
new CompositeFormatFragment();
|
|
|
|
pCompositeFormatFragment->AddFragment(
|
|
new MIDL_NDR64_POINTER_INSTANCE_HEADER_FORMAT( 0 ) );
|
|
|
|
ContinueGeneration( pChild, pCompositeFormatFragment );
|
|
|
|
pChildLayout = pCompositeFormatFragment;
|
|
NumberPointers = 1;
|
|
}
|
|
|
|
else if ( pChild->IsStruct() )
|
|
{
|
|
pChildLayout = GenSimplePtrLayout( dynamic_cast< CG_STRUCT *>( pChild ),
|
|
false,
|
|
&NumberPointers );
|
|
}
|
|
|
|
if ( pChildLayout )
|
|
{
|
|
|
|
pArrayLayout = new CompositeFormatFragment();
|
|
FormatFragment *pHeader;
|
|
|
|
if ( dynamic_cast<CG_FIXED_ARRAY*>( pArray ) )
|
|
{
|
|
|
|
CG_FIXED_ARRAY *pFixedArray = (CG_FIXED_ARRAY*)( pArray );
|
|
pHeader = new MIDL_NDR64_FIXED_REPEAT_FORMAT( dynamic_cast<CG_NDR*>( pChild )->GetMemorySize(),
|
|
MemoryOffset,
|
|
NumberPointers,
|
|
pFixedArray->GetNumOfElements(),
|
|
dynamic_cast<CG_NDR*>( pChild )->IsStruct() );
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
pHeader = new MIDL_NDR64_REPEAT_FORMAT( dynamic_cast<CG_NDR*>( pChild )->GetMemorySize(),
|
|
MemoryOffset,
|
|
NumberPointers,
|
|
dynamic_cast< CG_NDR* >( pChild )->IsStruct() );
|
|
}
|
|
|
|
pArrayLayout->AddFragment( pHeader );
|
|
pArrayLayout->AddFragment( pChildLayout );
|
|
|
|
if ( bGenHeaderFooter )
|
|
{
|
|
pArrayLayout->AddFragment( new MIDL_NDR64_FORMAT_CHAR( FC64_END ) );
|
|
}
|
|
|
|
}
|
|
|
|
return pArrayLayout;
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
// Structure layout
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::GenCmplxPtrLayout( CG_COMPLEX_STRUCT )
|
|
//
|
|
// Synopsis: Generate a pointer layout for a complex structure.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
FormatFragment * GenNdr64Format::GenCmplxPtrLayout( CG_COMPLEX_STRUCT *pStruct )
|
|
{
|
|
CompositeFormatFragment *pCompositeFormatFragment = NULL;
|
|
CCB *pCCB = GetCCB();
|
|
|
|
CG_ITERATOR Iterator;
|
|
pStruct->GetMembers( Iterator );
|
|
|
|
CG_FIELD *pField;
|
|
ITERATOR_INIT( Iterator );
|
|
|
|
while ( ITERATOR_GETNEXT( Iterator, pField ) )
|
|
{
|
|
|
|
CG_NDR * pOldPlaceHolder = pCCB->SetLastPlaceholderClass( pField );
|
|
|
|
CG_CLASS *pMember = (CG_NDR *) pField->GetChild();
|
|
|
|
if ( pMember->IsPointer() )
|
|
{
|
|
|
|
if (NULL == pCompositeFormatFragment)
|
|
pCompositeFormatFragment = new CompositeFormatFragment();
|
|
|
|
ContinueGeneration( pMember, pCompositeFormatFragment );
|
|
|
|
}
|
|
|
|
pCCB->SetLastPlaceholderClass( pOldPlaceHolder );
|
|
}
|
|
|
|
return pCompositeFormatFragment;
|
|
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::GenerateSimpleStructure( CG_STRUCT, bool )
|
|
//
|
|
// Synopsis: Generate the format string for a simple structure.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::GenerateSimpleStructure( CG_STRUCT *pStruct,
|
|
bool IsConformant )
|
|
{
|
|
// Add the fragment right away so recursive structure definitions
|
|
// are caught
|
|
|
|
CompositeFormatFragment *pMainFragment
|
|
= new CompositeFormatFragment( pStruct );
|
|
GetCurrent()->AddFragment( pMainFragment );
|
|
|
|
CG_FIELD *pOldRegionField = NULL;
|
|
CG_NDR *pOldContext = NULL;
|
|
|
|
if ( dynamic_cast<CG_REGION*>( pStruct ) )
|
|
pOldRegionField = pCCB->StartRegion();
|
|
else
|
|
pOldContext = pCCB->SetCGNodeContext( pStruct );
|
|
|
|
FormatFragment* pMemberLayout = NULL;
|
|
FormatFragment* pPointerLayout = GenSimplePtrLayout( pStruct );
|
|
|
|
if ( pCommand->NeedsNDR64DebugInfo() )
|
|
pMemberLayout = GenerateStructureMemberLayout( pStruct, true );
|
|
|
|
if ( IsConformant )
|
|
{
|
|
CG_CONFORMANT_STRUCT *pConfStruct = dynamic_cast<CG_CONFORMANT_STRUCT*>( pStruct );
|
|
CG_FIELD *pConfField = dynamic_cast<CG_FIELD*>( pConfStruct->GetConformantField() );
|
|
MIDL_ASSERT( NULL != pConfField );
|
|
CG_ARRAY *pConfArray = dynamic_cast<CG_ARRAY*>( pConfField->GetChild() );
|
|
MIDL_ASSERT( NULL != pConfArray );
|
|
|
|
CG_NDR * pOldPlaceholder = GetCCB()->SetLastPlaceholderClass( pConfField );
|
|
|
|
FormatFragment *pHeader =
|
|
new MIDL_NDR64_CONF_STRUCTURE_HEADER_FORMAT( pConfStruct,
|
|
NULL != pPointerLayout,
|
|
NULL != pMemberLayout,
|
|
ContinueGenerationInRoot( pConfArray ) );
|
|
|
|
pMainFragment->AddFragment( pHeader );
|
|
|
|
GetCCB()->SetLastPlaceholderClass( pOldPlaceholder );
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
FormatFragment *pHeader =
|
|
new MIDL_NDR64_STRUCTURE_HEADER_FORMAT( pStruct,
|
|
NULL != pPointerLayout,
|
|
NULL != pMemberLayout );
|
|
|
|
pMainFragment->AddFragment( pHeader );
|
|
|
|
}
|
|
|
|
if ( NULL != pPointerLayout ) pMainFragment->AddFragment( pPointerLayout );
|
|
if ( NULL != pMemberLayout ) pMainFragment->AddFragment( pMemberLayout );
|
|
|
|
if ( dynamic_cast<CG_REGION*>( pStruct ) )
|
|
pCCB->EndRegion( pOldRegionField );
|
|
else
|
|
pCCB->SetCGNodeContext( pOldContext );
|
|
|
|
GetRoot()->OptimizeFragment( pMainFragment );
|
|
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::GenerateComplexStruct( CG_STRUCT, bool )
|
|
//
|
|
// Synopsis: Generate the format string for a complex structure.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::GenerateComplexStruct( CG_COMPLEX_STRUCT *pStruct,
|
|
bool IsConformant )
|
|
{
|
|
|
|
if ( GetCurrent()->HasClassFragment( pStruct ) )
|
|
return;
|
|
|
|
// This must be done first to handle recurion.
|
|
CompositeFormatFragment *pMainFragment =
|
|
new CompositeFormatFragment( pStruct );
|
|
GetCurrent()->AddFragment( pMainFragment );
|
|
|
|
CG_NDR *pOldContext = pCCB->SetCGNodeContext( pStruct );
|
|
|
|
FormatInfoRef ArrayID = INVALID_FRAGMENT_ID;
|
|
CG_ARRAY *pConfArray = NULL;
|
|
|
|
if ( IsConformant )
|
|
{
|
|
CG_FIELD *pConfField = dynamic_cast<CG_FIELD*>( pStruct->GetConformantField() );
|
|
MIDL_ASSERT( NULL != pConfField );
|
|
pConfArray = dynamic_cast<CG_ARRAY*>( pConfField->GetChild() );
|
|
MIDL_ASSERT( NULL != pConfArray );
|
|
|
|
CG_NDR * pOldPlaceholder = GetCCB()->SetLastPlaceholderClass( pConfField );
|
|
ArrayID = ContinueGenerationInRoot( pConfArray );
|
|
GetCCB()->SetLastPlaceholderClass( pOldPlaceholder );
|
|
|
|
}
|
|
|
|
FormatInfoRef PointerID = INVALID_FRAGMENT_ID;
|
|
FormatFragment *pPointerLayout = GenCmplxPtrLayout( pStruct );
|
|
if ( NULL != pPointerLayout )
|
|
{
|
|
// Pointer Layout for complex struct goes in the root fragment.
|
|
PointerID = GetRoot()->AddFragment( pPointerLayout );
|
|
}
|
|
|
|
FormatFragment* pMemberLayout = GenerateStructureMemberLayout( pStruct, false );
|
|
|
|
// The only difference between the member layout with debugging
|
|
// and without debugging is that simple region become complex regions
|
|
// with member layouts.
|
|
FormatInfoRef DebugPointerID = INVALID_FRAGMENT_ID;
|
|
FormatInfoRef DebugMemberLayoutID = INVALID_FRAGMENT_ID;
|
|
if ( pCommand->NeedsNDR64DebugInfo() )
|
|
{
|
|
|
|
DebugPointerID = PointerID;
|
|
FormatFragment *pDebugMemberLayout = GenerateStructureMemberLayout( pStruct, true );
|
|
|
|
DebugMemberLayoutID = GetRoot()->AddFragment( pDebugMemberLayout );
|
|
}
|
|
|
|
|
|
FormatFragment* pHeader;
|
|
|
|
if ( IsConformant )
|
|
{
|
|
MIDL_ASSERT( NULL != pConfArray );
|
|
pHeader = new MIDL_NDR64_CONF_BOGUS_STRUCTURE_HEADER_FORMAT( pStruct,
|
|
pConfArray,
|
|
ArrayID,
|
|
DebugMemberLayoutID,
|
|
DebugPointerID,
|
|
PointerID );
|
|
}
|
|
else
|
|
{
|
|
pHeader = new MIDL_NDR64_BOGUS_STRUCTURE_HEADER_FORMAT( pStruct,
|
|
DebugMemberLayoutID,
|
|
DebugPointerID,
|
|
PointerID );
|
|
}
|
|
|
|
pMainFragment->AddFragment( pHeader );
|
|
pMainFragment->AddFragment( pMemberLayout );
|
|
|
|
pCCB->SetCGNodeContext( pOldContext );
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Class: StructureMemberGenerator
|
|
//
|
|
// Synopsis: This object is responsible for generating the member layout
|
|
// of a structure.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
class StructureMemberGenerator
|
|
{
|
|
private:
|
|
GenNdr64Format *pMainGenerator;
|
|
CompositeFormatFragment *pCompositeFormatFragment;
|
|
CG_VISITOR *pVisitor;
|
|
bool bIsDebug;
|
|
|
|
void StartGeneration( CG_STRUCT *pStruct );
|
|
void GenerateMember( CG_CLASS *pClass )
|
|
{
|
|
pClass->Visit( pVisitor );
|
|
}
|
|
|
|
public:
|
|
|
|
static FormatFragment* Generate( GenNdr64Format *pMainGenerator,
|
|
CG_STRUCT *pStruct,
|
|
bool bIsDebug )
|
|
{
|
|
CG_VISITOR_TEMPLATE<StructureMemberGenerator> TemplateVisitor;
|
|
StructureMemberGenerator & Visitor = TemplateVisitor;
|
|
|
|
Visitor.pMainGenerator = pMainGenerator;
|
|
Visitor.pCompositeFormatFragment = new CompositeFormatFragment();
|
|
Visitor.pVisitor = &TemplateVisitor;
|
|
Visitor.bIsDebug = bIsDebug;
|
|
|
|
Visitor.StartGeneration( pStruct );
|
|
|
|
return Visitor.pCompositeFormatFragment;
|
|
}
|
|
|
|
// Items that get a unique member layout item.
|
|
void Visit( CG_POINTER *pPointer)
|
|
{
|
|
pPointer;
|
|
FormatFragment *pFormatFragment = new MIDL_NDR64_SIMPLE_MEMBER_FORMAT( FC64_POINTER );
|
|
pCompositeFormatFragment->AddFragment( pFormatFragment );
|
|
}
|
|
|
|
void Visit( CG_IGNORED_POINTER *pPointer )
|
|
{
|
|
pPointer;
|
|
FormatFragment *pFormatFragment = new MIDL_NDR64_SIMPLE_MEMBER_FORMAT( FC64_IGNORE );
|
|
pCompositeFormatFragment->AddFragment( pFormatFragment );
|
|
}
|
|
|
|
void Visit( CG_BASETYPE *pBaseType )
|
|
{
|
|
if ( pBaseType->GetRangeAttribute() != NULL )
|
|
{
|
|
// Send to generic catch all case(Embedded complex)
|
|
Visit( (CG_CLASS*) pBaseType );
|
|
return;
|
|
}
|
|
NDR64_FORMAT_CHAR FormatCode = (NDR64_FORMAT_CHAR)pBaseType->GetNDR64FormatChar();
|
|
FormatFragment *pFormatFragment = new MIDL_NDR64_SIMPLE_MEMBER_FORMAT( FormatCode );
|
|
pCompositeFormatFragment->AddFragment( pFormatFragment );
|
|
}
|
|
|
|
void Visit( CG_SIMPLE_REGION *pSimpleRegion )
|
|
{
|
|
|
|
// If this member layout is for debugging, send this
|
|
// to the CG_CLASS visit function to create an
|
|
// embedded complex.
|
|
if ( bIsDebug )
|
|
{
|
|
Visit( (CG_CLASS*)pSimpleRegion );
|
|
return;
|
|
}
|
|
|
|
FormatFragment *pFormatFragment =
|
|
new MIDL_NDR64_SIMPLE_REGION_FORMAT( pSimpleRegion );
|
|
pCompositeFormatFragment->AddFragment( pFormatFragment );
|
|
}
|
|
|
|
void Visit( CG_PAD *pPad )
|
|
{
|
|
FormatFragment *pFormatFragment
|
|
= new MIDL_NDR64_BUFFER_ALIGN_FORMAT( pPad );
|
|
pCompositeFormatFragment->AddFragment( pFormatFragment );
|
|
}
|
|
|
|
// Do nothing for conformant arrays. They must be at the end.
|
|
void Visit( CG_CONFORMANT_ARRAY *pConfArray ) { pConfArray; }
|
|
void Visit( CG_CONFORMANT_VARYING_ARRAY *pConfVaryArray ) { pConfVaryArray; }
|
|
void Visit( CG_CONFORMANT_STRING_ARRAY *pConfStringArray ) { pConfStringArray; }
|
|
|
|
// Catch all case. Generates embedded complex
|
|
void Visit( CG_CLASS *pClass )
|
|
{
|
|
FormatInfoRef ID = pMainGenerator->ContinueGenerationInRoot( pClass );
|
|
FormatFragment *pFormatFragment = new MIDL_NDR64_EMBEDDED_COMPLEX_FORMAT( ID );
|
|
pCompositeFormatFragment->AddFragment( pFormatFragment );
|
|
}
|
|
};
|
|
|
|
void StructureMemberGenerator::StartGeneration( CG_STRUCT *pStruct )
|
|
{
|
|
CCB *pCCB = pMainGenerator->GetCCB();
|
|
CG_NDR * pOldPlaceholder = pCCB->GetLastPlaceholderClass();
|
|
|
|
CG_ITERATOR Iterator;
|
|
pStruct->GetMembers( Iterator );
|
|
|
|
CG_FIELD * pField;
|
|
unsigned long BufferOffset = 0;
|
|
|
|
ITERATOR_INIT( Iterator );
|
|
while( ITERATOR_GETNEXT( Iterator, pField ) )
|
|
{
|
|
|
|
//FormatFragment *FormatFragment = NULL;
|
|
unsigned long MemPad = pField->GetMemOffset() - BufferOffset;
|
|
|
|
if ( MemPad != 0 )
|
|
{
|
|
|
|
MIDL_NDR64_MEMPAD_FORMAT *pMemPadFormat =
|
|
new MIDL_NDR64_MEMPAD_FORMAT( MemPad );
|
|
pCompositeFormatFragment->AddFragment( pMemPadFormat );
|
|
}
|
|
|
|
BufferOffset += MemPad;
|
|
|
|
pCCB->SetLastPlaceholderClass( pField );
|
|
|
|
CG_NDR *pMember = (CG_NDR *) pField->GetChild();
|
|
|
|
// Embedded unknown represent as is not allowed.
|
|
MIDL_ASSERT( ! pField->HasEmbeddedUnknownRepAs() );
|
|
|
|
GenerateMember( pMember );
|
|
|
|
BufferOffset += pField->GetMemorySize();
|
|
|
|
}
|
|
|
|
// Account for padding at the end of the structure.
|
|
|
|
MIDL_ASSERT( pStruct->GetMemorySize() >= BufferOffset );
|
|
|
|
unsigned long EndingPad = pStruct->GetMemorySize() - BufferOffset;
|
|
|
|
|
|
if ( EndingPad )
|
|
{
|
|
MIDL_NDR64_MEMPAD_FORMAT *pMemPadFormat =
|
|
new MIDL_NDR64_MEMPAD_FORMAT( EndingPad );
|
|
pCompositeFormatFragment->AddFragment( pMemPadFormat );
|
|
}
|
|
|
|
FormatFragment* pEndFormatFragment = new MIDL_NDR64_SIMPLE_MEMBER_FORMAT( FC64_END );
|
|
pCompositeFormatFragment->AddFragment( pEndFormatFragment );
|
|
|
|
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
|
|
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::GenerateStructureMemberLayout( CG_STRUCT, bool )
|
|
//
|
|
// Synopsis: Wrapper for the member layout generator
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
FormatFragment *GenNdr64Format::GenerateStructureMemberLayout( CG_STRUCT *pStruct, bool bIsDebug )
|
|
{
|
|
return StructureMemberGenerator::Generate( this, pStruct, bIsDebug );
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
// Arrays
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
FormatFragment *GenNdr64Format::GenerateArrayElementInfo( CG_CLASS *pChild )
|
|
{
|
|
CG_NDR *pNdr = dynamic_cast<CG_NDR*>( pChild );
|
|
MIDL_ASSERT( NULL != pNdr );
|
|
|
|
MIDL_NDR64_ARRAY_ELEMENT_INFO *pElementInfo =
|
|
new MIDL_NDR64_ARRAY_ELEMENT_INFO();
|
|
|
|
pElementInfo->ElementMemSize = pNdr->GetMemorySize();
|
|
pElementInfo->Element = (PNDR64_FORMAT)ContinueGenerationInRoot( pNdr );
|
|
|
|
return pElementInfo;
|
|
}
|
|
|
|
void GenNdr64Format::Visit( CG_FIXED_ARRAY *pArray )
|
|
{
|
|
CompositeFormatFragment *pMainFragment = new CompositeFormatFragment( pArray );
|
|
GetCurrent()->AddFragment( pMainFragment );
|
|
|
|
FormatFragment *pMemberInfo = NULL;
|
|
FormatFragment *pPointerLayout = GenSimplePtrLayout( pArray );
|
|
|
|
if ( pCommand->NeedsNDR64DebugInfo() )
|
|
pMemberInfo = GenerateArrayElementInfo( pArray->GetChild() );
|
|
|
|
MIDL_NDR64_FIX_ARRAY_HEADER_FORMAT *pArrayFormat =
|
|
new MIDL_NDR64_FIX_ARRAY_HEADER_FORMAT( pArray );
|
|
|
|
memset( (NDR64_FIX_ARRAY_HEADER_FORMAT*)pArrayFormat,
|
|
0,
|
|
sizeof(NDR64_FIX_ARRAY_HEADER_FORMAT*));
|
|
|
|
pArrayFormat->FormatCode = (NDR64_FORMAT_CHAR) FC64_FIX_ARRAY;
|
|
pArrayFormat->Alignment = ConvertAlignment( pArray->GetWireAlignment() );
|
|
|
|
pArrayFormat->Flags.HasPointerInfo = (NULL != pPointerLayout);
|
|
pArrayFormat->Flags.HasElementInfo = (NULL != pMemberInfo );;
|
|
|
|
pArrayFormat->Reserved = 0;
|
|
pArrayFormat->TotalSize = pArray->GetMemorySize();
|
|
|
|
pMainFragment->AddFragment( pArrayFormat );
|
|
|
|
if ( pPointerLayout )
|
|
pMainFragment->AddFragment( pPointerLayout );
|
|
|
|
if ( pMemberInfo )
|
|
pMainFragment->AddFragment( pMemberInfo );
|
|
}
|
|
|
|
void GenNdr64Format::GenerateFixBogusArrayCommon( CG_FIXED_ARRAY *pArray, bool IsFullBogus )
|
|
{
|
|
CompositeFormatFragment *pMainFragment = new CompositeFormatFragment( pArray );
|
|
GetCurrent()->AddFragment( pMainFragment );
|
|
|
|
CG_ILANALYSIS_INFO *pAnalysisInfo = pArray->GetILAnalysisInfo();
|
|
|
|
|
|
MIDL_NDR64_BOGUS_ARRAY_HEADER_FORMAT *pHeaderFragment =
|
|
new MIDL_NDR64_BOGUS_ARRAY_HEADER_FORMAT( pArray );
|
|
|
|
memset( (NDR64_BOGUS_ARRAY_HEADER_FORMAT*)pHeaderFragment,
|
|
0,
|
|
sizeof(NDR64_BOGUS_ARRAY_HEADER_FORMAT));
|
|
|
|
pHeaderFragment->FormatCode = (NDR64_FORMAT_CHAR)
|
|
( IsFullBogus ? FC64_FIX_BOGUS_ARRAY :
|
|
FC64_FIX_FORCED_BOGUS_ARRAY );
|
|
|
|
pHeaderFragment->Alignment = ConvertAlignment( ((CG_NDR*)pArray->GetChild())
|
|
->GetWireAlignment() );
|
|
pHeaderFragment->Flags.HasPointerInfo = false;
|
|
pHeaderFragment->Flags.HasElementInfo = true;
|
|
pHeaderFragment->Flags.IsArrayofStrings = pAnalysisInfo->IsArrayofStrings();
|
|
pHeaderFragment->Flags.IsMultiDimensional = pAnalysisInfo->IsMultiDimensional();
|
|
|
|
pHeaderFragment->NumberDims = pAnalysisInfo->GetDimensions();
|
|
pHeaderFragment->NumberElements = pArray->GetNumOfElements();
|
|
pHeaderFragment->Element = (PNDR64_FORMAT)
|
|
ContinueGenerationInRoot( pArray->GetChild() );
|
|
|
|
pMainFragment->AddFragment( pHeaderFragment );
|
|
|
|
}
|
|
|
|
FormatFragment *
|
|
GenNdr64Format::GenerateNonStringQualifiedArrayLayout( CG_NDR *pNdr,
|
|
CompositeFormatFragment *pComp )
|
|
{
|
|
CompositeFormatFragment *pMainFragment = new CompositeFormatFragment( pNdr );
|
|
pComp->AddFragment( pMainFragment );
|
|
|
|
FormatFragment *pHeaderFragment;
|
|
FormatFragment *pPointerLayout = NULL;
|
|
FormatFragment *pMemberInfo = NULL;
|
|
|
|
CG_ILANALYSIS_INFO *pAnalysisInfo = pNdr->GetILAnalysisInfo();
|
|
|
|
FormatInfoRef SizeIsDescriptor = INVALID_FRAGMENT_ID;
|
|
FormatInfoRef OffsetOfDescriptor = INVALID_FRAGMENT_ID;
|
|
FormatInfoRef LengthIsDescriptor = INVALID_FRAGMENT_ID;
|
|
|
|
if ( pAnalysisInfo->IsConformant() )
|
|
{
|
|
CG_CONF_ATTRIBUTE *pConfAttribute = dynamic_cast<CG_CONF_ATTRIBUTE*>( pNdr );
|
|
expr_node *pSizeIs = pConfAttribute->GetSizeIsExpr();
|
|
if ( pSizeIs != NULL )
|
|
{
|
|
FormatFragment *pSizeIsFrag = GenerateCorrelationDescriptor( pSizeIs );
|
|
SizeIsDescriptor = pSizeIsFrag->GetRefID();
|
|
}
|
|
|
|
}
|
|
if ( pAnalysisInfo->IsVarying() )
|
|
{
|
|
CG_VARY_ATTRIBUTE *pVaryAttribute = dynamic_cast<CG_VARY_ATTRIBUTE*>( pNdr );
|
|
expr_node *pLengthIs = pVaryAttribute->GetLengthIsExpr();
|
|
if ( pLengthIs != NULL )
|
|
{
|
|
FormatFragment *pLengthIsFrag = GenerateCorrelationDescriptor( pLengthIs );
|
|
LengthIsDescriptor = pLengthIsFrag->GetRefID();
|
|
}
|
|
|
|
expr_node *pFirstIs = pVaryAttribute->GetFirstIsExpr();
|
|
if ( pFirstIs != NULL )
|
|
{
|
|
FormatFragment *pOffsetOfFrag = GenerateCorrelationDescriptor( pFirstIs );
|
|
OffsetOfDescriptor = pOffsetOfFrag->GetRefID();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if ( pAnalysisInfo->IsFullBogus() || pAnalysisInfo->IsForcedBogus() )
|
|
{
|
|
// treat like a bogus array
|
|
|
|
MIDL_NDR64_CONF_VAR_BOGUS_ARRAY_HEADER_FORMAT *pArrayHeader =
|
|
new MIDL_NDR64_CONF_VAR_BOGUS_ARRAY_HEADER_FORMAT( pNdr );
|
|
NDR64_BOGUS_ARRAY_HEADER_FORMAT *pFixedArrayHeader = &pArrayHeader->FixedArrayFormat;
|
|
pHeaderFragment = pArrayHeader;
|
|
|
|
bool bIsFullBogus = pAnalysisInfo->IsFullBogus();
|
|
|
|
NDR64_UINT32 NumberElements = 0;
|
|
CG_CONF_ATTRIBUTE *pConfAttribute = dynamic_cast<CG_CONF_ATTRIBUTE *>( pNdr );
|
|
|
|
if ( !pAnalysisInfo->IsConformant() &&
|
|
pConfAttribute &&
|
|
pConfAttribute->GetSizeIsExpr() &&
|
|
pConfAttribute->GetSizeIsExpr()->IsConstant() )
|
|
{
|
|
NumberElements = (NDR64_UINT32)pConfAttribute->GetSizeIsExpr()->GetValue();
|
|
}
|
|
|
|
CG_NDR *pChildNdr = dynamic_cast<CG_NDR*>( pNdr->GetChild() );
|
|
memset( (NDR64_CONF_VAR_BOGUS_ARRAY_HEADER_FORMAT*)pArrayHeader,
|
|
0,
|
|
sizeof(NDR64_CONF_VAR_BOGUS_ARRAY_HEADER_FORMAT));
|
|
|
|
pFixedArrayHeader->FormatCode = (NDR64_FORMAT_CHAR)
|
|
( bIsFullBogus ? FC64_BOGUS_ARRAY :
|
|
FC64_FORCED_BOGUS_ARRAY );
|
|
pFixedArrayHeader->Alignment = ConvertAlignment( pChildNdr->GetWireAlignment() );
|
|
|
|
pFixedArrayHeader->Flags.HasPointerInfo = false;
|
|
pFixedArrayHeader->Flags.HasElementInfo = true;
|
|
pFixedArrayHeader->Flags.IsArrayofStrings = pAnalysisInfo->IsArrayofStrings();
|
|
pFixedArrayHeader->Flags.IsMultiDimensional = pAnalysisInfo->IsMultiDimensional();
|
|
|
|
pFixedArrayHeader->NumberDims = pAnalysisInfo->GetDimensions();
|
|
|
|
pFixedArrayHeader->NumberElements = NumberElements;
|
|
|
|
pFixedArrayHeader->Element = (PNDR64_FORMAT)
|
|
ContinueGenerationInRoot( pChildNdr );
|
|
|
|
pArrayHeader->ConfDescription = (PNDR64_FORMAT)SizeIsDescriptor;
|
|
pArrayHeader->VarDescription = (PNDR64_FORMAT)LengthIsDescriptor;
|
|
pArrayHeader->OffsetDescription = (PNDR64_FORMAT)OffsetOfDescriptor;
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
pPointerLayout = GenSimplePtrLayout( pNdr );
|
|
|
|
if ( pCommand->NeedsNDR64DebugInfo() )
|
|
pMemberInfo = GenerateArrayElementInfo( pNdr->GetChild() );
|
|
|
|
if ( !pAnalysisInfo->IsConformant() &&
|
|
pAnalysisInfo->IsVarying() )
|
|
{
|
|
|
|
MIDL_NDR64_VAR_ARRAY_HEADER_FORMAT *pArrayHeader =
|
|
new MIDL_NDR64_VAR_ARRAY_HEADER_FORMAT( pNdr );
|
|
pHeaderFragment = pArrayHeader;
|
|
|
|
CG_NDR *pChildNdr = dynamic_cast<CG_NDR*>(pNdr->GetChild());
|
|
|
|
memset( (NDR64_VAR_ARRAY_HEADER_FORMAT*)pArrayHeader,
|
|
0,
|
|
sizeof(NDR64_VAR_ARRAY_HEADER_FORMAT));
|
|
|
|
pArrayHeader->FormatCode = (NDR64_FORMAT_CHAR) FC64_VAR_ARRAY;
|
|
pArrayHeader->Alignment = ConvertAlignment( pChildNdr->GetWireAlignment() );
|
|
|
|
pArrayHeader->Flags.HasPointerInfo = ( NULL != pPointerLayout );
|
|
pArrayHeader->Flags.HasElementInfo = ( NULL != pMemberInfo );
|
|
|
|
pArrayHeader->Reserved = 0;
|
|
pArrayHeader->TotalSize = pNdr->GetMemorySize();
|
|
pArrayHeader->ElementSize = pChildNdr->GetMemorySize();
|
|
|
|
pArrayHeader->VarDescriptor = (PNDR64_FORMAT)LengthIsDescriptor;
|
|
|
|
pMemberInfo = GenerateArrayElementInfo( pNdr->GetChild() );
|
|
}
|
|
else if ( pAnalysisInfo->IsConformant() &&
|
|
!pAnalysisInfo->IsVarying() )
|
|
{
|
|
|
|
MIDL_NDR64_CONF_ARRAY_HEADER_FORMAT *pArrayHeader =
|
|
new MIDL_NDR64_CONF_ARRAY_HEADER_FORMAT( pNdr );
|
|
pHeaderFragment = pArrayHeader;
|
|
|
|
CG_NDR *pChildNdr = dynamic_cast<CG_NDR*>(pNdr->GetChild());
|
|
|
|
memset( (NDR64_CONF_ARRAY_HEADER_FORMAT*)pArrayHeader,
|
|
0,
|
|
sizeof(NDR64_CONF_ARRAY_HEADER_FORMAT));
|
|
|
|
pArrayHeader->FormatCode = (NDR64_FORMAT_CHAR) FC64_CONF_ARRAY;
|
|
pArrayHeader->Alignment = ConvertAlignment( pChildNdr->GetWireAlignment() );
|
|
|
|
pArrayHeader->Flags.HasPointerInfo = (NULL != pPointerLayout);
|
|
pArrayHeader->Flags.HasElementInfo = (NULL != pMemberInfo);
|
|
|
|
pArrayHeader->Reserved = 0;
|
|
pArrayHeader->ElementSize = pChildNdr->GetMemorySize();
|
|
|
|
pArrayHeader->ConfDescriptor = (PNDR64_FORMAT)SizeIsDescriptor;
|
|
|
|
pMemberInfo = GenerateArrayElementInfo( pNdr->GetChild() );
|
|
|
|
}
|
|
else if ( pAnalysisInfo->IsConformant() &&
|
|
pAnalysisInfo->IsVarying() )
|
|
{
|
|
|
|
MIDL_NDR64_CONF_VAR_ARRAY_HEADER_FORMAT *pArrayHeader =
|
|
new MIDL_NDR64_CONF_VAR_ARRAY_HEADER_FORMAT( pNdr );
|
|
pHeaderFragment = pArrayHeader;
|
|
|
|
CG_NDR *pChildNdr = dynamic_cast<CG_NDR*>(pNdr->GetChild());
|
|
|
|
memset( (NDR64_CONF_VAR_ARRAY_HEADER_FORMAT*)pArrayHeader,
|
|
0,
|
|
sizeof(NDR64_CONF_VAR_ARRAY_HEADER_FORMAT));
|
|
|
|
pArrayHeader->FormatCode = (NDR64_FORMAT_CHAR) FC64_CONFVAR_ARRAY;
|
|
pArrayHeader->Alignment = ConvertAlignment( pChildNdr->GetWireAlignment() );
|
|
|
|
pArrayHeader->Flags.HasPointerInfo = (NULL != pPointerLayout);
|
|
pArrayHeader->Flags.HasElementInfo = (NULL != pMemberInfo);
|
|
|
|
pArrayHeader->Reserved = 0;
|
|
pArrayHeader->ElementSize = pChildNdr->GetMemorySize();
|
|
|
|
pArrayHeader->ConfDescriptor = (PNDR64_FORMAT)SizeIsDescriptor;
|
|
pArrayHeader->VarDescriptor = (PNDR64_FORMAT)LengthIsDescriptor;
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
// !pAnalysisInfo->IsConformant && !pAnalysisInfo->IsVarying
|
|
MIDL_ASSERT(0);
|
|
pHeaderFragment = NULL;
|
|
}
|
|
}
|
|
|
|
pMainFragment->AddFragment( pHeaderFragment );
|
|
if ( pPointerLayout )
|
|
pMainFragment->AddFragment( pPointerLayout );
|
|
if ( pMemberInfo )
|
|
pMainFragment->AddFragment( pMemberInfo );
|
|
|
|
return pMainFragment;
|
|
}
|
|
|
|
void GenNdr64Format::GenerateNonStringQualifiedArray( CG_ARRAY *pArray )
|
|
{
|
|
CompositeFormatFragment *pContainer;
|
|
MIDL_NDR64_POINTER_FORMAT* pPointerHdr = GenQualifiedArrayPtr( pArray );
|
|
if ( pPointerHdr != NULL)
|
|
{
|
|
GetCurrent()->AddFragment( pPointerHdr );
|
|
pContainer = GetRoot();
|
|
}
|
|
else
|
|
pContainer = GetCurrent();
|
|
|
|
FormatFragment *pArrayFragment =
|
|
GenerateNonStringQualifiedArrayLayout( pArray, pContainer );
|
|
|
|
if ( NULL != pPointerHdr )
|
|
{
|
|
pPointerHdr->Pointee = pArrayFragment->GetRefID();
|
|
}
|
|
|
|
}
|
|
|
|
void GenNdr64Format::InitStringHeader( CG_NDR *pString,
|
|
NDR64_STRING_HEADER_FORMAT *pHeader,
|
|
bool bIsConformant,
|
|
bool bIsSized )
|
|
{
|
|
NDR64_FORMAT_CHAR FormatCode;
|
|
CG_BASETYPE *pBT = dynamic_cast<CG_BASETYPE*>( pString->GetChild() );
|
|
|
|
if ( NULL != pBT )
|
|
{
|
|
|
|
switch( pBT->GetType()->GetBasicType()->NodeKind() )
|
|
{
|
|
case NODE_BYTE:
|
|
case NODE_CHAR:
|
|
FormatCode = (NDR64_FORMAT_CHAR)
|
|
( bIsConformant ? FC64_CONF_CHAR_STRING : FC64_CHAR_STRING );
|
|
break;
|
|
case NODE_WCHAR_T:
|
|
FormatCode = (NDR64_FORMAT_CHAR)
|
|
( bIsConformant ? FC64_CONF_WCHAR_STRING : FC64_WCHAR_STRING );
|
|
break;
|
|
default:
|
|
FormatCode = (NDR64_FORMAT_CHAR)
|
|
( bIsConformant ? FC64_CONF_STRUCT_STRING : FC64_STRUCT_STRING );
|
|
break;
|
|
}
|
|
|
|
}
|
|
else
|
|
FormatCode = (NDR64_FORMAT_CHAR)
|
|
( bIsConformant ? FC64_CONF_STRUCT_STRING : FC64_STRUCT_STRING );
|
|
|
|
CG_NDR *pChildNdr = dynamic_cast<CG_NDR*>( pString->GetChild() );
|
|
MIDL_ASSERT( pChildNdr->GetMemorySize() <= 0xFFFF );
|
|
NDR64_UINT16 ElementSize = (NDR64_UINT16)pChildNdr->GetMemorySize();
|
|
|
|
MIDL_ASSERT( (FC64_CHAR_STRING == FormatCode) ? (1 == ElementSize) : 1 );
|
|
MIDL_ASSERT( (FC64_WCHAR_STRING == FormatCode) ? (2 == ElementSize) : 1 );
|
|
|
|
memset( pHeader, 0, sizeof(NDR64_STRING_HEADER_FORMAT));
|
|
|
|
pHeader->FormatCode = FormatCode;
|
|
pHeader->Flags.IsSized = bIsSized;
|
|
pHeader->ElementSize = ElementSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GenNdr64Format::GenerateStringArray( CG_ARRAY *pArray,
|
|
bool bIsSized )
|
|
{
|
|
MIDL_NDR64_POINTER_FORMAT* pPointerHdr = GenQualifiedArrayPtr( pArray );
|
|
if ( pPointerHdr != NULL)
|
|
GetCurrent()->AddFragment( pPointerHdr );
|
|
|
|
FormatFragment *pStringFrag = NULL;
|
|
|
|
if ( bIsSized )
|
|
{
|
|
CG_CONF_ATTRIBUTE *pConfAttribute = dynamic_cast<CG_CONF_ATTRIBUTE*>( pArray );
|
|
expr_node *pSizeIs = pConfAttribute->GetSizeIsExpr();
|
|
|
|
if ( NULL != pSizeIs )
|
|
{
|
|
FormatFragment *pFrag = GenerateCorrelationDescriptor( pConfAttribute->GetSizeIsExpr() );
|
|
|
|
MIDL_NDR64_SIZED_CONFORMANT_STRING_FORMAT *pSizedConfFormat =
|
|
new MIDL_NDR64_SIZED_CONFORMANT_STRING_FORMAT( pArray );
|
|
pStringFrag = pSizedConfFormat;
|
|
|
|
InitStringHeader( pArray, &pSizedConfFormat->Header, true, true);
|
|
pSizedConfFormat->SizeDescription = (PNDR64_FORMAT)pFrag->GetRefID();
|
|
}
|
|
else
|
|
{
|
|
MIDL_NDR64_CONFORMANT_STRING_FORMAT *pConfFormat =
|
|
new MIDL_NDR64_CONFORMANT_STRING_FORMAT( pArray );
|
|
pStringFrag = pConfFormat;
|
|
|
|
InitStringHeader( pArray, &pConfFormat->Header, true, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MIDL_NDR64_NON_CONFORMANT_STRING_FORMAT *pNonConfFormat =
|
|
new MIDL_NDR64_NON_CONFORMANT_STRING_FORMAT( pArray );
|
|
pStringFrag = pNonConfFormat;
|
|
|
|
InitStringHeader( pArray, &pNonConfFormat->Header, false, false);
|
|
pNonConfFormat->TotalSize = pArray->GetMemorySize();
|
|
}
|
|
|
|
if ( NULL != pPointerHdr )
|
|
{
|
|
GetRoot()->AddFragment( pStringFrag );
|
|
pPointerHdr->Pointee = pStringFrag->GetRefID();
|
|
}
|
|
else
|
|
{
|
|
GetCurrent()->AddFragment( pStringFrag );
|
|
}
|
|
}
|
|
|
|
class ExpressionGenerator
|
|
{
|
|
public:
|
|
static CompositeFormatFragment *
|
|
Generate( CCB * pCCB,
|
|
expr_node * pSizeExpr
|
|
);
|
|
|
|
private:
|
|
static void
|
|
GenExprPadIfNecessary(
|
|
CompositeFormatFragment * FragmentList,
|
|
ulong * pExprLength,
|
|
ulong Align );
|
|
|
|
static FormatFragment *
|
|
GenExprConstant(
|
|
NDR64_FORMAT_CHARACTER fc,
|
|
EXPR_VALUE lValue,
|
|
CompositeFormatFragment * FragmentList,
|
|
ulong * pExprLength );
|
|
static BOOL
|
|
IsConstantExpr (expr_node * pExpr );
|
|
|
|
static NDR64_FORMAT_CHARACTER
|
|
GetTypeForExpression( node_skl *pType );
|
|
|
|
static FormatFragment *
|
|
GenExprFormatString(
|
|
CCB *pCCB,
|
|
expr_node *pSizeExpr,
|
|
CompositeFormatFragment *FragmentList,
|
|
BOOL * pIsEarly,
|
|
ulong * pExprLength );
|
|
|
|
static CG_FIELD*
|
|
FindField(
|
|
node_skl * pFieldType,
|
|
CG_STRUCT *pStruct,
|
|
const char *pPrintPrefix,
|
|
unsigned long *pMemOffset );
|
|
|
|
static void
|
|
ComputeFieldCorrelationOffset(
|
|
CCB *pCCB,
|
|
node_skl *pFieldType,
|
|
// return parameters
|
|
CG_FIELD **ppVariableField, // var in expression
|
|
long *pOffset,
|
|
BOOL *pIsEarly );
|
|
};
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::GenerateCorrelationDescriptor
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
FormatFragment*
|
|
GenNdr64Format::GenerateCorrelationDescriptor( expr_node *pExpr )
|
|
{
|
|
MIDL_ASSERT(NULL != pExpr);
|
|
|
|
FormatFragment *pCorrelationDescriptor =
|
|
ExpressionGenerator::Generate( pCCB, pExpr );
|
|
|
|
GetRoot()->AddFragment( pCorrelationDescriptor );
|
|
GetRoot()->OptimizeFragment( pCorrelationDescriptor );
|
|
|
|
return pCorrelationDescriptor;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: Generate
|
|
//
|
|
// Synopsis: generate correlation expression.
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
CompositeFormatFragment *
|
|
ExpressionGenerator::Generate( CCB * pCCB,
|
|
expr_node * pSizeExpr
|
|
)
|
|
{
|
|
|
|
if ( NULL == pSizeExpr )
|
|
return NULL ;
|
|
|
|
#if defined(DBG)
|
|
|
|
CG_CLASS *pAttributedNode = pCCB->GetLastPlaceholderClass( );
|
|
|
|
MIDL_ASSERT( ( NULL != dynamic_cast<CG_PARAM*>( pAttributedNode ) ) ||
|
|
( NULL != dynamic_cast<CG_FIELD*>( pAttributedNode ) ) );
|
|
|
|
#endif
|
|
|
|
BOOL IsEarly = FALSE;
|
|
CompositeFormatFragment * pExprComposite = new CompositeFormatFragment;
|
|
MIDL_NDR_FORMAT_UINT32 * pFlag = new MIDL_NDR_FORMAT_UINT32;
|
|
ulong ulExprLength = 0;
|
|
|
|
// correlation flags. 4 bytes.
|
|
pExprComposite->AddFragment( pFlag );
|
|
ulExprLength = sizeof( NDR64_UINT32 );
|
|
|
|
// recursive code to generate the expression stack.
|
|
GenExprFormatString( pCCB, pSizeExpr, pExprComposite, &IsEarly, &ulExprLength );
|
|
|
|
pFlag->Data = 0;
|
|
if ( IsEarly )
|
|
pFlag->Data |= FC_NDR64_EARLY_CORRELATION;
|
|
|
|
return pExprComposite;
|
|
}
|
|
|
|
void
|
|
ExpressionGenerator::GenExprPadIfNecessary(
|
|
CompositeFormatFragment * FragmentList,
|
|
ulong * pExprLength,
|
|
ulong Align )
|
|
{
|
|
MIDL_NDR64_EXPR_NOOP * pExprPad = NULL;
|
|
if ( *pExprLength & ( Align - 1 ) )
|
|
{
|
|
// need to add padding to align next element
|
|
pExprPad = new MIDL_NDR64_EXPR_NOOP;
|
|
pExprPad->Size = (NDR64_UINT8) ( ( Align - 1 ) & *pExprLength );
|
|
FragmentList->AddFragment( pExprPad );
|
|
*pExprLength += sizeof( NDR64_EXPR_NOOP );
|
|
}
|
|
else
|
|
return;
|
|
}
|
|
|
|
FormatFragment *
|
|
ExpressionGenerator::GenExprConstant(
|
|
NDR64_FORMAT_CHARACTER fc,
|
|
EXPR_VALUE lValue,
|
|
CompositeFormatFragment * FragmentList,
|
|
ulong * pExprLength )
|
|
{
|
|
if ( fc == FC64_INT64 )
|
|
{
|
|
MIDL_NDR64_EXPR_CONST64 * pFormat;
|
|
|
|
pFormat = new MIDL_NDR64_EXPR_CONST64;
|
|
pFormat->ConstValue = lValue;
|
|
GenExprPadIfNecessary( FragmentList, pExprLength, 8 );
|
|
FragmentList->AddFragment( pFormat );
|
|
*pExprLength += sizeof( NDR64_EXPR_CONST64 );
|
|
return pFormat;
|
|
}
|
|
else
|
|
{
|
|
MIDL_NDR64_EXPR_CONST32 *pFormat;
|
|
|
|
pFormat = new MIDL_NDR64_EXPR_CONST32;
|
|
pFormat->ConstValue = (NDR64_UINT32) lValue;
|
|
GenExprPadIfNecessary( FragmentList, pExprLength, 4 );
|
|
FragmentList->AddFragment( pFormat );
|
|
*pExprLength += sizeof( NDR64_EXPR_CONST64 );
|
|
return pFormat;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// check if the expression (including all sub expressions ) is a constant expression
|
|
BOOL
|
|
ExpressionGenerator::IsConstantExpr (expr_node * pExpr )
|
|
{
|
|
if ( pExpr->IsConstant() )
|
|
return TRUE;
|
|
|
|
if ( pExpr->IsAVariable() )
|
|
return FALSE;
|
|
|
|
|
|
if ( pExpr->IsBinaryOperator() )
|
|
{
|
|
return IsConstantExpr( ((expr_op_binary *)pExpr)->GetLeft() ) &&
|
|
IsConstantExpr( ((expr_op_binary *)pExpr)->GetRight() );
|
|
}
|
|
else
|
|
{
|
|
if ( pExpr->IsUnaryOperator() )
|
|
{
|
|
return IsConstantExpr( ((expr_op_unary *)pExpr)->GetLeft() );
|
|
}
|
|
else
|
|
{
|
|
MIDL_ASSERT( pExpr->IsRelationalOperator() );
|
|
return IsConstantExpr( ((expr_ternary *)pExpr)->GetLeft() ) &&
|
|
IsConstantExpr( ((expr_ternary *)pExpr)->GetRight() ) &&
|
|
IsConstantExpr( ((expr_ternary *)pExpr)->GetRelational() ) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
NDR64_FORMAT_CHARACTER
|
|
ExpressionGenerator::GetTypeForExpression(
|
|
node_skl *pType
|
|
)
|
|
{
|
|
|
|
|
|
// Get the size of the type.
|
|
unsigned long Size = pType->GetSize();
|
|
|
|
// determine if the type is signed or unsigned.
|
|
bool IsSigned = true;
|
|
node_base_type *pBaseType = dynamic_cast<node_base_type*>( pType->GetBasicType() );
|
|
|
|
if ( pBaseType )
|
|
{
|
|
IsSigned = !pBaseType->IsUnsigned();
|
|
}
|
|
|
|
switch ( Size )
|
|
{
|
|
case 1:
|
|
return IsSigned ? FC64_INT8 : FC64_UINT8;
|
|
case 2:
|
|
return IsSigned ? FC64_INT16 : FC64_UINT16;
|
|
case 4:
|
|
return IsSigned ? FC64_INT32 : FC64_UINT32;
|
|
case 8:
|
|
return IsSigned ? FC64_INT64 : FC64_UINT64;
|
|
default:
|
|
RpcError( NULL, 0, EXPR_NOT_EVALUATABLE, pType->GetSymName() );
|
|
return FC64_ZERO; // Keep the compiler happy
|
|
}
|
|
}
|
|
|
|
FormatFragment *
|
|
ExpressionGenerator::GenExprFormatString(
|
|
CCB *pCCB,
|
|
expr_node *pSizeExpr,
|
|
CompositeFormatFragment *FragmentList,
|
|
BOOL * pIsEarly,
|
|
ulong * pExprLength )
|
|
{
|
|
node_skl * pAttributeNodeType;
|
|
EXPR_TOKEN Op;
|
|
long Offset;
|
|
|
|
CG_PARAM * pParam = NULL;
|
|
CG_NDR * pSwitchNode = NULL;
|
|
|
|
// BUGBUG: how to generate 32bit constant?
|
|
if ( IsConstantExpr( pSizeExpr ) )
|
|
{
|
|
|
|
// Constant expressions are always early!
|
|
*pIsEarly = TRUE;
|
|
|
|
return GenExprConstant( FC64_INT64, pSizeExpr->GetValue(), FragmentList, pExprLength );
|
|
|
|
}
|
|
|
|
if ( pSizeExpr->IsAVariable() )
|
|
// variable
|
|
{
|
|
Op = FC_EXPR_VAR;
|
|
MIDL_NDR64_EXPR_VAR * pFormat;
|
|
|
|
CG_NDR * pNdr = pCCB->GetCGNodeContext();
|
|
CG_ITERATOR Iterator;
|
|
|
|
pAttributeNodeType = pSizeExpr->GetType();
|
|
|
|
if ( pNdr->IsProc() )
|
|
// top level param
|
|
{
|
|
CG_PARAM* pCurrentParam = (CG_PARAM*) pCCB->GetCurrentParam();
|
|
CG_PROC* pCurrentProc = (CG_PROC*) pNdr;
|
|
|
|
*pIsEarly = TRUE;
|
|
|
|
if ( ( (node_param *) pAttributeNodeType )->IsSaveForAsyncFinish() &&
|
|
pCurrentProc->IsFinishProc() )
|
|
{
|
|
|
|
// This is an async split where the finish proc is using
|
|
// a param from the begin proc. Since the parameter
|
|
// was stored on the split stack, the expression will
|
|
// always be early correlation. So all that is needed
|
|
// here is to find the parameter in the begin proc.
|
|
|
|
CG_PROC* pBeginProc = pCurrentProc->GetAsyncRelative();
|
|
pBeginProc->GetMembers( Iterator );
|
|
|
|
for (;;)
|
|
{
|
|
if (!ITERATOR_GETNEXT( Iterator, pParam ))
|
|
{
|
|
// Didn't find the parameter. We are in trouble!
|
|
MIDL_ASSERT(0);
|
|
return NULL;
|
|
}
|
|
|
|
if ( pParam->GetType() == pAttributeNodeType )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
// Typical case of correlation in the same parameter.
|
|
|
|
pCurrentProc->GetMembers( Iterator);
|
|
|
|
if ( pCurrentParam->GetType() == pAttributeNodeType )
|
|
*pIsEarly = FALSE;
|
|
|
|
for(;;)
|
|
{
|
|
|
|
if (!ITERATOR_GETNEXT( Iterator, pParam ))
|
|
{
|
|
// Didn't find the parameter. We are in trouble!
|
|
MIDL_ASSERT(0);
|
|
return NULL;
|
|
}
|
|
|
|
// If we find the current parameter before the variable,
|
|
// parameter, then late correlation is needed.
|
|
if ( pParam == pCurrentParam )
|
|
*pIsEarly = FALSE;
|
|
|
|
if ( pParam->GetType() == pAttributeNodeType )
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
pSwitchNode = (CG_NDR *) pParam->GetChild();
|
|
|
|
}
|
|
else
|
|
// structure /union etc.
|
|
{
|
|
CG_FIELD *pSwitchField;
|
|
ComputeFieldCorrelationOffset( pCCB,
|
|
pAttributeNodeType,
|
|
// return parameters
|
|
&pSwitchField,
|
|
&Offset,
|
|
pIsEarly );
|
|
pSwitchNode = (CG_NDR*)pSwitchField->GetChild();
|
|
}
|
|
|
|
// Code the type of the size_is etc. expression.
|
|
|
|
NDR64_FORMAT_CHARACTER Type = GetTypeForExpression( pSwitchNode->GetType() );
|
|
|
|
pAttributeNodeType = pSizeExpr->GetType();
|
|
|
|
pFormat = new MIDL_NDR64_EXPR_VAR;
|
|
|
|
pFormat->ExprType = FC_EXPR_VAR;
|
|
pFormat->VarType = (NDR64_UINT8)Type;
|
|
|
|
if ( pNdr->IsProc() )
|
|
{
|
|
CG_NDR* pOld = 0;
|
|
BOOL IsFinish = FALSE;
|
|
MIDL_NDR64_EXPR_OPERATOR * pAsyncOp;
|
|
if ( ( (node_param *) pAttributeNodeType )->IsSaveForAsyncFinish() )
|
|
{
|
|
pAsyncOp = new MIDL_NDR64_EXPR_OPERATOR;
|
|
if ( ( (CG_PROC *)pNdr )->IsFinishProc() )
|
|
{
|
|
pOld = pCCB->SetCGNodeContext( ( (CG_PROC *)pNdr )->GetAsyncRelative() );
|
|
IsFinish = TRUE;
|
|
}
|
|
|
|
pAsyncOp->ExprType = (NDR64_FORMAT_CHAR) FC_EXPR_OPER;
|
|
pAsyncOp->Operator = (NDR64_FORMAT_CHAR) OP_ASYNCSPLIT;
|
|
FragmentList->AddFragment( pAsyncOp );
|
|
*pExprLength += sizeof( NDR64_EXPR_OPERATOR );
|
|
}
|
|
pFormat->fStackOffset = TRUE;
|
|
pFormat->ia64Offset = pParam->GetStackOffset( pCCB, I386_STACK_SIZING );
|
|
|
|
if ( IsFinish )
|
|
pCCB->SetCGNodeContext( pOld );
|
|
}
|
|
else
|
|
{
|
|
// Structure
|
|
pFormat->fStackOffset = FALSE;
|
|
pFormat->Offset = Offset;
|
|
}
|
|
|
|
GenExprPadIfNecessary( FragmentList, pExprLength, 4 );
|
|
FragmentList->AddFragment( pFormat );
|
|
*pExprLength += sizeof( NDR64_EXPR_VAR );
|
|
|
|
return pFormat;
|
|
|
|
}
|
|
else
|
|
// operator
|
|
{
|
|
expr_node * pLeftExpr = NULL;
|
|
BOOL bLeftExprIsEarly = TRUE;
|
|
|
|
expr_node * pRightExpr = NULL;
|
|
BOOL bRightExprIsEarly = TRUE;
|
|
|
|
expr_node * pRationalExpr = NULL;
|
|
BOOL bRationalExprIsEarly = TRUE;
|
|
|
|
MIDL_NDR64_EXPR_OPERATOR *pFormat;
|
|
NDR64_FORMAT_CHARACTER fcKind = (NDR64_FORMAT_CHARACTER)0;
|
|
|
|
OPERATOR Operator ;
|
|
|
|
if ( pSizeExpr->IsBinaryOperator() )
|
|
{
|
|
Operator = ((expr_op_binary *)pSizeExpr)->GetOperator();
|
|
pLeftExpr = ((expr_op_binary *)pSizeExpr)->GetLeft();
|
|
pRightExpr = ((expr_op_binary *)pSizeExpr)->GetRight();
|
|
}
|
|
else
|
|
{
|
|
if ( pSizeExpr->IsUnaryOperator() )
|
|
{
|
|
Operator = ((expr_op_unary *)pSizeExpr)->GetOperator();
|
|
pLeftExpr = ((expr_op_unary *)pSizeExpr)->GetLeft();
|
|
}
|
|
else
|
|
{
|
|
Operator = ((expr_ternary *)pSizeExpr)->GetOperator();
|
|
pLeftExpr = ((expr_ternary *)pSizeExpr)->GetLeft();
|
|
pRightExpr = ((expr_ternary *)pSizeExpr)->GetRight();
|
|
pRationalExpr = ((expr_ternary *)pSizeExpr)->GetRelational();
|
|
}
|
|
}
|
|
|
|
switch ( Operator )
|
|
{
|
|
case OP_UNARY_SIZEOF:
|
|
EXPR_VALUE lSize;
|
|
lSize = pSizeExpr->GetType()->GetSize();
|
|
|
|
*pIsEarly = TRUE;
|
|
|
|
return GenExprConstant( FC64_INT8, lSize, FragmentList, pExprLength);
|
|
|
|
case OP_UNARY_CAST:
|
|
case OP_UNARY_INDIRECTION:
|
|
fcKind = GetTypeForExpression( pSizeExpr->GetType() );
|
|
break;
|
|
}
|
|
|
|
pFormat = new MIDL_NDR64_EXPR_OPERATOR;
|
|
|
|
pFormat->ExprType = (NDR64_FORMAT_CHAR) FC_EXPR_OPER;
|
|
pFormat->Operator = (NDR64_FORMAT_CHAR) Operator;
|
|
// This was initially 0
|
|
pFormat->CastType = (NDR64_FORMAT_CHAR) fcKind;
|
|
|
|
FragmentList->AddFragment( pFormat );
|
|
*pExprLength += sizeof( NDR64_EXPR_OPERATOR );
|
|
|
|
GenExprFormatString( pCCB, pLeftExpr, FragmentList, &bLeftExprIsEarly, pExprLength );
|
|
|
|
if ( pRightExpr )
|
|
GenExprFormatString( pCCB, pRightExpr, FragmentList, &bRightExprIsEarly, pExprLength );
|
|
if ( pRationalExpr )
|
|
GenExprFormatString( pCCB, pRationalExpr, FragmentList, &bRationalExprIsEarly, pExprLength );
|
|
|
|
//
|
|
// An operator is early if and only if all the arguments to the
|
|
// operator are early.
|
|
//
|
|
|
|
*pIsEarly = bLeftExprIsEarly && bRightExprIsEarly && bRationalExprIsEarly;
|
|
|
|
return pFormat;
|
|
}
|
|
}
|
|
|
|
|
|
CG_FIELD*
|
|
ExpressionGenerator::FindField(
|
|
node_skl * pFieldType,
|
|
CG_STRUCT *pStruct,
|
|
const char *pPrintPrefix,
|
|
unsigned long *pMemOffset )
|
|
{
|
|
CG_ITERATOR Iterator;
|
|
|
|
pStruct->GetMembers( Iterator );
|
|
ITERATOR_INIT( Iterator );
|
|
|
|
CG_FIELD *pField;
|
|
while ( ITERATOR_GETNEXT( Iterator, pField ) )
|
|
{
|
|
|
|
// First check if the fields are the same type. If they
|
|
// are, then check the print prefixes to make sure the fields came
|
|
// from the same structure.
|
|
|
|
if ( ( pField->GetType() == pFieldType ) &&
|
|
( strcmp( pField->GetPrintPrefix(), pPrintPrefix ) == 0 ) )
|
|
{
|
|
|
|
*pMemOffset = pField->GetMemOffset();
|
|
return pField;
|
|
}
|
|
|
|
CG_CLASS * pChildClass = pField->GetChild();
|
|
|
|
if ( pChildClass->IsStruct() )
|
|
{
|
|
unsigned long TempMemOffset;
|
|
CG_STRUCT *pChildStruct = (CG_STRUCT*)pChildClass;
|
|
|
|
CG_FIELD *pTempField = FindField( pFieldType,
|
|
pChildStruct,
|
|
pPrintPrefix,
|
|
&TempMemOffset );
|
|
|
|
if ( NULL != pTempField )
|
|
{
|
|
*pMemOffset = TempMemOffset + pField->GetMemOffset();
|
|
return pTempField;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
ExpressionGenerator::ComputeFieldCorrelationOffset(
|
|
CCB *pCCB,
|
|
node_skl *pFieldType,
|
|
// return parameters
|
|
CG_FIELD **ppVariableField, // var in expression
|
|
long *pOffset,
|
|
BOOL *pIsEarly )
|
|
{
|
|
|
|
//
|
|
// Find the fields.
|
|
//
|
|
CG_FIELD *pCurrentField = dynamic_cast<CG_FIELD*>( pCCB->GetLastPlaceholderClass() );
|
|
MIDL_ASSERT( NULL != pCurrentField );
|
|
const char *pPrintPrefix = pCurrentField->GetPrintPrefix();
|
|
|
|
CG_STRUCT *pContext = dynamic_cast<CG_STRUCT*>( pCCB->GetCGNodeContext() );
|
|
MIDL_ASSERT( NULL != pContext );
|
|
|
|
unsigned long VariableOffset;
|
|
CG_FIELD* pVariableField = FindField( pFieldType,
|
|
pContext,
|
|
pPrintPrefix,
|
|
&VariableOffset );
|
|
MIDL_ASSERT( NULL != pVariableField );
|
|
*ppVariableField = pVariableField;
|
|
|
|
unsigned long CurrentOffset;
|
|
CG_FIELD* pAlsoCurrentField = FindField( pCurrentField->GetType(),
|
|
pContext,
|
|
pPrintPrefix,
|
|
&CurrentOffset );
|
|
pAlsoCurrentField;
|
|
MIDL_ASSERT( pAlsoCurrentField == pCurrentField );
|
|
|
|
//
|
|
// Determine the correlation type.
|
|
// The correlation type is early if the variable field will
|
|
// be completely marshalled before the current field.
|
|
//
|
|
BOOL bVariableIsPointer = pVariableField->GetChild()->IsPointer();
|
|
BOOL bCurrentFieldIsPointer = pCurrentField->GetChild()->IsPointer();
|
|
|
|
BOOL bOnlyVariableIsPointer = bVariableIsPointer && !bCurrentFieldIsPointer;
|
|
|
|
*pIsEarly = ( CurrentOffset > VariableOffset ) && !bOnlyVariableIsPointer;
|
|
|
|
// In the land of the new transfer syntax, all offsets are a positive offset
|
|
// from the start of the stack or the last structure/region that was passed.
|
|
|
|
CG_FIELD *pRegionField = pCCB->GetCurrentRegionField();
|
|
|
|
// Make offset relative to start of region
|
|
if (NULL != pRegionField)
|
|
VariableOffset -= pRegionField->GetMemOffset();
|
|
|
|
*pOffset = VariableOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::Visit( CG_TRANSMIT_AS )
|
|
//
|
|
// Synopsis: Generate info for transmit_as types
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::Visit( CG_TRANSMIT_AS *pTransmitAs )
|
|
{
|
|
MIDL_NDR64_TRANSMIT_AS_FORMAT *format;
|
|
|
|
format = new MIDL_NDR64_TRANSMIT_AS_FORMAT( pTransmitAs );
|
|
|
|
GetCurrent()->AddFragment( format );
|
|
|
|
GenXmitOrRepAsFormat(
|
|
pTransmitAs,
|
|
format,
|
|
pTransmitAs->GetPresentedType()->GetSymName(),
|
|
pTransmitAs->GetPresentedType(),
|
|
pTransmitAs->GetTransmittedType() );
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::Visit( CG_REPRESENT_AS )
|
|
//
|
|
// Synopsis: Generate info for represent_as types
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::Visit( CG_REPRESENT_AS *pRepresentAs )
|
|
{
|
|
MIDL_NDR64_REPRESENT_AS_FORMAT *format;
|
|
|
|
format = new MIDL_NDR64_REPRESENT_AS_FORMAT( pRepresentAs );
|
|
|
|
GetCurrent()->AddFragment( format );
|
|
|
|
GenXmitOrRepAsFormat(
|
|
pRepresentAs,
|
|
format,
|
|
pRepresentAs->GetRepAsTypeName(),
|
|
pRepresentAs->GetRepAsType(),
|
|
pRepresentAs->GetTransmittedType() );
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::GenXmitOrRepAsFormat
|
|
//
|
|
// Synopsis: Do the actual work for transmit_as and represent_as types
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::GenXmitOrRepAsFormat(
|
|
CG_TYPEDEF *pXmitNode,
|
|
MIDL_NDR64_TRANSMIT_AS_FORMAT *format,
|
|
char *pPresentedTypeName,
|
|
node_skl *pPresentedType,
|
|
node_skl *pTransmittedType )
|
|
{
|
|
CG_NDR *pChild = (CG_NDR *) pXmitNode->GetChild();
|
|
BOOL fXmit = ( NULL == dynamic_cast<CG_REPRESENT_AS *>(pXmitNode) );
|
|
|
|
NDR64_UINT16 RoutineIndex = pXmitNode->GenXmitOrRepAsQuintuple(
|
|
pCCB,
|
|
fXmit,
|
|
pXmitNode,
|
|
pPresentedTypeName,
|
|
(fXmit ? pPresentedType
|
|
: pTransmittedType) );
|
|
|
|
|
|
format->FormatCode = (NDR64_FORMAT_CHAR) ( fXmit ? FC64_TRANSMIT_AS : FC64_REPRESENT_AS );
|
|
format->RoutineIndex = RoutineIndex;
|
|
format->TransmittedTypeWireAlignment = (NDR64_UINT16) ( pChild->GetWireAlignment() - 1 );
|
|
|
|
// REVIEW: The spec doesn't say whether "MemoryAlignment" is the
|
|
// presented type or the transmitted type. Transmitted doesn't
|
|
// make much sense but on the other hand presented has some
|
|
// alignment flags already.
|
|
format->MemoryAlignment = pXmitNode->GetMemoryAlignment();
|
|
|
|
if ( pPresentedType )
|
|
format->PresentedTypeMemorySize = (NDR64_UINT16) pPresentedType->GetSize();
|
|
else
|
|
MIDL_ASSERT(!"BUGBUG: unknown rep/transmit_as");
|
|
|
|
if ( pChild->HasAFixedBufferSize() )
|
|
format->TransmittedTypeBufferSize = (NDR64_UINT16) pChild->GetWireSize();
|
|
else
|
|
format->TransmittedTypeBufferSize = 0;
|
|
|
|
format->Flags.PresentedTypeIsArray = 0;
|
|
format->Flags.PresentedTypeAlign4 = 0;
|
|
format->Flags.PresentedTypeAlign8 = 0;
|
|
format->Flags.Reserved = 0;
|
|
|
|
if ( pPresentedType )
|
|
{
|
|
if ( pPresentedType->GetBasicType()->NodeKind() == NODE_ARRAY )
|
|
format->Flags.PresentedTypeIsArray = 1;
|
|
else
|
|
{
|
|
if ( pXmitNode->GetMemoryAlignment() == 4 )
|
|
format->Flags.PresentedTypeAlign4 = 1;
|
|
else if ( pXmitNode->GetMemoryAlignment() == 8 )
|
|
format->Flags.PresentedTypeAlign8 = 1;
|
|
}
|
|
}
|
|
|
|
if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
|
|
pChild = (CG_NDR *)pChild->GetChild();
|
|
|
|
format->TransmittedType = ContinueGenerationInRoot( pChild );
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::Visit( CG_USER_MARSHAL )
|
|
//
|
|
// Synopsis: Generate info for user_marshal types
|
|
//
|
|
// REVIEW: user_marshall and represent_as are so close to one another
|
|
// they really should probably be merged
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::Visit( CG_USER_MARSHAL *pUserMarshal )
|
|
{
|
|
MIDL_NDR64_USER_MARSHAL_FORMAT *format;
|
|
|
|
format = new MIDL_NDR64_USER_MARSHAL_FORMAT( pUserMarshal );
|
|
|
|
GetCurrent()->AddFragment( format );
|
|
|
|
CG_NDR *pChild = (CG_NDR *) pUserMarshal->GetChild();
|
|
|
|
format->FormatCode = FC64_USER_MARSHAL;
|
|
format->TransmittedTypeWireAlignment = (NDR64_UINT16) (pChild->GetWireAlignment() - 1);
|
|
format->MemoryAlignment = pChild->GetMemoryAlignment();
|
|
|
|
memset( &format->Flags, 0, sizeof(format->Flags) );
|
|
if ( pChild->IsPointer() )
|
|
{
|
|
CG_POINTER *pPointer = (CG_POINTER *) pChild;
|
|
MIDL_ASSERT( ! pPointer->IsFull() );
|
|
|
|
if ( pPointer->IsUnique() )
|
|
format->Flags.UniquePointer = 1;
|
|
else if ( pPointer->IsRef() )
|
|
format->Flags.RefPointer = 1;
|
|
}
|
|
|
|
format->Flags.IID = 0; // Only used by JIT compiler
|
|
format->Flags.Reserved = 0;
|
|
|
|
USER_MARSHAL_CONTEXT * pUserMarshalContext = new USER_MARSHAL_CONTEXT;
|
|
|
|
pUserMarshalContext->pTypeName = pUserMarshal->GetRepAsTypeName();
|
|
pUserMarshalContext->pType = pUserMarshal->GetRepAsType();
|
|
|
|
BOOL Added = pCCB->GetQuadrupleDictionary()->Add( pUserMarshalContext );
|
|
|
|
format->RoutineIndex = pUserMarshalContext->Index;
|
|
|
|
if ( !Added )
|
|
delete pUserMarshalContext;
|
|
|
|
if ( pUserMarshal->GetRepAsType() )
|
|
format->UserTypeMemorySize = pUserMarshal->GetRepAsType()->GetSize();
|
|
else
|
|
MIDL_ASSERT( !"BUGBUG: undefined user_marshal" );
|
|
|
|
if ( pChild->HasAFixedBufferSize() )
|
|
format->TransmittedTypeBufferSize = pChild->GetWireSize();
|
|
else
|
|
format->TransmittedTypeBufferSize = 0;
|
|
|
|
format->TransmittedType = ContinueGenerationInRoot( pChild );
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: GenNdr64Format::Visit( CG_PIPE )
|
|
//
|
|
// Synopsis: Generate info for [pipe] types
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void GenNdr64Format::Visit( CG_PIPE *pPipe )
|
|
{
|
|
pCommand->GetNdrVersionControl().SetHasRawPipes();
|
|
|
|
MIDL_NDR64_PIPE_FORMAT *format = new MIDL_NDR64_PIPE_FORMAT( pPipe );
|
|
|
|
GetCurrent()->AddFragment( format );
|
|
|
|
CG_NDR *pChild = (CG_NDR *) pPipe->GetChild();
|
|
NDR64_UINT32 BufferSize = 0;
|
|
node_range_attr *range = pPipe->GetRangeAttribute();
|
|
NDR64_UINT32 MinValue = 0;
|
|
NDR64_UINT32 MaxValue = 0;
|
|
|
|
CG_ILANALYSIS_INFO *pAnalysisInfo = pChild->GetILAnalysisInfo();
|
|
|
|
if ( pChild->HasAFixedBufferSize() )
|
|
BufferSize = pChild->GetWireSize();
|
|
|
|
if ( range )
|
|
{
|
|
MinValue = (NDR64_UINT32) range->GetMinExpr()->GetValue();
|
|
MaxValue = (NDR64_UINT32) range->GetMaxExpr()->GetValue();
|
|
}
|
|
|
|
format->FormatCode = FC64_PIPE;
|
|
format->Flags.Reserved1 = 0;
|
|
format->Flags.HasRange = (bool) ( NULL != range );
|
|
format->Flags.BlockCopy = !pAnalysisInfo->IsForcedBogus() && !pAnalysisInfo->IsFullBogus();
|
|
format->Flags.Reserved2 = 0;
|
|
format->Alignment = (NDR64_UINT8) ( pChild->GetWireAlignment() - 1 );
|
|
format->Reserved = 0;
|
|
format->Type = ContinueGenerationInRoot( pChild );
|
|
format->MemorySize = pChild->GetMemorySize();
|
|
format->BufferSize = BufferSize;
|
|
format->MinValue = MinValue;
|
|
format->MaxValue = MaxValue;
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: OutputParamFlagDescription
|
|
//
|
|
// Synopsis: Output a description string for the ndr64 param flags
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void OutputParamFlagDescription( CCB *pCCB, const NDR64_PARAM_FLAGS &flags )
|
|
{
|
|
static const PNAME flag_descrip[16] =
|
|
{
|
|
"MustSize",
|
|
"MustFree",
|
|
"pipe",
|
|
"[in]",
|
|
"[out]",
|
|
"IsReturn",
|
|
"Basetype",
|
|
"ByValue",
|
|
"SimpleRef",
|
|
"DontFreeInst",
|
|
"AsyncFinish",
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"UseCache"
|
|
};
|
|
|
|
pCCB->GetStream()->Write( " " );
|
|
OutputFlagDescriptions( pCCB->GetStream(), &flags, sizeof(flags), flag_descrip );
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: OutputFlagDescription
|
|
//
|
|
// Synopsis: Given a set of flags and a description for each flags,
|
|
// output the corresponding description for flag that is set.
|
|
// usused flags can be marked with a NULL description.
|
|
//
|
|
// Notes: Assumes little-endian memory layout!
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void OutputFlagDescriptions(
|
|
ISTREAM *stream,
|
|
const void *pvFlags,
|
|
int bytes,
|
|
const PNAME *description)
|
|
{
|
|
unsigned char *flags = (unsigned char *) pvFlags;
|
|
bool first = true;
|
|
|
|
stream->Write( "/*");
|
|
|
|
for (int i = 0; i < (bytes * 8); i++)
|
|
{
|
|
if ( ( NULL == description[i] )
|
|
|| ( 0 == ( flags[i / 8] & ( 1 << (i % 8) ) ) ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( !first )
|
|
stream->Write( "," );
|
|
|
|
first = false;
|
|
|
|
stream->Write( " " );
|
|
stream->Write( description[i] );
|
|
}
|
|
|
|
stream->Write( " */" );
|
|
}
|