Windows NT 4.0 source code leak
 
 
 
 
 
 

843 lines
26 KiB

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1993 Microsoft Corporation
Module Name:
pickle.cxx
Abstract:
This module contains methods for generating pickling support.
Notes:
Author:
Ryszard K. Kott (ryszardk) Sep 28, 1993
Revision History:
------------------------------------------------------------------------*/
#include "nulldefs.h"
extern "C"
{
#include <stdio.h>
#include <assert.h>
#include <string.h>
}
#include <typedef.hxx>
#include <miscnode.hxx>
#include <ptrarray.hxx>
#include <procnode.hxx>
#include <buffer.hxx>
#include <stubgen.hxx> // STRING_COMPONENT
#include <ctxt.hxx>
#include <pickle.hxx>
#define ACT_LEN "_ActualLength"
#define REQ_LEN "_RequiredLength"
#define PRE_PAD "_PrePad"
#define PCHAR_CAST "(char __RPC_FAR *)"
#define PPCHAR_CAST "(char __RPC_FAR * __RPC_FAR *)"
#define PVOID_CAST "(void __RPC_FAR *)"
#define PPVOID_CAST "(void __RPC_FAR * __RPC_FAR *)"
#define BUFFER "_prpcmsg->Buffer"
#define BUFFER_LEN "_prpcmsg->BufferLength"
extern char * STRING_TABLE[ LAST_COMPONENT ]; // needed for old print
extern OutputManager * pOutput; // needed for local decl
extern CTXTMGR * pGlobalContext; // needed to decorate
// type subgraphs
PickleManager * pPicControlBlock;
// ========================================================================
//
// PickleControlBlock.
//
// ========================================================================
PickleManager::PickleManager(
SIDE_T Side,
BOOL fEncode,
BOOL fDecode ):
Sides( Side ),
fEncodeAtIf( fEncode ),
fDecodeAtIf( fDecode ),
fUseProcessing( FALSE )
{
PicPrint = new MopPrintManager;
}
PickleManager::~PickleManager()
{
delete PicPrint;
}
// ========================================================================
//
// Emitting pickle routines for a type.
//
// ========================================================================
STATUS_T
node_def::PickleCodeGen(
void
)
/*++
Routine description:
This routine is the entry point for the type pickle generation.
Arguments:
--*/
{
SIDE_T Side = pPicControlBlock->GetSides();
char * pTypeName = GetSymName();
if ( Side & HEADER_SIDE )
PickleTypePrototypes( pTypeName );
if ( Side & CLIENT_STUB )
{
pPicControlBlock->GetPrintManager()->SetSide( CLIENT_STUB );
//.. Simulate appropriate environment for the walking methods.
//.. Set up a param node pointing to a pointer node pointing to
//.. the def node.
node_param * DummyParam = new node_param;
node_pointer * DummyPointer = new node_pointer( ATTR_REF );
DummyParam->SetChild( DummyPointer );
DummyParam->SetEdgeType( EDGE_USE );
DummyParam->SetSymName( PICKLE_OBJECT_NAME );
BOOL fEncodeUsed = FInSummary( ATTR_ENCODE ) ||
pPicControlBlock->GetEncodeAtIf();
BOOL fDecodeUsed = FInSummary( ATTR_DECODE ) ||
pPicControlBlock->GetDecodeAtIf();
if ( fEncodeUsed )
((node_skl *)DummyParam)->SetAttribute( ATTR_IN );
if ( fDecodeUsed )
((node_skl *)DummyParam)->SetAttribute( ATTR_OUT );
DummyPointer->SetChild( this );
BufferManager TempBuffer( 8, LAST_COMPONENT, STRING_TABLE );
//.. Decoratre stuff as needed
pPicControlBlock->SetUseProcessing();
pPicControlBlock->SetDummyParam( DummyParam );
pGlobalContext->PushContext( DummyParam );
pGlobalContext->PushContext( DummyPointer );
UseProcessing();
pGlobalContext->PopContext();
pGlobalContext->PopContext();
pPicControlBlock->ResetUseProcessing();
//.. For some types a macro is generated instead of the size routine.
int OptimCode = IsPickleSizeOptimizable();
PickleSize( &TempBuffer, DummyParam, OptimCode, FALSE );
PickleSize( &TempBuffer, DummyParam, OptimCode, TRUE );
if ( fEncodeUsed )
PickleSerialize ( &TempBuffer, DummyParam, OptimCode );
if ( fDecodeUsed )
PickleDeserialize( &TempBuffer, DummyParam, OptimCode );
}
return( STATUS_OK );
}
BOOL
node_def::IsAPredefinedType( void )
{
return( strcmp( GetSymName(), "error_status_t" ) == 0 ||
strcmp( GetSymName(), "wchar_t" ) == 0 );
}
void
node_def::PickleTypePrototypes(
char * pTypeName
)
/*++
Routine description:
This routine emits prototypes for the type pickling routines.
size_t <type>_Size ( <type> __RPC_FAR * _pObject );
size_t <type>_AlignSize( MIDL_ES_HANDLE _Handle,
<type> __RPC_FAR * _pObject );
void <type>_Encode ( MIDL_ES_HANDLE _Handle,
<type> __RPC_FAR * _pObject );
void <type>_Decode ( MIDL_ES_HANDLE _Handle,
<type> __RPC_FAR * _pObject );
Actually, _pObject is defined as PICKLE_OBJECT_NAME.
If the type is a base type, <type>_size routine is a macro
#define <type>_Size( x ) (unsigned long) <type_size>
Arguments:
--*/
{
MopPrintManager * pPrint = pPicControlBlock->GetPrintManager();
pPrint->SetSide( HEADER_SIDE );
pPrint->NewLine();
pPrint->EmitString( "/* Pickling routines for type %s */", pTypeName );
pPrint->NewLine();
if ( FInSummary( ATTR_ENCODE ) || pPicControlBlock->GetEncodeAtIf() )
{
if ( IsPickleSizeOptimizable() )
{
node_skl * pNode = GetBasicType();
unsigned long BaseTypeSize = pNode->GetSize( 0 );
pPrint->EmitString( "#define %s_Size( x ) (unsigned long)sizeof(",
pTypeName );
pPrint->EmitString( "%s)", pNode->GetSymName() );
pPrint->NewLine();
}
else
{
pPrint->EmitString( "size_t \n%s_Size( ", pTypeName );
pPrint->EmitString( "%s __RPC_FAR * " PICKLE_OBJECT_NAME " );",
pTypeName );
pPrint->NewLine();
}
pPrint->EmitString( "size_t \n%s_AlignSize( MIDL_ES_HANDLE _Handle, ",
pTypeName );
pPrint->EmitString( "%s __RPC_FAR * " PICKLE_OBJECT_NAME " );",
pTypeName );
pPrint->NewLine();
pPrint->EmitString( "void \n%s_Encode( MIDL_ES_HANDLE _Handle, ",
pTypeName );
pPrint->EmitString( "%s __RPC_FAR * " PICKLE_OBJECT_NAME " );",
pTypeName );
pPrint->NewLine();
}
if ( FInSummary( ATTR_DECODE ) || pPicControlBlock->GetDecodeAtIf() )
{
pPrint->EmitString( "void \n%s_Decode( MIDL_ES_HANDLE _Handle, ",
pTypeName );
pPrint->EmitString( "%s __RPC_FAR * " PICKLE_OBJECT_NAME " );", pTypeName );
pPrint->NewLine();
}
}
// ========================================================================
//
// Helpers for size optimization decisions affecting routines or macros
// that are generated.
//
// ========================================================================
int
node_def::IsPickleSizeOptimizable( void )
{
//.. Cannot find a routine for nailing down sizeable types ...
//.. Should be available somewhere, dammit!
NODE_T Type = GetBasicType()->GetNodeType();
static struct _NodeTypeToOptimCode
{
PicOptimCode Code;
NODE_T Type;
} PicTypeToOptimCode[] =
{
PicNoOptimization, NODE_ILLEGAL,
PicOptimFloat, NODE_FLOAT,
PicOptimDouble, NODE_DOUBLE,
PicOptimHyper, NODE_HYPER,
PicOptimLong, NODE_LONG,
PicNoOptimization, NODE_LONGLONG,
PicOptimShort, NODE_SHORT,
PicNoOptimization, NODE_INT,
PicOptimByte, NODE_SMALL,
PicOptimChar, NODE_CHAR,
PicOptimShort, NODE_BOOLEAN,
PicOptimByte, NODE_BYTE,
PicNoOptimization, NODE_VOID,
PicNoOptimization, NODE_HANDLE_T,
PicOptimLong, NODE_ERROR_STATUS_T,
PicOptimShort, NODE_ENUM,
PicOptimShort, NODE_WCHAR_T
};
int i = 0;
while ( i < sizeof(PicTypeToOptimCode)/sizeof(_NodeTypeToOptimCode) )
{
if ( Type == PicTypeToOptimCode[ i ].Type )
return( PicTypeToOptimCode[ i ].Code );
i++;
}
return( PicNoOptimization );
}
//.. Currrently these tables encode optimization that doesn't bother with
//.. endianness and floating point differences.
//.. The only thing of importance recognized here is the size of an entity.
//.. The ordering of the strings follows PicOptimCode enum type definition:
//.. NoOptimization, Byte, Short, Long, Hyper, Char, Float, Double.
static char * PicOptimizationType[ PicOptimEnumSize + 1 ] =
{
"PicNoOptimization!",
"char",
"short",
"long",
"double",
"char",
"long",
"double"
};
static char * PicOptimizationTypeSuffix[ PicOptimEnumSize + 1 ] =
{
"PicNoOptimization!",
"Byte",
"Short",
"Long",
"Hyper",
"Byte",
"Long",
"Hyper"
};
// ========================================================================
//
// Wrappers for local declarations and indentation.
//
// ========================================================================
void
PickleProcedureProlog(
int DeclCode
)
/*++
Routine description:
This routine generates more or less of local variables depending
on the level of optimization.
Argument:
DecCode - what is expected:
4 - no declariations at all optimized rotuines
3 - stub related variables only (*_Size)
2 - stub related + Act (*_AlignSize)
1 - stub related + Act + Req (*_Decode)
0 - stub related + Act, Req + Pad (*_Encode)
--*/
{
pOutput->InitBlock( CLIENT_STUB );
if ( DeclCode == 4 )
return;
if ( DeclCode == 0)
pOutput->Print( CLIENT_STUB, MOP_TAB "size_t " PRE_PAD ";\n" );
if ( DeclCode <= 1)
pOutput->Print( CLIENT_STUB, MOP_TAB "size_t " REQ_LEN ";\n" );
if ( DeclCode <= 2)
pOutput->Print( CLIENT_STUB, MOP_TAB "size_t " ACT_LEN ";\n" );
pOutput->Print( CLIENT_STUB, MOP_TAB "char * _tempbuf;\n" );
pOutput->Print( CLIENT_STUB, MOP_TAB "char * _savebuf;\n" );
pOutput->ProcedureProlog(
CLIENT_STUB,
TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE );
pOutput->Print( CLIENT_STUB, MOP_TAB "((void)(_status));\n" );
pOutput->Print( CLIENT_STUB, MOP_TAB "((void)(_tempbuf));\n" );
pOutput->Print( CLIENT_STUB, MOP_TAB "((void)(_savebuf));\n\n" MOP_TAB );
}
void
PickleProcedureEpilog( void )
{
pOutput->ExitBlock( CLIENT_STUB );
}
// ========================================================================
//
// Generating the pickle sizing routine.
//
// ========================================================================
void
node_def::PickleSize(
BufferManager * pBuffer,
node_param * pDummyParam,
int OptimCode,
BOOL fAlignSize
)
/*++
Routine description:
This routine generates the pickling sizing routines:
size_t
<type>_Size( <type> * PICKLE_OBJECT_NAME )
{
<additional variables, if needed>
prpcmsg = &rpcmsg;
I_MesMessageInit( prpcmsg );;
<code to calculate the size>
return( prpcmsg->BufferLength );
}
size_t
<type>_AlignSize(
MIDL_ES_HANDLE _Handle,
<type> * PICKLE_OBJECT_NAME )
{
<additional variables, if needed>
prpcmsg = &_Handle->rpcmsg;
_ActualLentgh = prpcmsg->BufferLength;
prpcmsg->BufferLength += MIDL_ES_HEADER_PAD( prpcmsg->BufferLength );
prpcmsg->BufferLength += MIDL_ES_HEADER_SIZE;
<code to calculate the size>
return( prpcmsg->BufferLength - _ActualLength );
}
However for the types that can be optimized (currently base types and such),
instead of the first routine a macro is generated in the header file and
the second routine is just a ndr library call.
#define <type>_Size sizeof( type )
size_t
<type>_AlignSize(
MIDL_ES_HANDLE _Handle,
<type> * PICKLE_OBJECT_NAME )
{
((void)PICKLE_OBJECT_NAME);
return( I_MesAlignSize<correct_type>( _Handle ));
}
Arguments:
pBuffer - output connection
pDummyParam - Subtree for the "parameter" with the def node
SizingStatus- controls how many decl to emit
fAlignSize - controls which sizing routine to emit
--*/
{
MopPrintManager * pPrint = pPicControlBlock->GetPrintManager();
if ( OptimCode && ! fAlignSize )
{
//.. A macro in the header file generated.
return;
}
//.. Header is mostly the same
pPrint->EmitLine( "\nsize_t" );
pPrint->Emit( GetSymName() );
pPrint->Emit( fAlignSize ? "_AlignSize( " : "_Size( " );
if ( fAlignSize )
pPrint->Emit( "MIDL_ES_HANDLE _Handle, " );
pPrint->Emit( GetSymName() );
pPrint->EmitLine( " * " PICKLE_OBJECT_NAME " ) " );
PickleProcedureProlog( OptimCode ? 4
: (fAlignSize ? 2
: 3 ));
//.. Now the body of the routines.
if ( OptimCode )
{
pPrint->EmitLineInc( MOP_TAB "((void)" PICKLE_OBJECT_NAME ");" );
pPrint->EmitString( "return( I_MesAlignSize%s( _Handle ));",
PicOptimizationTypeSuffix[ OptimCode ] );
pPrint->NewLine();
}
else
{
if ( fAlignSize )
{
pPrint->EmitLineInc( "_prpcmsg = &_Handle->rpcmsg;" );
pPrint->EmitLineInc( ACT_LEN " = " BUFFER_LEN ";" );
pPrint->EmitLineInc( BUFFER_LEN " += MIDL_ES_HEADER_PAD(" BUFFER_LEN ");" );
pPrint->EmitLineInc( BUFFER_LEN " += MIDL_ES_HEADER_SIZE;" );
}
else
pPrint->EmitLineInc( "I_MesMessageInit( _prpcmsg );" );
pPrint->NewLine();
pBuffer->Clear();
pDummyParam->WalkTree( CALC_SIZE, CLIENT_STUB, NODE_PROC, pBuffer );
pPrint->NewLineInc ();
if ( fAlignSize )
pPrint->EmitLine( "return( " BUFFER_LEN " - " ACT_LEN " );" );
else
pPrint->EmitLine( "return( " BUFFER_LEN " );" );
}
PickleProcedureEpilog();
}
// ========================================================================
//
// Generating the pickle serializing (marshalling) routine.
//
// ========================================================================
void
node_def::PickleSerialize(
BufferManager * pBuffer,
node_param * pDummyParam,
int OptimCode
)
/*++
Routine description:
This routine generates the pickling serializing routine:
void
<type>_Encode(
MIDL_ES_HANDLE _Handle,
<type> * pObject )
{
size_t _ActualLen, _RequiredLen _PrePad;
<additional variables, if needed>
_prpcmsg = &_Handle->rpcmsg;
_PrePad = MIDL_ES_HEADER_PAD( BUFFER_LEN );
_RequiredLen = _ActualLen = <type>_AlignSize( _Handle, pObject );
(_pHandle->Alloc)( _Handle->UserState,
&_Handle->rpcmsg.Buffer,
&_ActualLen );
if ( _ActualLen < _RequiredLen )
RpcRaiseException( ERROR_OUTOFMEMORY );
_ActualLen = _RequiredLen - <type>_Size( pObject );
((char *)_prpcmsg->Buffer) += _PrePad;
*((unsigned long *)_prpcmsg->Buffer) = _RequiredLen - _PrePad
- MIDL_ES_HEADER_SIZE;
((char *)_prpcmsg->Buffer) += ActualLen - _PrePad;
<code to marshall >
_ActualLen = _RequiredLen;
(_Handle->Write)(
_Handle->UserState,
_prpcmsg->Buffer,
&ActualLen );
if ( _ActualLen < _RequiredLen )
RpcRaiseException( ERROR_OUTOFMEMORY );
}
However, if the <type> can be optimized, the routine is just a wrapper
for a ndr library call.
void
<type>_Encode(
MIDL_ES_HANDLE _Handle,
<type> * pObject )
{
I_MesEncode<correct_type>( _Handle, PICKLE_OBJECT_NAME );
}
Arguments:
Note:
Size of the object in the buffer can have padding preceding it
as well as following it (this one is between the header and the object).
So, to get things correctly when deserializing, the size as written
to the buffer is equal to the size of the object + padding between
the header and the object.
--*/
{
MopPrintManager * pPrint = pPicControlBlock->GetPrintManager();
char * TypeName = GetSymName();
//.. Header is the same with or without optimization.
pPrint->EmitLine( "\nvoid" );
pPrint->EmitStringNLInc( "%s_Encode(", TypeName );
pPrint->EmitLineInc ( "MIDL_ES_HANDLE _Handle, ");
pPrint->EmitString ( "%s * " PICKLE_OBJECT_NAME " ) ", TypeName );
pPrint->NewLine();
PickleProcedureProlog( OptimCode ? 4
: 0 );
if ( OptimCode )
{
pPrint->EmitString( MOP_TAB "I_MesEncode%s( _Handle, ",
PicOptimizationTypeSuffix[ OptimCode ] );
pPrint->EmitString( "(%s __RPC_FAR *)" PICKLE_OBJECT_NAME ");",
PicOptimizationType[ OptimCode ] );
pPrint->NewLine();
}
else
{
pPrint->EmitLineInc( "_prpcmsg = & _Handle->rpcmsg;" );
pPrint->EmitLineInc( PRE_PAD " = MIDL_ES_HEADER_PAD(" BUFFER_LEN ");" );
pPrint->EmitStringNLInc( REQ_LEN " = " ACT_LEN " = %s_AlignSize( _Handle, " PICKLE_OBJECT_NAME " );",
TypeName );
pPrint->EmitLineInc( "(_Handle->Alloc)( _Handle->UserState," );
pPrint->EmitLineInc( " " PPCHAR_CAST "&" BUFFER "," );
pPrint->EmitLineInc( " &" ACT_LEN " );" );
pPrint->EmitLineInc( "if ( " ACT_LEN " < " REQ_LEN " )" );
pPrint->EmitLineInc( MOP_TAB "RpcRaiseException( ERROR_OUTOFMEMORY );\n" );
pPrint->EmitStringNLInc( ACT_LEN " = " REQ_LEN " - %s_Size( " PICKLE_OBJECT_NAME " );",
TypeName );
pPrint->EmitLineInc( PCHAR_CAST BUFFER " += " PRE_PAD ";" );
pPrint->EmitLineInc( "*((unsigned long *)" BUFFER ") = (unsigned long)" REQ_LEN " - " PRE_PAD " - MIDL_ES_HEADER_SIZE;" );
pPrint->EmitLineInc( PCHAR_CAST BUFFER " += " ACT_LEN " - " PRE_PAD ";" );
pBuffer->Clear();
pDummyParam->WalkTree( SEND_NODE, CLIENT_STUB, NODE_PROC, pBuffer );
pPrint->NewLineInc();
pPrint->EmitLineInc( ACT_LEN " = " REQ_LEN ";" );
pPrint->EmitLineInc( "(_Handle->Write)( _Handle->UserState," );
pPrint->EmitLineInc( " " PCHAR_CAST BUFFER "," );
pPrint->EmitLineInc( " " ACT_LEN ");" );
pPrint->EmitLineInc( "if ( " ACT_LEN " < " REQ_LEN " )" );
pPrint->EmitLineInc( MOP_TAB "RpcRaiseException( ERROR_OUTOFMEMORY );\n" );
}
PickleProcedureEpilog();
}
// ========================================================================
//
// Generating the pickle deserializing (unmarshalling) routine.
//
// ========================================================================
void
node_def::PickleDeserialize(
BufferManager * pBuffer,
node_param * pDummyParam,
int OptimCode
)
/*++
Routine description:
This routine generates the pickling deserializing routine:
void
<type>_Decode(
MIDL_ES_HANDLE _Handle,
<type> * PICKLE_OBJECT_NAME )
{
size_t _RequiredLen, ActualLen;
<additional variables, if needed>
_prpcmsg = &_Handle->rpcmsg;
_ReqiredLen = _ActualLen = MIDL_ES_HEADER_PAD( BUFFER )
+ MIDL_ES_HEADER_SIZE;
(_Handle->Read)( _Handle->UserState,
&_prpcmsg->Buffer,
&_ActualLen );
if ( _ActualLen < _RequiredLen )
RpcRaiseException( ERROR_OUTOFMEMORY );
BUFFER += MIDL_ES_HEADER_PAD( BUFFER )
_ReqiredLen = _ActualLen = (size_t)*((unsigned long *)_prpcmsg->Buffer);
((char *)_prpcmsg->Buffer) += MIDL_ES_HEADER_SIZE;
(_Handle->Read)( _Handle->UserState,
&_prpcmsg->Buffer,
&_ActualLen );
if ( _ActualLen < _RequiredLen )
RpcRaiseException( ERROR_OUTOFMEMORY );
<code to unmarshall >
}
However, if the <type> can be optimized, the routine is just a wrapper
for a ndr library call.
void
<type>_Decode(
MIDL_ES_HANDLE _Handle,
<type> * pObject )
{
I_MesDecode<correct_type>( _Handle, PICKLE_OBJECT_NAME );
}
Arguments:
--*/
{
MopPrintManager * pPrint = pPicControlBlock->GetPrintManager();
char * TypeName = GetSymName();
//.. Header is the same with or without optimization.
pPrint->EmitLine( "\nvoid" );
pPrint->EmitStringNLInc( "%s_Decode(", TypeName );
pPrint->EmitLineInc ( "MIDL_ES_HANDLE _Handle, ");
pPrint->EmitString ( "%s * " PICKLE_OBJECT_NAME " ) ", TypeName );
pPrint->NewLine();
PickleProcedureProlog( OptimCode ? 4
: 1 );
if ( OptimCode )
{
pPrint->EmitString( MOP_TAB "I_MesDecode%s( _Handle, ",
PicOptimizationTypeSuffix[ OptimCode ] );
pPrint->EmitString( "(%s __RPC_FAR *)" PICKLE_OBJECT_NAME ");",
PicOptimizationType[ OptimCode ] );
pPrint->NewLine();
}
else
{
pPrint->EmitLine ( "_prpcmsg = & _Handle->rpcmsg;\n" );
pPrint->EmitLineInc( REQ_LEN " = " ACT_LEN " = MIDL_ES_HEADER_PAD(" BUFFER ") +" );
pPrint->EmitLineInc( MOP_TAB MOP_TAB " MIDL_ES_HEADER_SIZE;" );
pPrint->EmitLineInc( "(_Handle->Read)( _Handle->UserState," );
pPrint->EmitLineInc( " " PPCHAR_CAST "&" BUFFER "," );
pPrint->EmitLineInc( " &" ACT_LEN " );" );
pPrint->EmitLineInc( "if ( " ACT_LEN " < " REQ_LEN " )" );
pPrint->EmitLineInc( MOP_TAB "RpcRaiseException( ERROR_OUTOFMEMORY );\n" );
pPrint->EmitLineInc( PCHAR_CAST BUFFER " += MIDL_ES_HEADER_PAD(" BUFFER ");" );
pPrint->EmitLineInc( REQ_LEN " = " ACT_LEN " = (size_t)*((unsigned long *)" BUFFER ");" );
pPrint->EmitLineInc( PCHAR_CAST BUFFER " += MIDL_ES_HEADER_SIZE;" );
pPrint->EmitLineInc( "(_Handle->Read)( _Handle->UserState," );
pPrint->EmitLineInc( " " PPCHAR_CAST "&" BUFFER "," );
pPrint->EmitLineInc( " &" ACT_LEN " );" );
pPrint->EmitLineInc( "if ( " ACT_LEN " < " REQ_LEN " )" );
pPrint->EmitLineInc( MOP_TAB "RpcRaiseException( ERROR_OUTOFMEMORY );\n" );
pBuffer->Clear();
pDummyParam->WalkTree( RECV_NODE, CLIENT_STUB, NODE_PROC, pBuffer );
}
PickleProcedureEpilog();
}
// ========================================================================
//
// Interface layer.
//
// ========================================================================
BOOL
node_source::HasAnyPicklingAttr( void )
{
STATUS_T Status;
type_node_list FileList;
node_skl * pNode;
BOOL HasAny = FALSE;
if ( (Status = GetMembers( &FileList )) != STATUS_OK )
return( FALSE );
FileList.Init();
while ( FileList.GetPeer( &pNode ) == STATUS_OK )
if ( ((node_file *)pNode)->HasAnyPicklingAttr() )
{
HasAny = TRUE;
break;
}
return( HasAny );
}
BOOL
node_file::HasAnyPicklingAttr( void )
{
STATUS_T Status;
type_node_list IfList;
node_skl * pNode;
BOOL HasAny = FALSE;
if ( (Status = GetMembers( &IfList )) != STATUS_OK )
return( FALSE );
IfList.Init();
while ( IfList.GetPeer( &pNode ) == STATUS_OK )
if ( ((node_interface *)pNode)->HasAnyPicklingAttr() )
{
HasAny = TRUE;
break;
}
return( HasAny );
}
BOOL
node_interface::HasAnyPicklingAttr( void )
{
STATUS_T Status;
type_node_list NodeList;
node_skl * pNode;
BOOL HasAny = FALSE;
if ( FInSummary( ATTR_ENCODE ) || FInSummary( ATTR_DECODE ) )
return( TRUE );
if ( (Status = GetMembers( &NodeList )) != STATUS_OK )
return( FALSE );
NodeList.Init();
while ( NodeList.GetPeer( &pNode ) == STATUS_OK )
if ( pNode->GetNodeType() == NODE_DEF &&
((node_def *)pNode)->HasAnyPicklingAttr() )
{
HasAny = TRUE;
break;
}
return( HasAny );
}
/*
BOOL
node_proc::HasAnyPicklingAttr( void )
{
return( FALSE );
}
*/
BOOL
node_def::HasAnyPicklingAttr( void )
{
return( FInSummary( ATTR_ENCODE ) || FInSummary( ATTR_DECODE ) );
}