mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2953 lines
63 KiB
2953 lines
63 KiB
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
filecls.hxx
|
|
|
|
Abstract:
|
|
|
|
Code generation methods for file cg classes.
|
|
|
|
Notes:
|
|
|
|
|
|
History:
|
|
|
|
Sep-01-1993 VibhasC Created.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
/****************************************************************************
|
|
* include files
|
|
***************************************************************************/
|
|
#include "becls.hxx"
|
|
#pragma hdrstop
|
|
|
|
/****************************************************************************
|
|
* local definitions
|
|
***************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* local data
|
|
***************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* externs
|
|
***************************************************************************/
|
|
extern CMD_ARG * pCommand;
|
|
|
|
extern BOOL IsTempName( char * );
|
|
|
|
/****************************************************************************/
|
|
|
|
void
|
|
CG_FILE::CheckForHeadingToken(
|
|
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();
|
|
|
|
if ( pCCB->IsReparsingCurrentFile() )
|
|
{
|
|
MIDL_TOKEN FoundToken;
|
|
|
|
((RW_ISTREAM *) pStream)->SaveToNextMidlToken( FoundToken );
|
|
if ( FoundToken.GetTokenType() != FILE_HEADING_TOKEN )
|
|
{
|
|
assert(!"expecting file heading token" );
|
|
}
|
|
}
|
|
|
|
pStream->EmitToken( MIDL_TOKEN( FILE_HEADING_TOKEN ) );
|
|
pStream->NewLine();
|
|
}
|
|
|
|
void
|
|
CG_FILE::EmitStandardHeadingBlock(
|
|
CCB * pCCB,
|
|
char * CommentStr )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
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();
|
|
|
|
if ( CommentStr )
|
|
pStream->Write( CommentStr );
|
|
else
|
|
pStream->Write( "/*" );
|
|
|
|
pStream->Write(" File created by MIDL compiler version ");
|
|
pStream->Write( GetCompilerVersion() );
|
|
if ( CommentStr == 0 )
|
|
pStream->Write(" */");
|
|
|
|
pStream->NewLine();
|
|
|
|
if ( CommentStr )
|
|
pStream->Write( CommentStr );
|
|
else
|
|
pStream->Write( "/*" );
|
|
|
|
pStream->Write(" at ");
|
|
pStream->Write( GetCompileTime() );
|
|
if ( CommentStr == 0 )
|
|
pStream->Write(" */");
|
|
pStream->NewLine();
|
|
|
|
// Emit command line switches information.
|
|
|
|
pCommand->EmitConfirm( pStream );
|
|
|
|
if ( pCCB->IsReparsingCurrentFile() )
|
|
{
|
|
MIDL_TOKEN FoundToken;
|
|
|
|
((RW_ISTREAM *) pStream)->DiscardToNextMidlToken( FoundToken );
|
|
if ( FoundToken.GetTokenType() != FILE_HEADING_TOKEN )
|
|
{
|
|
assert(!"expecting file heading token" );
|
|
}
|
|
}
|
|
|
|
pStream->EmitToken( MIDL_TOKEN( FILE_HEADING_TOKEN ) );
|
|
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.
|
|
|
|
Arguments:
|
|
|
|
pCCB - a pointer to the code generation control block.
|
|
|
|
Notes:
|
|
|
|
The typedefs are going to be fixed later by a call to
|
|
EmitFixupFormatStringTpedefs. This is needed for ANSI.
|
|
The dummies would work for ANSI non-compliant code.
|
|
|
|
--------------------------------------------------------------------------*/
|
|
{
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
pStream->NewLine(2);
|
|
pStream->Write( "#define TYPE_FORMAT_STRING_SIZE " );
|
|
SetTypeSizeContextPosition( pStream->GetCurrentPosition() );
|
|
pStream->Write( " " );
|
|
pStream->NewLine();
|
|
|
|
pStream->Write( "#define PROC_FORMAT_STRING_SIZE " );
|
|
SetProcSizeContextPosition( pStream->GetCurrentPosition() );
|
|
pStream->Write( " " );
|
|
|
|
if (pCommand->IsHookOleEnabled())
|
|
{
|
|
pStream->NewLine();
|
|
pStream->Write( "#define LOCAL_TYPE_FORMAT_STRING_SIZE " );
|
|
SetLocalTypeSizeContextPosition( pStream->GetCurrentPosition() );
|
|
pStream->Write( " " );
|
|
pStream->NewLine();
|
|
|
|
pStream->Write( "#define LOCAL_PROC_FORMAT_STRING_SIZE " );
|
|
SetLocalProcSizeContextPosition( pStream->GetCurrentPosition() );
|
|
pStream->Write( " " );
|
|
}
|
|
pStream->NewLine(2);
|
|
|
|
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();
|
|
|
|
if (pCommand->IsHookOleEnabled())
|
|
{
|
|
pStream->NewLine();
|
|
pStream->Write( "typedef struct _" LOCAL_FORMAT_STRING_TYPE_NAME );
|
|
pStream->IndentInc();
|
|
pStream->Write( "{" );
|
|
pStream->NewLine();
|
|
pStream->Write( "short Pad;" );
|
|
pStream->NewLine();
|
|
pStream->Write( "unsigned char Format[ LOCAL_TYPE_FORMAT_STRING_SIZE ];" );
|
|
pStream->NewLine();
|
|
pStream->Write( "} " LOCAL_FORMAT_STRING_TYPE_NAME ";" );
|
|
pStream->IndentDec();
|
|
pStream->NewLine(2);
|
|
|
|
pStream->Write( "typedef struct _" LOCAL_PROC_FORMAT_STRING_TYPE_NAME );
|
|
pStream->IndentInc();
|
|
pStream->NewLine();
|
|
pStream->Write( "{" );
|
|
pStream->NewLine();
|
|
pStream->Write( "short Pad;" );
|
|
pStream->NewLine();
|
|
pStream->Write( "unsigned char Format[ LOCAL_PROC_FORMAT_STRING_SIZE ];" );
|
|
pStream->NewLine();
|
|
pStream->Write( "} " LOCAL_PROC_FORMAT_STRING_TYPE_NAME ";" );
|
|
pStream->IndentDec();
|
|
pStream->NewLine();
|
|
}
|
|
}
|
|
|
|
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 = pStream->GetCurrentPosition();
|
|
|
|
pStream->SetCurrentPosition( GetTypeSizeContextPosition() );
|
|
sprintf( Buffer, "%d", pCCB->GetFormatString()->GetCurrentOffset() + 1);
|
|
pStream->Write( Buffer );
|
|
|
|
pStream->SetCurrentPosition( GetProcSizeContextPosition() );
|
|
sprintf( Buffer, "%d", pCCB->GetProcFormatString()->GetCurrentOffset() + 1);
|
|
pStream->Write( Buffer );
|
|
|
|
if ( pCommand->IsHookOleEnabled() )
|
|
{
|
|
pStream->SetCurrentPosition( GetLocalTypeSizeContextPosition() );
|
|
sprintf( Buffer, "%d", GetLocalFormatString()->GetCurrentOffset() + 1);
|
|
pStream->Write( Buffer );
|
|
|
|
pStream->SetCurrentPosition( GetLocalProcSizeContextPosition() );
|
|
sprintf( Buffer, "%d", GetLocalProcFormatString()->GetCurrentOffset() + 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;
|
|
}
|
|
|
|
void
|
|
CG_CSTUB_FILE::EmitFileHeadingBlock(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Emit block comment file heading.
|
|
|
|
Arguments:
|
|
|
|
pCCB - a pointer to the code generation control block.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
pStream->Write( "/* this ALWAYS GENERATED file contains the RPC client stubs */" );
|
|
pStream->NewLine(2);
|
|
|
|
EmitStandardHeadingBlock( pCCB );
|
|
}
|
|
|
|
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);
|
|
|
|
// Set HasStublessProxies and HasOi2 for each interface.
|
|
|
|
EvaluateVersionControl();
|
|
|
|
EmitFileHeadingBlock( pCCB );
|
|
|
|
// Emit the hash includes.
|
|
|
|
Out_IncludeOfFile( pCCB, STRING_H_INC_FILE_NAME, TRUE );
|
|
pStream->NewLine();
|
|
pStream->Write( ALPHA_IFDEF );
|
|
Out_IncludeOfFile( pCCB, STDARG_H_INC_FILE_NAME, TRUE );
|
|
pStream->NewLine();
|
|
pStream->Write( "#endif");
|
|
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 );
|
|
|
|
//
|
|
// Emit the external variables needed.
|
|
//
|
|
|
|
pStream->NewLine();
|
|
|
|
//
|
|
// Emit the format string extern declarations.
|
|
//
|
|
Out_TypeFormatStringExtern( pCCB );
|
|
Out_ProcFormatStringExtern( pCCB );
|
|
Out_LocalTypeFormatStringExtern( pCCB );
|
|
Out_LocalProcFormatStringExtern( pCCB );
|
|
|
|
|
|
pCCB->ClearOptionalExternFlags();
|
|
|
|
pCCB->SetFileCG(this);
|
|
|
|
//
|
|
// Create a new format string object if it does not yet exist.
|
|
//
|
|
if ( !GetFormatString() )
|
|
{
|
|
SetFormatString(new FORMAT_STRING());
|
|
SetLocalFormatString(new FORMAT_STRING());
|
|
}
|
|
pCCB->SetFormatString( GetFormatString() );
|
|
|
|
if ( !GetProcFormatString() )
|
|
{
|
|
SetProcFormatString(new FORMAT_STRING());
|
|
SetLocalProcFormatString(new FORMAT_STRING());
|
|
}
|
|
pCCB->SetProcFormatString( GetProcFormatString() );
|
|
|
|
//
|
|
// Send the message to the children to emit code.
|
|
//
|
|
|
|
//
|
|
// for all interfaces in this file, generate code.
|
|
//
|
|
|
|
ITERATOR_INIT( I );
|
|
|
|
while( ITERATOR_GETNEXT( I, pCG ) )
|
|
{
|
|
switch(pCG->GetCGID())
|
|
{
|
|
case ID_CG_INTERFACE:
|
|
((CG_INTERFACE *)pCG)->OutputInterfaceIdComment( pCCB );
|
|
((CG_INTERFACE *)pCG)->GenClientStub( pCCB );
|
|
break;
|
|
|
|
case ID_CG_OBJECT_INTERFACE:
|
|
case ID_CG_INHERITED_OBJECT_INTERFACE:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Output the tables that may be common to several interfaces.
|
|
//
|
|
EmitFixupToFormatStringTypedefs( pCCB );
|
|
|
|
pCCB->OutputMultipleInterfaceTables(GetLocalFormatString(), GetLocalProcFormatString());
|
|
|
|
return CG_OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* sstub file implementation class.
|
|
***************************************************************************/
|
|
|
|
|
|
void
|
|
CG_SSTUB_FILE::EmitFileHeadingBlock(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Emit block comment file heading.
|
|
|
|
Arguments:
|
|
|
|
pCCB - a pointer to the code generation control block.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
pStream->Write( "/* this ALWAYS GENERATED file contains the RPC server stubs */" );
|
|
pStream->NewLine(2);
|
|
|
|
EmitStandardHeadingBlock( pCCB );
|
|
}
|
|
|
|
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);
|
|
|
|
// Set HasStublessProxies and HasOi2 for each interface.
|
|
|
|
EvaluateVersionControl();
|
|
|
|
EmitFileHeadingBlock( pCCB );
|
|
|
|
//
|
|
// Emit the hash includes.
|
|
//
|
|
|
|
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 );
|
|
|
|
//
|
|
// Emit the external variables needed.
|
|
//
|
|
|
|
//
|
|
// Emit the format string extern declarations.
|
|
//
|
|
Out_TypeFormatStringExtern( pCCB );
|
|
Out_ProcFormatStringExtern( pCCB );
|
|
Out_LocalTypeFormatStringExtern( pCCB );
|
|
Out_LocalProcFormatStringExtern( pCCB );
|
|
|
|
pCCB->ClearOptionalExternFlags();
|
|
|
|
pCCB->SetFileCG(this);
|
|
|
|
//
|
|
// Create a new format string object if it does not exist.
|
|
//
|
|
if ( !GetFormatString() )
|
|
{
|
|
SetFormatString(new FORMAT_STRING());
|
|
SetLocalFormatString(new FORMAT_STRING());
|
|
}
|
|
pCCB->SetFormatString( GetFormatString() );
|
|
|
|
if ( !GetProcFormatString() )
|
|
{
|
|
SetProcFormatString(new FORMAT_STRING());
|
|
SetLocalProcFormatString(new FORMAT_STRING());
|
|
}
|
|
pCCB->SetProcFormatString( GetProcFormatString() );
|
|
|
|
//
|
|
// Send the message to the children to emit code.
|
|
//
|
|
|
|
//
|
|
// For all interfaces in this file, generate code.
|
|
//
|
|
|
|
PNAME ContextHandleTypeName = NULL;
|
|
BOOL GotContextHandle = FALSE;
|
|
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)->GenServerStub( pCCB );
|
|
|
|
if ( ((CG_INTERFACE *)pCG)->HasInterpretedProc() )
|
|
HasInterpretedProc = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Output the tables that may be common to several interfaces.
|
|
|
|
pCCB->SetCodeGenSide( CGSIDE_SERVER );
|
|
|
|
//
|
|
// 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( pCCB->GetOptimOption() | OPTIMIZE_INTERPRETER );
|
|
|
|
pCCB->OutputMultipleInterfaceTables(GetLocalFormatString(), GetLocalProcFormatString());
|
|
|
|
return CG_OK;
|
|
}
|
|
|
|
|
|
class GUID_DICTIONARY : public Dictionary
|
|
{
|
|
public:
|
|
GUID_DICTIONARY()
|
|
{
|
|
}
|
|
|
|
virtual
|
|
int 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 * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
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;
|
|
|
|
if ( ((CG_OBJECT_INTERFACE*)pCG)->IsLocal() && !pCommand->IsHookOleEnabled())
|
|
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();
|
|
}
|
|
|
|
|
|
void
|
|
CG_PROXY_FILE::EmitFileHeadingBlock(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Emit block comment file heading.
|
|
|
|
Arguments:
|
|
|
|
pCCB - a pointer to the code generation control block.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
pStream->Write( "/* this ALWAYS GENERATED file contains the proxy stub code */" );
|
|
pStream->NewLine(2);
|
|
|
|
EmitStandardHeadingBlock( pCCB );
|
|
}
|
|
|
|
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);
|
|
|
|
// Set HasStublessProxies and HasOi2 for each interface.
|
|
|
|
EvaluateVersionControl();
|
|
|
|
EmitFileHeadingBlock( 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();
|
|
}
|
|
|
|
//
|
|
// Emit the hash includes.
|
|
//
|
|
Out_IncludeOfFile( pCCB, "rpcproxy.h", FALSE );
|
|
|
|
_splitpath( GetHeaderFileName(), Drive, Path, Name, Ext );
|
|
strcpy( Buffer, Name );
|
|
strcat( Buffer, Ext );
|
|
Out_IncludeOfFile( pCCB, Buffer, FALSE );
|
|
|
|
EmitFormatStringTypedefs( pCCB );
|
|
|
|
//
|
|
// Emit the external variables needed.
|
|
//
|
|
|
|
pStream->NewLine();
|
|
|
|
//
|
|
// Emit the format string extern declarations.
|
|
//
|
|
Out_TypeFormatStringExtern( pCCB );
|
|
Out_ProcFormatStringExtern( pCCB );
|
|
Out_LocalTypeFormatStringExtern( pCCB );
|
|
Out_LocalProcFormatStringExtern( pCCB );
|
|
|
|
pCCB->ClearOptionalExternFlags();
|
|
|
|
pStream->NewLine();
|
|
|
|
pCCB->SetFileCG(this);
|
|
|
|
//
|
|
// Create a new format string object if it does not yet exist.
|
|
//
|
|
if ( !GetFormatString() )
|
|
{
|
|
SetFormatString(new FORMAT_STRING());
|
|
SetLocalFormatString(new FORMAT_STRING());
|
|
}
|
|
pCCB->SetFormatString( GetFormatString() );
|
|
|
|
if ( !GetProcFormatString() )
|
|
{
|
|
SetProcFormatString(new FORMAT_STRING());
|
|
SetLocalProcFormatString(new FORMAT_STRING());
|
|
}
|
|
pCCB->SetProcFormatString( GetProcFormatString() );
|
|
|
|
// 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_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->GenCode( pCCB );
|
|
// make no code or tables for local interfaces
|
|
if ( pInhObjCG->IsLocal() && !pCommand->IsHookOleEnabled())
|
|
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 =
|
|
(CG_OBJECT_INTERFACE * ) pCG;
|
|
|
|
// make no code or tables for local interfaces
|
|
pObjCG->OutputInterfaceIdComment( pCCB );
|
|
pObjCG->GenCode( pCCB );
|
|
if ( pObjCG->IsLocal() && !pCommand->IsHookOleEnabled())
|
|
break;
|
|
pObjCG->GenInterfaceProxy( pCCB, index );
|
|
pObjCG->GenInterfaceStub( pCCB, index );
|
|
if (pObjCG->IsLocal())
|
|
break;
|
|
index++; // index is index in stub/proxy buffer tables
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
pCCB->SetSkipFormatStreamGeneration( FALSE );
|
|
|
|
pStream->NewLine();
|
|
pStream->Write( "#pragma data_seg(\".rdata\")" );
|
|
pStream->NewLine();
|
|
|
|
EmitFixupToFormatStringTypedefs( pCCB );
|
|
|
|
pCCB->OutputMultipleInterfaceTables(GetLocalFormatString(), GetLocalProcFormatString());
|
|
|
|
Out_ProxyFileInfo(pCCB);
|
|
|
|
UpdateDLLDataFile( pCCB );
|
|
|
|
return CG_OK;
|
|
}
|
|
|
|
|
|
void
|
|
CG_COM_METHODS_FILE::EmitFileHeadingBlock(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Emit block comment file heading.
|
|
|
|
Arguments:
|
|
|
|
pCCB - a pointer to the code generation control block.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
CheckForHeadingToken( pCCB );
|
|
|
|
pStream->Write( "/* this USER-ALTERABLE file contains the class methods for COM classes */" );
|
|
pStream->NewLine(2);
|
|
|
|
EmitStandardHeadingBlock( pCCB );
|
|
}
|
|
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
COM_METHODS_FILE overall structure:
|
|
|
|
<< optional user stuff >>
|
|
|
|
< MIDL header comment, always generated>
|
|
|
|
//@@MIDL_INCLUDES_LIST()
|
|
<headers>
|
|
//@@MIDL_INCLUDES_LIST_END()
|
|
|
|
repeat the below:
|
|
| //@@MIDL_CLASS( <class> )
|
|
|
|
|
| repeat the below:
|
|
| | //@@MIDL_CLASS_METHODS( <class::interface> )
|
|
| |
|
|
| | repeat the below:
|
|
| | | //@@MIDL_METHOD( <class::method> )
|
|
| | | <function header>
|
|
| | | //@@MIDL_METHOD_BODY( <class::method> )
|
|
| | |
|
|
| //@@MIDL_CLASS_END( class )
|
|
|
|
|
//@@MIDL_CLASS_METHODS_END()
|
|
|
|
user changes are preserved outside of :
|
|
the file includes block
|
|
the function headers
|
|
|
|
new methods/interfaces/classes have their stuff added at
|
|
the end of their block.
|
|
|
|
deleted methods/interfaces/classes are mentioned in added comments and
|
|
ignored.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
CG_STATUS
|
|
CG_COM_METHODS_FILE::GenCode(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Generate a COM server file containing the class factory and class
|
|
implementation for the COM classes 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;
|
|
unsigned long index = 0;
|
|
|
|
if( !GetMembers( I ) )
|
|
{
|
|
return CG_OK;
|
|
}
|
|
|
|
RW_ISTREAM Stream( GetFileName(), 4 );
|
|
RW_ISTREAM * pStream = &Stream;
|
|
|
|
pCCB->SetStream(pStream);
|
|
|
|
if ( Stream.IsTempStream() )
|
|
{
|
|
pCCB->SetReparsingCurrentFile( TRUE );
|
|
}
|
|
|
|
EmitFileHeadingBlock( pCCB );
|
|
|
|
//
|
|
// Emit the hash includes.
|
|
//
|
|
OutputIncludes( pCCB );
|
|
|
|
//
|
|
// Emit the external variables needed.
|
|
//
|
|
pStream->NewLine();
|
|
|
|
|
|
if ( Stream.IsTempStream() )
|
|
{
|
|
ParseAndGenCode( pCCB, pStream );
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// generate code for all com classes in the IDL file.
|
|
//
|
|
|
|
while( ITERATOR_GETNEXT( I, pCG ) )
|
|
{
|
|
switch(pCG->GetCGID())
|
|
{
|
|
case ID_CG_INHERITED_OBJECT_INTERFACE:
|
|
case ID_CG_OBJECT_INTERFACE:
|
|
|
|
if ( ((CG_OBJECT_INTERFACE*)pCG)->IsIUnknown() )
|
|
pCCB->SetIUnknownCG( (CG_IUNKNOWN_OBJECT_INTERFACE *) pCG );
|
|
else if ( !strcmp( pCG->GetSymName(), "IClassFactory" ) )
|
|
pCCB->SetIClassfCG( (CG_OBJECT_INTERFACE *) pCG );
|
|
break;
|
|
|
|
case ID_CG_COM_CLASS:
|
|
{
|
|
CG_COM_CLASS * pComCG = ( CG_COM_CLASS * ) pCG;
|
|
|
|
pComCG->GenComClassServer( pCCB );
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// propogate changes from the tmpfile, if any
|
|
Stream.UpdateOriginalFile();
|
|
|
|
pCCB->SetReparsingCurrentFile( FALSE );
|
|
|
|
return CG_OK;
|
|
}
|
|
|
|
|
|
CG_STATUS
|
|
CG_COM_METHODS_FILE::ParseAndGenCode(
|
|
CCB * pCCB,
|
|
RW_ISTREAM * pStream )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Generate a COM server file containing the class factory and class
|
|
implementation for the COM classes 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;
|
|
unsigned long index = 0;
|
|
|
|
if( !GetMembers( I ) )
|
|
{
|
|
return CG_OK;
|
|
}
|
|
|
|
//
|
|
// go through the old file, propogating changes and
|
|
// generating code for new things
|
|
//
|
|
|
|
while( ITERATOR_GETNEXT( I, pCG ) )
|
|
{
|
|
switch(pCG->GetCGID())
|
|
{
|
|
case ID_CG_INHERITED_OBJECT_INTERFACE:
|
|
case ID_CG_OBJECT_INTERFACE:
|
|
|
|
if ( ((CG_OBJECT_INTERFACE*)pCG)->IsIUnknown() )
|
|
pCCB->SetIUnknownCG( (CG_IUNKNOWN_OBJECT_INTERFACE *) pCG );
|
|
else if ( !strcmp( pCG->GetSymName(), "IClassFactory" ) )
|
|
pCCB->SetIClassfCG( (CG_OBJECT_INTERFACE *) pCG );
|
|
break;
|
|
|
|
case ID_CG_COM_CLASS:
|
|
{
|
|
CG_COM_CLASS * pComCG = ( CG_COM_CLASS * ) pCG;
|
|
|
|
pComCG->ReGenComClassServer( pCCB );
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return CG_OK;
|
|
}
|
|
|
|
|
|
void
|
|
CG_COM_IUNKNOWN_FILE::EmitFileHeadingBlock(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Emit block comment file heading.
|
|
|
|
Arguments:
|
|
|
|
pCCB - a pointer to the code generation control block.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
pStream->Write( "/* this ALWAYS GENERATED file contains the implementations of */" );
|
|
pStream->NewLine();
|
|
pStream->Write( "/* the IUnknowns and the class factories */" );
|
|
pStream->NewLine(2);
|
|
|
|
EmitStandardHeadingBlock( pCCB );
|
|
}
|
|
|
|
CG_STATUS
|
|
CG_COM_IUNKNOWN_FILE::GenCode(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Generate a COM server file containing the class factory and class
|
|
implementation for the COM classes 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;
|
|
unsigned long index = 0;
|
|
|
|
if( !GetMembers( I ) )
|
|
{
|
|
return CG_OK;
|
|
}
|
|
|
|
ISTREAM Stream( GetFileName(), 4 );
|
|
ISTREAM * pStream = &Stream;
|
|
|
|
pCCB->SetStream(pStream);
|
|
|
|
EmitFileHeadingBlock( pCCB );
|
|
|
|
Out_IncludeOfFile( pCCB, "rpcunkcf.h", FALSE );
|
|
//
|
|
// Emit the hash includes.
|
|
//
|
|
OutputIncludes( pCCB );
|
|
|
|
//
|
|
// Emit the external variables needed.
|
|
//
|
|
|
|
pStream->NewLine();
|
|
//
|
|
// generate code for all com classes in the IDL file.
|
|
//
|
|
|
|
while( ITERATOR_GETNEXT( I, pCG ) )
|
|
{
|
|
switch(pCG->GetCGID())
|
|
{
|
|
case ID_CG_INHERITED_OBJECT_INTERFACE:
|
|
case ID_CG_OBJECT_INTERFACE:
|
|
|
|
if ( ((CG_OBJECT_INTERFACE*)pCG)->IsIUnknown() )
|
|
pCCB->SetIUnknownCG( (CG_IUNKNOWN_OBJECT_INTERFACE *) pCG );
|
|
else if ( !strcmp( pCG->GetSymName(), "IClassFactory" ) )
|
|
pCCB->SetIClassfCG( (CG_OBJECT_INTERFACE *) pCG );
|
|
break;
|
|
|
|
case ID_CG_COM_CLASS:
|
|
{
|
|
CG_COM_CLASS * pComCG = ( CG_COM_CLASS * ) pCG;
|
|
|
|
pComCG->GenComClassIUnknown( pCCB );
|
|
pComCG->GenComClassFactory( pCCB );
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return CG_OK;
|
|
}
|
|
|
|
|
|
void
|
|
CG_PROXY_DEF_FILE::EmitFileHeadingBlock(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Emit block comment file heading.
|
|
|
|
Arguments:
|
|
|
|
pCCB - a pointer to the code generation control block.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
pStream->Write( "; this GENERATED ONCE file contains the contains the exports for the proxy dll */" );
|
|
pStream->NewLine(2);
|
|
|
|
EmitStandardHeadingBlock( pCCB, ";" );
|
|
}
|
|
|
|
CG_STATUS
|
|
CG_PROXY_DEF_FILE::GenCode(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Generate a COM server file containing the class factory and class
|
|
implementation for the COM classes 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;
|
|
unsigned long index = 0;
|
|
|
|
if( !GetMembers( I ) )
|
|
{
|
|
return CG_OK;
|
|
}
|
|
|
|
ISTREAM Stream( GetFileName(), 4 );
|
|
ISTREAM * pStream = &Stream;
|
|
|
|
pCCB->SetStream(pStream);
|
|
|
|
EmitFileHeadingBlock( pCCB );
|
|
|
|
//
|
|
// Emit the external variables needed.
|
|
//
|
|
|
|
pStream->NewLine();
|
|
//
|
|
// generate code for all com classes in the IDL file.
|
|
//
|
|
|
|
while( ITERATOR_GETNEXT( I, pCG ) )
|
|
{
|
|
#if 0
|
|
switch(pCG->GetCGID())
|
|
{
|
|
case ID_CG_INHERITED_OBJECT_INTERFACE:
|
|
case ID_CG_OBJECT_INTERFACE:
|
|
|
|
if ( ((CG_OBJECT_INTERFACE*)pCG)->IsIUnknown() )
|
|
pCCB->SetIUnknownCG( (CG_IUNKNOWN_OBJECT_INTERFACE *) pCG );
|
|
else if ( !strcmp( pCG->GetSymName(), "IClassFactory" ) )
|
|
pCCB->SetIClassfCG( (CG_OBJECT_INTERFACE *) pCG );
|
|
break;
|
|
|
|
case ID_CG_COM_CLASS:
|
|
{
|
|
CG_COM_CLASS * pComCG = ( CG_COM_CLASS * ) pCG;
|
|
|
|
pComCG->GenComClassIUnknown( pCCB );
|
|
pComCG->GenComClassFactory( pCCB );
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
return CG_OK;
|
|
}
|
|
|
|
|
|
void
|
|
CG_DLL_SERVER_DEF_FILE::EmitFileHeadingBlock(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Emit block comment file heading.
|
|
|
|
Arguments:
|
|
|
|
pCCB - a pointer to the code generation control block.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
pStream->Write( "; this GENERATED ONCE file contains the contains the implementations of the exports for */" );
|
|
pStream->NewLine();
|
|
pStream->Write( "; the InprocServer32 " );
|
|
pStream->NewLine(2);
|
|
|
|
EmitStandardHeadingBlock( pCCB, ";" );
|
|
}
|
|
|
|
CG_STATUS
|
|
CG_DLL_SERVER_DEF_FILE::GenCode(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Generate a COM server file containing the class factory and class
|
|
implementation for the COM classes 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;
|
|
unsigned long index = 0;
|
|
|
|
if( !GetMembers( I ) )
|
|
{
|
|
return CG_OK;
|
|
}
|
|
|
|
ISTREAM Stream( GetFileName(), 4 );
|
|
ISTREAM * pStream = &Stream;
|
|
|
|
pCCB->SetStream(pStream);
|
|
|
|
EmitFileHeadingBlock( pCCB );
|
|
|
|
//
|
|
// Emit the external variables needed.
|
|
//
|
|
|
|
//
|
|
// generate code for all com classes in the IDL file.
|
|
//
|
|
|
|
while( ITERATOR_GETNEXT( I, pCG ) )
|
|
{
|
|
switch(pCG->GetCGID())
|
|
{
|
|
case ID_CG_COM_SERVER_DLL:
|
|
{
|
|
CG_COM_SERVER_DLL * pDllCG = ( CG_COM_SERVER_DLL * ) pCG;
|
|
|
|
pDllCG->GenDllDefFile( pCCB );
|
|
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return CG_OK;
|
|
}
|
|
|
|
|
|
void
|
|
CG_DLL_SERVER_FILE::EmitFileHeadingBlock(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Emit block comment file heading.
|
|
|
|
Arguments:
|
|
|
|
pCCB - a pointer to the code generation control block.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
pStream->Write( "/* this ALWAYS GENERATED file contains the implementations of */" );
|
|
pStream->NewLine();
|
|
pStream->Write( "/* the IUnknowns and the class factories */" );
|
|
pStream->NewLine(2);
|
|
|
|
EmitStandardHeadingBlock( pCCB );
|
|
}
|
|
|
|
CG_STATUS
|
|
CG_DLL_SERVER_FILE::GenCode(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Generate a COM server file containing the class factory and class
|
|
implementation for the COM classes 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;
|
|
unsigned long index = 0;
|
|
|
|
if( !GetMembers( I ) )
|
|
{
|
|
return CG_OK;
|
|
}
|
|
|
|
ISTREAM Stream( GetFileName(), 4 );
|
|
ISTREAM * pStream = &Stream;
|
|
|
|
pCCB->SetStream(pStream);
|
|
|
|
EmitFileHeadingBlock( pCCB );
|
|
|
|
//
|
|
// Emit the hash includes.
|
|
//
|
|
Out_IncludeOfFile( pCCB, "rpcunkcf.h", FALSE );
|
|
|
|
pStream->NewLine();
|
|
OutputIncludes( pCCB );
|
|
|
|
//
|
|
// Emit the external variables needed.
|
|
//
|
|
|
|
pStream->NewLine();
|
|
//
|
|
// generate code for all com classes in the IDL file.
|
|
//
|
|
|
|
while( ITERATOR_GETNEXT( I, pCG ) )
|
|
{
|
|
switch(pCG->GetCGID())
|
|
{
|
|
case ID_CG_COM_SERVER_DLL:
|
|
case ID_CG_COM_SERVER_EXE:
|
|
{
|
|
pCG->GenCode( pCCB );
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return CG_OK;
|
|
}
|
|
|
|
|
|
void
|
|
CG_SERVER_REG_FILE::EmitFileHeadingBlock(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Emit block comment file heading.
|
|
|
|
Arguments:
|
|
|
|
pCCB - a pointer to the code generation control block.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
static STRING_BLOCK RegHeader =
|
|
{
|
|
"#",
|
|
"# This .reg file is recreated every time a dllserver or exeserver",
|
|
"# is processed by MIDL. User changes are preserved.",
|
|
"#",
|
|
"# the pathnames should be changed if the executables will not be",
|
|
"# in the system directory",
|
|
"#",
|
|
0
|
|
};
|
|
|
|
pStream->Write("REGEDIT");
|
|
|
|
pStream->NewLine();
|
|
EmitStandardHeadingBlock( pCCB, "#" );
|
|
|
|
pStream->WriteBlock( RegHeader );
|
|
|
|
}
|
|
|
|
CG_STATUS
|
|
CG_SERVER_REG_FILE::GenCode(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Generate a COM server file containing the class factory and class
|
|
implementation for the COM classes 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;
|
|
unsigned long index = 0;
|
|
|
|
if( !GetMembers( I ) )
|
|
{
|
|
return CG_OK;
|
|
}
|
|
|
|
ISTREAM Stream( GetFileName(), 4 );
|
|
ISTREAM * pStream = &Stream;
|
|
|
|
pCCB->SetStream(pStream);
|
|
|
|
//
|
|
// Emit the external variables needed.
|
|
//
|
|
|
|
EmitFileHeadingBlock( pCCB );
|
|
|
|
pStream->NewLine();
|
|
|
|
//
|
|
// generate code for all com classes in the IDL file.
|
|
//
|
|
|
|
while( ITERATOR_GETNEXT( I, pCG ) )
|
|
{
|
|
#if 0
|
|
switch(pCG->GetCGID())
|
|
{
|
|
case ID_CG_INHERITED_OBJECT_INTERFACE:
|
|
case ID_CG_OBJECT_INTERFACE:
|
|
|
|
if ( ((CG_OBJECT_INTERFACE*)pCG)->IsIUnknown() )
|
|
pCCB->SetIUnknownCG( (CG_IUNKNOWN_OBJECT_INTERFACE *) pCG );
|
|
else if ( !strcmp( pCG->GetSymName(), "IClassFactory" ) )
|
|
pCCB->SetIClassfCG( (CG_OBJECT_INTERFACE *) pCG );
|
|
break;
|
|
|
|
case ID_CG_COM_CLASS:
|
|
{
|
|
CG_COM_CLASS * pComCG = ( CG_COM_CLASS * ) pCG;
|
|
|
|
pComCG->GenComClassIUnknown( pCCB );
|
|
pComCG->GenComClassFactory( pCCB );
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
return CG_OK;
|
|
}
|
|
|
|
|
|
void
|
|
CG_COM_FILE::OutputIncludes(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
output an includes file list to the stream.
|
|
|
|
Arguments:
|
|
|
|
pCCB - a pointer to the code generation control block.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
char Buffer[ _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 1 ];
|
|
char Name[ _MAX_FNAME ];
|
|
char Ext[ _MAX_EXT ];
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
MIDL_TOKEN DelimiterToken( START_INCLUDES_TOKEN );
|
|
|
|
RW_ISTREAM * pOldStream = NULL;
|
|
|
|
if ( pCCB->IsReparsingCurrentFile() )
|
|
{
|
|
MIDL_TOKEN FoundToken;
|
|
|
|
pOldStream = (RW_ISTREAM *) pStream;
|
|
|
|
pOldStream->SaveToNextMidlToken( FoundToken );
|
|
if ( FoundToken.GetTokenType() != START_INCLUDES_TOKEN )
|
|
{
|
|
assert( 0 );
|
|
}
|
|
}
|
|
else
|
|
pStream->NewLine();
|
|
|
|
DelimiterToken.EmitToken( pStream );
|
|
pStream->NewLine();
|
|
|
|
if ( GetHeaderFileName() )
|
|
{
|
|
_splitpath( GetHeaderFileName(), NULL, NULL, Name, Ext );
|
|
strcpy( Buffer, Name );
|
|
strcat( Buffer, Ext );
|
|
Out_IncludeOfFile( pCCB, Buffer, FALSE );
|
|
}
|
|
else
|
|
{
|
|
// Include the import files.
|
|
OutputImportIncludes( pCCB );
|
|
}
|
|
|
|
pStream->NewLine(2);
|
|
DelimiterToken.SetTokenType( END_INCLUDES_TOKEN );
|
|
DelimiterToken.EmitToken( pStream );
|
|
|
|
if ( pCCB->IsReparsingCurrentFile() )
|
|
{
|
|
MIDL_TOKEN FoundToken;
|
|
|
|
pOldStream->DiscardToNextMidlToken( FoundToken );
|
|
if ( FoundToken.GetTokenType() != END_INCLUDES_TOKEN )
|
|
{
|
|
assert( 0 );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void
|
|
CG_EXE_SERVER_FILE::EmitFileHeadingBlock(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Emit block comment file heading.
|
|
|
|
Arguments:
|
|
|
|
pCCB - a pointer to the code generation control block.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
pStream->Write( "/* this ALWAYS GENERATED file contains support routines for the LocalServer32 */" );
|
|
pStream->NewLine(2);
|
|
|
|
EmitStandardHeadingBlock( pCCB );
|
|
}
|
|
|
|
CG_STATUS
|
|
CG_EXE_SERVER_FILE::GenCode(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Generate a COM server file containing the class factory and class
|
|
implementation for the COM classes 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;
|
|
unsigned long index = 0;
|
|
|
|
if( !GetMembers( I ) )
|
|
{
|
|
return CG_OK;
|
|
}
|
|
|
|
ISTREAM Stream( GetFileName(), 4 );
|
|
ISTREAM * pStream = &Stream;
|
|
|
|
pCCB->SetStream(pStream);
|
|
|
|
EmitFileHeadingBlock( pCCB );
|
|
|
|
Out_IncludeOfFile( pCCB, "rpcunkcf.h", FALSE );
|
|
//
|
|
// Emit the hash includes.
|
|
//
|
|
OutputIncludes( pCCB );
|
|
|
|
//
|
|
// Emit the external variables needed.
|
|
//
|
|
|
|
pStream->NewLine();
|
|
//
|
|
// generate code for all com classes in the IDL file.
|
|
//
|
|
|
|
while( ITERATOR_GETNEXT( I, pCG ) )
|
|
{
|
|
switch(pCG->GetCGID())
|
|
{
|
|
case ID_CG_COM_SERVER_DLL:
|
|
case ID_CG_COM_SERVER_EXE:
|
|
{
|
|
pCG->GenCode( pCCB );
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return CG_OK;
|
|
}
|
|
|
|
|
|
void
|
|
CG_EXE_SERVER_MAIN_FILE::EmitFileHeadingBlock(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Emit block comment file heading.
|
|
|
|
Arguments:
|
|
|
|
pCCB - a pointer to the code generation control block.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
pStream->Write( "/* this GENERATED ONCE file contains support routines for the LocalServer32 */" );
|
|
pStream->NewLine(2);
|
|
|
|
EmitStandardHeadingBlock( pCCB );
|
|
}
|
|
|
|
CG_STATUS
|
|
CG_EXE_SERVER_MAIN_FILE::GenCode(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Generate a COM server file containing the class factory and class
|
|
implementation for the COM classes 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;
|
|
unsigned long index = 0;
|
|
|
|
if( !GetMembers( I ) )
|
|
{
|
|
return CG_OK;
|
|
}
|
|
|
|
ISTREAM Stream( GetFileName(), 4 );
|
|
ISTREAM * pStream = &Stream;
|
|
|
|
pCCB->SetStream(pStream);
|
|
|
|
EmitFileHeadingBlock( pCCB );
|
|
|
|
Out_IncludeOfFile( pCCB, "rpcunkcf.h", FALSE );
|
|
//
|
|
// Emit the hash includes.
|
|
//
|
|
OutputIncludes( pCCB );
|
|
|
|
//
|
|
// Emit the external variables needed.
|
|
//
|
|
|
|
pStream->NewLine();
|
|
//
|
|
// generate code for all com classes in the IDL file.
|
|
//
|
|
|
|
while( ITERATOR_GETNEXT( I, pCG ) )
|
|
{
|
|
#if 0
|
|
switch(pCG->GetCGID())
|
|
{
|
|
case ID_CG_INHERITED_OBJECT_INTERFACE:
|
|
case ID_CG_OBJECT_INTERFACE:
|
|
|
|
if ( ((CG_OBJECT_INTERFACE*)pCG)->IsIUnknown() )
|
|
pCCB->SetIUnknownCG( (CG_IUNKNOWN_OBJECT_INTERFACE *) pCG );
|
|
else if ( !strcmp( pCG->GetSymName(), "IClassFactory" ) )
|
|
pCCB->SetIClassfCG( (CG_OBJECT_INTERFACE *) pCG );
|
|
break;
|
|
|
|
case ID_CG_COM_CLASS:
|
|
{
|
|
CG_COM_CLASS * pComCG = ( CG_COM_CLASS * ) pCG;
|
|
|
|
pComCG->GenComClassIUnknown( pCCB );
|
|
pComCG->GenComClassFactory( pCCB );
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
return CG_OK;
|
|
}
|
|
|
|
|
|
void
|
|
CG_TEST_CLIENT_FILE::EmitFileHeadingBlock(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Emit block comment file heading.
|
|
|
|
Arguments:
|
|
|
|
pCCB - a pointer to the code generation control block.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
pStream->Write( "/* this GENERATED ONCE file contains the example test client for the interfaces in the COM class */" );
|
|
pStream->NewLine(2);
|
|
|
|
EmitStandardHeadingBlock( pCCB );
|
|
}
|
|
|
|
CG_STATUS
|
|
CG_TEST_CLIENT_FILE::GenCode(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Generate a COM test client file to create a COM object, and invoke all
|
|
the methods of the COM classes 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:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
#if 0
|
|
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 ];
|
|
ITERATOR ProcList;
|
|
ISTREAM * pStream;
|
|
unsigned long index = 0;
|
|
|
|
if( !GetMembers( I ) )
|
|
{
|
|
return CG_OK;
|
|
}
|
|
|
|
pStream = new ISTREAM( (char *) GetFileName(), 4 );
|
|
pCCB->SetStream(pStream);
|
|
|
|
EmitFileHeadingBlock( pCCB );
|
|
|
|
//
|
|
// Emit the hash includes.
|
|
//
|
|
Out_IncludeOfFile( pCCB, "rpcproxy.h", FALSE );
|
|
|
|
_splitpath( GetHeaderFileName(), Drive, Path, Name, Ext );
|
|
strcpy( Buffer, Name );
|
|
strcat( Buffer, Ext );
|
|
Out_IncludeOfFile( pCCB, Buffer, FALSE );
|
|
|
|
EmitFormatStringTypedefs( pCCB );
|
|
|
|
//
|
|
// Emit the external variables needed.
|
|
//
|
|
|
|
pStream->NewLine();
|
|
|
|
//
|
|
// Emit the format string extern declarations.
|
|
//
|
|
Out_TypeFormatStringExtern( pCCB );
|
|
Out_ProcFormatStringExtern( pCCB );
|
|
Out_LocalTypeFormatStringExtern( pCCB );
|
|
Out_LocalProcFormatStringExtern( pCCB );
|
|
|
|
pCCB->ClearOptionalExternFlags();
|
|
|
|
pStream->NewLine();
|
|
|
|
pCCB->SetFileCG(this);
|
|
|
|
//
|
|
// Create a new format string object if it does not yet exist.
|
|
//
|
|
if ( !GetFormatString() )
|
|
{
|
|
SetFormatString(new FORMAT_STRING());
|
|
SetLocalFormatString(new FORMAT_STRING());
|
|
}
|
|
pCCB->SetFormatString( GetFormatString() );
|
|
|
|
if ( !GetProcFormatString() )
|
|
{
|
|
SetProcFormatString(new FORMAT_STRING());
|
|
SetLocalProcFormatString(new FORMAT_STRING());
|
|
}
|
|
pCCB->SetProcFormatString( GetProcFormatString() );
|
|
|
|
//
|
|
// 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_INTERFACE:
|
|
break;
|
|
case ID_CG_INHERITED_OBJECT_INTERFACE:
|
|
//
|
|
// Generate format string description for all procs.
|
|
//
|
|
((CG_INHERITED_OBJECT_INTERFACE *)pCG)->GenCode( pCCB );
|
|
// make no code or tables for local interfaces
|
|
if ( ((CG_INHERITED_OBJECT_INTERFACE*)pCG)->IsLocal() )
|
|
break;
|
|
|
|
//
|
|
// Both of these do nothing right now. 4/25.
|
|
//
|
|
((CG_INHERITED_OBJECT_INTERFACE *)pCG)->
|
|
GenInterfaceProxy( pCCB, index );
|
|
((CG_INHERITED_OBJECT_INTERFACE *)pCG)->
|
|
GenInterfaceStub( pCCB, index );
|
|
break;
|
|
case ID_CG_OBJECT_INTERFACE:
|
|
// make no code or tables for local interfaces
|
|
((CG_OBJECT_INTERFACE *)pCG)->GenCode( pCCB );
|
|
if ( ((CG_OBJECT_INTERFACE*)pCG)->IsLocal() )
|
|
break;
|
|
((CG_OBJECT_INTERFACE *)pCG)->GenInterfaceProxy( pCCB, index );
|
|
((CG_OBJECT_INTERFACE *)pCG)->GenInterfaceStub( pCCB, index );
|
|
index++; // index is index in stub/proxy buffer tables
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
EmitFixupToFormatStringTypedefs( pCCB );
|
|
|
|
pCCB->SetSkipFormatStreamGeneration( FALSE );
|
|
pCCB->OutputMultipleInterfaceTables();
|
|
|
|
Out_ProxyFileInfo(pCCB);
|
|
|
|
UpdateDLLDataFile( pCCB );
|
|
#endif // 0
|
|
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
|
|
CG_HDR_FILE::EmitFileHeadingBlock(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Emit block comment file heading.
|
|
|
|
Arguments:
|
|
|
|
pCCB - a pointer to the code generation control block.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
pStream->Write( "/* this ALWAYS GENERATED file contains the definitions for the interfaces */" );
|
|
pStream->NewLine(2);
|
|
|
|
EmitStandardHeadingBlock( pCCB );
|
|
}
|
|
|
|
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;
|
|
|
|
while( ITERATOR_GETNEXT( I, pCG ) )
|
|
{
|
|
switch(pCG->GetCGID())
|
|
{
|
|
case ID_CG_INTERFACE:
|
|
case ID_CG_INHERITED_OBJECT_INTERFACE:
|
|
break;
|
|
|
|
case ID_CG_OBJECT_INTERFACE:
|
|
case ID_CG_DISPINTERFACE:
|
|
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
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
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 );
|
|
CG_ITERATOR I;
|
|
CG_INTERFACE * pCG;
|
|
char * pszInterfaceName;
|
|
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;
|
|
}
|
|
|
|
EmitFileHeadingBlock( pCCB );
|
|
|
|
// Include standard files.
|
|
|
|
pStream->Write( "#include \"rpc.h\"\n#include \"rpcndr.h\"\n" );
|
|
|
|
// If there is at least one pickle interface, emit the include
|
|
// of midles.h
|
|
|
|
while( ITERATOR_GETNEXT( I, pCG ) )
|
|
{
|
|
if ( pCG->HasPicklingStuff() )
|
|
{
|
|
fHasPickle = TRUE;
|
|
}
|
|
if ( pCG->IsObject() )
|
|
{
|
|
fHasObject = TRUE;
|
|
}
|
|
}
|
|
|
|
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 );
|
|
|
|
// Write out the #ifndefs and #defines
|
|
pStream->NewLine();
|
|
sprintf( Buffer,
|
|
"#ifndef __%s_%s__\n#define __%s_%s__",
|
|
Name,
|
|
&Ext[1], // skip the "." in the extension
|
|
Name,
|
|
&Ext[1] // skip the "." in the extension
|
|
);
|
|
|
|
pStream->Write( Buffer );
|
|
|
|
// Write out the cplusplus guard.
|
|
|
|
pStream->NewLine( 2 );
|
|
|
|
pStream->Write( "#ifdef __cplusplus\nextern \"C\"{\n#endif " );
|
|
pStream->NewLine();
|
|
|
|
//Generate forward declarations for object interfaces.
|
|
pStream->NewLine();
|
|
pStream->Write("/* Forward Declarations */ ");
|
|
I.Init();
|
|
OutputInterfaceForwards( pStream, I );
|
|
pStream->NewLine();
|
|
|
|
// Include the import files.
|
|
OutputImportIncludes( pCCB );
|
|
|
|
pStream->NewLine();
|
|
|
|
pStream->Write(
|
|
"void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);" );
|
|
pStream->NewLine();
|
|
pStream->Write(
|
|
"void __RPC_USER MIDL_user_free( void __RPC_FAR * ); " );
|
|
|
|
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_COM_CLASS:
|
|
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();
|
|
pStream->Close();
|
|
|
|
return CG_OK;
|
|
}
|
|
|
|
void
|
|
CG_HDR_FILE::OutputMultipleInterfacePrototypes(
|
|
CCB * pCCB )
|
|
|
|
{
|
|
ITERATOR I;
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
pStream->NewLine();
|
|
pStream->Write("/* Additional Prototypes for ALL interfaces */");
|
|
pStream->NewLine();
|
|
|
|
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( I ) )
|
|
{
|
|
Out_UserMarshalPrototypes( pCCB, I );
|
|
}
|
|
|
|
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->GetListOfNotifyRoutines( I ) )
|
|
{
|
|
Out_NotifyPrototypes( pCCB, I, FALSE ); // without flags
|
|
}
|
|
|
|
if( pCCB->GetListOfNotifyFlagRoutines( I ) )
|
|
{
|
|
Out_NotifyPrototypes( pCCB, I, TRUE ); // with flags
|
|
}
|
|
|
|
pStream->NewLine();
|
|
pStream->Write("/* end of Additional Prototypes */");
|
|
pStream->NewLine( 2 );
|
|
|
|
}
|
|
|
|
|
|
void
|
|
CG_COM_HDR_FILE::EmitFileHeadingBlock(
|
|
CCB * pCCB )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Emit block comment file heading.
|
|
|
|
Arguments:
|
|
|
|
pCCB - a pointer to the code generation control block.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
CheckForHeadingToken( pCCB );
|
|
|
|
pStream->Write( "/* this USER-ALTERABLE file contains the definition of COM classes */" );
|
|
pStream->NewLine(2);
|
|
|
|
EmitStandardHeadingBlock( pCCB );
|
|
}
|
|
|
|
void
|
|
CG_COM_HDR_FILE::EmitIncludesBlock(
|
|
CCB * pCCB)
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Generate the header file includes block.
|
|
|
|
Arguments:
|
|
|
|
pCCB - The code gen controller block.
|
|
|
|
Return Value:
|
|
|
|
CG_OK if all is well.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
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 ];
|
|
BOOL fReParse = pCCB->IsReparsingCurrentFile();
|
|
MIDL_TOKEN Token( START_INCLUDES_TOKEN );
|
|
|
|
if ( fReParse )
|
|
{
|
|
MIDL_TOKEN FoundToken;
|
|
|
|
((RW_ISTREAM *) pStream)->SaveToNextMidlToken( FoundToken );
|
|
if ( FoundToken.GetTokenType() != START_INCLUDES_TOKEN )
|
|
{
|
|
assert(!"expecting includes token" );
|
|
}
|
|
}
|
|
else
|
|
pStream->NewLine();
|
|
|
|
pStream->EmitToken( Token );
|
|
|
|
pStream->NewLine();
|
|
pStream->Write( "/* the standard includes */" );
|
|
|
|
// Include standard files.
|
|
|
|
pStream->NewLine();
|
|
pStream->Write( "#include \"rpc.h\"\n#include \"rpcndr.h\"\n#include \"rpcunkcf.h\"\n" );
|
|
|
|
|
|
pStream->NewLine();
|
|
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");
|
|
|
|
// tbd - do the include of the plain header
|
|
|
|
// extract the name and the extension to create the ifdefs
|
|
|
|
_splitpath( GetFileName(), Drive, Path, Name, Ext );
|
|
|
|
// Write out the #ifndefs and #defines
|
|
pStream->NewLine();
|
|
sprintf( Buffer,
|
|
"#ifndef __%s_%s__\n#define __%s_%s__",
|
|
Name,
|
|
&Ext[1], // skip the "." in the extension
|
|
Name,
|
|
&Ext[1] // skip the "." in the extension
|
|
);
|
|
|
|
pStream->Write( Buffer );
|
|
|
|
if ( GetPlainHdrName() )
|
|
{
|
|
_splitpath( GetPlainHdrName(), Drive, Path, Name, Ext );
|
|
|
|
pStream->NewLine(2);
|
|
pStream->Write( "#include \"" );
|
|
pStream->Write( Name );
|
|
if ( Ext[0] )
|
|
{
|
|
pStream->Write( Ext );
|
|
}
|
|
pStream->Write( "\"" );
|
|
pStream->NewLine();
|
|
}
|
|
else
|
|
{
|
|
pStream->NewLine(2);
|
|
// Include the import files.
|
|
OutputImportIncludes( pCCB );
|
|
}
|
|
|
|
if ( fReParse )
|
|
{
|
|
MIDL_TOKEN FoundToken;
|
|
|
|
((RW_ISTREAM *) pStream)->DiscardToNextMidlToken( FoundToken );
|
|
if ( FoundToken.GetTokenType() != END_INCLUDES_TOKEN )
|
|
{
|
|
assert(!"expecting includes token" );
|
|
}
|
|
}
|
|
|
|
pStream->NewLine();
|
|
Token.SetTokenType( END_INCLUDES_TOKEN );
|
|
pStream->EmitToken( Token );
|
|
pStream->NewLine( ( fReParse ) ? 1 : 2 );
|
|
|
|
|
|
}
|
|
|
|
void
|
|
CG_COM_HDR_FILE::EmitClosingBlock(
|
|
CCB * pCCB)
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Generate the header file includes block.
|
|
|
|
Arguments:
|
|
|
|
pCCB - The code gen controller block.
|
|
|
|
Return Value:
|
|
|
|
CG_OK if all is well.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
ISTREAM * pStream = pCCB->GetStream();
|
|
|
|
// print out the closing endifs.
|
|
// The endif for the file name ifndef
|
|
|
|
pStream->NewLine();
|
|
|
|
pStream->Write( "#endif" );
|
|
pStream->NewLine();
|
|
|
|
}
|
|
|
|
|
|
CG_STATUS
|
|
CG_COM_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:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
CG_ITERATOR I;
|
|
CG_INTERFACE * pCG;
|
|
BOOL fHasPlainHeader = FALSE;
|
|
|
|
|
|
RW_ISTREAM Stream( GetFileName(), 4 );
|
|
RW_ISTREAM * pStream = &Stream;
|
|
|
|
pCCB->SetStream(pStream);
|
|
|
|
if ( Stream.IsTempStream() )
|
|
{
|
|
pCCB->SetReparsingCurrentFile( TRUE );
|
|
}
|
|
|
|
|
|
EmitFileHeadingBlock( pCCB );
|
|
|
|
EmitIncludesBlock( pCCB );
|
|
|
|
//
|
|
// For all com classes in this file, generate code.
|
|
//
|
|
|
|
GetMembers( I );
|
|
|
|
I.Init();
|
|
while( ITERATOR_GETNEXT( I, pCG ) )
|
|
{
|
|
switch(pCG->GetCGID())
|
|
{
|
|
case ID_CG_COM_CLASS:
|
|
pCG->GenHeader( pCCB );
|
|
case ID_CG_OBJECT_INTERFACE:
|
|
case ID_CG_INTERFACE:
|
|
case ID_CG_INHERITED_OBJECT_INTERFACE:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
EmitClosingBlock( pCCB );
|
|
|
|
// propogate changes from the tmpfile, if any
|
|
Stream.UpdateOriginalFile();
|
|
|
|
pCCB->SetReparsingCurrentFile( FALSE );
|
|
|
|
return CG_OK;
|
|
}
|
|
|
|
|