|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1989 Microsoft Corporation
Module Name:
comsrv.cxx
Abstract: Generates com class server framework file
Notes:
History:
----------------------------------------------------------------------------*/
/****************************************************************************
* include files ***************************************************************************/ #include "becls.hxx"
#pragma hdrstop
#include "buffer.hxx"
/****************************************************************************
* local definitions ***************************************************************************/
/****************************************************************************
* externs ***************************************************************************/ extern CMD_ARG * pCommand;
#include "szbuffer.h"
CG_STATUS CG_COM_CLASS::GenComOuterUnknown( CCB * pCCB, char * pDesignatedClassName ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for the outer IUnknown for a COM class
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(); char * pName = GetSymName(); CG_IUNKNOWN_OBJECT_INTERFACE * pIUnknown = pCCB->GetIUnknownCG(); node_object * pClass = (node_object *) GetType(); MEM_ITER Iter( (node_interface *)pIUnknown->GetType() );
// get pointers to all the methods
named_node * pQI; named_node * pAR; named_node * pRel;
while ( ( pQI = Iter.GetNext() )->NodeKind() != NODE_PROC ) ;
while ( ( pAR = Iter.GetNext() )->NodeKind() != NODE_PROC ) ;
while ( ( pRel = Iter.GetNext() )->NodeKind() != NODE_PROC ) ;
pStream->NewLine(); pStream->Write( pDelimiterString ); pStream->NewLine(); pStream->Write( "// IUnknown implementation for class: " ); pStream->Write( pName ); pStream->NewLine(2);
////////////////////////////////////////////////////////////////////////
// QueryInterface
pQI->PrintType( PRT_QUALIFIED_NAME | PRT_PROC_PROTOTYPE, pStream, NULL, pClass );
// print a (nearly) empty function body
pStream->IndentInc(); pStream->NewLine(); pStream->Write( '{' ); pStream->NewLine();
pStream->Write("return "); if ( pDesignatedClassName ) { pStream->Write( pDesignatedClassName ); pStream->Write( "::" ); } pStream->Write("pUnkOuter->QueryInterface( riid, ppvObject );"); pStream->NewLine(); pStream->Write( '}' ); pStream->IndentDec(); pStream->NewLine( 2 );
////////////////////////////////////////////////////////////////////////
// AddRef
pAR->PrintType( PRT_QUALIFIED_NAME | PRT_PROC_PROTOTYPE, pStream, NULL, pClass );
// print a (nearly) empty function body
pStream->IndentInc(); pStream->NewLine(); pStream->Write( '{' ); pStream->NewLine();
pStream->Write("return "); if ( pDesignatedClassName ) { pStream->Write( pDesignatedClassName ); pStream->Write( "::" ); } pStream->Write("pUnkOuter->AddRef();"); pStream->NewLine(); pStream->Write( '}' ); pStream->IndentDec(); pStream->NewLine( 2 );
////////////////////////////////////////////////////////////////////////
// Release
pRel->PrintType( PRT_QUALIFIED_NAME | PRT_PROC_PROTOTYPE, pStream, NULL, pClass );
// print a (nearly) empty function body
pStream->IndentInc(); pStream->NewLine(); pStream->Write( '{' ); pStream->NewLine();
pStream->Write("return "); if ( pDesignatedClassName ) { pStream->Write( pDesignatedClassName ); pStream->Write( "::" ); } pStream->Write("pUnkOuter->Release();"); pStream->NewLine(); pStream->Write( '}' ); pStream->IndentDec(); pStream->NewLine( 2 );
return CG_OK; }
CG_STATUS CG_COM_CLASS::GenComInnerUnknown( CCB * pCCB, char * pDesignatedClassName ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for the inner IUnknown for a COM class
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(); char * pName = GetSymName(); CG_IUNKNOWN_OBJECT_INTERFACE * pIUnknown = pCCB->GetIUnknownCG(); node_object * pClass = (node_object *) GetType(); MEM_ITER Iter( (node_interface *)pIUnknown->GetType() ); ITERATOR I;
CSzBuffer ExpandedName; node_object Alternate_Class = *pClass;
char * pMemberQualifier = pName; BOOL fFirstItf = TRUE; CG_OBJECT_INTERFACE * pIntf; char * pItfName;
// make the class name for the inner unknown
ExpandedName.Append( pName ); ExpandedName.Append( "_Internal_Unknown" ); Alternate_Class.SetSymName( ExpandedName );
// get pointers to all the methods
named_node * pQI; named_node * pAR; named_node * pRel;
while ( ( pQI = Iter.GetNext() )->NodeKind() != NODE_PROC ) ;
while ( ( pAR = Iter.GetNext() )->NodeKind() != NODE_PROC ) ;
while ( ( pRel = Iter.GetNext() )->NodeKind() != NODE_PROC ) ;
pStream->NewLine(); pStream->Write( pDelimiterString ); pStream->NewLine(); pStream->Write( "// Internal IUnknown implementation for class: " ); pStream->Write( pName ); pStream->NewLine(2); if ( pDesignatedClassName ) { pMemberQualifier = pDesignatedClassName; }
////////////////////////////////////////////////////////////////////////
// QueryInterface
pQI->PrintType( PRT_QUALIFIED_NAME | PRT_PROC_PROTOTYPE, pStream, NULL, &Alternate_Class );
// print a (nearly) empty function body
pStream->IndentInc(); pStream->NewLine(); pStream->Write( '{' ); pStream->NewLine();
pStream->Write("HRESULT hr = E_NOINTERFACE;"); pStream->NewLine(2);
pStream->Write("*ppvObject = 0;"); pStream->NewLine(2);
// get all provided interfaces,
GetListOfUniqueBaseInterfaces( I );
// now unmark them all
for ( ITERATOR_INIT(I); ITERATOR_GETNEXT( I, pIntf ); pIntf->MarkVisited(FALSE) ) ;
// for now, just do a linear search; see OutInfoSearchRoutine for further scheme
for ( ITERATOR_INIT(I); ITERATOR_GETNEXT( I, pIntf ); pIntf->MarkVisited(FALSE) ) { if ( pIntf->IsIUnknown() ) continue;
if ( pIntf->GetCGID() == ID_CG_COM_CLASS ) continue;
pItfName = pIntf->GetSymName();
if ( fFirstItf ) { pStream->Write("if ( IsEqualGUID( riid, IID_IUnknown ) || "); fFirstItf = FALSE; } else { pStream->Write("else if ( "); }
pStream->Write("IsEqualGUID( riid, IID_"); pStream->Write( pItfName ); pStream->Write(" ) )");
pStream->IndentInc(); pStream->NewLine(); pStream->Write( '{' ); pStream->NewLine();
pStream->Write("*ppvObject = GET_MIDL_INTERFACE( "); pStream->Write( pItfName ); pStream->Write( ", " ); pStream->Write( pName ); pStream->Write( ", "); pStream->Write( pMemberQualifier ); pStream->Write( " );"); pStream->NewLine();
pStream->Write("hr = S_OK;"); pStream->NewLine();
pStream->Write( '}' ); pStream->IndentDec(); pStream->NewLine( 2 ); }
pStream->Write( "if ( FAILED( hr ) )"); pStream->NewLine(); pStream->Write( " hr = GET_MIDL_CLASS( " ); pStream->Write( pName ); pStream->Write( ", " ); pStream->Write( pMemberQualifier ); pStream->Write( " )" ); pStream->NewLine(); pStream->Write( " ->QueryInterfaceExtension( riid, ppvObject );" ); pStream->NewLine(); pStream->Write( "else" ); pStream->NewLine(); pStream->Write(" AddRef();");
pStream->NewLine(); pStream->Write("return hr;");
pStream->NewLine(2); pStream->Write( '}' ); pStream->IndentDec();
////////////////////////////////////////////////////////////////////////
// AddRef
pStream->NewLine( 2 ); pAR->PrintType( PRT_QUALIFIED_NAME | PRT_PROC_PROTOTYPE, pStream, NULL, &Alternate_Class );
// print a (nearly) empty function body
pStream->IndentInc(); pStream->NewLine(); pStream->Write( '{' ); pStream->NewLine();
pStream->Write("IncrementRefCount( "); if ( pDesignatedClassName ) { pStream->Write( pDesignatedClassName ); pStream->Write( "::" ); } pStream->Write("m_ulRefCnt );"); pStream->NewLine();
pStream->Write("return "); if ( pDesignatedClassName ) { pStream->Write( pDesignatedClassName ); pStream->Write( "::" ); } pStream->Write("m_ulRefCnt;"); pStream->NewLine();
pStream->Write( '}' ); pStream->IndentDec(); pStream->NewLine( 2 );
static STRING_BLOCK ReleaseCommonPart = { "if ( ulReturned )", " return ulReturned;", "", "// object refcount has dropped to 0", "", "//decrement the object count", "if(DecrementRefCount(gLifetimeInfo.ulObjectRefCnt) == 0)", "{", " //The last object in this module has been destroyed.", " if ( gLifetimeInfo.pfnObjectCleanUpRtn )", " (*gLifetimeInfo.pfnObjectCleanUpRtn)();", "}", "", "//decrement the module count", "if(DecrementRefCount(gLifetimeInfo.ulModuleRefCnt) == 0)", "{", " //The last object in this module has been destroyed.", " if ( gLifetimeInfo.pfnModuleCleanUpRtn )", " (*gLifetimeInfo.pfnModuleCleanUpRtn)();", "}", 0 }; ////////////////////////////////////////////////////////////////////////
// Release
pRel->PrintType( PRT_QUALIFIED_NAME | PRT_PROC_PROTOTYPE, pStream, NULL, &Alternate_Class );
// print the function body
pStream->IndentInc(); pStream->NewLine(); pStream->Write( '{' ); pStream->NewLine();
pStream->Write("unsigned long ulReturned = DecrementRefCount( "); if ( pDesignatedClassName ) { pStream->Write( pDesignatedClassName ); pStream->Write( "::" ); } pStream->Write("m_ulRefCnt );");
pStream->WriteBlock( ReleaseCommonPart );
pStream->NewLine(2); pStream->Write("delete GET_MIDL_CLASS( "); pStream->Write( pName ); pStream->Write( ", " ); pStream->Write( pMemberQualifier ); pStream->Write( " );" ); pStream->NewLine(); pStream->Write( "return 0;" ); pStream->NewLine(); pStream->Write( '}' ); pStream->IndentDec(); pStream->NewLine( 2 );
return CG_OK; }
CG_STATUS CG_COM_CLASS::GenComClassConstructor( CCB * pCCB, char * pDesignatedClassName ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for the constructor for a COM class
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(); char * pName = GetSymName();
pStream->Write( pDelimiterString ); pStream->NewLine(); pStream->Write("// Constructor"); pStream->NewLine(); pStream->Write("// Override InitInstance to do your own initialization"); pStream->NewLine(2); pStream->Write( pName ); pStream->Write( "::" ); pStream->Write( pName ); pStream->Write( "( IUnknown * pUnknownOuter )" ); pStream->IndentInc(); pStream->NewLine(); pStream->Write( '{' ); pStream->NewLine(); pStream->Write( "// support aggregation"); pStream->NewLine(); pStream->Write( "if ( !pUnknownOuter )"); pStream->IndentInc(); pStream->NewLine(); if ( pDesignatedClassName ) { pStream->Write( pDesignatedClassName ); pStream->Write( "::" ); } pStream->Write( "pUnkOuter = (IUnknown*) &"); if ( pDesignatedClassName ) { pStream->Write( pDesignatedClassName ); pStream->Write( "::" ); } pStream->Write( "m_UnkInner;"); pStream->IndentDec(); pStream->NewLine(); pStream->Write( "else"); pStream->IndentInc(); pStream->NewLine(); if ( pDesignatedClassName ) { pStream->Write( pDesignatedClassName ); pStream->Write( "::" ); } pStream->Write( "pUnkOuter = pUnknownOuter;"); pStream->IndentDec(); pStream->NewLine(2); pStream->Write( "CONSTRUCT_INNER_UNKNOWN( "); pStream->Write( pName ); pStream->Write( ", " ); pStream->Write( (pDesignatedClassName) ? pDesignatedClassName : pName ); pStream->Write( " );" ); pStream->NewLine(2); pStream->Write( '}' ); pStream->IndentDec(); pStream->NewLine( 2 );
return CG_OK; }
CG_STATUS CG_COM_CLASS::GenComClassIUnknown( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for the IUnknown for a COM class
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(); char * pName = GetSymName();
pCCB->SetInterfaceCG( this );
pStream->NewLine(); pStream->Write( pDelimiterString ); pStream->NewLine(); pStream->Write( pDelimiterString ); pStream->NewLine(); pStream->Write( "// IUnknown implementations for class: " ); pStream->Write( pName ); pStream->NewLine(2); // generate the outer unknown methods that defer to the punkOuter
GenComOuterUnknown( pCCB, NULL );
// generate the inner unknown methods
GenComInnerUnknown( pCCB, NULL );
// generate the constructor
GenComClassConstructor( pCCB, NULL );
return CG_OK; }
CG_STATUS CG_COM_CLASS::GenComClassFactory( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for the class factory for a COM class
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(); char * pName = GetSymName();
pCCB->SetInterfaceCG( this );
pStream->NewLine(); pStream->Write( pDelimiterString ); pStream->NewLine(); pStream->Write( "// ClassFactory implementation for class: " ); pStream->Write( pName ); pStream->NewLine(2); // make the CreateInstance routine
GenComClassFactoryCreateInstance( pCCB );
// make the tables, and construct the object and the info
GenComClassFactoryTables( pCCB );
pStream->NewLine(2);
return CG_OK; }
CG_STATUS CG_COM_CLASS::GenComClassFactoryCreateInstance( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for the class factory for a COM class
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(); char * pName = GetSymName(); CG_OBJECT_INTERFACE * pIClassf = pCCB->GetIClassfCG(); node_interface * pIClassfNode = (node_interface*)pIClassf->GetType();
CG_OBJECT_PROC * pCreateInstance = (CG_OBJECT_PROC *) pIClassf->GetChild(); node_proc * pCreateInstNode = (node_proc*) pCreateInstance->GetType();
node_call_as * pAttr; if ( pAttr = (node_call_as *) pCreateInstNode->GetAttribute( ATTR_CALL_AS ) ) { pCreateInstNode = (node_proc *) pAttr->GetCallAsType(); }
// a new node_proc (on the stack)
node_proc RenamedProc( pCreateInstNode ); CSzBuffer NewName;
NewName.Append( pName ); NewName.Append( "_Factory_CreateInstance" );
RenamedProc.SetSymName( NewName );
RenamedProc.PrintType( PRT_THIS_POINTER | PRT_PROC_PROTOTYPE, pStream, NULL, pIClassfNode );
// print the function body
pStream->IndentInc(); pStream->NewLine(); pStream->Write( '{' ); pStream->NewLine(); pStream->Write("HRESULT hr = E_OUTOFMEMORY;");
pStream->NewLine(); pStream->Write( pName ); pStream->Write(" * pInstance;");
pStream->NewLine(2); pStream->Write("*ppvObject = 0;");
pStream->NewLine(2); pStream->Write("pInstance = new "); pStream->Write( pName ); pStream->Write( "( pUnkOuter );");
static STRING_BLOCK CreateInstanceCommonPart = { "if ( pInstance )", " {", " hr = pInstance->InitInstance( pUnkOuter, riid, ppvObject );", " if ( FAILED( hr ) )", " {", " delete pInstance;", " return hr;", " }", "", " //increment the object count.", " //The module count will keep this process alive until all", " //objects in this module are released.", " IncrementRefCount( gLifetimeInfo.ulModuleRefCnt );", " IncrementRefCount( gLifetimeInfo.ulObjectRefCnt );", " hr = pInstance->QueryInterface( riid, (void**)ppvObject);", " }", "", "return hr;", 0 };
pStream->NewLine(); pStream->WriteBlock( CreateInstanceCommonPart );
pStream->NewLine(); pStream->Write( '}' ); pStream->IndentDec(); pStream->NewLine( 2 );
return CG_OK; }
CG_STATUS CG_COM_CLASS::GenComClassFactoryTables( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for the class factory for a COM class
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(); char * pName = GetSymName();
pStream->NewLine(2); pStream->Write( pDelimiterString ); pStream->NewLine(); pStream->Write( "// important data structures for the class factory and server" );
// print the vtable
pStream->NewLine(2); pStream->Write( "const struct Midl_Factory_Object_Vtbl " ); pStream->Write( pName ); pStream->Write( "_Factory_Object_Vtbl =" );
pStream->IndentInc(); pStream->NewLine(); pStream->Write( '{' );
pStream->NewLine(); pStream->Write( "&Generic_Midl_Factory_QueryInterface," ); pStream->NewLine(); pStream->Write( "&Generic_Midl_Factory_AddRef," ); pStream->NewLine(); pStream->Write( "&Generic_Midl_Factory_Release," ); pStream->NewLine(); pStream->Write( '&' ); pStream->Write( pName ); pStream->Write( "_Factory_CreateInstance," ); pStream->NewLine(); pStream->Write( "&Generic_Midl_Factory_LockServer," );
pStream->NewLine(); pStream->Write( "};" ); pStream->IndentDec();
// print the object instance
pStream->NewLine(2); pStream->Write( "const CMidlFactory_Object " ); pStream->Write( pName ); pStream->Write( "_Factory_Object =" );
pStream->IndentInc(); pStream->NewLine(); pStream->Write( '{' );
pStream->NewLine(); pStream->Write( '&' ); pStream->Write( pName ); pStream->Write( "_Factory_Object_Vtbl," ); pStream->NewLine(); pStream->Write( "&gLifetimeInfo" );
pStream->NewLine(); pStream->Write( "};" ); pStream->IndentDec();
// print the object pointer instance
pStream->NewLine(2); //pStream->Write( "const " );
pStream->Write( pName ); pStream->Write( "_Factory * p" ); pStream->Write( pName ); pStream->Write( "_Factory = "); pStream->IndentInc(); pStream->IndentInc(); pStream->IndentInc(); pStream->NewLine(); pStream->Write( '(' ); pStream->Write( pName ); pStream->Write( "_Factory *) &" ); pStream->Write( pName ); pStream->Write( "_Factory_Object;" ); pStream->IndentDec(); pStream->IndentDec(); pStream->IndentDec();
// print the factory info block
pStream->NewLine(2); pStream->Write( "// here is the class factory info block" ); pStream->NewLine(); pStream->Write( "Midl_Class_Factory_Info " ); pStream->Write( pName ); pStream->Write( "_Factory_Info =" );
pStream->IndentInc(); pStream->NewLine(); pStream->Write( '{' );
pStream->NewLine(); pStream->Write( '\"' ); pStream->Write( pName ); pStream->Write( "\"," ); pStream->NewLine(); pStream->Write( "&CLSID_" ); pStream->Write( pName ); pStream->Write( ',' ); pStream->NewLine(); pStream->Write( "(CGenericMidlClassFactory** )&p" ); pStream->Write( pName ); pStream->Write( "_Factory" );
pStream->NewLine(); pStream->Write( "};" ); pStream->IndentDec();
return CG_OK; }
CG_STATUS CG_COM_CLASS::GenComClassServer( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for the class implementation for a COM class 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:
----------------------------------------------------------------------------*/ { ISTREAM * pStream = pCCB->GetStream(); const char * pName = GetSymName(); CG_OBJECT_INTERFACE * pIntf; ITERATOR I; MIDL_TOKEN FlagToken( START_CLASS_TOKEN, pName );
pCCB->SetInterfaceCG( this );
pStream->NewLine(); pStream->EmitToken( FlagToken ); pStream->NewLine(); pStream->Write( pDelimiterString ); pStream->NewLine(); pStream->Write( "// COM class server for class: " ); pStream->Write( pName ); pStream->NewLine(); // go through all the methods, emitting shell code
// for IUnknown, emit special code
// for con/destructors, emit special code
// go through all base interfaces, printing them and THEIR base
// interfaces, avoiding duplicates...
GetListOfUniqueBaseInterfaces( I );
// now print them all, unmarking as we go
for ( ITERATOR_INIT(I); ITERATOR_GETNEXT( I, pIntf ); pIntf->MarkVisited(FALSE) ) { CSzBuffer NameBuffer; char * pIntfName;
if ( pIntf->IsIUnknown() ) continue;
pIntfName = pIntf->GetInterfaceName();
NameBuffer.Append( pName ); NameBuffer.Append( "::" ); NameBuffer.Append( pIntfName );
pStream->NewLine( 2 ); pStream->EmitToken( MIDL_TOKEN( START_CLASS_METHODS_TOKEN, NameBuffer ) ); pStream->NewLine(); pStream->Write( pDelimiterString ); pStream->NewLine(); pStream->Write("// Member functions from: "); pStream->Write( ( pIntf->GetCGID() == ID_CG_COM_CLASS ) ? "Class " : "Interface " ); pStream->Write( pIntfName ); pStream->NewLine(); pIntf->GenComClassServerMembers( pCCB ); }
pStream->NewLine( 2 ); pStream->Write( pDelimiterString ); pStream->NewLine( 2 ); pStream->EmitToken( MIDL_TOKEN( CLASS_DESTRUCTOR_TOKEN, pName ) ); pStream->NewLine(); pStream->Write("// virtual destructor"); pStream->NewLine();
pStream->Write( pName ); pStream->Write( "::~" ); pStream->Write( pName ); pStream->Write( "()" ); pStream->IndentInc(); pStream->NewLine(); pStream->Write( '{' ); pStream->NewLine(2); pStream->Write( "// TODO: fill in any destructor action" ); pStream->NewLine(2); pStream->Write( '}' ); pStream->IndentDec(); pStream->NewLine(); pStream->NewLine();
pStream->NewLine(); FlagToken.SetTokenType( END_CLASS_TOKEN ); pStream->EmitToken( FlagToken ); pStream->Write( '\n' );
return CG_OK; }
CG_STATUS CG_COM_CLASS::ReGenComClassServer( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for the class implementation for a COM class 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:
----------------------------------------------------------------------------*/ { RW_ISTREAM * pStream = (RW_ISTREAM *)pCCB->GetStream(); const char * pName = GetSymName(); CG_OBJECT_INTERFACE * pIntf; ITERATOR I; MIDL_TOKEN FoundToken; MIDL_TOKEN FlagToken( START_CLASS_TOKEN, pName );
pCCB->SetInterfaceCG( this );
pStream->SaveToNextMidlToken( FoundToken ); if ( FoundToken.GetTokenType() != START_CLASS_TOKEN ) { assert( !"bad token found" ); }
pStream->EmitToken( FlagToken ); pStream->NewLine(); // go through all the methods, emitting shell code
// for IUnknown, emit special code
// for con/destructors, emit special code
// go through all base interfaces, printing them and THEIR base
// interfaces, avoiding duplicates...
GetListOfUniqueBaseInterfaces( I );
// now print them all, unmarking as we go
for ( ITERATOR_INIT(I); ITERATOR_GETNEXT( I, pIntf ); pIntf->MarkVisited(FALSE) ) { CSzBuffer NameBuffer; char * pIntfName;
if ( pIntf->IsIUnknown() ) continue;
pStream->SaveToNextMidlToken( FoundToken ); if ( FoundToken.GetTokenType() != START_CLASS_METHODS_TOKEN ) { assert( !"bad token found" ); }
pIntfName = pIntf->GetInterfaceName();
NameBuffer.Append( pName ); NameBuffer.Append( "::" ); NameBuffer.Append( pIntfName );
pStream->EmitToken( MIDL_TOKEN( START_CLASS_METHODS_TOKEN, NameBuffer ) ); pStream->NewLine(); pIntf->ReGenComClassServerMembers( pCCB ); }
pStream->SaveToNextMidlToken( FoundToken ); if ( FoundToken.GetTokenType() != CLASS_DESTRUCTOR_TOKEN ) { assert( !"bad token found" ); }
pStream->EmitToken( MIDL_TOKEN( CLASS_DESTRUCTOR_TOKEN, pName ) ); pStream->NewLine();
pStream->SaveToNextMidlToken( FoundToken ); if ( FoundToken.GetTokenType() != END_CLASS_TOKEN ) { assert( !"bad token found" ); }
FlagToken.SetTokenType( END_CLASS_TOKEN ); pStream->EmitToken( FlagToken ); pStream->Write( '\n' );
return CG_OK; }
CG_STATUS CG_OBJECT_INTERFACE::GenComClassServerMembers( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for an interface inherited by a COM class 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_OBJECT_PROC * pCG;
if( !GetMembers( I ) ) { return CG_OK; }
while( ITERATOR_GETNEXT( I, pCG ) ) { pCG->GenComClassMemberFunction( pCCB );
}
return CG_OK; }
CG_STATUS CG_OBJECT_INTERFACE::ReGenComClassServerMembers( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for an interface inherited by a COM class 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_OBJECT_PROC * pCG;
if( !GetMembers( I ) ) { return CG_OK; }
while( ITERATOR_GETNEXT( I, pCG ) ) { pCG->ReGenComClassMemberFunction( pCCB );
}
return CG_OK; }
CG_STATUS CG_OBJECT_PROC::GenComClassMemberFunction( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for an interface inherited by a COM class 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:
----------------------------------------------------------------------------*/ { node_proc * pTypeNode = (node_proc *) GetType(); ISTREAM * pStream = pCCB->GetStream(); node_skl * pClass = pCCB->GetInterfaceCG()->GetType();
CSzBuffer NameBuffer; NameBuffer.Append( pClass->GetSymName() ); NameBuffer.Append( "::" ); NameBuffer.Append( pTypeNode->GetSymName() );
MIDL_TOKEN FlagToken( START_METHOD_TOKEN, NameBuffer ); pStream->NewLine(); pStream->EmitToken( FlagToken );
pStream->NewLine(2); pTypeNode->PrintType( PRT_QUALIFIED_NAME | PRT_PROC_PROTOTYPE, pStream, NULL, pClass );
// print a (nearly) empty function body
pStream->IndentInc(); pStream->NewLine(2); FlagToken.SetTokenType( START_METHOD_BODY_TOKEN ); pStream->EmitToken( FlagToken );
pStream->NewLine(); pStream->NewLine(); pStream->Write( '{' ); pStream->NewLine(2);
pStream->Write("// uncomment the below macro if you make calls out and may get"); pStream->NewLine(); pStream->Write("// a Release() while blocked on the call."); pStream->NewLine(); pStream->Write("// MAKES_REENTERABLE_CALLS"); pStream->NewLine(2); pStream->Write("// TODO: Fill in this method with your code"); pStream->NewLine(2); pStream->Write("return S_OK;"); pStream->NewLine(2);
pStream->Write( '}' ); pStream->IndentDec(); pStream->NewLine( 2 );
return CG_OK; }
CG_STATUS CG_OBJECT_PROC::ReGenComClassMemberFunction( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for an interface inherited by a COM class 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:
----------------------------------------------------------------------------*/ { node_proc * pTypeNode = (node_proc *) GetType(); RW_ISTREAM * pStream = (RW_ISTREAM*)pCCB->GetStream(); node_skl * pClass = pCCB->GetInterfaceCG()->GetType(); MIDL_TOKEN FoundToken;
CSzBuffer NameBuffer; NameBuffer.Append( pClass->GetSymName() ); NameBuffer.Append( "::" ); NameBuffer.Append( pTypeNode->GetSymName() );
pStream->SaveToNextMidlToken( FoundToken ); if ( FoundToken.GetTokenType() != START_METHOD_TOKEN ) { assert( !"bad token found" ); }
MIDL_TOKEN FlagToken( START_METHOD_TOKEN, NameBuffer ); pStream->EmitToken( FlagToken );
pStream->NewLine(2); pTypeNode->PrintType( PRT_QUALIFIED_NAME | PRT_PROC_PROTOTYPE, pStream, NULL, pClass );
// print a (nearly) empty function body
pStream->IndentInc(); pStream->NewLine(2);
pStream->DiscardToNextMidlToken( FoundToken ); if ( FoundToken.GetTokenType() != START_METHOD_BODY_TOKEN ) { assert( !"bad token found" ); }
FlagToken.SetTokenType( START_METHOD_BODY_TOKEN ); pStream->EmitToken( FlagToken );
pStream->IndentDec(); pStream->NewLine();
return CG_OK; }
CG_COM_SERVER::CG_COM_SERVER( node_com_server * pI, ITERATOR * pBCG ) : CG_NDR( pI, XLAT_SIZE_INFO() ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
constructor for a com server DLL or EXE base class.
Arguments: pI - a pointer to the node in the typegraph.
Return Value:
none. Notes:
----------------------------------------------------------------------------*/ { pBaseCGList = pBCG; }
CG_STATUS CG_COM_SERVER::GenClassFactoryArray( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the data structures for the _g.cxx file.
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(); ITERATOR * pClassList = GetClassList(); CG_COM_CLASS * pClassCG;
pStream->NewLine(); pStream->Write( "// here are the class factories all connected together" ); pStream->NewLine(); pStream->Write( "const Midl_Class_Factory_Info * Midl_Class_Factory_Array[] =" ); pStream->IndentInc(); pStream->NewLine(); pStream->Write( '{' );
ITERATOR_INIT( *pClassList );
while ( ITERATOR_GETNEXT ( *pClassList, pClassCG ) ) { pStream->NewLine(); pStream->Write( '&' ); pStream->Write( pClassCG->GetSymName() ); pStream->Write( "_Factory_Info," ); }
pStream->NewLine(); pStream->Write( "0 // terminator" ); pStream->NewLine(); pStream->Write( "};" ); pStream->IndentDec(); pStream->NewLine();
return CG_OK; }
CG_STATUS CG_COM_SERVER_DLL::GenDataStructures( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the data structures for the _g.cxx file.
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(); unsigned long ulClassCnt = ITERATOR_GETCOUNT( *GetClassList() );
pStream->NewLine(); pStream->Write( "// the number of classes provided by this DLL" ); pStream->NewLine(); pStream->Write( "const unsigned long ulClassCnt = " ); pStream->WriteNumber( "%d", ulClassCnt ); pStream->Write( ";" );
pStream->NewLine(2);
GenClassFactoryArray( pCCB );
static STRING_BLOCK DataStructs = { "// lifetime information for the module (dll) containing this object", "struct MidlModuleLifetimeInfo gLifetimeInfo =", " {", " 0, // ulModuleRefCnt", " NULL,", " 0, // ulObjectRefCnt", " NULL", " };", "", "HINSTANCE hProxyDll = 0;", 0 };
pStream->NewLine(); pStream->WriteBlock( DataStructs );
pStream->NewLine(2);
return CG_OK; }
CG_STATUS CG_COM_SERVER_DLL::GenEntryPts( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the DllGetClassObject and DllCanUnloadNow code for an inprocserver32.
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(); char * pName = GetSymName(); #if 0
ITERATOR * pClassList = GetClassList(); CG_COM_CLASS * pClassCG; #endif
static STRING_BLOCK DGCO_header = { " REFCLSID rclsid,", " REFIID riid,", " void ** ppv )", "{", " HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;", " unsigned long idx;", "", " // lookup customized for this DLL", 0 };
pStream->NewLine(); pStream->Write( "EXTERN_C HRESULT STDAPICALLTYPE " ); pStream->Write( pName ); pStream->Write( "_DllGetClassObject (" );
pStream->NewLine(); pStream->WriteBlock( DGCO_header ); pStream->IndentInc();
// tbd - for now, just do linear search
static STRING_BLOCK DGCO_search = { "for( idx = 0; idx < ulClassCnt; idx++ )", " {", " if ( IsEqualGUID( rclsid, *Midl_Class_Factory_Array[idx]->pFactoryID ) )", " {", " hr = (*Midl_Class_Factory_Array[idx]->ppFactory)->QueryInterface( riid, ppv );", " break;", " }", " }", 0 };
pStream->WriteBlock( DGCO_search );
pStream->IndentDec();
static STRING_BLOCK DGCO_trailer = { " // fail case", " if ( FAILED (hr) )", " *ppv = 0;", " return hr;", "}", "", 0 };
pStream->NewLine(); pStream->WriteBlock( DGCO_trailer );
static STRING_BLOCK DCUN = { "{", " return (gLifetimeInfo.ulModuleRefCnt) ? S_FALSE : S_OK;", "}", 0 };
pStream->NewLine(); pStream->Write( "EXTERN_C HRESULT STDAPICALLTYPE " ); pStream->Write( pName ); pStream->Write( "_DllCanUnloadNow()" );
pStream->NewLine(); pStream->WriteBlock( DCUN );
return CG_OK; }
CG_STATUS CG_COM_SERVER_DLL::GenRegistryEntryPts( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the dllmain, RegisterServer and UnRegisterServer entry points.
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(); char * pName = GetSymName(); pStream->NewLine(2);
static STRING_BLOCK DllEntryPt = { " HINSTANCE hinstDLL,", " DWORD fdwReason,", " LPVOID lpvReserved)", "{", " if(fdwReason == DLL_PROCESS_ATTACH)", " hProxyDll = hinstDLL;", " return TRUE;", "}", 0 };
pStream->NewLine(); pStream->Write( "EXTERN_C BOOL WINAPI " ); pStream->Write( pName ); pStream->Write( "_DllEntryPoint(" );
pStream->NewLine(); pStream->WriteBlock( DllEntryPt );
static STRING_BLOCK DllRegSvr = { "{", " return S_OK;", " //tbd return NdrDllRegisterServer(hProxyDll, pProxyFileList, pClsID);", "}", 0 };
pStream->NewLine(2); pStream->Write( "EXTERN_C HRESULT STDAPICALLTYPE " ); pStream->Write( pName ); pStream->Write( "_DllRegisterServer()" );
pStream->NewLine(); pStream->WriteBlock( DllRegSvr );
static STRING_BLOCK DllUnRegSvr = { "{", " return S_OK;", " //tbd return NdrDllUnregisterServer(hProxyDll, pProxyFileList, pClsID);", "}", 0 };
pStream->NewLine(2); pStream->Write( "EXTERN_C HRESULT STDAPICALLTYPE " ); pStream->Write( pName ); pStream->Write( "_DllUnregisterServer()" );
pStream->NewLine(); pStream->WriteBlock( DllRegSvr );
pStream->NewLine(2);
return CG_OK; }
CG_STATUS CG_COM_SERVER_DLL::GenDllDefFile( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the def file for the InprocServer32.
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(); char * pName = GetSymName(); pStream->NewLine(); pStream->Write( "; to override the functionality of one of these entries, point" ); pStream->NewLine(); pStream->Write( "; the export to your routine (which may call the generated routine)" );
pStream->NewLine(2); pStream->Write( "LIBRARY" );
pStream->NewLine( 2 ); pStream->Write( "DESCRIPTION \'" ); pStream->Write( pName ); pStream->Write( " InprocServer32 DLL\'" );
pStream->NewLine( 2 ); pStream->Write( "EXPORTS" );
pStream->IndentInc(); pStream->NewLine( 2 ); pStream->Write( "DllGetClassObject = " ); pStream->Write( pName ); pStream->Write( "_DllGetClassObject" );
pStream->NewLine(); pStream->Write( "DllCanUnloadNow = " ); pStream->Write( pName ); pStream->Write( "_DllCanUnloadNow" );
pStream->NewLine(); pStream->Write( "DllRegisterServer = " ); pStream->Write( pName ); pStream->Write( "_DllRegisterServer" );
pStream->NewLine(); pStream->Write( "DllUnregisterServer = " ); pStream->Write( pName ); pStream->Write( "_DllUnregisterServer" );
pStream->NewLine(); pStream->Write( "DllMain = " ); pStream->Write( pName ); pStream->Write( "_DllEntryPoint" );
pStream->IndentDec(); pStream->NewLine(2);
return CG_OK; }
CG_STATUS CG_COM_SERVER_DLL::GenCode( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for an interface inherited by a COM class 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:
----------------------------------------------------------------------------*/ { GenDataStructures( pCCB ); GenEntryPts( pCCB ); GenRegistryEntryPts( pCCB ); pCCB->GetStream()->Write('\n'); return CG_OK; }
CG_STATUS CG_COM_SERVER_EXE::GenCode( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for an interface inherited by a COM class 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:
----------------------------------------------------------------------------*/ { GenCleanupRoutines( pCCB ); GenDataStructures( pCCB ); GenIteratorClass( pCCB ); GenClassRegisterRevoke( pCCB ); GenRegistryCode( pCCB ); return CG_OK; }
CG_STATUS CG_COM_SERVER_EXE::GenMain( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for an interface inherited by a COM class 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:
----------------------------------------------------------------------------*/ { return CG_OK; }
CG_STATUS CG_COM_SERVER_EXE::GenCleanupRoutines( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the clean-up routines for the _e.cxx file.
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(); char * pName = GetSymName();
static STRING_BLOCK CleanupRtns = { "///////////////////////////////////////////////////////////////", "// cleanup-on-Release routines", "//", "// clean-up routine for the entire module", "// this is called when all the objects AND all", "// the class factories are released", "void __stdcall ModuleUnReferenced()", "{", " // no factories or objects remaining, go away", " PostQuitMessage(0);", "}", "", "// clean-up routine for the objects in the module", "// this is called when all live objects other than ", "// the class factories are released", "void __stdcall ObjectsUnReferenced()", "{", " // revoke all the registered classes", " UnregisterAllClassFactories();", "}", 0 };
pStream->NewLine(); pStream->WriteBlock( CleanupRtns );
pStream->NewLine(3); return CG_OK; }
CG_STATUS CG_COM_SERVER_EXE::GenDataStructures( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the data structures for the _g.cxx file.
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(); unsigned long ulClassCnt = ITERATOR_GETCOUNT( *GetClassList() );
pStream->NewLine(); pStream->Write( "// the number of classes provided by this DLL" ); pStream->NewLine(); pStream->Write( "const unsigned long ulClassCnt = " ); pStream->WriteNumber( "%d", ulClassCnt ); pStream->Write( ";" );
pStream->NewLine(2);
GenClassFactoryArray( pCCB );
static STRING_BLOCK DataStructs = { "// lifetime information for the module (dll) containing this object", "struct MidlModuleLifetimeInfo gLifetimeInfo =", " {", " 0, // ulModuleRefCnt", " &ModuleUnReferenced,", " 0, // ulObjectRefCnt", " &ObjectsUnReferenced", " };", 0 };
pStream->NewLine(); pStream->WriteBlock( DataStructs );
pStream->NewLine(2);
return CG_OK; }
CG_STATUS CG_COM_SERVER_EXE::GenIteratorClass( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the custom iterator class for the _e.cxx file.
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(); char * pName = GetSymName();
static STRING_BLOCK IterClass = { "// a special iterator class over these class factories", "class Exe_Class_Iterator : public Midl_Class_Factory_Iterator", " {", "public:", " // just a convenience constructor", " Exe_Class_Iterator()", " : Midl_Class_Factory_Iterator(", " Midl_Class_Factory_Array, ", " ulClassCnt )", " {", " }", "", " void Init()", " {", " Midl_Class_Factory_Iterator::Init(", " Midl_Class_Factory_Array, ", " ulClassCnt );", " }", "", " };", 0 };
pStream->NewLine(); pStream->WriteBlock( IterClass );
pStream->NewLine(2); return CG_OK; }
CG_STATUS CG_COM_SERVER_EXE::GenClassRegisterRevoke( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the clean-up routines for the _e.cxx file.
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(); char * pName = GetSymName();
static STRING_BLOCK RegisterRevokeCode = { "// these are the handles returned by the CoRegisterClassObject", "DWORD dwRegisterHandles[ulClassCnt] = {0};", "", "// flag to make sure we only call CoRevokeClassObject once", "int fFactoriesRevoked = TRUE;", "", "// do a CoRevokeClassObject on all the live class factories", "HRESULT __stdcall UnregisterAllClassFactories()", "{", " HRESULT hr;", "", " // if we already revoked all the objects, do nothing", " if ( fFactoriesRevoked )", " return S_OK;", "", " Exe_Class_Iterator Iter;", " Midl_Class_Factory_Info * pCur;", " DWORD * pdwHandle = dwRegisterHandles;", "", " // revoke all the class factories", " while ( pCur = Iter.GetNext() )", " {", " hr = CoRevokeClassObject(*pdwHandle);", " if ( FAILED(hr) )", " return hr;", " pdwHandle++;", " }", "", " fFactoriesRevoked = TRUE;", " return hr;", "}", "", "// do a CoRegisterClassObject on all the class factories", "HRESULT __stdcall RegisterAllClassFactories()", "{", " Exe_Class_Iterator Iter;", " Midl_Class_Factory_Info * pCur;", " HRESULT hr = S_OK;", " DWORD * pdwHandle = dwRegisterHandles;", "", " fFactoriesRevoked = FALSE;", "", " // register all the valid class factories", " while ( pCur = Iter.GetNext() )", " {", " hr =CoRegisterClassObject( ", " *pCur->pFactoryID,", " (IUnknown*)(*pCur->ppFactory),", " CLSCTX_LOCAL_SERVER,", " REGCLS_MULTI_SEPARATE,", " pdwHandle);", " if ( FAILED( hr ) )", " return hr;", "", " pdwHandle++;", " }", "", " return hr;", "}", 0 };
pStream->NewLine(); pStream->WriteBlock( RegisterRevokeCode );
pStream->NewLine(2); return CG_OK; }
CG_STATUS CG_COM_SERVER_EXE::GenRegistryCode( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the clean-up routines for the _e.cxx file.
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(); char * pName = GetSymName();
static STRING_BLOCK RegistryCode = { "///////////////////////////////////////////////////////////////////////", "// these routines maintain the registry information for these classes", "//", "// call UpdateServerRegistry to add all the classes to the registry", "// call CleanupServerRegistry to remove the classes from the registry", "", "HRESULT __stdcall UpdateServerRegistry()", "{", " char szDllFileName[MAX_PATH];", " HRESULT hr;", "", " // get the exe name", " if ( !GetModuleFileNameA(NULL, szDllFileName, sizeof(szDllFileName)) )", " return E_FAIL;", "", " Exe_Class_Iterator Iter;", " Midl_Class_Factory_Info * pCur;", "", " // register all the clsid's", " while ( pCur = Iter.GetNext() )", " {", " hr = NdrRegisterServerExe( szDllFileName, pCur );", " if ( FAILED(hr) )", " return hr;", " }", "", " return S_OK;", "}", "", "// remove the registry entries for the class here", "HRESULT __stdcall CleanupServerRegistry()", "{", " HRESULT hr;", "", " Exe_Class_Iterator Iter;", " Midl_Class_Factory_Info * pCur;", "", " // register all the clsid's", " while ( pCur = Iter.GetNext() )", " {", " hr = NdrUnregisterServerExe( pCur );", " if ( FAILED(hr) )", " return hr;", " }", "", " return S_OK;", "}", 0 };
pStream->NewLine(); pStream->WriteBlock( RegistryCode );
pStream->NewLine(2); return CG_OK; }
CG_STATUS CG_COM_SERVER::GenHeader( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the COM server file code for an interface inherited by a COM class 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:
----------------------------------------------------------------------------*/ { return CG_OK; }
|