Source code of Windows XP (NT5)
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

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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( " */" );
}