windows-nt/Source/XPSP1/NT/com/rpc/midl/analysis/ptrana.cxx
2020-09-26 16:20:57 +08:00

554 lines
12 KiB
C++

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