/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Copyright (c) 1989-1999 Microsoft Corporation Module Name: ptrana.cxx Abstract: Contains implementations of analysis routines for pointer types. Notes: History: Oct-10-1993 VibhasC Created ----------------------------------------------------------------------------*/ /**************************************************************************** * include files ***************************************************************************/ #include "allana.hxx" #pragma hdrstop /**************************************************************************** * local definitions ***************************************************************************/ /**************************************************************************** * local data ***************************************************************************/ /**************************************************************************** * externs ***************************************************************************/ /****************************************************************************/ CG_STATUS CG_POINTER::UnMarshallAnalysis( ANALYSIS_INFO * pAna ) { CG_STATUS Status; // Unmarshall the pointer body first. If the pointer needs to be deferred, // then dont perform the pointee unmarshall analysis. Just indicate that // there is a pointee that needs to be unmarshalled later. Status = PtrUnMarshallAnalysis( pAna ); if( pAna->IsPointeeDeferred() ) { pAna->SetHasAtLeastOneDeferredPointee(); } else Status = PteUnMarshallAnalysis( pAna ); return Status; } CG_STATUS CG_POINTER::PtrUnMarshallAnalysis( ANALYSIS_INFO * pAna ) { // Perform the analysis for the pointer body. For a [ref] pointer, nothing // needs to be done. if( IsRef() && !pAna->IsMemoryAllocDone() ) { SetUAction( RecommendUAction( pAna->GetCurrentSide(), pAna->IsMemoryAllocDone(), pAna->IsRefAllocDone(), FALSE, // no buffer re-use for ref. UAFLAGS_NONE )); } return CG_OK; } CG_STATUS CG_POINTER::PteUnMarshallAnalysis( ANALYSIS_INFO * pAna ) { CG_STATUS Status; pAna->PushIndirectionLevel(); Status = CorePteUnMarshallAnalysis( pAna ); pAna->PopIndirectionLevel(); return Status; } CG_STATUS CG_POINTER::MarshallAnalysis( ANALYSIS_INFO * pAna ) { CG_STATUS Status; short EmbedLevel; // Marshall the pointer body first. If the pointee needs to be deferred, // dont perform marshall analysis on the pointee. Just indicate that a // pointee needs to be marshalled later. Status = PtrMarshallAnalysis( pAna ); if( pAna->IsPointeeDeferred() ) { pAna->SetHasAtLeastOneDeferredPointee(); } else { EmbedLevel = pAna->GetCurrentEmbeddingLevel(); pAna->ResetEmbeddingLevel(); Status = PteMarshallAnalysis( pAna ); pAna->SetCurrentEmbeddingLevel( EmbedLevel ); } return Status; } CG_STATUS CG_POINTER::PtrMarshallAnalysis( ANALYSIS_INFO * pAna ) { pAna; return CG_OK; } CG_STATUS CG_POINTER::PteMarshallAnalysis( ANALYSIS_INFO * pAna ) { CG_STATUS Status; pAna->PushIndirectionLevel(); pAna->SetMemoryAllocDone(); // Needed ? Status = CorePteMarshallAnalysis( pAna ); pAna->PopIndirectionLevel(); return Status; } CG_STATUS CG_POINTER::FollowerMarshallAnalysis( ANALYSIS_INFO * pAna ) { return PteMarshallAnalysis( pAna ); } CG_STATUS CG_POINTER::FollowerUnMarshallAnalysis( ANALYSIS_INFO * pAna ) { return PteUnMarshallAnalysis( pAna ); } CG_STATUS CG_POINTER::S_OutLocalAnalysis( ANALYSIS_INFO * pAna ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Routine Description: Perform analysis for [out] params that need to be allocated as locals on server stub. Arguments: pAna - The analysis block. Return Value: CG_OK if all is well error otherwise. Notes: ----------------------------------------------------------------------------*/ { CG_STATUS Status = CG_OK; CG_NDR * pC = (CG_NDR *)GetNonGenericHandleChild(); if( !pAna->IsMemoryAllocDone() ) { if( pAna->GetCurrentSide() != C_SIDE ) { PNAME pName = pAna->GenTempResourceName( 0 ); SetResource( pAna->AddLocalResource( pName, MakeIDNode( pName, GetType() ) )); } SetAllocatedOnStack( 1 ); } // If it is a ref pointer, chase it further. if( IsRef() && !IsQualifiedPointer() ) { pAna->ResetMemoryAllocDone(); pAna->SetRefAllocDone(); Status = pC->S_OutLocalAnalysis( pAna ); // If this is the server side, and the pointee is allocated on stack, // then dont free the pointee, else free it. if( pC->IsAllocatedOnStack() ) { SetPointerShouldFree( 0 ); } } return Status; } CG_STATUS CG_POINTER::InLocalAnalysis( ANALYSIS_INFO * pAna ) { if( IsRef() && GetChild() ) { ((CG_NDR *)GetChild())->InLocalAnalysis( pAna ); } return CG_OK; } /**************************************************************************** * CG_QUALIFIED_POINTER ***************************************************************************/ CG_STATUS CG_QUALIFIED_POINTER::CorePteMarshallAnalysis( ANALYSIS_INFO * pAna ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Routine Description: Perform the core pointee marshall analysis for a conformant string Arguments: pAna - The analysis block pointer. Return Value: CG_OK if all is well, error otherwise. Notes: The ndr for a conformant string (eg typedef [string] char *p ) is: - MaxCount - Offset from start of the valid character - Actual Count. We need to declare a local variable which will hold the length of the string, so that the length can be used in the actual marshall for memcopy. ----------------------------------------------------------------------------*/ { node_skl * pType; PNAME pResName; BOOL fNeedsCount; BOOL fNeedsFirstAndLength; if( pAna->IsArrayContext() ) { SetUsedInArray(); } if ( ( fNeedsCount = NeedsMaxCountMarshall() ) == TRUE ) { if( !GetSizeResource() ) { GetBaseTypeNode( &pType, SIGN_UNSIGNED, SIZE_LONG, TYPE_INT ); pResName = pAna->GenTempResourceName(0); pType = MakeIDNode( pResName, pType ); SetSizeResource( pAna->AddTransientResource( pResName, pType ) ); } else { pAna->AddTransientResource( GetSizeResource()->GetResourceName(), GetSizeResource()->GetType() ); } } if ( ( fNeedsFirstAndLength = NeedsFirstAndLengthMarshall() ) == TRUE ) { if( !GetLengthResource() ) { GetBaseTypeNode( &pType, SIGN_UNSIGNED, SIZE_LONG, TYPE_INT ); pResName = pAna->GenTempResourceName(0); pType = MakeIDNode( pResName, pType ); SetLengthResource( pAna->AddTransientResource( pResName, pType ) ); } else { pAna->AddTransientResource( GetLengthResource()->GetResourceName(), GetLengthResource()->GetType() ); } if( NeedsExplicitFirst() ) { if( !GetFirstResource() ) { GetBaseTypeNode( &pType, SIGN_UNSIGNED, SIZE_LONG, TYPE_INT ); pResName = pAna->GenTempResourceName(0); pType = MakeIDNode( pResName, pType ); SetFirstResource( pAna->AddTransientResource( pResName, pType ) ); } else { pAna->AddTransientResource(GetLengthResource()->GetResourceName(), GetLengthResource()->GetType() ); } } } return CG_OK; } CG_STATUS CG_QUALIFIED_POINTER::CorePteUnMarshallAnalysis( ANALYSIS_INFO * pAna ) { node_skl * pType; PNAME pResName; BOOL fNeedsMaxCount; BOOL fNeedsFirstAndLength; // If a resource for the length has not already been allocated, allocate // one. if ( ( fNeedsMaxCount = NeedsMaxCountMarshall() ) == TRUE ) { if( !GetSizeResource() ) { GetBaseTypeNode( &pType, SIGN_UNSIGNED, SIZE_LONG, TYPE_INT ); pResName = pAna->GenTempResourceName(0); pType = MakeIDNode( pResName, pType ); SetSizeResource( pAna->AddTransientResource( pResName, pType ) ); } else pAna->AddTransientResource( GetSizeResource()->GetResourceName(), GetSizeResource()->GetType() ); } if ( ( fNeedsFirstAndLength = NeedsFirstAndLengthMarshall() ) == TRUE ) { if( !GetLengthResource() ) { GetBaseTypeNode( &pType, SIGN_UNSIGNED, SIZE_LONG, TYPE_INT ); pResName = pAna->GenTempResourceName(0); pType = MakeIDNode( pResName, pType ); SetLengthResource( pAna->AddTransientResource( pResName, pType ) ); } else pAna->AddTransientResource( GetLengthResource()->GetResourceName(), GetLengthResource()->GetType() ); if( NeedsExplicitFirst() ) { if( !GetFirstResource() ) { GetBaseTypeNode( &pType, SIGN_UNSIGNED, SIZE_LONG, TYPE_INT ); pResName = pAna->GenTempResourceName(0); pType = MakeIDNode( pResName, pType ); SetFirstResource( pAna->AddTransientResource( pResName, pType ) ); } else pAna->AddTransientResource(GetFirstResource()->GetResourceName(), GetFirstResource()->GetType() ); } } return CG_OK; } CG_STATUS CG_INTERFACE_POINTER::S_OutLocalAnalysis( ANALYSIS_INFO * pAna ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Routine Description: Perform analysis for out params, allocated as locals on the server side. Arguments: pAna - A pointer to the analysis block. Return Value: CG_OK if all is well error otherwise. Notes: ----------------------------------------------------------------------------*/ { if( pAna->IsRefAllocDone() ) { if( pAna->GetCurrentSide() != C_SIDE ) { PNAME pName = pAna->GenTempResourceName( 0 ); node_skl * pType = GetType(); node_skl * pActualType; if ( pType->NodeKind() == NODE_DEF ) pActualType = MakeIDNode( pName, pType ); else pActualType = MakePtrIDNode( pName, pType ); SetResource( pAna->AddLocalResource( pName, pActualType )); } SetAllocatedOnStack( 1 ); } return CG_OK; } CG_STATUS CG_INTERFACE_POINTER::MarshallAnalysis( ANALYSIS_INFO * pAna ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Routine Description: Perform marshall analysis for interface ptr. Arguments: pCCB - The code gen controller block. Return Value: CG_OK Notes: ----------------------------------------------------------------------------*/ { pAna; return CG_OK; } CG_STATUS CG_IIDIS_INTERFACE_POINTER::S_OutLocalAnalysis( ANALYSIS_INFO * pAna ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Routine Description: Perform analysis for out params, allocated as locals on the server side. Arguments: pAna - A pointer to the analysis block. Return Value: CG_OK if all is well error otherwise. Notes: ----------------------------------------------------------------------------*/ { if( pAna->IsRefAllocDone() ) { if( pAna->GetCurrentSide() != C_SIDE ) { PNAME pName = pAna->GenTempResourceName( 0 ); node_skl * pType = GetType(); node_skl * pActualType; if ( pType->NodeKind() == NODE_DEF ) pActualType = MakeIDNode( pName, pType ); else pActualType = MakePtrIDNode( pName, pType ); SetResource( pAna->AddLocalResource( pName, pActualType )); } SetAllocatedOnStack( 1 ); } return CG_OK; } CG_STATUS CG_IIDIS_INTERFACE_POINTER::MarshallAnalysis( ANALYSIS_INFO * pAna ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Routine Description: Perform marshall analysis for interface ptr. Arguments: pCCB - The code gen controller block. Return Value: CG_OK Notes: ----------------------------------------------------------------------------*/ { pAna; return CG_OK; } /**************************************************************************** * utility functions ***************************************************************************/ U_ACTION CG_POINTER::RecommendUAction( SIDE CurrentSide, BOOL fMemoryAllocated, BOOL fRefAllocated, BOOL fBufferReUsePossible, UAFLAGS AdditionalFlags ) { U_ACTION UAction = CG_NDR::RecommendUAction( CurrentSide, fMemoryAllocated, fRefAllocated, fBufferReUsePossible, AdditionalFlags ); return UAction; }