554 lines
12 KiB
C++
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;
|
|
|
|
}
|