/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 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 // { // , // // ... // } // //--------------------------------------------------------------------------- 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: // // { // , // // ... // } // //--------------------------------------------------------------------------- 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(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 *pVisitor = new CG_VISITOR_TEMPLATE; 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(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(pSwitch) ); MIDL_ASSERT( NULL != pUnion && NULL != dynamic_cast(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(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(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 ( 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(pPointer) ) { CG_CONF_ATTRIBUTE *pConfAttribute = dynamic_cast( 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( 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( 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 (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( 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( 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( 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( pArray ) ) { CG_FIXED_ARRAY *pFixedArray = (CG_FIXED_ARRAY*)( pArray ); pHeader = new MIDL_NDR64_FIXED_REPEAT_FORMAT( dynamic_cast( pChild )->GetMemorySize(), MemoryOffset, NumberPointers, pFixedArray->GetNumOfElements(), dynamic_cast( pChild )->IsStruct() ); } else { pHeader = new MIDL_NDR64_REPEAT_FORMAT( dynamic_cast( 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( 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( pStruct ); CG_FIELD *pConfField = dynamic_cast( pConfStruct->GetConformantField() ); MIDL_ASSERT( NULL != pConfField ); CG_ARRAY *pConfArray = dynamic_cast( 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( 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( pStruct->GetConformantField() ); MIDL_ASSERT( NULL != pConfField ); pConfArray = dynamic_cast( 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 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( 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( 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( 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( pNdr ); if ( !pAnalysisInfo->IsConformant() && pConfAttribute && pConfAttribute->GetSizeIsExpr() && pConfAttribute->GetSizeIsExpr()->IsConstant() ) { NumberElements = (NDR64_UINT32)pConfAttribute->GetSizeIsExpr()->GetValue(); } CG_NDR *pChildNdr = dynamic_cast( 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(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(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(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( 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( 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( 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( pAttributedNode ) ) || ( NULL != dynamic_cast( 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( 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( pCCB->GetLastPlaceholderClass() ); MIDL_ASSERT( NULL != pCurrentField ); const char *pPrintPrefix = pCurrentField->GetPrintPrefix(); CG_STRUCT *pContext = dynamic_cast( 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(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( " */" ); }