Windows NT 4.0 source code leak
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

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