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

1955 lines
52 KiB
C++

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
filecls.hxx
Abstract:
Code generation methods for file cg classes.
Notes:
History:
Sep-01-1993 VibhasC Created.
----------------------------------------------------------------------------*/
#pragma warning ( disable : 4238 4239 )
/****************************************************************************
* include files
***************************************************************************/
#include "becls.hxx"
#pragma hdrstop
/****************************************************************************
* local definitions
***************************************************************************/
/****************************************************************************
* local data
***************************************************************************/
/****************************************************************************
* externs
***************************************************************************/
extern CMD_ARG * pCommand;
char* GetRpcNdrHVersionGuard( char* );
char* GetRpcProxyHVersionGuard( char* );
extern BOOL IsTempName( char * );
/****************************************************************************/
void
CG_FILE::EmitFileHeadingBlock(
CCB * pCCB,
char * CommentStr,
char * CommentStr2,
bool fDualFile )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Emit double platform ifdef as needed and the opening comment to the file.
Arguments:
pCCB - a pointer to the code generation control block.
CommentStr - a comment customizing the file.
CommentStr2 - optional comment used in *_i.c
fDualFile - true for client stub, server stub and froxy file
false for the header file
----------------------------------------------------------------------------*/
{
ISTREAM * pStream = pCCB->GetStream();
// A guard for double, i.e. 32b-64b, files.
pStream->NewLine();
pStream->Write( "#pragma warning( disable: 4049 ) /* more than 64k source lines */");
// Comment customizing the file.
pStream->NewLine(2);
pStream->Write( "/* this ALWAYS GENERATED file contains " );
pStream->Write( CommentStr );
pStream->Write( " */" );
pStream->NewLine(2);
if ( CommentStr2 )
{
pStream->Write( "/* " );
pStream->Write( CommentStr2 );
pStream->Write( " */" );
pStream->NewLine(2);
}
EmitStandardHeadingBlock( pCCB );
if ( fDualFile )
{
pStream->NewLine();
if ( pCommand->Is64BitEnv() )
pStream->Write( "#if defined(_M_IA64) || defined(_M_AMD64)" );
else if ( pCommand->Is32BitEnv() )
{
pStream->Write( "#if !defined(_M_IA64) && !defined(_M_AMD64)" );
}
}
}
void
CG_FILE::EmitFileClosingBlock(
CCB * pCCB,
bool fDualFile )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Emit an endif matching the one emitted in EmitFileHeadingBlock
Arguments:
pCCB - a pointer to the code generation control block.
CommentStr - a comment customizing the file.
fDualFile - true for client stub, server stub and froxy file
false for the header file
----------------------------------------------------------------------------*/
{
ISTREAM * pStream = pCCB->GetStream();
if ( fDualFile )
{
pStream->NewLine(2);
if ( pCommand->Is64BitEnv() )
pStream->Write( "#endif /* defined(_M_IA64) || defined(_M_AMD64)*/" );
else if ( pCommand->Is32BitEnv() )
{
pStream->Write( "#endif /* !defined(_M_IA64) && !defined(_M_AMD64)*/" );
}
}
pStream->NewLine(2);
}
void
CG_FILE::EmitStandardHeadingBlock(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Emit standard block comment file heading portion.
Arguments:
pCCB - a pointer to the code generation control block.
Return Value:
CG_OK if all is well, error otherwise.
Notes:
----------------------------------------------------------------------------*/
{
ISTREAM * pStream = pCCB->GetStream();
pStream->NewLine();
pStream->Write(" /* File created by MIDL compiler version ");
pStream->Write( pCommand->GetCompilerVersion() );
pStream->Write(" */");
pStream->NewLine();
if ( !pCommand->IsSwitchDefined( SWITCH_NO_STAMP ) )
{
pStream->Write("/* at ");
pStream->Write( pCommand->GetCompileTime() );
pStream->Write(" */");
pStream->NewLine();
}
// Emit command line switches information.
pCommand->EmitConfirm( pStream );
// Write this remnant of the reparsing scheme for our testers.
pStream->Write( "//@@MIDL_FILE_HEADING( )" );
pStream->NewLine();
}
void
CG_FILE::Out_TransferSyntaxDefs(
CCB * pCCB )
{
ISTREAM *pStream = pCCB->GetStream();
// NDR transfer syntax id is needed for
if ( pCommand->NeedsNDRRun() )
{
// BUGBUG: transfer syntax guids should be in rpcrt4.lib or something
pStream->WriteOnNewLine("static " TRANSFER_SYNTAX_TYPE_NAME " ");
pStream->Write( NDR_TRANSFER_SYNTAX_VAR_NAME );
pStream->Write( " = ");
pStream->NewLine();
Out_TransferSyntax( pCCB,
TransferSyntaxGuidStrs,
NDR_UUID_MAJOR_VERSION,
NDR_UUID_MINOR_VERSION );
pStream->Write( ';' );
pStream->NewLine();
}
if ( pCommand->NeedsNDR64Run() )
{
pStream->WriteOnNewLine("static " TRANSFER_SYNTAX_TYPE_NAME " ");
pStream->Write( NDR64_TRANSFER_SYNTAX_VAR_NAME );
pStream->Write( " = ");
pStream->NewLine();
if ( pCommand->IsSwitchDefined( SWITCH_INTERNAL ) &&
pCommand->GetEnv() == ENV_WIN32 )
Out_TransferSyntax( pCCB,
FakeNDR64TransferSyntaxGuidStrs,
NDR64_UUID_MAJOR_VERSION,
NDR64_UUID_MINOR_VERSION );
else
Out_TransferSyntax( pCCB,
NDR64TransferSyntaxGuidStrs,
NDR64_UUID_MAJOR_VERSION,
NDR64_UUID_MINOR_VERSION );
pStream->Write( ';' );
pStream->NewLine();
}
}
void
CG_FILE::EmitFormatStringTypedefs(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Emit dummy #defines with sizes for the format string structs,
then emit typedefs for the type and proc format string structs.
Sets the context position in the file node for later use.
Additional tables serviced here:
transmit_as, element is a quad
wire_marshal element is a quad
Arguments:
pCCB - a pointer to the code generation control block.
Notes:
The typedefs are going to be fixed later by a call to
EmitFixupToFormatStringTypedefs. This is needed for ANSI.
The dummies would work for ANSI non-compliant code.
--------------------------------------------------------------------------*/
{
ISTREAM * pStream = pCCB->GetStream();
// we'll only generate this once in the first run.
if ( pCommand->Is2ndCodegenRun() )
return;
pStream->NewLine(2);
if ( pCommand->NeedsNDRRun() )
{
pStream->Write( "#define TYPE_FORMAT_STRING_SIZE " );
SetOptionalTableSizePosition( TypeFormatStringSizePosition,
pStream->GetCurrentPosition() );
pStream->Write( " " );
pStream->NewLine();
pStream->Write( "#define PROC_FORMAT_STRING_SIZE " );
SetOptionalTableSizePosition( ProcFormatStringSizePosition,
pStream->GetCurrentPosition() );
pStream->Write( " " );
pStream->NewLine();
}
pStream->Write( "#define " TRANSMIT_AS_TABLE_SIZE " " );
SetOptionalTableSizePosition( TransmitAsSizePosition,
pStream->GetCurrentPosition() );
pStream->Write( " " );
pStream->NewLine();
pStream->Write( "#define " WIRE_MARSHAL_TABLE_SIZE " " );
SetOptionalTableSizePosition( WireMarshalSizePosition,
pStream->GetCurrentPosition() );
pStream->Write( " " );
pStream->NewLine();
if ( pCommand->NeedsNDRRun() )
{
pStream->NewLine();
pStream->Write( "typedef struct _" FORMAT_STRING_TYPE_NAME );
pStream->IndentInc();
pStream->NewLine();
pStream->Write( "{" );
pStream->NewLine();
pStream->Write( "short Pad;" );
pStream->NewLine();
pStream->Write( "unsigned char Format[ TYPE_FORMAT_STRING_SIZE ];" );
pStream->NewLine();
pStream->Write( "} " FORMAT_STRING_TYPE_NAME ";" );
pStream->IndentDec();
pStream->NewLine(2);
pStream->Write( "typedef struct _" PROC_FORMAT_STRING_TYPE_NAME );
pStream->IndentInc();
pStream->NewLine();
pStream->Write( "{" );
pStream->NewLine();
pStream->Write( "short Pad;" );
pStream->NewLine();
pStream->Write( "unsigned char Format[ PROC_FORMAT_STRING_SIZE ];" );
pStream->NewLine();
pStream->Write( "} " PROC_FORMAT_STRING_TYPE_NAME ";" );
pStream->IndentDec();
pStream->NewLine(2);
}
}
void
CG_FILE::EmitFixupToFormatStringTypedefs(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Fixes he dummy #defines emitted by EmitFormatStringTypedefs.
Arguments:
pCCB - a pointer to the code generation control block.
pContext - a pointer to the position context
--------------------------------------------------------------------------*/
{
char Buffer[20];
ISTREAM * pStream = pCCB->GetStream();
long EofPosition;
EofPosition = pStream->GetCurrentPosition();
if ( !pCommand->Is2ndCodegenRun() )
{
pStream->SetCurrentPosition(
GetOptionalTableSizePosition( TransmitAsSizePosition ) );
sprintf( Buffer, "%d", pCCB->GetQuintupleDictionary()->GetCount() );
pStream->Write( Buffer );
pStream->SetCurrentPosition(
GetOptionalTableSizePosition( WireMarshalSizePosition ) );
sprintf( Buffer, "%d", pCCB->GetQuadrupleDictionary()->GetCount() );
pStream->Write( Buffer );
}
if ( pCommand->IsNDRRun() )
{
pStream->SetCurrentPosition(
GetOptionalTableSizePosition( TypeFormatStringSizePosition ) );
sprintf( Buffer, "%d", pCCB->GetFormatString()->GetCurrentOffset() + 1);
pStream->Write( Buffer );
pStream->SetCurrentPosition(
GetOptionalTableSizePosition( ProcFormatStringSizePosition ) );
sprintf( Buffer, "%d", pCCB->GetProcFormatString()->GetCurrentOffset() + 1);
pStream->Write( Buffer );
#ifdef PRINT_METRICS
printf (
"Format string sizes %16d, %16d, %s\n",
pCCB->GetFormatString()->GetCurrentOffset() + 1,
pCCB->GetProcFormatString()->GetCurrentOffset() + 1,
GetFileName()
);
#endif
}
pStream->SetCurrentPosition( EofPosition );
}
void
CG_FILE::EmitOptionalClientTableSizeTypedefs(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Emit dummy #defines with sizes for the optional tables:
generic handles, element is a pair
Tables serviced in the EmitFormStringtypedefs routine:
transmit_as
wire_marshal
Arguments:
pCCB - a pointer to the code generation control block.
Notes:
The typedefs are going to be fixed later by a call to
EmitFixupToOptionalTableSizeTypedefs. This is needed for ANSI.
Note that we have the following tables that are not affected
by the ANSI issue because element is not a struct:
context rundown routine table
expression evaluation table
notify table
--------------------------------------------------------------------------*/
{
ISTREAM * pStream = pCCB->GetStream();
pStream->NewLine(2);
pStream->Write( "#define " GENERIC_BINDING_TABLE_SIZE " " );
SetOptionalTableSizePosition( GenericHandleSizePosition,
pStream->GetCurrentPosition() );
pStream->Write( " " );
pStream->NewLine();
}
void
CG_FILE::EmitFixupToOptionalClientTableSizeTypedefs(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Emit dummy #defines with sizes for the optional tables:
generic handles,
Arguments:
pCCB - a pointer to the code generation control block.
Notes:
The typedefs are going to be fixed later by a call to
EmitFixupOptionalTableSizeTpedefs. This is needed for ANSI.
--------------------------------------------------------------------------*/
{
char Buffer[20];
ISTREAM * pStream = pCCB->GetStream();
long EofPosition = pStream->GetCurrentPosition();
pStream->SetCurrentPosition(
GetOptionalTableSizePosition( GenericHandleSizePosition ) );
sprintf( Buffer, "%d", pCCB->GetGenericIndexMgr()->GetIndex() - 1 );
pStream->Write( Buffer );
pStream->SetCurrentPosition( EofPosition );
}
CG_STATUS
CG_SOURCE::GenCode(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate code for the source node.
Arguments:
pCCB - a pointer to the code generation control block.
Return Value:
CG_OK if all is well, error otherwise.
Notes:
----------------------------------------------------------------------------*/
{
CG_ITERATOR I;
CG_FILE * pCG;
//
// for all files nodes in this interface, generate code.
//
GetMembers( I );
while( ITERATOR_GETNEXT( I, pCG ) )
{
pCG->GenCode( pCCB );
}
return CG_OK;
}
CG_STATUS
CG_CSTUB_FILE::GenCode(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate code for the file node.
Arguments:
pCCB - a pointer to the code generation control block.
Return Value:
CG_OK if all is well, error otherwise.
Notes:
----------------------------------------------------------------------------*/
{
CG_ITERATOR I;
CG_NDR * pCG;
char Buffer[ _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 1 ];
char Drive[ _MAX_DRIVE ];
char Path[ _MAX_DIR ];
char Name[ _MAX_FNAME ];
char Ext[ _MAX_EXT ];
if( !GetMembers( I ) )
{
return CG_OK;
}
ISTREAM Stream( GetFileName(), 4 );
ISTREAM * pStream = &Stream;
pCCB->SetStream( pStream, this );
// Set HasStublessProxies and HasOi2 for each interface.
EvaluateVersionControl();
EmitFileHeadingBlock( pCCB, "the RPC client stubs" );
SetNoOutputIn2ndCodegen( pCCB );
// Emit the hash includes.
Out_IncludeOfFile( pCCB, STRING_H_INC_FILE_NAME, TRUE );
pStream->NewLine();
// rpcssm puts a reference to malloc and free in the stub_c.c.
// So, we have to emit the appropriate include.
// In ms_ext when explicit, in osf always, to cover some weird cases.
while( ITERATOR_GETNEXT( I, pCG ) )
{
if ( ( ((CG_INTERFACE *)pCG)->GetUsesRpcSS() || (pCCB->GetMode() == 0) ))
{
Out_IncludeOfFile( pCCB, "malloc.h", TRUE );
break;
}
}
_splitpath( GetHeaderFileName(), Drive, Path, Name, Ext );
strcpy( Buffer, Name );
strcat( Buffer, Ext );
Out_IncludeOfFile( pCCB, Buffer, FALSE );
EmitFormatStringTypedefs( pCCB );
Out_TransferSyntaxDefs( pCCB );
//
// Emit the external variables needed.
//
pStream->NewLine();
//
// Emit the format string extern declarations.
//
Out_FormatInfoExtern( pCCB );
Out_TypeFormatStringExtern( pCCB );
Out_ProcFormatStringExtern( pCCB );
EmitOptionalClientTableSizeTypedefs( pCCB );
pCCB->ClearOptionalExternFlags();
pCCB->SetFileCG(this);
MIDL_ASSERT( pCommand->IsNDR64Run() || pCommand->IsNDRRun() );
if ( pCommand->IsNDR64Run() )
{
pCCB->SetFormatString( NULL );
pCCB->SetProcFormatString( NULL );
pCCB->SetNdr64Format( GenNdr64Format::CreateInstance( pCCB ) );
}
else
{
//
// Create a new format string object if it does not yet exist.
//
if ( !pCCB->GetFormatString() )
{
pCCB->SetFormatString( new FORMAT_STRING() );
// push a dummy short 0 at the beginning. This disambiguates
// the case where offset 0 means recursion and a valid offset
// always push the 0 at the beginning, otherwise we'll av in
// some idl files (contain VARIANT for example) if -internal
// is specified.
// if ( !pCommand->IsSwitchDefined( SWITCH_INTERNAL ) )
// {
pCCB->GetFormatString()->PushShort( ( short ) 0 );
// }
}
if ( !pCCB->GetProcFormatString() )
{
pCCB->SetProcFormatString( new FORMAT_STRING() );
}
}
//
// for all interfaces in this file, generate format info.
//
ITERATOR_INIT( I );
while( ITERATOR_GETNEXT( I, pCG ) )
{
switch(pCG->GetCGID())
{
case ID_CG_INTERFACE:
((CG_INTERFACE *)pCG)->OutputInterfaceIdComment( pCCB );
((CG_INTERFACE *)pCG)->GenClientInfo( pCCB );
break;
}
}
//
// Output the tables that may be common to several interfaces.
//
EmitFixupToOptionalClientTableSizeTypedefs( pCCB );
ResetNoOutputIn2ndCodegen( pCCB );
EmitFixupToFormatStringTypedefs( pCCB );
// REVIEW: The externs may not be necessary anymore
pCCB->OutputExternsToMultipleInterfaceTables();
pCCB->OutputMultipleInterfaceTables();
OutputTypePicklingTables( pCCB );
//
// for all interfaces in this file, output stubs, proc tables, etc.
//
ITERATOR_INIT( I );
while( ITERATOR_GETNEXT( I, pCG ) )
{
switch(pCG->GetCGID())
{
case ID_CG_INTERFACE:
((CG_INTERFACE *)pCG)->OutputClientStub( pCCB );
break;
}
}
EmitFileClosingBlock( pCCB );
return CG_OK;
}
void
CG_CSTUB_FILE::OutputTypePicklingTables(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Output tables of offsets to type information for type pickling.
If this is the final run, also output the "table of tables"
Arguments:
pCCB - a pointer to the code generation control block.
Notes:
Pickled simple types don't end up in the the table. They are special
cased.
Tables looks like:
static unsigned long DCE_TypePicklingOffsets[] =
{
...
};
static unsigned long Ndr64_TypePicklingOffsets[] =
{
...
};
static unsigned long * TypePicklingOffsetTable[] =
{
DCE_TypePicklingOffsets,
Ndr64_TypePicklingOffsets
}
----------------------------------------------------------------------------*/
{
// straight DCE mode passes the offset directly to the type pickling API
if ( !pCommand->NeedsNDR64Run() )
return;
IndexedList PickledTypes = pCCB->GetListOfPickledTypes();
if ( 0 == PickledTypes.GetCount() )
return;
ISTREAM *pStream = pCCB->GetStream();
PNAME syntax;
CG_TYPE_ENCODE *type;
bool first = true;
if ( pCommand->IsNDR64Run() )
syntax = "FormatInfoRef Ndr64";
else
syntax = "unsigned long DCE";
//
// Output the type offset table for the current syntax
//
pStream->NewLine();
pStream->WriteFormat(
"static %s_TypePicklingOffsets[] =",
syntax );
pStream->WriteOnNewLine( '{' );
pStream->IndentInc();
ITERATOR_INIT( PickledTypes );
while ( ITERATOR_GETNEXT( PickledTypes, type ) )
{
if ( !first )
pStream->Write( ',' );
pStream->NewLine();
CG_NDR *pChild = (CG_NDR *) type->GetChild();
ulong TypeOffset;
char *format;
if ( pCommand->IsNDR64Run() )
{
format = "&__midl_frag%d";
TypeOffset = (ulong) (size_t) pCCB->GetNdr64Format()->GetRoot()
->LookupFragmentID( pChild );
MIDL_ASSERT( 0 != TypeOffset );
}
else
{
format = "%d";
TypeOffset = pChild->GetFormatStringOffset();
MIDL_ASSERT( ((ulong) -1) != TypeOffset );
}
pStream->WriteFormat( format, TypeOffset );
pStream->WriteFormat( " /* %s */", type->GetSymName() );
first = false;
}
pStream->IndentDec();
pStream->WriteOnNewLine( "};" );
pStream->NewLine();
//
// If this isn't the final protocol, quit now. Otherwise output the
// table of tables.
//
if ( !pCommand->IsFinalProtocolRun() )
return;
pStream->WriteOnNewLine( "static unsigned long * "
"TypePicklingOffsetTable[] =" );
pStream->WriteOnNewLine( "{" );
pStream->IndentInc();
first = true;
if ( pCommand->NeedsNDRRun() )
{
pStream->WriteOnNewLine( "DCE_TypePicklingOffsets" );
first = false;
}
if ( pCommand->NeedsNDR64Run() )
{
if ( !first ) pStream->Write( ',' );
pStream->WriteOnNewLine( "(unsigned long *) Ndr64_TypePicklingOffsets" );
first = false;
}
pStream->IndentDec();
pStream->WriteOnNewLine( "};" );
pStream->NewLine();
}
/****************************************************************************
* sstub file implementation class.
***************************************************************************/
CG_STATUS
CG_SSTUB_FILE::GenCode(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate code for the file node.
Arguments:
pCCB - a pointer to the code generation control block.
Return Value:
CG_OK if all is well, error otherwise.
Notes:
----------------------------------------------------------------------------*/
{
CG_ITERATOR I;
CG_NDR * pCG;
char Buffer[ _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 1 ];
char Drive[ _MAX_DRIVE ];
char Path[ _MAX_DIR ];
char Name[ _MAX_FNAME ];
char Ext[ _MAX_EXT ];
if( !GetMembers( I ) )
{
return CG_OK;
}
ISTREAM Stream( GetFileName(), 4 );
ISTREAM * pStream = &Stream;
pCCB->SetStream( pStream, this );
// Set HasStublessProxies and HasOi2 for each interface.
EvaluateVersionControl();
EmitFileHeadingBlock( pCCB, "the RPC server stubs" );
//
// Emit the hash includes.
//
SetNoOutputIn2ndCodegen( pCCB );
Out_IncludeOfFile( pCCB, STRING_H_INC_FILE_NAME, TRUE );
_splitpath( GetHeaderFileName(), Drive, Path, Name, Ext );
strcpy( Buffer, Name );
strcat( Buffer, Ext );
Out_IncludeOfFile( pCCB, Buffer, FALSE );
EmitFormatStringTypedefs( pCCB );
Out_TransferSyntaxDefs( pCCB );
//
// Emit the external variables needed.
//
//
// Emit the format string extern declarations.
//
Out_FormatInfoExtern( pCCB );
Out_TypeFormatStringExtern( pCCB );
Out_ProcFormatStringExtern( pCCB );
pCCB->ClearOptionalExternFlags();
pCCB->SetFileCG(this);
Out_NotifyTableExtern( pCCB );
MIDL_ASSERT( pCommand->IsNDR64Run() || pCommand->IsNDRRun() );
if ( pCommand->IsNDR64Run() )
{
pCCB->SetFormatString( NULL );
pCCB->SetProcFormatString( NULL );
pCCB->SetNdr64Format( GenNdr64Format::CreateInstance( pCCB ) );
}
else
{
//
// Create a new format string object if it does not exist.
//
if ( !pCCB->GetFormatString() )
{
pCCB->SetFormatString( new FORMAT_STRING() );
// push a dummy short 0 at the beginning. This disambiguates
// the case where offset 0 means recursion and a valid offset
pCCB->GetFormatString()->PushShort( ( short ) 0 );
}
if ( !pCCB->GetProcFormatString() )
{
pCCB->SetProcFormatString( new FORMAT_STRING() );
}
}
//
// Send the message to the children to emit code.
//
//
// For all interfaces in this file, generate code.
//
BOOL HasInterpretedProc = FALSE;
while( ITERATOR_GETNEXT( I, pCG ) )
{
if ( pCG->GetCGID() == ID_CG_INTERFACE )
{
if ( ! ((CG_INTERFACE *)pCG)->HasPicklingStuffOnly() )
{
pCCB->SetSkipFormatStreamGeneration( FALSE );
((CG_INTERFACE *)pCG)->OutputInterfaceIdComment( pCCB );
((CG_INTERFACE *)pCG)->GenServerInfo( pCCB );
if ( ((CG_INTERFACE *)pCG)->HasInterpretedProc() )
HasInterpretedProc = TRUE;
}
}
}
//
// Output the tables that may be common to several interfaces.
pCCB->SetCodeGenSide( CGSIDE_SERVER );
Out_NotifyTable( pCCB );
ResetNoOutputIn2ndCodegen( pCCB );
//
// If there was at least one interpreted proc in the interfaces of this
// file than make sure to turn the optimization bit in the CCB's
// OptimOption on.
//
EmitFixupToFormatStringTypedefs( pCCB );
if ( HasInterpretedProc )
pCCB->SetOptimOption( unsigned short( pCCB->GetOptimOption() | OPTIMIZE_INTERPRETER ) );
// REVIEW: The externs may not be necessary anymore
pCCB->OutputExternsToMultipleInterfaceTables();
pCCB->OutputMultipleInterfaceTables();
ITERATOR_INIT( I );
while( ITERATOR_GETNEXT( I, pCG ) )
{
if ( pCG->GetCGID() == ID_CG_INTERFACE )
{
if ( ! ((CG_INTERFACE *)pCG)->HasPicklingStuffOnly() )
{
((CG_INTERFACE *)pCG)->OutputServerStub( pCCB );
}
}
}
EmitFileClosingBlock( pCCB );
return CG_OK;
}
class GUID_DICTIONARY : public Dictionary
{
public:
GUID_DICTIONARY()
{
}
virtual
SSIZE_T Compare (pUserType p1, pUserType p2)
{
INTERNAL_UUID * u1 = &( ((CG_INTERFACE *)p1)->GetGuidStrs().Value );
INTERNAL_UUID * u2 = &( ((CG_INTERFACE *)p2)->GetGuidStrs().Value );
return memcmp( u1, u2, 16 );
}
};
void
CG_PROXY_FILE::MakeImplementedInterfacesList( CCB* )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Make a list of all the interfaces supported by this proxy file
( non-inherited, non-local interfaces ).
Arguments:
pCCB - a pointer to the code generation control block.
Return Value:
CG_OK if all is well, error otherwise.
Notes:
----------------------------------------------------------------------------*/
{
CG_INTERFACE * pCG;
CG_ITERATOR I;
GUID_DICTIONARY GuidDict;
// work directly on the real list
GetMembers( I );
while( ITERATOR_GETNEXT( I, pCG ) )
{
if ( pCG->GetCGID() != ID_CG_OBJECT_INTERFACE )
continue;
// Note that we don't need proxies and stubs for a pipe interface.
if ( ((CG_OBJECT_INTERFACE*)pCG)->IsLocal() )
continue;
GuidDict.Dict_Insert( pCG );
}
GuidDict.Dict_GetList( ImplementedInterfaces );
GuidDict.Dict_Discard();
}
void
CG_FILE::EvaluateVersionControl()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Calculates HasStublessProxies and Oi2 flags only through the
interfaces.
Arguments:
pCCB - a pointer to the code generation control block.
Return Value:
Notes:
----------------------------------------------------------------------------*/
{
if ( (pCommand->GetOptimizationFlags() & OPTIMIZE_STUBLESS_CLIENT ) ||
pCommand->GetNdrVersionControl().HasStublessProxies() )
GetNdrVersionControl().SetHasStublessProxies();
if ( (pCommand->GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 ) ||
pCommand->GetNdrVersionControl().HasOi2() )
GetNdrVersionControl().SetHasOi2();
CG_ITERATOR I;
CG_NDR * pCG;
CG_INTERFACE * pIntf;
if( !GetMembers( I ) )
{
return;
}
while( ITERATOR_GETNEXT( I, pCG ) )
{
pIntf = (CG_INTERFACE *)pCG;
switch(pCG->GetCGID())
{
case ID_CG_INTERFACE:
case ID_CG_INHERITED_OBJECT_INTERFACE:
case ID_CG_OBJECT_INTERFACE:
pIntf->EvaluateVersionControl();
if ( pIntf->HasStublessProxies() )
GetNdrVersionControl().SetHasStublessProxies();
if ( pIntf->GetNdrVersionControl().HasOi2() )
GetNdrVersionControl().SetHasOi2();
break;
default:
break;
}
}
if ( GetNdrVersionControl().HasStublessProxies() )
pCommand->GetNdrVersionControl().SetHasStublessProxies();
if ( GetNdrVersionControl().HasOi2() )
pCommand->GetNdrVersionControl().SetHasOi2();
}
CG_STATUS
CG_PROXY_FILE::GenCode(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate a proxy file containing the proxies and stubs for
the [object] interfaces defined in the IDL file.
Arguments:
pCCB - a pointer to the code generation control block.
Return Value:
CG_OK if all is well, error otherwise.
Notes:
----------------------------------------------------------------------------*/
{
CG_ITERATOR I;
CG_NDR * pCG;
char Buffer[ _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 1 ];
char Drive[ _MAX_DRIVE ];
char Path[ _MAX_DIR ];
char Name[ _MAX_FNAME ];
char Ext[ _MAX_EXT ];
unsigned long index = 0;
if( !GetMembers( I ) )
{
return CG_OK;
}
ISTREAM Stream( GetFileName(), 4 );
ISTREAM * pStream = &Stream;
pCCB->SetStream( pStream, this );
// Set HasStublessProxies and HasOi2 for each interface.
EvaluateVersionControl();
EmitFileHeadingBlock( pCCB, "the proxy stub code" );
SetNoOutputIn2ndCodegen( pCCB );
//
// Check if midl was invoked with -O1. This means we can create
// binaries using stubless proxies (if also compiled -Oi). These
// proxies will not work on 807.
//
if ( GetNdrVersionControl().HasStublessProxies() )
{
pStream->NewLine();
pStream->Write( "#define USE_STUBLESS_PROXY" );
pStream->NewLine();
}
// rpcproxy.h version guard
pStream->NewLine(2);
char sz[192];
pStream->Write( GetRpcProxyHVersionGuard( sz ) );
//
// Emit the hash includes.
//
Out_IncludeOfFile( pCCB, "rpcproxy.h", FALSE );
// rpcproxy.h version guard
char *sz2 = "\n"
"#ifndef __RPCPROXY_H_VERSION__\n"
"#error this stub requires an updated version of <rpcproxy.h>\n"
"#endif // __RPCPROXY_H_VERSION__\n\n";
pStream->Write( sz2 );
_splitpath( GetHeaderFileName(), Drive, Path, Name, Ext );
strcpy( Buffer, Name );
strcat( Buffer, Ext );
Out_IncludeOfFile( pCCB, Buffer, FALSE );
EmitFormatStringTypedefs( pCCB );
Out_TransferSyntaxDefs( pCCB );
//
// Emit the external variables needed.
//
pStream->NewLine();
//
// Emit the format string extern declarations.
//
Out_FormatInfoExtern( pCCB );
Out_TypeFormatStringExtern( pCCB );
Out_ProcFormatStringExtern( pCCB );
pCCB->ClearOptionalExternFlags();
pStream->NewLine();
pCCB->SetFileCG(this);
MIDL_ASSERT( pCommand->IsNDR64Run() || pCommand->IsNDRRun() );
if ( pCommand->IsNDR64Run() )
{
pCCB->SetFormatString( NULL );
pCCB->SetProcFormatString( NULL );
pCCB->SetNdr64Format( GenNdr64Format::CreateInstance( pCCB ) );
}
else
{
//
// Create a new format string object if it does not yet exist.
//
if ( !pCCB->GetFormatString() )
{
pCCB->SetFormatString( new FORMAT_STRING() );
// push a dummy short 0 at the beginning. This disambiguates
// the case where offset 0 means recursion and a valid offset
// if ( !pCommand->IsSwitchDefined( SWITCH_INTERNAL ) )
// {
pCCB->GetFormatString()->PushShort( ( short ) 0 );
// }
}
if ( !pCCB->GetProcFormatString() )
{
pCCB->SetProcFormatString( new FORMAT_STRING() );
}
}
// make the list of interfaces provided by this proxy file
MakeImplementedInterfacesList( pCCB );
//
// Send the message to the children to emit code.
//
//
// generate code for all [object] interfaces in the IDL file.
//
while( ITERATOR_GETNEXT( I, pCG ) )
{
switch(pCG->GetCGID())
{
case ID_CG_INHERITED_OBJECT_INTERFACE:
{
CG_INHERITED_OBJECT_INTERFACE * pInhObjCG =
( CG_INHERITED_OBJECT_INTERFACE * ) pCG;
//
// Generate format string description for all procs.
//
pInhObjCG->GenProxy( pCCB );
break;
}
case ID_CG_OBJECT_INTERFACE:
{
CG_OBJECT_INTERFACE * pObjCG;
pObjCG = (CG_OBJECT_INTERFACE *) pCG;
// make no code or tables for local interfaces
pObjCG->GenProxy( pCCB );
if ( pObjCG->IsLocal() )
break;
index++; // index is index in stub/proxy buffer tables
break;
}
default:
break;
}
}
Out_NotifyTable( pCCB );
pCCB->SetSkipFormatStreamGeneration( FALSE );
pStream->NewLine();
// BUGBUG: figure out where to put this. yongqu
// pStream->Write( "#pragma data_seg(\".rdata\")" );
// pStream->NewLine();
ResetNoOutputIn2ndCodegen( pCCB );
pCCB->OutputExternsToMultipleInterfaceTables();
EmitFixupToFormatStringTypedefs( pCCB );
pCCB->OutputMultipleInterfaceTables();
ITERATOR_INIT( I );
while( ITERATOR_GETNEXT( I, pCG ) )
{
switch(pCG->GetCGID())
{
case ID_CG_INTERFACE:
((CG_INTERFACE *)pCG)->OutputInterfaceIdComment( pCCB );
break;
case ID_CG_INHERITED_OBJECT_INTERFACE:
{
CG_INHERITED_OBJECT_INTERFACE * pInhObjCG =
( CG_INHERITED_OBJECT_INTERFACE * ) pCG;
//
// Generate format string description for all procs.
//
pInhObjCG->OutputInterfaceIdComment( pCCB );
pInhObjCG->OutputProxy( pCCB );
// make no code or tables for local interfaces
if ( pInhObjCG->IsLocal() )
break;
//
// Both of these do nothing right now. 4/25.
//
pInhObjCG->GenInterfaceProxy( pCCB, index );
pInhObjCG->GenInterfaceStub( pCCB, index );
break;
}
case ID_CG_OBJECT_INTERFACE:
{
CG_OBJECT_INTERFACE * pObjCG;
pObjCG = (CG_OBJECT_INTERFACE *) pCG;
// make no code or tables for local interfaces
pObjCG->OutputInterfaceIdComment( pCCB );
pObjCG->OutputProxy( pCCB );
if ( pObjCG->IsLocal() )
break;
pObjCG->GenInterfaceProxy( pCCB, index ); // index is not used
pObjCG->GenInterfaceStub( pCCB, index ); // index is not used
index++; // index is index in stub/proxy buffer tables
break;
}
default:
break;
}
}
Out_StubDescriptor(0, pCCB);
if ( pCommand->IsFinalProtocolRun() )
Out_ProxyFileInfo(pCCB);
EmitFileClosingBlock( pCCB );
UpdateDLLDataFile( pCCB );
return CG_OK;
}
void
CG_HDR_FILE::OutputImportIncludes(
CCB * pCCB)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the header file.
Arguments:
pCCB - The code gen controller block.
Return Value:
none.
Notes:
----------------------------------------------------------------------------*/
{
ITERATOR * pImpList = GetImportList();
node_file * pIFile;
ISTREAM * pStream = pCCB->GetStream();
char Buffer[ _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 1 ];
char Drive[ _MAX_DRIVE ];
char Path[ _MAX_DIR ];
char Name[ _MAX_FNAME ];
char Ext[ _MAX_EXT ];
if( pImpList && pImpList->NonNull() )
{
pStream->NewLine();
pStream->Write( "/* header files for imported files */" );
pImpList->Init();
while( ITERATOR_GETNEXT( (*pImportList), pIFile ) )
{
pStream->NewLine();
// if this was specified with ACF include, print out as is
if ( pIFile->IsAcfInclude() )
sprintf( Buffer, "#include \"%s\"", pIFile->GetSymName() );
else if ( pIFile->HasComClasses() )
{
_splitpath( pIFile->GetSymName(), Drive, Path, Name, Ext );
sprintf( Buffer, "#include \"%s_d.h\"", Name );
}
else
{
_splitpath( pIFile->GetSymName(), Drive, Path, Name, Ext );
sprintf( Buffer, "#include \"%s.h\"", Name );
}
pStream->Write( Buffer );
}
pStream->NewLine();
}
}
void OutputInterfaceForwards(
ISTREAM * pStream,
CG_ITERATOR & I )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the forwards section of the header file.
Arguments:
pCCB - The code gen controller block.
I - an iterator for the nodes to process
Return Value:
none.
Notes:
----------------------------------------------------------------------------*/
{
CG_INTERFACE * pCG;
char * pszInterfaceName;
ID_CG id;
while( ITERATOR_GETNEXT( I, pCG ) )
{
id = pCG->GetCGID();
switch( id )
{
case ID_CG_INTERFACE:
case ID_CG_INHERITED_OBJECT_INTERFACE:
break;
case ID_CG_OBJECT_INTERFACE:
case ID_CG_DISPINTERFACE:
case ID_CG_COCLASS:
pszInterfaceName = pCG->GetType()->GetSymName();
pStream->NewLine();
// put out the interface guards
pStream->Write("\n#ifndef __");
pStream->Write( pszInterfaceName );
pStream->Write( "_FWD_DEFINED__\n" );
pStream->Write( "#define __");
pStream->Write( pszInterfaceName );
pStream->Write( "_FWD_DEFINED__\n" );
// put out the forward definition
if ( ID_CG_COCLASS == id )
{
pStream->Write("\n#ifdef __cplusplus\n");
pStream->Write("typedef class ");
pStream->Write(pszInterfaceName);
pStream->Write(' ');
pStream->Write(pszInterfaceName);
pStream->Write(';');
pStream->Write("\n#else\n");
pStream->Write("typedef struct ");
pStream->Write(pszInterfaceName);
pStream->Write(' ');
pStream->Write(pszInterfaceName);
pStream->Write(';');
pStream->Write( "\n#endif /* __cplusplus */\n");
}
else
{
pStream->Write("typedef interface ");
pStream->Write(pszInterfaceName);
pStream->Write(' ');
pStream->Write(pszInterfaceName);
pStream->Write(';');
}
// put out the trailing interface guard
pStream->Write( "\n#endif \t/* __");
pStream->Write( pszInterfaceName );
pStream->Write( "_FWD_DEFINED__ */\n" );
break;
case ID_CG_LIBRARY:
{
CG_ITERATOR Inner;
if ( pCG->GetMembers( Inner ) )
{
OutputInterfaceForwards( pStream, Inner );
}
break;
}
default:
break;
}
}
}
#define NibbleToAscii(x) ((x) >= 0x0A ? (x) + 'A' - 0x0A : (x) + '0')
#define IsAlphaNum_(x) (((x) >= '0' && (x) <= '9') || ((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z') || (x) == '_')
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Setup a flag (fIgnore) in STREAM no to write anything out .
Arguments:
Return Value:
none.
Notes:
This routine is called to avoid generating the same data structure twice, in
both NDR32 and NDR64 run.
----------------------------------------------------------------------------*/
void SetNoOutputIn2ndCodegen( CCB *pCCB)
{
if ( pCommand->Is2ndCodegenRun() )
{
pCCB->GetStream()->SetIgnore();
}
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Reset Ignore flag in STREAM so Write will really write to the stream.
Arguments:
Return Value:
none.
Notes:
This routine is called to avoid generating the same data structure twice, in
both NDR32 and NDR64 run. This should be called after SetNoOutputInNdr64 to
resume regular output to stream. Current I assume we'll already generate both.
The correct checking should be Is2ndNdrRun().
----------------------------------------------------------------------------*/
void ResetNoOutputIn2ndCodegen( CCB *pCCB)
{
if ( pCommand->Is2ndCodegenRun() )
{
pCCB->GetStream()->ResetIgnore();
}
}
void NormalizeString(
char* szSrc,
char* szNrm )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Transform a string by converting spaces to underscores and other non-
alphanumerics to thier hex representation.
Arguments:
szSrc - The source string
szNrm - The normalized string
Return Value:
none.
Notes:
This routine is typically called when some generated variable is biased
by the filename. If the filename has a space or DBCS chars then the
generated variable wouldn't conform to C/C++ naming rules.
----------------------------------------------------------------------------*/
{
for ( ; *szSrc; szSrc++ )
{
if (IsAlphaNum_(*szSrc))
{
*szNrm++ = *szSrc;
}
else if (*szSrc == ' ')
{
*szNrm++ = '_';
}
else
{
unsigned char ch;
ch = unsigned char( (*szSrc >> 4) & 0x0F );
*szNrm++ = (char) NibbleToAscii(ch);
ch = unsigned char(*szSrc & 0x0F);
*szNrm++ = (char)NibbleToAscii(ch);
}
}
*szNrm = 0;
}
CG_STATUS
CG_HDR_FILE::GenCode(
CCB * pCCB)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the header file.
Arguments:
pCCB - The code gen controller block.
Return Value:
CG_OK if all is well.
Notes:
----------------------------------------------------------------------------*/
{
ISTREAM Stream( GetFileName(), 4 );
ISTREAM * pStream = pCCB->SetStream( &Stream, this );
CG_ITERATOR I;
CG_INTERFACE * pCG;
BOOL fHasPickle = FALSE;
BOOL fHasObject = FALSE;
char Buffer[ _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 1 ];
char Drive[ _MAX_DRIVE ];
char Path[ _MAX_DIR ];
char Name[ _MAX_FNAME ];
char Ext[ _MAX_EXT ];
if( !GetMembers( I ) )
{
return CG_OK;
}
if ( pCommand->Is64BitEnv() && pCommand->HasAppend64() )
{
// Don't generate the same h file definitions twice.
return CG_OK;
}
EmitFileHeadingBlock( pCCB,
"the definitions for the interfaces",
0, // optional comment
false ); // no 64 vs.32 ifdef
while( ITERATOR_GETNEXT( I, pCG ) )
{
if ( pCG->HasPicklingStuff() )
{
fHasPickle = TRUE;
}
if ( pCG->IsObject() )
{
fHasObject = TRUE;
}
}
// rpcndr.h version guard
pStream->NewLine(2);
char sz[192];
pStream->Write( GetRpcNdrHVersionGuard( sz ) );
// Include standard files.
pStream->Write( "#include \"rpc.h\"\n#include \"rpcndr.h\"\n" );
// rpcndr.h version guard
if ( pCommand->GetNdrVersionControl().HasNdr50Feature() || fHasObject )
{
char *sz2 = "\n"
"#ifndef __RPCNDR_H_VERSION__\n"
"#error this stub requires an updated version of <rpcndr.h>\n"
"#endif // __RPCNDR_H_VERSION__\n\n";
pStream->Write( sz2 );
}
// If there is at least one pickle interface, emit the include
// of midles.h
if ( fHasPickle )
{
pStream->Write( "#include \"midles.h\"\n" );
}
if ( fHasObject )
{
pStream->Write( "#ifndef COM_NO_WINDOWS_H\n");
pStream->Write( "#include \"windows.h\"\n#include \"ole2.h\"\n" );
pStream->Write( "#endif /*COM_NO_WINDOWS_H*/\n");
}
// extract the name and the extension to create the ifdefs
_splitpath( GetFileName(), Drive, Path, Name, Ext );
char szNrmName[ _MAX_FNAME * 2 + 1 ];
char szNrmExt[ _MAX_EXT * 2 + 1 ];
NormalizeString( Name, szNrmName );
// ignore the '.' preceding the extension
if ( '.' == Ext[0] )
NormalizeString( &Ext[1], szNrmExt );
else
NormalizeString( Ext, szNrmExt );
// Write out the #ifndefs and #defines
pStream->NewLine();
sprintf( Buffer,
"#ifndef __%s_%s__\n#define __%s_%s__",
szNrmName,
szNrmExt,
szNrmName,
szNrmExt
);
pStream->Write( Buffer );
pStream->NewLine( 2 );
// Generate the #pragma once.
pStream->Write( "#if defined(_MSC_VER) && (_MSC_VER >= 1020)\n" );
pStream->Write( "#pragma once\n#endif" );
pStream->NewLine(2);
//Generate forward declarations for object interfaces.
pStream->Write("/* Forward Declarations */ ");
I.Init();
OutputInterfaceForwards( pStream, I );
pStream->NewLine();
// Include the import files.
OutputImportIncludes( pCCB );
pStream->NewLine();
// Write out the cplusplus guard.
pStream->Write( "#ifdef __cplusplus\nextern \"C\"{\n#endif " );
pStream->NewLine( 2 );
pStream->Write(
"void * __RPC_USER MIDL_user_allocate(size_t);" );
pStream->NewLine();
pStream->Write(
"void __RPC_USER MIDL_user_free( void * ); " );
pStream->NewLine();
//
// For all interfaces in this file, generate code.
//
I.Init();
while( ITERATOR_GETNEXT( I, pCG ) )
{
switch(pCG->GetCGID())
{
case ID_CG_INTERFACE:
case ID_CG_OBJECT_INTERFACE:
case ID_CG_LIBRARY:
pCG->GenHeader( pCCB );
case ID_CG_INHERITED_OBJECT_INTERFACE:
default:
break;
}
}
// put out all the prototypes that are only needed once
OutputMultipleInterfacePrototypes( pCCB );
// print out the closing endifs.
// first the cplusplus stuff.
pStream->Write( "#ifdef __cplusplus\n}\n#endif\n" );
// The endif for the file name ifndef
pStream->NewLine();
pStream->Write( "#endif" );
pStream->NewLine();
EmitFileClosingBlock( pCCB, false );
pStream->Close();
return CG_OK;
}
void
CG_HDR_FILE::OutputMultipleInterfacePrototypes(
CCB * pCCB )
{
ITERATOR I;
ITERATOR UserI;
ISTREAM * pStream = pCCB->GetStream();
pStream->NewLine();
pStream->Write("/* Additional Prototypes for ALL interfaces */");
pStream->NewLine();
// ALERT! we are using the same iterator for all different type of objects,
// so none of code below should Init the list or it'll step into something else.
// Use a new iterator if you need to rewind the list.
if( pCCB->GetListOfGenHdlTypes( I ) )
{
Out_GenHdlPrototypes( pCCB, I );
}
if( pCCB->GetListOfCtxtHdlTypes( I ) )
{
Out_CtxtHdlPrototypes( pCCB, I );
}
if( pCCB->GetListOfPresentedTypes( I ) )
{
Out_TransmitAsPrototypes( pCCB, I );
}
if( pCCB->GetListOfRepAsWireTypes( I ) )
{
Out_RepAsPrototypes( pCCB, I );
}
if( pCCB->GetQuadrupleDictionary()->GetListOfItems( UserI ) )
{
Out_UserMarshalPrototypes( pCCB, UserI );
}
Out_CSSizingAndConversionPrototypes( pCCB, pCCB->GetCsTypeList() );
if( pCCB->GetListOfTypeAlignSizeTypes( I ) )
{
Out_TypeAlignSizePrototypes( pCCB, I );
}
if( pCCB->GetListOfTypeEncodeTypes( I ) )
{
Out_TypeEncodePrototypes( pCCB, I );
}
if( pCCB->GetListOfTypeDecodeTypes( I ) )
{
Out_TypeDecodePrototypes( pCCB, I );
}
if( pCCB->GetListOfTypeFreeTypes( I ) )
{
Out_TypeFreePrototypes( pCCB, I );
}
if ( pCCB->GetListOfCallAsRoutines( I ) )
{
Out_CallAsProxyPrototypes( pCCB, I );
}
if ( pCCB->GetListOfCallAsRoutines( I ) )
{
Out_CallAsServerPrototypes( pCCB, I );
}
if( pCCB->GetListOfNotifyTableEntries( I ) )
{
Out_NotifyPrototypes( pCCB, I );
}
pStream->NewLine();
pStream->Write("/* end of Additional Prototypes */");
pStream->NewLine( 2 );
}