|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
ccb.cxx
Abstract:
Some method implementations of the ccb code generation class.
Notes:
History:
Sep-20-1993 VibhasC Created.
----------------------------------------------------------------------------*/
#pragma warning ( disable : 4505 )
/****************************************************************************
* include files ***************************************************************************/ #include "becls.hxx"
#pragma hdrstop
extern CMD_ARG * pCommand;
/****************************************************************************
* local definitions ***************************************************************************/
/****************************************************************************
* local data ***************************************************************************/
/****************************************************************************
* externs ***************************************************************************/ /****************************************************************************/
CCB::CCB( PNAME pGBRtnName, PNAME pSRRtnName, PNAME pFBRtnName, OPTIM_OPTION OptimOption, BOOL fManagerEpv, BOOL fNoDefEpv, BOOL fOldNames, unsigned long Mode, BOOL fRpcSSSwitchSetInCompiler, BOOL fMustCheckAllocError, BOOL fCheckRef, BOOL fCheckEnum, BOOL fCheckBounds, BOOL fCheckStubData ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Arguments:
pGBRtnName - default get buffer routine name pSRRtnName - default send receive routine name pFBRtnName - default free buffer routine name OptimOption - optimisation options. fManagerEpvFlag - manager epv flag. fOldNames - Do we want MIDL 1.0 style names. fNoDefEpv - we dont want a default epv generated. Mode - Compiler mode : 0 for osf, 1 for ms_ext fRpcSSSwitchSetInCompiler - corresponds to -rpcss enabled fMustCheckAllocError - corresponds to -error allocation on command line fCheckRef - Check ref pointers fCheckEnum - Check enums fCheckBounds - Check array bounds. fCheckStubData - Check for bad stub data.
Return Value:
Notes:
If the manager epv was set, then we generate the epv calls. Else produce statically linked stubs (default behaviour). ----------------------------------------------------------------------------*/ { SetStream( 0, NULL ); SetOptimOption( OptimOption );
// We can't use SetRuntimeRtnNames here because if any of the names
// are NULL the member won't get initialized. This also make the
// existing version of SetRuntimeRtnNames obsolete.
pGetBufferRtnName = pGBRtnName; pSendReceiveRtnName = pSRRtnName; pFreeBufferRtnName = pFBRtnName;
// These don't appear to be used
pIUnknownCG = 0; pIClassfCG = 0; pStubDescResource = 0;
// These all seem to be lazily initialized so strictly speaking they don't
// need to be initialized here but it's lots safer
EmbeddingLevel = 0; IndirectionLevel = 0; fDeferPointee = 0; fAtLeastOneDeferredPointee = 0; fMemoryAllocDone = 0; fRefAllocDone = 0; fReturnContext = 0;
pInterfaceCG = 0; pFileCG = 0; pInterfaceName = 0; MajorVersion = 0; MinorVersion = 0; CurrentProcNum = 0; CurrentVarNum = 0; RpcFlags = 0; pAllocRtnName = 0; pFreeRtnName = 0; pResDictDatabase = 0; pCurrentSizePointer = 0; lcid = 0;
// There is no "uninitialized" value to set CodeGenPhase and CodeGenSide
// to nor any logical value to initialize them to at this point. Manual
// inspection seems to indicate that they are properly set as needed.
// CodeGenPhase = ??
// CodeGenSide = ??
//
// GetPtrToPtrInBuffer is used in CG_POINTER::PointerChecks but nobody
// seems to call SetPtrInPtrInBuffer so this may be dead wood
//
PtrToPtrInBuffer = 0;
pFormatString = NULL; pProcFormatString = NULL; pExprFormatString = NULL;
pGenericHandleRegistry = new TREGISTRY; pContextHandleRegistry = new TREGISTRY; pPresentedTypeRegistry = new TREGISTRY; pRepAsWireTypeRegistry = new TREGISTRY; pQuintupleRegistry = new TREGISTRY; pExprEvalRoutineRegistry= new TREGISTRY; pSizingRoutineRegistry = new TREGISTRY; pMarshallRoutineRegistry= new TREGISTRY; pUnMarshallRoutineRegistry = new TREGISTRY; pFreeRoutineRegistry = new TREGISTRY; pMemorySizingRoutineRegistry = new TREGISTRY; pTypeAlignSizeRegistry = new TREGISTRY; pTypeEncodeRegistry = new TREGISTRY; pTypeDecodeRegistry = new TREGISTRY; pTypeFreeRegistry = new TREGISTRY; pPickledTypeList = new IndexedList; pProcEncodeDecodeRegistry= new TREGISTRY; pCallAsRoutineRegistry = new TREGISTRY;
pRecPointerFixupRegistry = NULL;
SetImplicitHandleIDNode( 0 );
SetCGNodeContext( NULL ); pCurrentRegionField = NULL; SetLastPlaceholderClass( NULL ); SetPrefix( 0 );
pGenericIndexMgr = new CCB_RTN_INDEX_MGR(); pContextIndexMgr = new CCB_RTN_INDEX_MGR();
pExprEvalIndexMgr = new CCB_RTN_INDEX_MGR();
pExprFrmtStrIndexMgr = NULL;
pTransmitAsIndexMgr = new CCB_RTN_INDEX_MGR(); pRepAsIndexMgr = new CCB_RTN_INDEX_MGR();
pQuintupleDictionary = new QuintupleDict; pQuadrupleDictionary = new QuadrupleDict;
pRepAsPadExprDictionary = new RepAsPadExprDict(); pRepAsSizeDictionary = new RepAsSizeDict();
SetImbedingMemSize(0); SetImbedingBufSize(0);
ClearInCallback();
fMEpV = fManagerEpv; fNoDefaultEpv = fNoDefEpv; fInterpretedRoutinesUseGenHandle = 0;
ClearOptionalExternFlags(); fSkipFormatStreamGeneration = 1;
SetOldNames( (fOldNames == TRUE) ? 1 : 0 );
SetMode( Mode );
SetInObjectInterface( FALSE );
SetRpcSSSwitchSet( fRpcSSSwitchSetInCompiler ); SetMustCheckAllocationError( fMustCheckAllocError ); SetMustCheckRef( fCheckRef ); SetMustCheckEnum( fCheckEnum ); SetMustCheckBounds( fCheckBounds ); SetMustCheckStubData( fCheckStubData ); pCreateTypeLib = NULL; pCreateTypeInfo = NULL; szDllName = NULL; SetInDispinterface(FALSE);
SetCurrentParam( 0 ); SetInterpreterOutSize( 0 );
SetNdr64Format( NULL ); }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
These routines simply bounce to the file level routines. They really should be inline but the depencies between ccb.hxx and filecls.cxx are really ugly and I haven't figured them out yet
----------------------------------------------------------------------------*/
BOOL CCB::GetMallocAndFreeStructExternEmitted() { return pFile->GetMallocAndFreeStructExternEmitted(); }
void CCB::SetMallocAndFreeStructExternEmitted() { pFile->SetMallocAndFreeStructExternEmitted(); }
char * CCB::GenMangledName() /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Given an input name, mangle it with the interface name and version.
Arguments:
Return Value:
A pointer to allocated string containing the complete mangled string.
Notes:
This is how the mangling takes place:
<interface-name>_v<Major>_<Minor>_<pInputName>
This is what is returned by the routine:
"v<Major>_<Minor>"
or
"" ----------------------------------------------------------------------------*/ { static char TempBuf[30]; unsigned short M,m;
GetVersion( &M, &m );
if( IsOldNames() ) { TempBuf[ 0 ] = '\0'; } else { sprintf( TempBuf, "_v%d_%d", M, m ); }
return TempBuf; }
RESOURCE * CCB::GetStandardResource( STANDARD_RES_ID ResID ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Search for a resource with a standard name.
Arguments:
ResID - The standard resource ID.
Return Value:
Notes:
Translate the enum to the name. Search in all dictionaries. ----------------------------------------------------------------------------*/ { PNAME pName; RESOURCE * pResource;
static char * LocalResIDToResName[] = { RPC_MESSAGE_VAR_NAME ,STUB_MESSAGE_VAR_NAME ,GetInterfaceCG()->GetStubDescName() ,BUFFER_POINTER_VAR_NAME ,RPC_STATUS_VAR_NAME ,LENGTH_VAR_NAME ,BH_LOCAL_VAR_NAME ,PXMIT_VAR_NAME };
static char * ParamResIDToResName[] = { PRPC_MESSAGE_VAR_NAME };
static char * GlobalResIDToResName[] = { AUTO_BH_VAR_NAME };
if( IS_STANDARD_LOCAL_RESOURCE( ResID ) ) { pName = LocalResIDToResName[ ResID - ST_LOCAL_RESOURCE_START ]; } else if( IS_STANDARD_PARAM_RESOURCE( ResID ) ) { pName = ParamResIDToResName[ ResID - ST_PARAM_RESOURCE_START ]; } else if( IS_STANDARD_GLOBAL_RESOURCE( ResID ) ) { pName = GlobalResIDToResName[ ResID - ST_GLOBAL_RESOURCE_START ]; } #if defined(MIDL_ENABLE_ASSERTS)
else MIDL_ASSERT(0); #endif
if ( ( pResource = GetResDictDatabase()->GetLocalResourceDict()->Search( pName ) ) == 0 ) { if ( ( pResource = GetResDictDatabase()->GetParamResourceDict()->Search( pName ) ) == 0) { if ( (pResource = GetResDictDatabase()->GetTransientResourceDict()->Search(pName) ) == 0) { if ( ( pResource=GetResDictDatabase()->GetGlobalResourceDict()->Search(pName) ) == 0 ) return 0; } } }
return pResource; }
RESOURCE * CCB::DoAddResource( RESOURCE_DICT * pResDict, PNAME pName, node_skl * pType ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Add a resource to a dictionary.
Arguments:
pResDict - A pointer to the resource dictionary. pName - The resource name. pType - The type of the resource.
Return Value:
Notes:
If the type of the resource does not indicate a param node, assume it is an ID node and create an id node for it.
----------------------------------------------------------------------------*/ { RESOURCE * pRes;
if( (pRes = pResDict->Search( pName )) == 0 ) { pRes = pResDict->Insert( pName, pType ); }
return pRes; }
RESOURCE * CCB::SetStubDescResource() /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Set up the stub descriptor resource.
Arguments:
None.
Return Value:
None.
Notes:
----------------------------------------------------------------------------*/ { node_id * pStubDescVar = new node_id( GetInterfaceCG()->GetStubDescName() );
pStubDescVar->SetBasicType( (node_skl *) new node_def( STUB_DESC_STRUCT_TYPE_NAME ) );
pStubDescVar->SetEdgeType( EDGE_USE );
pStubDescResource = new RESOURCE( GetInterfaceCG()->GetStubDescName(), (node_skl *)pStubDescVar ); return pStubDescResource; }
void CCB::OutputRundownRoutineTable() { OutputSimpleRoutineTable( pContextIndexMgr, RUNDOWN_ROUTINE_TABLE_TYPE, RUNDOWN_ROUTINE_TABLE_VAR ); }
void CCB::OutputExprEvalRoutineTable() { OutputSimpleRoutineTable( pExprEvalIndexMgr, EXPR_EVAL_ROUTINE_TABLE_TYPE, EXPR_EVAL_ROUTINE_TABLE_VAR ); }
void CCB::OutputSimpleRoutineTable( CCB_RTN_INDEX_MGR * pIndexMgr, char * pTableTypeName, char * pTableVarName ) { long i; char * pName;
pStream->NewLine(); pStream->Write( "static const " ); pStream->Write( pTableTypeName ); pStream->Write( ' ' ); pStream->Write( pTableVarName ); pStream->Write( "[] = ");
pStream->IndentInc(); pStream->NewLine();
pStream->Write( '{' ); pStream->NewLine();
for ( i = 1; ( pName = pIndexMgr->Lookup(i) ) != 0 ; i++ ) { if ( i != 1 ) pStream->Write( ',' ); pStream->Write( pName ); pStream->NewLine(); }
pStream->Write( "};" );
pStream->IndentDec(); pStream->NewLine( 2 ); }
void CCB::OutputOldExprEvalRoutine(EXPR_EVAL_CONTEXT *pExprEvalContext) { CG_NDR * pContainer = pExprEvalContext->pContainer; expr_node * pMinExpr = pExprEvalContext->pMinExpr; expr_node * pSizeExpr = pExprEvalContext->pSizeExpr; char * pRoutineName= pExprEvalContext->pRoutineName; unsigned long Displacement= pExprEvalContext->Displacement; pStream = GetStream();
// generate the header of the evaluation routine
pStream->NewLine(); pStream->Write( "static void __RPC_USER " ); pStream->Write( pRoutineName ); pStream->Write( "( PMIDL_STUB_MESSAGE pStubMsg )" ); pStream->NewLine(); pStream->Write( '{'); pStream->IndentInc(); pStream->NewLine();
//
// Get the proper struct type.
//
char * pContainerTypeName = 0;
MIDL_ASSERT( pContainer->IsStruct() || pContainer->IsProc() );
if ( pContainer->IsProc() ) { MIDL_ASSERT( GetOptimOption() | OPTIMIZE_INTERPRETER );
SetCGNodeContext( pContainer );
((CG_PROC *)pContainer)->GenNdrInterpreterParamStruct( this );
pContainerTypeName = PARAM_STRUCT_TYPE_NAME; } else { pContainerTypeName = ((CG_STRUCT *)pContainer)-> GetType()->GetSymName(); }
expr_node * pExpr = new expr_variable( "pStubMsg->StackTop" );
if ( Displacement ) { expr_constant * pConstExpr = new expr_constant( (long) Displacement ); expr_op_binary * pSubtrExpr = new expr_op_binary( OP_MINUS, pExpr, pConstExpr ); pExpr = pSubtrExpr; }
//
// Don't change this call - Dave.
//
node_id * pId;
if ( pContainer->IsProc() ) { pId = MakePtrIDNodeFromTypeNameWithCastedExpr( "pS", pContainerTypeName, pExpr ); } else { pId = MakePtrIDNodeWithCastedExpr( "pS", pContainer->GetType(), pExpr ); }
pId->PrintType( PRT_ID_DECLARATION, pStream ); pStream->NewLine();
// generate calculation for the Offset field
char TotalPrefix[256];
strcpy( TotalPrefix, "pS->" ); strcat( TotalPrefix, pExprEvalContext->pPrintPrefix );
pStream->Write( "pStubMsg->Offset = " ); if ( pMinExpr ) { pMinExpr->PrintWithPrefix( pStream, TotalPrefix ); pStream->Write( ';' ); } else pStream->Write( "0;" ); pStream->NewLine();
// generate calculation for MaxCount.
if ( pCommand->Is64BitEnv() ) { // pStubMsg->MaxCount = (ULONG_PTR) ...
pStream->Write( "pStubMsg->MaxCount = (ULONG_PTR) ( " ); } else { // pStubMsg->MaxCount = ( unsigned long ) ...
pStream->Write( "pStubMsg->MaxCount = ( unsigned long ) ( " ); } pSizeExpr->PrintWithPrefix( pStream, TotalPrefix );
pStream->Write( " );" );
/***
*** Let's leave this out as the default for now. This means first_is() with last_is() is broken, but first_is() with length_is() will work.
if ( pMinExpr ) { pStream->Write( " - pStubMsg->Offset;" ); } else pStream->Write( ";" );
*** ***/
// generate the closing of the evaluation routine
pStream->IndentDec(); pStream->NewLine(); pStream->Write( '}' ); pStream->NewLine(); }
void CCB::OutputRegisteredExprEvalRoutines() { ITERATOR RegisteredRoutines; EXPR_EVAL_CONTEXT * pExprEvalContext;
GetListOfExprEvalRoutines( RegisteredRoutines);
while ( ITERATOR_GETNEXT( RegisteredRoutines, pExprEvalContext ) ) { OutputOldExprEvalRoutine(pExprEvalContext); } }
void CCB::OutputExpressionFormatString() { CCB_EXPR_INDEX_MGR * pIndexMgr = GetExprFrmtStrIndexMgr(); char Buf[200]; pStream->NewLine(); pStream->Write("static const unsigned short "EXPR_FORMAT_STRING_OFFSET_TABLE "[] =") ; pStream->NewLine(); pStream->Write("{"); pStream->NewLine();
for (long i = 1; i < pIndexMgr->GetIndex(); i++) { pStream->Write( MIDL_ITOA(pIndexMgr->GetOffset(i), Buf, 10 ) ); pStream->NewLine(); } pStream->Write("};"); pStream->NewLine(); // GetExprFormatString()->OutputExprEvalFormatString(GetStream());
}
// ========================================================================
// user_marshall Quadruple table
// ========================================================================
void CCB::OutputQuadrupleTable() {
static char * QuadrupleNames[] = { USER_MARSHAL_SIZE, USER_MARSHAL_MARSHALL, USER_MARSHAL_UNMARSHALL, USER_MARSHAL_FREE };
static char * Ndr64QuadrupleNames[] = { NDR64_USER_MARSHAL_SIZE, NDR64_USER_MARSHAL_MARSHALL, NDR64_USER_MARSHAL_UNMARSHALL, NDR64_USER_MARSHAL_FREE };
long NoOfEntries = GetQuadrupleDictionary()->GetCount();
pStream->NewLine(); pStream->Write("static const " USER_MARSHAL_ROUTINE_TABLE_TYPE ); if ( pCommand->IsNDR64Run() ) { pStream->Write( " " NDR64_USER_MARSHAL_ROUTINE_TABLE_VAR "[ " WIRE_MARSHAL_TABLE_SIZE " ] = " ); } else { pStream->Write( " " USER_MARSHAL_ROUTINE_TABLE_VAR "[ " WIRE_MARSHAL_TABLE_SIZE " ] = " ); } pStream->IndentInc(); pStream->IndentInc(); pStream->NewLine();
pStream->Write( '{' ); pStream->IndentInc(); pStream->NewLine();
USER_MARSHAL_CONTEXT * * QuadrupleLookupTable; USER_MARSHAL_CONTEXT * pQContext; int i;
QuadrupleLookupTable = new USER_MARSHAL_CONTEXT *[ NoOfEntries ];
ITERATOR Quadruples;
GetQuadrupleDictionary()->GetListOfItems( Quadruples );
for ( i = 0; ITERATOR_GETNEXT( Quadruples, pQContext ); i++ ) { MIDL_ASSERT( pQContext->Index < NoOfEntries && "look up index violation" ); QuadrupleLookupTable[ pQContext->Index ] = pQContext; }
MIDL_ASSERT( i == NoOfEntries );
ISTREAM * pStream = GetStream();
for ( i = 0; i < NoOfEntries; i++ ) { pQContext = QuadrupleLookupTable[i];
if ( i ) pStream->Write( ',' ); pStream->NewLine(); pStream->Write( '{' ); pStream->NewLine(); for ( int FuncNo = 0; FuncNo < 4; FuncNo++) { if ( FuncNo ) pStream->Write( ',' ); pStream->Write( pQContext->pTypeName ); if ( pCommand->IsNDR64Run() ) pStream->Write( Ndr64QuadrupleNames[ FuncNo ] ); else pStream->Write( QuadrupleNames[ FuncNo ] ); pStream->NewLine(); } pStream->Write( '}' ); }
pStream->IndentDec(); pStream->NewLine( 2 ); pStream->Write( "};" );
pStream->IndentDec(); pStream->IndentDec(); pStream->NewLine( 2 );
delete QuadrupleLookupTable; }
// =======================================================================
// International character sizing/conversion routine table
// =======================================================================
void CCB::OutputCsRoutineTables() { char *pRoutineSuffix[4] = { CS_NET_SIZE, CS_TO_NET_CS, CS_LOCAL_SIZE, CS_FROM_NET_CS };
//
// Output the sizing/conversion routines table
//
pStream->Write( CS_SIZE_CONVERT_ROUTINE_TABLE_TYPE ); pStream->Write( ' ' ); pStream->Write( CS_SIZE_CONVERT_ROUTINE_TABLE_VAR ); pStream->Write( "[] =" ); pStream->IndentInc(); pStream->WriteOnNewLine( '{' ); pStream->IndentInc();
PNAME pType; bool fFirst = true;
ITERATOR_INIT( CsTypes );
while ( ITERATOR_GETNEXT( CsTypes, pType ) ) { if ( ! fFirst ) pStream->Write( ',' );
pStream->WriteOnNewLine( '{' );
for (int i = 0; i < 4; i++ ) { pStream->WriteOnNewLine( pType ); pStream->Write( pRoutineSuffix[i] ); pStream->Write( ',' ); }
pStream->WriteOnNewLine( '}' );
fFirst = false; } pStream->IndentDec(); pStream->WriteOnNewLine( "};" ); pStream->IndentDec(); pStream->NewLine();
//
// Output the tag routines table
//
if ( 0 != CsTagRoutines.GetCount() ) { pStream->WriteOnNewLine( CS_TAG_ROUTINE_TABLE_TYPE ); pStream->Write( ' ' ); pStream->Write( CS_TAG_ROUTINE_TABLE_VAR ); pStream->Write( "[] =" ); pStream->IndentInc(); pStream->WriteOnNewLine( '{' ); fFirst = true;
ITERATOR_INIT( CsTagRoutines );
while ( ITERATOR_GETNEXT( CsTagRoutines, pType ) ) { if ( ! fFirst ) pStream->Write( ',' );
pStream->WriteOnNewLine( pType );
fFirst = false; }
pStream->WriteOnNewLine( "};" ); pStream->IndentDec(); pStream->NewLine(); }
//
// Output the pointers-to-tables structure
//
pStream->WriteOnNewLine( CS_ROUTINE_TABLES_TYPE ); pStream->Write( ' ' ); pStream->Write( CS_ROUTINE_TABLES_VAR ); pStream->Write( " =" ); pStream->IndentInc(); pStream->WriteOnNewLine( '{' ); pStream->WriteOnNewLine( CS_SIZE_CONVERT_ROUTINE_TABLE_VAR ); pStream->Write( ',' ); pStream->WriteOnNewLine( ( 0 != CsTagRoutines.GetCount() ) ? CS_TAG_ROUTINE_TABLE_VAR : "0" ); pStream->WriteOnNewLine( "};" ); pStream->IndentDec(); pStream->NewLine(); }
// =======================================================================
// Transmit as and Represent As tables.
// =======================================================================
char * MakeAnXmitName( char * pTypeName, char * pRoutineName, unsigned short ) /*++
makes the following name: <type_name>_<routine_name>_<index> --*/ { MIDL_ASSERT( pTypeName && pRoutineName ); char * pXmitName = new char[ strlen(pTypeName) + strlen(pRoutineName) + 1 ]; strcpy( pXmitName, pTypeName ); strcat( pXmitName, pRoutineName ); return( pXmitName ); }
#define QUINTUPLE_SIZE 4
typedef struct _QUINTUPLE_NAMES { char * TableType; char * TableVar; char * FuncName[ QUINTUPLE_SIZE ]; } QUINTUPLE_NAMES;
void CCB::OutputQuintupleTable() { static QUINTUPLE_NAMES TransmitNames = { XMIT_AS_ROUTINE_TABLE_TYPE, XMIT_AS_ROUTINE_TABLE_VAR, XMIT_TO_XMIT, XMIT_FROM_XMIT, XMIT_FREE_XMIT, XMIT_FREE_INST };
static QUINTUPLE_NAMES RepNames= { REP_AS_ROUTINE_TABLE_TYPE, REP_AS_ROUTINE_TABLE_VAR, REP_FROM_LOCAL, REP_TO_LOCAL, REP_FREE_INST, REP_FREE_LOCAL };
long NoOfEntries = GetQuintupleDictionary()->GetCount();
pStream->NewLine(); pStream->Write("static const "XMIT_AS_ROUTINE_TABLE_TYPE ); pStream->Write( " " XMIT_AS_ROUTINE_TABLE_VAR "[ " TRANSMIT_AS_TABLE_SIZE " ] = " );
pStream->IndentInc(); pStream->IndentInc(); pStream->NewLine();
pStream->Write( '{' ); pStream->IndentInc(); pStream->NewLine();
// Now construct a lookup table with entries in the order of indexes.
// (we have to keep index managers separate for rep_as and xmit_as
// and we still have a common table)
XMIT_AS_CONTEXT * * QuintupleLookupTable; XMIT_AS_CONTEXT * pQContext; int i;
QuintupleLookupTable = new XMIT_AS_CONTEXT *[ NoOfEntries ];
ITERATOR Quintuples;
GetListOfQuintuples( Quintuples ); for ( i = 0; ITERATOR_GETNEXT( Quintuples, pQContext ); i++ ) { MIDL_ASSERT( pQContext->Index < NoOfEntries && "look up index violation" ); QuintupleLookupTable[ pQContext->Index ] = pQContext; }
ISTREAM * pStream = GetStream();
for ( i = 0; i < NoOfEntries; i++ ) { pQContext = QuintupleLookupTable[i];
char * pName = pQContext->fXmit ? pQContext->pTypeName : ((CG_REPRESENT_AS *)pQContext->pXmitNode)-> GetTransmittedType()->GetSymName(); unsigned short Index = pQContext->Index;
MIDL_ASSERT( (i == Index) && " xmit index violation" );
QUINTUPLE_NAMES * pQNames = pQContext->fXmit ? & TransmitNames : & RepNames; if ( i ) pStream->Write( ',' ); pStream->NewLine(); pStream->Write( '{' ); pStream->NewLine(); for ( int FuncNo = 0; FuncNo < QUINTUPLE_SIZE; FuncNo++) { char * pTempName = MakeAnXmitName( pName, pQNames->FuncName[ FuncNo ], Index ); if ( FuncNo ) pStream->Write( ',' ); pStream->Write( pTempName ); pStream->NewLine(); delete pTempName; } pStream->Write( '}' ); }
pStream->IndentDec(); pStream->NewLine( 2 ); pStream->Write( "};" );
pStream->IndentDec(); pStream->IndentDec(); pStream->NewLine( 2 );
delete QuintupleLookupTable; }
// =======================================================================
// helpers for Transmit as and Represent As routines
// =======================================================================
static void OpenXmitOrRepRoutine( ISTREAM * pStream, char * pName ) /*++
Routine description:
This routine emits the header of a *_as helper routine:
void __RPC_API <name>( PMIDL_STUB_MESSAGE pStubMsg ) {
Note:
There is a side effect here that the name of the routine is deleted (this is always the name created by a call to MakeAnXmitName).
--*/ { pStream->Write ( "NDR_SHAREABLE void __RPC_USER" ); pStream->NewLine(); pStream->Write ( pName ); pStream->Write ( "( PMIDL_STUB_MESSAGE pStubMsg )" ); pStream->NewLine(); pStream->Write( '{'); pStream->IndentInc(); pStream->NewLine();
delete pName; }
static void CloseXmitOrRepRoutine( ISTREAM * pStream ) /*++
Routine description:
Just a complement to the OpenXmitOrRepRoutine:
}
--*/ { pStream->IndentDec(); pStream->NewLine(); pStream->Write( '}'); pStream->NewLine(); }
static void OutputPresentedTypeInit( ISTREAM * pStream, char * pPresentedTypeName ) /*++
Routine description:
Emits
memset( pStubMsg->pPresentedType, 0, sizeof( <presented type> ));
--*/ { pStream->NewLine(); pStream->Write( MIDL_MEMSET_RTN_NAME "( "PSTUB_MESSAGE_PAR_NAME"->pPresentedType, 0, sizeof(" ); pStream->Write( pPresentedTypeName ); pStream->Write( " ));" ); }
static void OutputCastedPtr( ISTREAM * pStream, char * pTypeName, char * pVarName ) { pStream->Write( '(' ); pStream->Write( pTypeName ); pStream->Write( " *) " ); pStream->Write( pVarName ); }
// =======================================================================
// Transmit as
// =======================================================================
//
// The presented type size problem.
// The engine doesn't use pStubMsg->PresentedTypeSize field anymore.
// The presented type size nowadays is passed within the format code.
//
static void OutputToXmitCall( ISTREAM * pStream, char * pPresentedTypeName, char * pTransmitTypeName ) { pStream->Write( pPresentedTypeName ); pStream->Write( "_to_xmit( " ); OutputCastedPtr( pStream, pPresentedTypeName, PSTUB_MESSAGE_PAR_NAME"->pPresentedType, " ); pStream->IndentInc(); pStream->NewLine(); pStream->Write( '(' ); pStream->Write( pTransmitTypeName ); pStream->Write( " * *) &pStubMsg->pTransmitType );" ); pStream->IndentDec(); // pStream->NewLine();
}
static void OutputFreeXmitCall( ISTREAM * pStream, char * pPresentedTypeName, char * pTransmitTypeName ) { pStream->Write( pPresentedTypeName ); pStream->Write( "_free_xmit( " ); OutputCastedPtr( pStream, pTransmitTypeName, "pStubMsg->pTransmitType );" ); }
void CCB::OutputTransmitAsQuintuple( void * pQuintupleContext ) /*++
Routine description:
This routine emits the following helper routines for a transmit as type:
static void __RPC_API <pres_type>_Xmit_ToXmit_<index>( PMIDL_STUB_MESSAGE pStubMsg ) { <pres_type>_to_xmit( (<pres_type> *) pStubMsg->pPresentedType, (<tran_type> * *) &pStubMsg->pTransmitType ); }
static void __RPC_API <pres_type>_Xmit_FromXmit_<index>( PMIDL_STUB_MESSAGE pStubMsg ) { <pres_type>_from_xmit( (<tran_type> *) pStubMsg->pTransmitType, (<pres_type> *) pStubMsg->pPresentedType );
}
static void __RPC_API <pres_type>_Xmit_FreeXmit_<index>( PMIDL_STUB_MESSAGE pStubMsg ) { <pres_type>_free_xmit( (<tran_type> *) pStubMsg-p>TransmitType );
}
static void __RPC_API <pres_type>_Xmit_FreeInst_<index>( PMIDL_STUB_MESSAGE pStubMsg ) { <pres_type>_free_xmit( (<pres_type> *) pStubMsg->pPresentedType );
}
--*/ { XMIT_AS_CONTEXT * pTransmitAsContext = (XMIT_AS_CONTEXT*) pQuintupleContext; int i = pTransmitAsContext->Index;
ISTREAM * pStream = GetStream(); pStream->NewLine();
CG_TRANSMIT_AS* pXmitNode = (CG_TRANSMIT_AS *) pTransmitAsContext->pXmitNode;
char * pPresentedTypeName = pXmitNode->GetPresentedType()->GetSymName(); char * pTransmitTypeName = pXmitNode->GetTransmittedType()-> GetSymName(); // *_XmitTranslateToXmit
OpenXmitOrRepRoutine( pStream, MakeAnXmitName( pPresentedTypeName, XMIT_TO_XMIT, unsigned short(i) ) ); OutputToXmitCall( pStream, pPresentedTypeName, pTransmitTypeName ); CloseXmitOrRepRoutine( pStream );
// *_XmitTranslateFromXmit
OpenXmitOrRepRoutine( pStream, MakeAnXmitName( pPresentedTypeName, XMIT_FROM_XMIT, unsigned short(i) ) ); pStream->Write( pPresentedTypeName ); pStream->Write( "_from_xmit( " ); OutputCastedPtr( pStream, pTransmitTypeName, "pStubMsg->pTransmitType, " ); pStream->IndentInc(); pStream->NewLine(); OutputCastedPtr( pStream, pPresentedTypeName, "pStubMsg->pPresentedType ); " ); pStream->IndentDec(); CloseXmitOrRepRoutine( pStream );
// *_XmitFreeXmit
OpenXmitOrRepRoutine( pStream, MakeAnXmitName( pPresentedTypeName, XMIT_FREE_XMIT, unsigned short(i) ) ); OutputFreeXmitCall( pStream, pPresentedTypeName, pTransmitTypeName ); CloseXmitOrRepRoutine( pStream );
// *_XmitFreeInst
OpenXmitOrRepRoutine( pStream, MakeAnXmitName( pPresentedTypeName, XMIT_FREE_INST, unsigned short(i) ) ); pStream->Write( pPresentedTypeName ); pStream->Write( "_free_inst( " ); OutputCastedPtr( pStream, pPresentedTypeName, "pStubMsg->pPresentedType ); " ); CloseXmitOrRepRoutine( pStream ); }
void CCB::OutputQuintupleRoutines() /*++
--*/ { ITERATOR Quintuples; XMIT_AS_CONTEXT * pQuintupleContext; int i;
// Multi-interface problem: This routine is only called after the last
// interface.
GetListOfQuintuples( Quintuples ); for ( i = 1; ITERATOR_GETNEXT( Quintuples, pQuintupleContext ); i++ ) { if ( pQuintupleContext->fXmit ) OutputTransmitAsQuintuple( pQuintupleContext ); else OutputRepAsQuintuple( pQuintupleContext ); } }
// ========================================================================
// Represent As
// ========================================================================
//
// There is a lot of symmetry between transmit as and represent as.
// We use that where possible. So, among other things there is the following
// mapping between represent as routines and the transmit as ones.
// (So called quintuple actually has 4 routines now.)
//
// wrapers
// pfnTranslateToXmit *_to_xmit *_from_local
// pfnTranslateFromXmit *_from_xmit *_to_local
// pfnFreeXmit *_free_xmit *_free_inst
// pfnFreeInst *_free_inst *_free_local
//
// The presented type size problem.
// This is either known and put into the format code explicitely,
// or unknown and then put there via a C-compile macro.
//
// The presented type alignment problem.
// There is a problem when there is a padding preceding a represent as
// field. The engine needs to know what the alignment for the represent
// as field is. As we may not know its type at the midl compile time,
// the only way to deal with it is to use the parent structure name,
// and the represent as field name.
//
static void OutputToLocalCall( ISTREAM * pStream, char * pLocalTypeName, char * pTransmitTypeName ) { pStream->Write( pTransmitTypeName ); pStream->Write( "_to_local( " ); OutputCastedPtr( pStream, pTransmitTypeName, PSTUB_MESSAGE_PAR_NAME"->pTransmitType, " ); pStream->IndentInc(); pStream->NewLine(); OutputCastedPtr( pStream, pLocalTypeName, PSTUB_MESSAGE_PAR_NAME"->pPresentedType ); " ); pStream->IndentDec(); }
static void OutputFromLocalCall( ISTREAM * pStream, char * pLocalTypeName, char * pTransmitTypeName ) { pStream->Write( pTransmitTypeName ); pStream->Write( "_from_local( " ); OutputCastedPtr( pStream, pLocalTypeName, PSTUB_MESSAGE_PAR_NAME"->pPresentedType, " ); pStream->IndentInc(); pStream->NewLine(); pStream->Write( '(' ); pStream->Write( pTransmitTypeName ); pStream->Write( " * *) &pStubMsg->pTransmitType );" ); pStream->IndentDec(); }
static void OutputRepAsFreeInstCall( ISTREAM * pStream, char * pTransmitTypeName ) { pStream->Write( pTransmitTypeName ); pStream->Write( "_free_inst( " ); OutputCastedPtr( pStream, pTransmitTypeName, PSTUB_MESSAGE_PAR_NAME"->pTransmitType );" ); }
void CCB::OutputRepAsQuintuple( void * pQuintupleContext ) /*++
Routine description:
This routine emits the following helper routines for a transmit as type:
static void __RPC_API <trans_type>_RepAsFromLocal_<index>( PMIDL_STUB_MESSAGE pStubMsg ) { <trans_type>_from_local( (<pres_type> *) pStubMsg->pPresentedType, (<tran_type> * *) &pStubMsg->pTransmitType ); }
static void __RPC_API <trans_type>_RepAsToLocal_<index>( PMIDL_STUB_MESSAGE pStubMsg ) { <trans_type>_to_local( (<tran_type> *) pStubMsg->pTransmitType, (<pres_type> *) pStubMsg->pPresentedType );
}
static void __RPC_API <trans_type>_RepAsFreeInst_<index>( PMIDL_STUB_MESSAGE pStubMsg ) { <trans_type>_free_inst( (<tran_type> *) pStubMsg-p>TransmitType );
}
static void __RPC_API <trans_type>_RepAsFreeLocal_<index>( PMIDL_STUB_MESSAGE pStubMsg ) { <trans_type>_free_local( (<pres_type> *) pStubMsg->pPresentedType );
}
--*/ { XMIT_AS_CONTEXT * pRepAsContext = (XMIT_AS_CONTEXT*) pQuintupleContext; int i = pRepAsContext->Index;
ISTREAM * pStream = GetStream();
CG_REPRESENT_AS * pRepAsNode = (CG_REPRESENT_AS *) pRepAsContext->pXmitNode;
char * pLocalTypeName = pRepAsNode->GetRepAsTypeName(); char * pTransmitTypeName = pRepAsNode->GetTransmittedType()-> GetSymName(); // *_RepAsTranslateToLocal
OpenXmitOrRepRoutine( pStream, MakeAnXmitName( pTransmitTypeName, REP_TO_LOCAL, unsigned short(i) ) ); OutputToLocalCall( pStream, pLocalTypeName, pTransmitTypeName ); CloseXmitOrRepRoutine( pStream );
// *_RepAsTranslateFromLocal
OpenXmitOrRepRoutine( pStream, MakeAnXmitName( pTransmitTypeName, REP_FROM_LOCAL, unsigned short(i) ) ); OutputFromLocalCall( pStream, pLocalTypeName, pTransmitTypeName ); CloseXmitOrRepRoutine( pStream );
// *_RepAsFreeInst
OpenXmitOrRepRoutine( pStream, MakeAnXmitName( pTransmitTypeName, REP_FREE_INST, unsigned short(i) ) ); OutputRepAsFreeInstCall( pStream, pTransmitTypeName ); CloseXmitOrRepRoutine( pStream );
// *_RepAsFreeLocal
OpenXmitOrRepRoutine( pStream, MakeAnXmitName( pTransmitTypeName, REP_FREE_LOCAL, unsigned short(i) ) ); pStream->Write( pTransmitTypeName ); pStream->Write( "_free_local( " ); OutputCastedPtr( pStream, pLocalTypeName, "pStubMsg->pPresentedType ); " ); CloseXmitOrRepRoutine( pStream );
}
// ========================================================================
// end of Transmit As and Represent As
// ========================================================================
BOOL CCB::HasBindingRoutines( CG_HANDLE * pImplicitHandle ) { return ! pGenericIndexMgr->IsEmpty() || (pImplicitHandle && pImplicitHandle->IsGenericHandle()); }
void CCB::OutputBindingRoutines() { long i; char * pName;
pStream->NewLine(); pStream->Write( "static const " BINDING_ROUTINE_TABLE_TYPE ); pStream->Write( " " BINDING_ROUTINE_TABLE_VAR "[ " GENERIC_BINDING_TABLE_SIZE " ] = " );
pStream->IndentInc(); pStream->IndentInc(); pStream->NewLine();
pStream->Write( '{' ); pStream->NewLine();
for ( i = 1; ( pName = pGenericIndexMgr->Lookup(i) ) != 0 ; i++ ) { if ( i != 1 ) pStream->Write( ',' ); pStream->Write( '{' ); pStream->IndentInc(); pStream->NewLine();
pStream->Write( "(" GENERIC_BINDING_ROUTINE_TYPE ")" ); pStream->Write( pName ); pStream->Write( "_bind" ); pStream->Write( ',' ); pStream->NewLine();
pStream->Write( "(" GENERIC_UNBINDING_ROUTINE_TYPE ")" ); pStream->Write( pName ); pStream->Write( "_unbind" );
pStream->IndentDec(); pStream->NewLine();
pStream->Write( " }" ); pStream->NewLine(); }
pStream->NewLine(); pStream->Write( "};" );
pStream->IndentDec(); pStream->IndentDec(); pStream->NewLine(); pStream->NewLine(); }
void CCB::OutputMallocAndFreeStruct() /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Outputs the malloc and free struct for the RpcSsm connection.
This is needed only at the client side and non object interfaces.
If the [enable_allocate] affects a remote routine, the client side stub defaults to malloc and free when unmarshalling regardless of the compiler mode (osf vs. non-osf).
Therefore, the structure gets generated: - always in the osf mode or - in non-osf when at least one routine is affected by the attribute. This is one-per-many-interfaces structure.
Because of win16 DS register problems, malloc and free have to be accessed via wrappers with appropriate calling conventions. To simplify, we generate wrappers for every platform.
REVIEW: win16 is gone, we should be able to get rid of the wrappers.
----------------------------------------------------------------------------*/ { // malloc and free wrappers.
pStream->NewLine(); pStream->Write( "static void * __RPC_USER" ); pStream->NewLine(); pStream->Write( GetInterfaceName() ); pStream->Write( "_malloc_wrapper( size_t _Size )" ); pStream->NewLine(); pStream->Write( "{" ); pStream->IndentInc(); pStream->NewLine(); pStream->Write( "return( malloc( _Size ) );" ); pStream->IndentDec(); pStream->NewLine(); pStream->Write( "}" ); pStream->NewLine();
pStream->NewLine(); pStream->Write( "static void __RPC_USER" ); pStream->NewLine(); pStream->Write( GetInterfaceName() ); pStream->Write( "_free_wrapper( void * _p )" ); pStream->NewLine(); pStream->Write( "{" ); pStream->IndentInc(); pStream->NewLine(); pStream->Write( "free( _p );" ); pStream->IndentDec(); pStream->NewLine(); pStream->Write( "}" ); pStream->NewLine();
// The structure.
pStream->NewLine(); pStream->Write( "static " MALLOC_FREE_STRUCT_TYPE_NAME ); pStream->Write( " " MALLOC_FREE_STRUCT_VAR_NAME " = "); pStream->NewLine(); pStream->Write( "{"); pStream->IndentInc(); pStream->NewLine();
pStream->Write( GetInterfaceName() ); pStream->Write( "_malloc_wrapper," ); pStream->NewLine(); pStream->Write( GetInterfaceName() ); pStream->Write( "_free_wrapper" );
pStream->IndentDec(); pStream->NewLine(); pStream->Write( "};" ); pStream->NewLine(); }
// ========================================================================
void CCB::OutputExternsToMultipleInterfaceTables() /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the tables that may be common to multiple interfaces.
Arguments:
pCCB - A pointer to the code gen controller block.
Return Value:
None.
Notes:
----------------------------------------------------------------------------*/ { CGSIDE Side = GetCodeGenSide();
pStream->NewLine();
//
// Emit extern to the rundown routine table on the server Oi side,
// if needed.
//
if ( (Side == CGSIDE_SERVER) && ( GetOptimOption() & OPTIMIZE_INTERPRETER) && HasRundownRoutines() && ! GetRundownExternEmitted() ) { pStream->Write( "extern const " RUNDOWN_ROUTINE_TABLE_TYPE ); pStream->Write( " " RUNDOWN_ROUTINE_TABLE_VAR "[];" ); pStream->NewLine(); SetRundownExternEmitted(); }
//
// Emit extern to the binding routine pair table on the client Oi stub
// if needed.
//
if ( (Side == CGSIDE_CLIENT) && GetInterpretedRoutinesUseGenHandle() && ! GetGenericHExternEmitted() ) { pStream->Write( "extern const " BINDING_ROUTINE_TABLE_TYPE ); pStream->Write( " " BINDING_ROUTINE_TABLE_VAR "[ " GENERIC_BINDING_TABLE_SIZE " ];" ); pStream->NewLine(); SetGenericHExternEmitted(); }
//
// Emit extern to the expr eval routine table on both sides.
//
if ( HasExprEvalRoutines() && ! GetExprEvalExternEmitted() ) { pStream->Write( "extern const " EXPR_EVAL_ROUTINE_TABLE_TYPE ); pStream->Write( " " EXPR_EVAL_ROUTINE_TABLE_VAR "[];" ); pStream->NewLine(); SetExprEvalExternEmitted(); }
//
// Emit extrn to the transmit as and rep as routine table on both sides.
//
if ( HasQuintupleRoutines() && ! GetQuintupleExternEmitted() ) { pStream->Write( "extern const " XMIT_AS_ROUTINE_TABLE_TYPE ); pStream->Write( " " XMIT_AS_ROUTINE_TABLE_VAR "[ " TRANSMIT_AS_TABLE_SIZE " ];" ); pStream->NewLine(); SetQuintupleExternEmitted(); }
//
// Emit extrn to the user_marshal routine table on both sides.
//
if ( HasQuadrupleRoutines() && ! GetQuadrupleExternEmitted() ) { if ( pCommand->NeedsNDR64Run() ) { pStream->Write( "extern const " USER_MARSHAL_ROUTINE_TABLE_TYPE ); pStream->Write( " " NDR64_USER_MARSHAL_ROUTINE_TABLE_VAR "[ " WIRE_MARSHAL_TABLE_SIZE " ];" ); pStream->NewLine(); } if ( pCommand->NeedsNDRRun() ) { pStream->Write( "extern const " USER_MARSHAL_ROUTINE_TABLE_TYPE ); pStream->Write( " " USER_MARSHAL_ROUTINE_TABLE_VAR "[ " WIRE_MARSHAL_TABLE_SIZE " ];" ); pStream->NewLine(); } SetQuadrupleExternEmitted(); }
if ( HasCsTypes() ) { //
// Emit the international character sizing/conversion routine table
//
OutputCsRoutineTables(); } }
void OutputPlatformCheck( ISTREAM * pStream ) /*++
Routine Description :
Outputs an ifdef checking if the platform usage is as expected
Arguments :
pStream - Stream to output the format string to.
--*/ { pStream->NewLine(); if ( pCommand->GetEnv() == ENV_WIN64 ) { pStream->Write( "#if !defined(__RPC_WIN64__)" ); } else pStream->Write( "#if !defined(__RPC_WIN32__)" );
pStream->NewLine(); pStream->Write( "#error Invalid build platform for this stub." ); pStream->NewLine(); pStream->Write( "#endif" ); pStream->NewLine(); }
const char * Nt51Guard[] = { "#if !(TARGET_IS_NT51_OR_LATER)", "#error You need a Windows XP or later to run this stub because it uses these features:", 0 };
const char * Nt50Guard[] = { "", "#if !(TARGET_IS_NT50_OR_LATER)", "#error You need a Windows 2000 or later to run this stub because it uses these features:", 0 };
const char * Nt40Guard[] = { "", "#if !(TARGET_IS_NT40_OR_LATER)", "#error You need a Windows NT 4.0 or later to run this stub because it uses these features:", 0 };
const char * Nt351win95Guard[] = { "", "#if !(TARGET_IS_NT351_OR_WIN95_OR_LATER)", "#error You need a Windows NT 3.51 or Windows95 or later to run this stub because it uses these features:", 0 };
const char * NtGuardClose[] = { "#error However, your C/C++ compilation flags indicate you intend to run this app on earlier systems.", "#error This app will die there with the RPC_X_WRONG_STUB_VERSION error.", "#endif", 0 };
void OutputMultilineMessage( ISTREAM * pStream, const char * Message[] ) { for (int i = 0; Message[i]; i++) { pStream->Write( Message[i] ); pStream->NewLine(); } }
// should be local OutputVersion Guard but it can't.
class MessageSet { private: char * Messages[10]; int MessageCount; ISTREAM * pStream;
public: MessageSet( ISTREAM * pIStream ) : MessageCount(0), pStream( pIStream ) { }
void AddMessage( char * Message ) { if ( MessageCount < 10 ) Messages[ MessageCount++ ] = Message; }
void PrintMessages() { pStream->Write( "#error " ); for (int i = 0; i < MessageCount; i++ ) { pStream->Write( Messages[i] ); pStream->Write( (i < MessageCount -1) ? ", " : ".\n" ); } } };
void OutputNdrVersionGuard( ISTREAM * pStream ) /*++
Routine Description :
Outputs target release guards.
Arguments :
pStream - Stream to output the format string to.
--*/ { MessageSet Features( pStream ); NdrVersionControl & VC = pCommand->GetNdrVersionControl();
if ( VC.HasNdr60Feature() ) { OutputMultilineMessage( pStream, Nt51Guard ); if ( VC.HasStructPadN() ) Features.AddMessage( "large structure padding" ); if ( VC.HasForceAllocate() ) Features.AddMessage( "The [force_allocate] attribte" ); if ( VC.HasPartialIgnore() ) Features.AddMessage( "The [partial_ignore] attribute" ); if ( VC.HasMultiTransferSyntax() ) Features.AddMessage( "Uses -protocol all or -protocol ndr64" ); } else if ( VC.HasNdr50Feature() ) { OutputMultilineMessage( pStream, Nt50Guard ); if ( VC.HasAsyncHandleRpc() ) Features.AddMessage( "[async] attribute" ); if ( VC.HasNT5VTableSize() ) Features.AddMessage( "more than 110 methods in the interface" ); if ( VC.HasDOA() ) Features.AddMessage( "/robust command line switch" ); if ( VC.HasAsyncUUID() ) Features.AddMessage( "[async_uuid] attribute" ); if ( VC.HasInterpretedNotify() ) Features.AddMessage( "[notify] or [notify_flag] attribute in interpreted mode" ); if ( VC.HasContextSerialization() ) Features.AddMessage( "[serialize] or [noserialize] attribute" ); if ( VC.HasOicfPickling() ) Features.AddMessage( "[encode] or [decode] with -Oicf" ); } else if ( VC.HasNdr20Feature() ) { OutputMultilineMessage( pStream, Nt40Guard ); if ( VC.HasOi2() ) Features.AddMessage( "-Oif or -Oicf" ); if ( VC.HasUserMarshal() ) Features.AddMessage( "[wire_marshal] or [user_marshal] attribute" ); if ( VC.HasRawPipes() ) Features.AddMessage( "idl pipes" ); if ( VC.HasMoreThan64DelegatedProcs() ) Features.AddMessage( "more than 64 delegated procs" ); if ( VC.HasFloatOrDoubleInOi() ) Features.AddMessage( "float, double or hyper in -Oif or -Oicf" ); if ( VC.HasMessageAttr() ) Features.AddMessage( "[message] attribute" ); if ( VC.HasNT4VTableSize() ) Features.AddMessage( "more than 32 methods in the interface" ); } else if ( VC.HasNdr11Feature() ) { OutputMultilineMessage( pStream, Nt351win95Guard ); if ( VC.HasStublessProxies() ) Features.AddMessage( "old (-Oic) stubless proxies" ); if ( VC.HasCommFaultStatusInOi12() ) Features.AddMessage( "[comm_status] or [fault_status] in an -Oi* mode" ); } else return;
Features.PrintMessages(); OutputMultilineMessage( pStream, NtGuardClose );
pStream->NewLine(); }
void CCB::OutputMultipleInterfaceTables() /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the tables that may be common to multiple interfaces.
Arguments:
Return Value:
None.
Notes:
----------------------------------------------------------------------------*/ { CGSIDE Side = GetCodeGenSide();
// First, output the platform consistency check.
OutputPlatformCheck( pStream ); // Now, the ndr version guard against usage on old platforms.
if ( pCommand->GetEnv() == ENV_WIN32 ) OutputNdrVersionGuard( pStream );
MIDL_ASSERT( pCommand->IsNDRRun() || pCommand->IsNDR64Run() );
if ( pCommand->IsNDRRun() ) { if ( pCommand->IsNDRRun() ) GetProcFormatString()->Output( pStream, PROC_FORMAT_STRING_TYPE_NAME, PROC_FORMAT_STRING_STRUCT_NAME, GetRepAsPadExprDict(), GetRepAsSizeDict() ); FixupRecPointers(); GetFormatString()->Output( pStream, FORMAT_STRING_TYPE_NAME, FORMAT_STRING_STRUCT_NAME, GetRepAsPadExprDict(), GetRepAsSizeDict() );
} else {
// If this is the 64bit transfer syntax run, then the proc and type format strings
// should be NULL.
MIDL_ASSERT( NULL == GetProcFormatString() ); MIDL_ASSERT( NULL == GetFormatString() );
GetNdr64Format()->Output();
}
if ( HasQuadrupleRoutines() ) { //
// Emit the user_marshall table on both sides.
//
OutputQuadrupleTable(); } //
// Emit the rundown routine table on the server side, if needed.
//
SetNoOutputIn2ndCodegen( this );
if ( (Side == CGSIDE_SERVER) && (GetOptimOption() & OPTIMIZE_INTERPRETER) && HasRundownRoutines() ) { OutputRundownRoutineTable(); }
//
// Emit the binding routine pair table on the client interpreted stub
// if needed.
//
if ( (Side == CGSIDE_CLIENT) && GetInterpretedRoutinesUseGenHandle() ) { OutputBindingRoutines(); }
if ( HasExprEvalRoutines() ) { //
// Emit the expr eval routines both sides.
//
OutputRegisteredExprEvalRoutines();
//
// Emit the expr eval routine table on both sides.
//
OutputExprEvalRoutineTable(); }
if ( HasExprFormatString() ) { OutputExpressionFormatString(); }
if ( HasQuintupleRoutines() ) { //
// Emit transmit as and represent as routines both sides.
//
OutputQuintupleRoutines();
//
// Emit the xmit as and rep as routine table on both sides.
//
OutputQuintupleTable(); }
if ( GetMallocAndFreeStructExternEmitted() ) { // This is needed for the RpcSs support.
OutputMallocAndFreeStruct(); }
ResetNoOutputIn2ndCodegen( this ); }
long CCB_RTN_INDEX_MGR::Lookup( char * pName ) { long i;
for ( i = 1; i < NextIndex; i++ ) if ( ! strcmp(NameId[i],pName) ) return i;
//
// Insert a new entry
//
MIDL_ASSERT( NextIndex < MGR_INDEX_TABLE_SIZE );
NameId[NextIndex] = new char[strlen(pName) + 1]; strcpy(NameId[NextIndex],pName); NextIndex++;
return NextIndex - 1; }
char * CCB_RTN_INDEX_MGR::Lookup( long Index ) { if ( Index >= NextIndex ) return NULL;
return NameId[Index]; }
long CCB_EXPR_INDEX_MGR::Lookup( char * pName ) { long i;
for ( i = 1; i < NextIndex; i++ ) if ( ! strcmp(NameId[i],pName) ) return i;
//
// Insert a new entry
//
MIDL_ASSERT( NextIndex < MGR_INDEX_TABLE_SIZE );
NameId[NextIndex] = new char[strlen(pName) + 1]; strcpy(NameId[NextIndex],pName); NextIndex++;
return NextIndex - 1; }
char * CCB_EXPR_INDEX_MGR::Lookup( long Index ) { if ( Index >= NextIndex ) return NULL;
return NameId[Index]; }
PNAME CCB::GenTRNameOffLastParam( char * pPrefix ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the name for a temporary resource.
Arguments:
pPrefix - A null terminated prefix string. If this is null, nothing is added.
Return Value:
A freshly allocated resource name string.
Notes:
----------------------------------------------------------------------------*/ { char TempBuffer[ 30 ];
sprintf( TempBuffer, "_%sM", pPrefix ? pPrefix : "" );
PNAME pName = (PNAME) new char [ strlen(TempBuffer) + 1 ]; strcpy( pName, TempBuffer ); return pName; }
|