Source code of Windows XP (NT5)
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.

2122 lines
57 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. ccb.cxx
  5. Abstract:
  6. Some method implementations of the ccb code generation class.
  7. Notes:
  8. History:
  9. Sep-20-1993 VibhasC Created.
  10. ----------------------------------------------------------------------------*/
  11. #pragma warning ( disable : 4505 )
  12. /****************************************************************************
  13. * include files
  14. ***************************************************************************/
  15. #include "becls.hxx"
  16. #pragma hdrstop
  17. extern CMD_ARG * pCommand;
  18. /****************************************************************************
  19. * local definitions
  20. ***************************************************************************/
  21. /****************************************************************************
  22. * local data
  23. ***************************************************************************/
  24. /****************************************************************************
  25. * externs
  26. ***************************************************************************/
  27. /****************************************************************************/
  28. CCB::CCB(
  29. PNAME pGBRtnName,
  30. PNAME pSRRtnName,
  31. PNAME pFBRtnName,
  32. OPTIM_OPTION OptimOption,
  33. BOOL fManagerEpv,
  34. BOOL fNoDefEpv,
  35. BOOL fOldNames,
  36. unsigned long Mode,
  37. BOOL fRpcSSSwitchSetInCompiler,
  38. BOOL fMustCheckAllocError,
  39. BOOL fCheckRef,
  40. BOOL fCheckEnum,
  41. BOOL fCheckBounds,
  42. BOOL fCheckStubData )
  43. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  44. Routine Description:
  45. Arguments:
  46. pGBRtnName - default get buffer routine name
  47. pSRRtnName - default send receive routine name
  48. pFBRtnName - default free buffer routine name
  49. OptimOption - optimisation options.
  50. fManagerEpvFlag - manager epv flag.
  51. fOldNames - Do we want MIDL 1.0 style names.
  52. fNoDefEpv - we dont want a default epv generated.
  53. Mode - Compiler mode : 0 for osf, 1 for ms_ext
  54. fRpcSSSwitchSetInCompiler - corresponds to -rpcss enabled
  55. fMustCheckAllocError - corresponds to -error allocation on command line
  56. fCheckRef - Check ref pointers
  57. fCheckEnum - Check enums
  58. fCheckBounds - Check array bounds.
  59. fCheckStubData - Check for bad stub data.
  60. Return Value:
  61. Notes:
  62. If the manager epv was set, then we generate the epv calls. Else produce
  63. statically linked stubs (default behaviour).
  64. ----------------------------------------------------------------------------*/
  65. {
  66. SetStream( 0, NULL );
  67. SetOptimOption( OptimOption );
  68. // We can't use SetRuntimeRtnNames here because if any of the names
  69. // are NULL the member won't get initialized. This also make the
  70. // existing version of SetRuntimeRtnNames obsolete.
  71. pGetBufferRtnName = pGBRtnName;
  72. pSendReceiveRtnName = pSRRtnName;
  73. pFreeBufferRtnName = pFBRtnName;
  74. // These don't appear to be used
  75. pIUnknownCG = 0;
  76. pIClassfCG = 0;
  77. pStubDescResource = 0;
  78. // These all seem to be lazily initialized so strictly speaking they don't
  79. // need to be initialized here but it's lots safer
  80. EmbeddingLevel = 0;
  81. IndirectionLevel = 0;
  82. fDeferPointee = 0;
  83. fAtLeastOneDeferredPointee = 0;
  84. fMemoryAllocDone = 0;
  85. fRefAllocDone = 0;
  86. fReturnContext = 0;
  87. pInterfaceCG = 0;
  88. pFileCG = 0;
  89. pInterfaceName = 0;
  90. MajorVersion = 0;
  91. MinorVersion = 0;
  92. CurrentProcNum = 0;
  93. CurrentVarNum = 0;
  94. RpcFlags = 0;
  95. pAllocRtnName = 0;
  96. pFreeRtnName = 0;
  97. pResDictDatabase = 0;
  98. pCurrentSizePointer = 0;
  99. lcid = 0;
  100. // There is no "uninitialized" value to set CodeGenPhase and CodeGenSide
  101. // to nor any logical value to initialize them to at this point. Manual
  102. // inspection seems to indicate that they are properly set as needed.
  103. // CodeGenPhase = ??
  104. // CodeGenSide = ??
  105. //
  106. // GetPtrToPtrInBuffer is used in CG_POINTER::PointerChecks but nobody
  107. // seems to call SetPtrInPtrInBuffer so this may be dead wood
  108. //
  109. PtrToPtrInBuffer = 0;
  110. pFormatString = NULL;
  111. pProcFormatString = NULL;
  112. pExprFormatString = NULL;
  113. pGenericHandleRegistry = new TREGISTRY;
  114. pContextHandleRegistry = new TREGISTRY;
  115. pPresentedTypeRegistry = new TREGISTRY;
  116. pRepAsWireTypeRegistry = new TREGISTRY;
  117. pQuintupleRegistry = new TREGISTRY;
  118. pExprEvalRoutineRegistry= new TREGISTRY;
  119. pSizingRoutineRegistry = new TREGISTRY;
  120. pMarshallRoutineRegistry= new TREGISTRY;
  121. pUnMarshallRoutineRegistry = new TREGISTRY;
  122. pFreeRoutineRegistry = new TREGISTRY;
  123. pMemorySizingRoutineRegistry = new TREGISTRY;
  124. pTypeAlignSizeRegistry = new TREGISTRY;
  125. pTypeEncodeRegistry = new TREGISTRY;
  126. pTypeDecodeRegistry = new TREGISTRY;
  127. pTypeFreeRegistry = new TREGISTRY;
  128. pPickledTypeList = new IndexedList;
  129. pProcEncodeDecodeRegistry= new TREGISTRY;
  130. pCallAsRoutineRegistry = new TREGISTRY;
  131. pRecPointerFixupRegistry = NULL;
  132. SetImplicitHandleIDNode( 0 );
  133. SetCGNodeContext( NULL );
  134. pCurrentRegionField = NULL;
  135. SetLastPlaceholderClass( NULL );
  136. SetPrefix( 0 );
  137. pGenericIndexMgr = new CCB_RTN_INDEX_MGR();
  138. pContextIndexMgr = new CCB_RTN_INDEX_MGR();
  139. pExprEvalIndexMgr = new CCB_RTN_INDEX_MGR();
  140. pExprFrmtStrIndexMgr = NULL;
  141. pTransmitAsIndexMgr = new CCB_RTN_INDEX_MGR();
  142. pRepAsIndexMgr = new CCB_RTN_INDEX_MGR();
  143. pQuintupleDictionary = new QuintupleDict;
  144. pQuadrupleDictionary = new QuadrupleDict;
  145. pRepAsPadExprDictionary = new RepAsPadExprDict();
  146. pRepAsSizeDictionary = new RepAsSizeDict();
  147. SetImbedingMemSize(0);
  148. SetImbedingBufSize(0);
  149. ClearInCallback();
  150. fMEpV = fManagerEpv;
  151. fNoDefaultEpv = fNoDefEpv;
  152. fInterpretedRoutinesUseGenHandle = 0;
  153. ClearOptionalExternFlags();
  154. fSkipFormatStreamGeneration = 1;
  155. SetOldNames( (fOldNames == TRUE) ? 1 : 0 );
  156. SetMode( Mode );
  157. SetInObjectInterface( FALSE );
  158. SetRpcSSSwitchSet( fRpcSSSwitchSetInCompiler );
  159. SetMustCheckAllocationError( fMustCheckAllocError );
  160. SetMustCheckRef( fCheckRef );
  161. SetMustCheckEnum( fCheckEnum );
  162. SetMustCheckBounds( fCheckBounds );
  163. SetMustCheckStubData( fCheckStubData );
  164. pCreateTypeLib = NULL;
  165. pCreateTypeInfo = NULL;
  166. szDllName = NULL;
  167. SetInDispinterface(FALSE);
  168. SetCurrentParam( 0 );
  169. SetInterpreterOutSize( 0 );
  170. SetNdr64Format( NULL );
  171. }
  172. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  173. These routines simply bounce to the file level routines. They really
  174. should be inline but the depencies between ccb.hxx and filecls.cxx are
  175. really ugly and I haven't figured them out yet
  176. ----------------------------------------------------------------------------*/
  177. BOOL CCB::GetMallocAndFreeStructExternEmitted()
  178. {
  179. return pFile->GetMallocAndFreeStructExternEmitted();
  180. }
  181. void CCB::SetMallocAndFreeStructExternEmitted()
  182. {
  183. pFile->SetMallocAndFreeStructExternEmitted();
  184. }
  185. char *
  186. CCB::GenMangledName()
  187. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  188. Routine Description:
  189. Given an input name, mangle it with the interface name and version.
  190. Arguments:
  191. Return Value:
  192. A pointer to allocated string containing the complete mangled string.
  193. Notes:
  194. This is how the mangling takes place:
  195. <interface-name>_v<Major>_<Minor>_<pInputName>
  196. This is what is returned by the routine:
  197. "v<Major>_<Minor>"
  198. or
  199. ""
  200. ----------------------------------------------------------------------------*/
  201. {
  202. static char TempBuf[30];
  203. unsigned short M,m;
  204. GetVersion( &M, &m );
  205. if( IsOldNames() )
  206. {
  207. TempBuf[ 0 ] = '\0';
  208. }
  209. else
  210. {
  211. sprintf( TempBuf,
  212. "_v%d_%d",
  213. M,
  214. m );
  215. }
  216. return TempBuf;
  217. }
  218. RESOURCE *
  219. CCB::GetStandardResource(
  220. STANDARD_RES_ID ResID )
  221. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  222. Routine Description:
  223. Search for a resource with a standard name.
  224. Arguments:
  225. ResID - The standard resource ID.
  226. Return Value:
  227. Notes:
  228. Translate the enum to the name. Search in all dictionaries.
  229. ----------------------------------------------------------------------------*/
  230. {
  231. PNAME pName;
  232. RESOURCE * pResource;
  233. static char * LocalResIDToResName[] =
  234. {
  235. RPC_MESSAGE_VAR_NAME
  236. ,STUB_MESSAGE_VAR_NAME
  237. ,GetInterfaceCG()->GetStubDescName()
  238. ,BUFFER_POINTER_VAR_NAME
  239. ,RPC_STATUS_VAR_NAME
  240. ,LENGTH_VAR_NAME
  241. ,BH_LOCAL_VAR_NAME
  242. ,PXMIT_VAR_NAME
  243. };
  244. static char * ParamResIDToResName[] =
  245. {
  246. PRPC_MESSAGE_VAR_NAME
  247. };
  248. static char * GlobalResIDToResName[] =
  249. {
  250. AUTO_BH_VAR_NAME
  251. };
  252. if( IS_STANDARD_LOCAL_RESOURCE( ResID ) )
  253. {
  254. pName = LocalResIDToResName[ ResID - ST_LOCAL_RESOURCE_START ];
  255. }
  256. else if( IS_STANDARD_PARAM_RESOURCE( ResID ) )
  257. {
  258. pName = ParamResIDToResName[ ResID - ST_PARAM_RESOURCE_START ];
  259. }
  260. else if( IS_STANDARD_GLOBAL_RESOURCE( ResID ) )
  261. {
  262. pName = GlobalResIDToResName[ ResID - ST_GLOBAL_RESOURCE_START ];
  263. }
  264. #if defined(MIDL_ENABLE_ASSERTS)
  265. else MIDL_ASSERT(0);
  266. #endif
  267. if ( ( pResource = GetResDictDatabase()->GetLocalResourceDict()->Search( pName ) ) == 0 )
  268. {
  269. if ( ( pResource = GetResDictDatabase()->GetParamResourceDict()->Search( pName ) ) == 0)
  270. {
  271. if ( (pResource = GetResDictDatabase()->GetTransientResourceDict()->Search(pName) ) == 0)
  272. {
  273. if ( ( pResource=GetResDictDatabase()->GetGlobalResourceDict()->Search(pName) ) == 0 )
  274. return 0;
  275. }
  276. }
  277. }
  278. return pResource;
  279. }
  280. RESOURCE *
  281. CCB::DoAddResource(
  282. RESOURCE_DICT * pResDict,
  283. PNAME pName,
  284. node_skl * pType )
  285. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  286. Routine Description:
  287. Add a resource to a dictionary.
  288. Arguments:
  289. pResDict - A pointer to the resource dictionary.
  290. pName - The resource name.
  291. pType - The type of the resource.
  292. Return Value:
  293. Notes:
  294. If the type of the resource does not indicate a param node, assume it
  295. is an ID node and create an id node for it.
  296. ----------------------------------------------------------------------------*/
  297. {
  298. RESOURCE * pRes;
  299. if( (pRes = pResDict->Search( pName )) == 0 )
  300. {
  301. pRes = pResDict->Insert( pName, pType );
  302. }
  303. return pRes;
  304. }
  305. RESOURCE *
  306. CCB::SetStubDescResource()
  307. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  308. Routine Description:
  309. Set up the stub descriptor resource.
  310. Arguments:
  311. None.
  312. Return Value:
  313. None.
  314. Notes:
  315. ----------------------------------------------------------------------------*/
  316. {
  317. node_id * pStubDescVar = new node_id( GetInterfaceCG()->GetStubDescName() );
  318. pStubDescVar->SetBasicType( (node_skl *)
  319. new node_def( STUB_DESC_STRUCT_TYPE_NAME ) );
  320. pStubDescVar->SetEdgeType( EDGE_USE );
  321. pStubDescResource = new RESOURCE( GetInterfaceCG()->GetStubDescName(),
  322. (node_skl *)pStubDescVar );
  323. return pStubDescResource;
  324. }
  325. void
  326. CCB::OutputRundownRoutineTable()
  327. {
  328. OutputSimpleRoutineTable( pContextIndexMgr,
  329. RUNDOWN_ROUTINE_TABLE_TYPE,
  330. RUNDOWN_ROUTINE_TABLE_VAR );
  331. }
  332. void
  333. CCB::OutputExprEvalRoutineTable()
  334. {
  335. OutputSimpleRoutineTable( pExprEvalIndexMgr,
  336. EXPR_EVAL_ROUTINE_TABLE_TYPE,
  337. EXPR_EVAL_ROUTINE_TABLE_VAR );
  338. }
  339. void
  340. CCB::OutputSimpleRoutineTable(
  341. CCB_RTN_INDEX_MGR * pIndexMgr,
  342. char * pTableTypeName,
  343. char * pTableVarName
  344. )
  345. {
  346. long i;
  347. char * pName;
  348. pStream->NewLine();
  349. pStream->Write( "static const " );
  350. pStream->Write( pTableTypeName );
  351. pStream->Write( ' ' );
  352. pStream->Write( pTableVarName );
  353. pStream->Write( "[] = ");
  354. pStream->IndentInc();
  355. pStream->NewLine();
  356. pStream->Write( '{' );
  357. pStream->NewLine();
  358. for ( i = 1; ( pName = pIndexMgr->Lookup(i) ) != 0 ; i++ )
  359. {
  360. if ( i != 1 )
  361. pStream->Write( ',' );
  362. pStream->Write( pName );
  363. pStream->NewLine();
  364. }
  365. pStream->Write( "};" );
  366. pStream->IndentDec();
  367. pStream->NewLine( 2 );
  368. }
  369. void
  370. CCB::OutputOldExprEvalRoutine(EXPR_EVAL_CONTEXT *pExprEvalContext)
  371. {
  372. CG_NDR * pContainer = pExprEvalContext->pContainer;
  373. expr_node * pMinExpr = pExprEvalContext->pMinExpr;
  374. expr_node * pSizeExpr = pExprEvalContext->pSizeExpr;
  375. char * pRoutineName= pExprEvalContext->pRoutineName;
  376. unsigned long Displacement= pExprEvalContext->Displacement;
  377. pStream = GetStream();
  378. // generate the header of the evaluation routine
  379. pStream->NewLine();
  380. pStream->Write( "static void __RPC_USER " );
  381. pStream->Write( pRoutineName );
  382. pStream->Write( "( PMIDL_STUB_MESSAGE pStubMsg )" );
  383. pStream->NewLine();
  384. pStream->Write( '{');
  385. pStream->IndentInc();
  386. pStream->NewLine();
  387. //
  388. // Get the proper struct type.
  389. //
  390. char * pContainerTypeName = 0;
  391. MIDL_ASSERT( pContainer->IsStruct() || pContainer->IsProc() );
  392. if ( pContainer->IsProc() )
  393. {
  394. MIDL_ASSERT( GetOptimOption() | OPTIMIZE_INTERPRETER );
  395. SetCGNodeContext( pContainer );
  396. ((CG_PROC *)pContainer)->GenNdrInterpreterParamStruct( this );
  397. pContainerTypeName = PARAM_STRUCT_TYPE_NAME;
  398. }
  399. else
  400. {
  401. pContainerTypeName = ((CG_STRUCT *)pContainer)->
  402. GetType()->GetSymName();
  403. }
  404. expr_node * pExpr = new expr_variable( "pStubMsg->StackTop" );
  405. if ( Displacement )
  406. {
  407. expr_constant * pConstExpr =
  408. new expr_constant( (long) Displacement );
  409. expr_op_binary * pSubtrExpr = new expr_op_binary( OP_MINUS,
  410. pExpr,
  411. pConstExpr );
  412. pExpr = pSubtrExpr;
  413. }
  414. //
  415. // Don't change this call - Dave.
  416. //
  417. node_id * pId;
  418. if ( pContainer->IsProc() )
  419. {
  420. pId = MakePtrIDNodeFromTypeNameWithCastedExpr(
  421. "pS",
  422. pContainerTypeName,
  423. pExpr );
  424. }
  425. else
  426. {
  427. pId = MakePtrIDNodeWithCastedExpr(
  428. "pS",
  429. pContainer->GetType(),
  430. pExpr );
  431. }
  432. pId->PrintType( PRT_ID_DECLARATION, pStream );
  433. pStream->NewLine();
  434. // generate calculation for the Offset field
  435. char TotalPrefix[256];
  436. strcpy( TotalPrefix, "pS->" );
  437. strcat( TotalPrefix, pExprEvalContext->pPrintPrefix );
  438. pStream->Write( "pStubMsg->Offset = " );
  439. if ( pMinExpr )
  440. {
  441. pMinExpr->PrintWithPrefix( pStream, TotalPrefix );
  442. pStream->Write( ';' );
  443. }
  444. else
  445. pStream->Write( "0;" );
  446. pStream->NewLine();
  447. // generate calculation for MaxCount.
  448. if ( pCommand->Is64BitEnv() )
  449. {
  450. // pStubMsg->MaxCount = (ULONG_PTR) ...
  451. pStream->Write( "pStubMsg->MaxCount = (ULONG_PTR) ( " );
  452. }
  453. else
  454. {
  455. // pStubMsg->MaxCount = ( unsigned long ) ...
  456. pStream->Write( "pStubMsg->MaxCount = ( unsigned long ) ( " );
  457. }
  458. pSizeExpr->PrintWithPrefix( pStream, TotalPrefix );
  459. pStream->Write( " );" );
  460. /***
  461. *** Let's leave this out as the default for now. This means first_is() with
  462. last_is() is broken, but first_is() with length_is() will work.
  463. if ( pMinExpr )
  464. {
  465. pStream->Write( " - pStubMsg->Offset;" );
  466. }
  467. else
  468. pStream->Write( ";" );
  469. ***
  470. ***/
  471. // generate the closing of the evaluation routine
  472. pStream->IndentDec();
  473. pStream->NewLine();
  474. pStream->Write( '}' );
  475. pStream->NewLine();
  476. }
  477. void
  478. CCB::OutputRegisteredExprEvalRoutines()
  479. {
  480. ITERATOR RegisteredRoutines;
  481. EXPR_EVAL_CONTEXT * pExprEvalContext;
  482. GetListOfExprEvalRoutines( RegisteredRoutines);
  483. while ( ITERATOR_GETNEXT( RegisteredRoutines, pExprEvalContext ) )
  484. {
  485. OutputOldExprEvalRoutine(pExprEvalContext);
  486. }
  487. }
  488. void
  489. CCB::OutputExpressionFormatString()
  490. {
  491. CCB_EXPR_INDEX_MGR * pIndexMgr = GetExprFrmtStrIndexMgr();
  492. char Buf[200];
  493. pStream->NewLine();
  494. pStream->Write("static const unsigned short "EXPR_FORMAT_STRING_OFFSET_TABLE "[] =") ;
  495. pStream->NewLine();
  496. pStream->Write("{");
  497. pStream->NewLine();
  498. for (long i = 1; i < pIndexMgr->GetIndex(); i++)
  499. {
  500. pStream->Write( MIDL_ITOA(pIndexMgr->GetOffset(i), Buf, 10 ) );
  501. pStream->NewLine();
  502. }
  503. pStream->Write("};");
  504. pStream->NewLine();
  505. // GetExprFormatString()->OutputExprEvalFormatString(GetStream());
  506. }
  507. // ========================================================================
  508. // user_marshall Quadruple table
  509. // ========================================================================
  510. void
  511. CCB::OutputQuadrupleTable()
  512. {
  513. static char * QuadrupleNames[] =
  514. {
  515. USER_MARSHAL_SIZE,
  516. USER_MARSHAL_MARSHALL,
  517. USER_MARSHAL_UNMARSHALL,
  518. USER_MARSHAL_FREE
  519. };
  520. static char * Ndr64QuadrupleNames[] =
  521. {
  522. NDR64_USER_MARSHAL_SIZE,
  523. NDR64_USER_MARSHAL_MARSHALL,
  524. NDR64_USER_MARSHAL_UNMARSHALL,
  525. NDR64_USER_MARSHAL_FREE
  526. };
  527. long NoOfEntries = GetQuadrupleDictionary()->GetCount();
  528. pStream->NewLine();
  529. pStream->Write("static const " USER_MARSHAL_ROUTINE_TABLE_TYPE );
  530. if ( pCommand->IsNDR64Run() )
  531. {
  532. pStream->Write( " " NDR64_USER_MARSHAL_ROUTINE_TABLE_VAR
  533. "[ " WIRE_MARSHAL_TABLE_SIZE " ] = " );
  534. }
  535. else
  536. {
  537. pStream->Write( " " USER_MARSHAL_ROUTINE_TABLE_VAR
  538. "[ " WIRE_MARSHAL_TABLE_SIZE " ] = " );
  539. }
  540. pStream->IndentInc();
  541. pStream->IndentInc();
  542. pStream->NewLine();
  543. pStream->Write( '{' );
  544. pStream->IndentInc();
  545. pStream->NewLine();
  546. USER_MARSHAL_CONTEXT * * QuadrupleLookupTable;
  547. USER_MARSHAL_CONTEXT * pQContext;
  548. int i;
  549. QuadrupleLookupTable = new USER_MARSHAL_CONTEXT *[ NoOfEntries ];
  550. ITERATOR Quadruples;
  551. GetQuadrupleDictionary()->GetListOfItems( Quadruples );
  552. for ( i = 0;
  553. ITERATOR_GETNEXT( Quadruples, pQContext );
  554. i++ )
  555. {
  556. MIDL_ASSERT( pQContext->Index < NoOfEntries && "look up index violation" );
  557. QuadrupleLookupTable[ pQContext->Index ] = pQContext;
  558. }
  559. MIDL_ASSERT( i == NoOfEntries );
  560. ISTREAM * pStream = GetStream();
  561. for ( i = 0; i < NoOfEntries; i++ )
  562. {
  563. pQContext = QuadrupleLookupTable[i];
  564. if ( i )
  565. pStream->Write( ',' );
  566. pStream->NewLine();
  567. pStream->Write( '{' );
  568. pStream->NewLine();
  569. for ( int FuncNo = 0; FuncNo < 4; FuncNo++)
  570. {
  571. if ( FuncNo )
  572. pStream->Write( ',' );
  573. pStream->Write( pQContext->pTypeName );
  574. if ( pCommand->IsNDR64Run() )
  575. pStream->Write( Ndr64QuadrupleNames[ FuncNo ] );
  576. else
  577. pStream->Write( QuadrupleNames[ FuncNo ] );
  578. pStream->NewLine();
  579. }
  580. pStream->Write( '}' );
  581. }
  582. pStream->IndentDec();
  583. pStream->NewLine( 2 );
  584. pStream->Write( "};" );
  585. pStream->IndentDec();
  586. pStream->IndentDec();
  587. pStream->NewLine( 2 );
  588. delete QuadrupleLookupTable;
  589. }
  590. // =======================================================================
  591. // International character sizing/conversion routine table
  592. // =======================================================================
  593. void CCB::OutputCsRoutineTables()
  594. {
  595. char *pRoutineSuffix[4] =
  596. {
  597. CS_NET_SIZE,
  598. CS_TO_NET_CS,
  599. CS_LOCAL_SIZE,
  600. CS_FROM_NET_CS
  601. };
  602. //
  603. // Output the sizing/conversion routines table
  604. //
  605. pStream->Write( CS_SIZE_CONVERT_ROUTINE_TABLE_TYPE );
  606. pStream->Write( ' ' );
  607. pStream->Write( CS_SIZE_CONVERT_ROUTINE_TABLE_VAR );
  608. pStream->Write( "[] =" );
  609. pStream->IndentInc();
  610. pStream->WriteOnNewLine( '{' );
  611. pStream->IndentInc();
  612. PNAME pType;
  613. bool fFirst = true;
  614. ITERATOR_INIT( CsTypes );
  615. while ( ITERATOR_GETNEXT( CsTypes, pType ) )
  616. {
  617. if ( ! fFirst )
  618. pStream->Write( ',' );
  619. pStream->WriteOnNewLine( '{' );
  620. for (int i = 0; i < 4; i++ )
  621. {
  622. pStream->WriteOnNewLine( pType );
  623. pStream->Write( pRoutineSuffix[i] );
  624. pStream->Write( ',' );
  625. }
  626. pStream->WriteOnNewLine( '}' );
  627. fFirst = false;
  628. }
  629. pStream->IndentDec();
  630. pStream->WriteOnNewLine( "};" );
  631. pStream->IndentDec();
  632. pStream->NewLine();
  633. //
  634. // Output the tag routines table
  635. //
  636. if ( 0 != CsTagRoutines.GetCount() )
  637. {
  638. pStream->WriteOnNewLine( CS_TAG_ROUTINE_TABLE_TYPE );
  639. pStream->Write( ' ' );
  640. pStream->Write( CS_TAG_ROUTINE_TABLE_VAR );
  641. pStream->Write( "[] =" );
  642. pStream->IndentInc();
  643. pStream->WriteOnNewLine( '{' );
  644. fFirst = true;
  645. ITERATOR_INIT( CsTagRoutines );
  646. while ( ITERATOR_GETNEXT( CsTagRoutines, pType ) )
  647. {
  648. if ( ! fFirst )
  649. pStream->Write( ',' );
  650. pStream->WriteOnNewLine( pType );
  651. fFirst = false;
  652. }
  653. pStream->WriteOnNewLine( "};" );
  654. pStream->IndentDec();
  655. pStream->NewLine();
  656. }
  657. //
  658. // Output the pointers-to-tables structure
  659. //
  660. pStream->WriteOnNewLine( CS_ROUTINE_TABLES_TYPE );
  661. pStream->Write( ' ' );
  662. pStream->Write( CS_ROUTINE_TABLES_VAR );
  663. pStream->Write( " =" );
  664. pStream->IndentInc();
  665. pStream->WriteOnNewLine( '{' );
  666. pStream->WriteOnNewLine( CS_SIZE_CONVERT_ROUTINE_TABLE_VAR );
  667. pStream->Write( ',' );
  668. pStream->WriteOnNewLine( ( 0 != CsTagRoutines.GetCount() )
  669. ? CS_TAG_ROUTINE_TABLE_VAR
  670. : "0" );
  671. pStream->WriteOnNewLine( "};" );
  672. pStream->IndentDec();
  673. pStream->NewLine();
  674. }
  675. // =======================================================================
  676. // Transmit as and Represent As tables.
  677. // =======================================================================
  678. char *
  679. MakeAnXmitName(
  680. char * pTypeName,
  681. char * pRoutineName,
  682. unsigned short )
  683. /*++
  684. makes the following name: <type_name>_<routine_name>_<index>
  685. --*/
  686. {
  687. MIDL_ASSERT( pTypeName && pRoutineName );
  688. char * pXmitName = new char[ strlen(pTypeName) +
  689. strlen(pRoutineName) + 1 ];
  690. strcpy( pXmitName, pTypeName );
  691. strcat( pXmitName, pRoutineName );
  692. return( pXmitName );
  693. }
  694. #define QUINTUPLE_SIZE 4
  695. typedef struct _QUINTUPLE_NAMES
  696. {
  697. char * TableType;
  698. char * TableVar;
  699. char * FuncName[ QUINTUPLE_SIZE ];
  700. } QUINTUPLE_NAMES;
  701. void
  702. CCB::OutputQuintupleTable()
  703. {
  704. static QUINTUPLE_NAMES TransmitNames =
  705. {
  706. XMIT_AS_ROUTINE_TABLE_TYPE,
  707. XMIT_AS_ROUTINE_TABLE_VAR,
  708. XMIT_TO_XMIT,
  709. XMIT_FROM_XMIT,
  710. XMIT_FREE_XMIT,
  711. XMIT_FREE_INST
  712. };
  713. static QUINTUPLE_NAMES RepNames=
  714. {
  715. REP_AS_ROUTINE_TABLE_TYPE,
  716. REP_AS_ROUTINE_TABLE_VAR,
  717. REP_FROM_LOCAL,
  718. REP_TO_LOCAL,
  719. REP_FREE_INST,
  720. REP_FREE_LOCAL
  721. };
  722. long NoOfEntries = GetQuintupleDictionary()->GetCount();
  723. pStream->NewLine();
  724. pStream->Write("static const "XMIT_AS_ROUTINE_TABLE_TYPE );
  725. pStream->Write( " " XMIT_AS_ROUTINE_TABLE_VAR
  726. "[ " TRANSMIT_AS_TABLE_SIZE " ] = " );
  727. pStream->IndentInc();
  728. pStream->IndentInc();
  729. pStream->NewLine();
  730. pStream->Write( '{' );
  731. pStream->IndentInc();
  732. pStream->NewLine();
  733. // Now construct a lookup table with entries in the order of indexes.
  734. // (we have to keep index managers separate for rep_as and xmit_as
  735. // and we still have a common table)
  736. XMIT_AS_CONTEXT * * QuintupleLookupTable;
  737. XMIT_AS_CONTEXT * pQContext;
  738. int i;
  739. QuintupleLookupTable = new XMIT_AS_CONTEXT *[ NoOfEntries ];
  740. ITERATOR Quintuples;
  741. GetListOfQuintuples( Quintuples );
  742. for ( i = 0;
  743. ITERATOR_GETNEXT( Quintuples, pQContext );
  744. i++ )
  745. {
  746. MIDL_ASSERT( pQContext->Index < NoOfEntries && "look up index violation" );
  747. QuintupleLookupTable[ pQContext->Index ] = pQContext;
  748. }
  749. ISTREAM * pStream = GetStream();
  750. for ( i = 0; i < NoOfEntries; i++ )
  751. {
  752. pQContext = QuintupleLookupTable[i];
  753. char * pName = pQContext->fXmit
  754. ? pQContext->pTypeName
  755. : ((CG_REPRESENT_AS *)pQContext->pXmitNode)->
  756. GetTransmittedType()->GetSymName();
  757. unsigned short Index = pQContext->Index;
  758. MIDL_ASSERT( (i == Index) && " xmit index violation" );
  759. QUINTUPLE_NAMES * pQNames = pQContext->fXmit ? & TransmitNames
  760. : & RepNames;
  761. if ( i )
  762. pStream->Write( ',' );
  763. pStream->NewLine();
  764. pStream->Write( '{' );
  765. pStream->NewLine();
  766. for ( int FuncNo = 0; FuncNo < QUINTUPLE_SIZE; FuncNo++)
  767. {
  768. char * pTempName = MakeAnXmitName( pName,
  769. pQNames->FuncName[ FuncNo ],
  770. Index );
  771. if ( FuncNo )
  772. pStream->Write( ',' );
  773. pStream->Write( pTempName );
  774. pStream->NewLine();
  775. delete pTempName;
  776. }
  777. pStream->Write( '}' );
  778. }
  779. pStream->IndentDec();
  780. pStream->NewLine( 2 );
  781. pStream->Write( "};" );
  782. pStream->IndentDec();
  783. pStream->IndentDec();
  784. pStream->NewLine( 2 );
  785. delete QuintupleLookupTable;
  786. }
  787. // =======================================================================
  788. // helpers for Transmit as and Represent As routines
  789. // =======================================================================
  790. static void
  791. OpenXmitOrRepRoutine(
  792. ISTREAM * pStream,
  793. char * pName )
  794. /*++
  795. Routine description:
  796. This routine emits the header of a *_as helper routine:
  797. void __RPC_API
  798. <name>( PMIDL_STUB_MESSAGE pStubMsg )
  799. {
  800. Note:
  801. There is a side effect here that the name of the routine is deleted
  802. (this is always the name created by a call to MakeAnXmitName).
  803. --*/
  804. {
  805. pStream->Write ( "NDR_SHAREABLE void __RPC_USER" );
  806. pStream->NewLine();
  807. pStream->Write ( pName );
  808. pStream->Write ( "( PMIDL_STUB_MESSAGE pStubMsg )" );
  809. pStream->NewLine();
  810. pStream->Write( '{');
  811. pStream->IndentInc();
  812. pStream->NewLine();
  813. delete pName;
  814. }
  815. static void
  816. CloseXmitOrRepRoutine(
  817. ISTREAM * pStream )
  818. /*++
  819. Routine description:
  820. Just a complement to the OpenXmitOrRepRoutine:
  821. }
  822. --*/
  823. {
  824. pStream->IndentDec();
  825. pStream->NewLine();
  826. pStream->Write( '}');
  827. pStream->NewLine();
  828. }
  829. static void
  830. OutputPresentedTypeInit(
  831. ISTREAM * pStream,
  832. char * pPresentedTypeName )
  833. /*++
  834. Routine description:
  835. Emits
  836. memset( pStubMsg->pPresentedType, 0, sizeof( <presented type> ));
  837. --*/
  838. {
  839. pStream->NewLine();
  840. pStream->Write( MIDL_MEMSET_RTN_NAME "( "PSTUB_MESSAGE_PAR_NAME"->pPresentedType, 0, sizeof(" );
  841. pStream->Write( pPresentedTypeName );
  842. pStream->Write( " ));" );
  843. }
  844. static void
  845. OutputCastedPtr(
  846. ISTREAM * pStream,
  847. char * pTypeName,
  848. char * pVarName )
  849. {
  850. pStream->Write( '(' );
  851. pStream->Write( pTypeName );
  852. pStream->Write( " *) " );
  853. pStream->Write( pVarName );
  854. }
  855. // =======================================================================
  856. // Transmit as
  857. // =======================================================================
  858. //
  859. // The presented type size problem.
  860. // The engine doesn't use pStubMsg->PresentedTypeSize field anymore.
  861. // The presented type size nowadays is passed within the format code.
  862. //
  863. static void
  864. OutputToXmitCall(
  865. ISTREAM * pStream,
  866. char * pPresentedTypeName,
  867. char * pTransmitTypeName )
  868. {
  869. pStream->Write( pPresentedTypeName );
  870. pStream->Write( "_to_xmit( " );
  871. OutputCastedPtr( pStream,
  872. pPresentedTypeName,
  873. PSTUB_MESSAGE_PAR_NAME"->pPresentedType, " );
  874. pStream->IndentInc();
  875. pStream->NewLine();
  876. pStream->Write( '(' );
  877. pStream->Write( pTransmitTypeName );
  878. pStream->Write( " * *) &pStubMsg->pTransmitType );" );
  879. pStream->IndentDec();
  880. // pStream->NewLine();
  881. }
  882. static void
  883. OutputFreeXmitCall(
  884. ISTREAM * pStream,
  885. char * pPresentedTypeName,
  886. char * pTransmitTypeName )
  887. {
  888. pStream->Write( pPresentedTypeName );
  889. pStream->Write( "_free_xmit( " );
  890. OutputCastedPtr( pStream, pTransmitTypeName, "pStubMsg->pTransmitType );" );
  891. }
  892. void
  893. CCB::OutputTransmitAsQuintuple(
  894. void * pQuintupleContext
  895. )
  896. /*++
  897. Routine description:
  898. This routine emits the following helper routines for a transmit as type:
  899. static void __RPC_API
  900. <pres_type>_Xmit_ToXmit_<index>( PMIDL_STUB_MESSAGE pStubMsg )
  901. {
  902. <pres_type>_to_xmit( (<pres_type> *) pStubMsg->pPresentedType,
  903. (<tran_type> * *) &pStubMsg->pTransmitType );
  904. }
  905. static void __RPC_API
  906. <pres_type>_Xmit_FromXmit_<index>( PMIDL_STUB_MESSAGE pStubMsg )
  907. {
  908. <pres_type>_from_xmit(
  909. (<tran_type> *) pStubMsg->pTransmitType,
  910. (<pres_type> *) pStubMsg->pPresentedType );
  911. }
  912. static void __RPC_API
  913. <pres_type>_Xmit_FreeXmit_<index>( PMIDL_STUB_MESSAGE pStubMsg )
  914. {
  915. <pres_type>_free_xmit(
  916. (<tran_type> *) pStubMsg-p>TransmitType );
  917. }
  918. static void __RPC_API
  919. <pres_type>_Xmit_FreeInst_<index>( PMIDL_STUB_MESSAGE pStubMsg )
  920. {
  921. <pres_type>_free_xmit(
  922. (<pres_type> *) pStubMsg->pPresentedType );
  923. }
  924. --*/
  925. {
  926. XMIT_AS_CONTEXT * pTransmitAsContext = (XMIT_AS_CONTEXT*) pQuintupleContext;
  927. int i = pTransmitAsContext->Index;
  928. ISTREAM * pStream = GetStream();
  929. pStream->NewLine();
  930. CG_TRANSMIT_AS* pXmitNode = (CG_TRANSMIT_AS *)
  931. pTransmitAsContext->pXmitNode;
  932. char * pPresentedTypeName = pXmitNode->GetPresentedType()->GetSymName();
  933. char * pTransmitTypeName = pXmitNode->GetTransmittedType()->
  934. GetSymName();
  935. // *_XmitTranslateToXmit
  936. OpenXmitOrRepRoutine( pStream, MakeAnXmitName( pPresentedTypeName,
  937. XMIT_TO_XMIT,
  938. unsigned short(i) ) );
  939. OutputToXmitCall( pStream, pPresentedTypeName, pTransmitTypeName );
  940. CloseXmitOrRepRoutine( pStream );
  941. // *_XmitTranslateFromXmit
  942. OpenXmitOrRepRoutine( pStream, MakeAnXmitName( pPresentedTypeName,
  943. XMIT_FROM_XMIT,
  944. unsigned short(i) ) );
  945. pStream->Write( pPresentedTypeName );
  946. pStream->Write( "_from_xmit( " );
  947. OutputCastedPtr( pStream, pTransmitTypeName, "pStubMsg->pTransmitType, " );
  948. pStream->IndentInc();
  949. pStream->NewLine();
  950. OutputCastedPtr( pStream, pPresentedTypeName, "pStubMsg->pPresentedType ); " );
  951. pStream->IndentDec();
  952. CloseXmitOrRepRoutine( pStream );
  953. // *_XmitFreeXmit
  954. OpenXmitOrRepRoutine( pStream, MakeAnXmitName( pPresentedTypeName,
  955. XMIT_FREE_XMIT,
  956. unsigned short(i) ) );
  957. OutputFreeXmitCall( pStream, pPresentedTypeName, pTransmitTypeName );
  958. CloseXmitOrRepRoutine( pStream );
  959. // *_XmitFreeInst
  960. OpenXmitOrRepRoutine( pStream, MakeAnXmitName( pPresentedTypeName,
  961. XMIT_FREE_INST,
  962. unsigned short(i) ) );
  963. pStream->Write( pPresentedTypeName );
  964. pStream->Write( "_free_inst( " );
  965. OutputCastedPtr( pStream, pPresentedTypeName, "pStubMsg->pPresentedType ); " );
  966. CloseXmitOrRepRoutine( pStream );
  967. }
  968. void
  969. CCB::OutputQuintupleRoutines()
  970. /*++
  971. --*/
  972. {
  973. ITERATOR Quintuples;
  974. XMIT_AS_CONTEXT * pQuintupleContext;
  975. int i;
  976. // Multi-interface problem: This routine is only called after the last
  977. // interface.
  978. GetListOfQuintuples( Quintuples );
  979. for ( i = 1;
  980. ITERATOR_GETNEXT( Quintuples, pQuintupleContext );
  981. i++ )
  982. {
  983. if ( pQuintupleContext->fXmit )
  984. OutputTransmitAsQuintuple( pQuintupleContext );
  985. else
  986. OutputRepAsQuintuple( pQuintupleContext );
  987. }
  988. }
  989. // ========================================================================
  990. // Represent As
  991. // ========================================================================
  992. //
  993. // There is a lot of symmetry between transmit as and represent as.
  994. // We use that where possible. So, among other things there is the following
  995. // mapping between represent as routines and the transmit as ones.
  996. // (So called quintuple actually has 4 routines now.)
  997. //
  998. // wrapers
  999. // pfnTranslateToXmit *_to_xmit *_from_local
  1000. // pfnTranslateFromXmit *_from_xmit *_to_local
  1001. // pfnFreeXmit *_free_xmit *_free_inst
  1002. // pfnFreeInst *_free_inst *_free_local
  1003. //
  1004. // The presented type size problem.
  1005. // This is either known and put into the format code explicitely,
  1006. // or unknown and then put there via a C-compile macro.
  1007. //
  1008. // The presented type alignment problem.
  1009. // There is a problem when there is a padding preceding a represent as
  1010. // field. The engine needs to know what the alignment for the represent
  1011. // as field is. As we may not know its type at the midl compile time,
  1012. // the only way to deal with it is to use the parent structure name,
  1013. // and the represent as field name.
  1014. //
  1015. static void
  1016. OutputToLocalCall(
  1017. ISTREAM * pStream,
  1018. char * pLocalTypeName,
  1019. char * pTransmitTypeName )
  1020. {
  1021. pStream->Write( pTransmitTypeName );
  1022. pStream->Write( "_to_local( " );
  1023. OutputCastedPtr( pStream, pTransmitTypeName,
  1024. PSTUB_MESSAGE_PAR_NAME"->pTransmitType, " );
  1025. pStream->IndentInc();
  1026. pStream->NewLine();
  1027. OutputCastedPtr( pStream, pLocalTypeName,
  1028. PSTUB_MESSAGE_PAR_NAME"->pPresentedType ); " );
  1029. pStream->IndentDec();
  1030. }
  1031. static void
  1032. OutputFromLocalCall(
  1033. ISTREAM * pStream,
  1034. char * pLocalTypeName,
  1035. char * pTransmitTypeName )
  1036. {
  1037. pStream->Write( pTransmitTypeName );
  1038. pStream->Write( "_from_local( " );
  1039. OutputCastedPtr( pStream, pLocalTypeName,
  1040. PSTUB_MESSAGE_PAR_NAME"->pPresentedType, " );
  1041. pStream->IndentInc();
  1042. pStream->NewLine();
  1043. pStream->Write( '(' );
  1044. pStream->Write( pTransmitTypeName );
  1045. pStream->Write( " * *) &pStubMsg->pTransmitType );" );
  1046. pStream->IndentDec();
  1047. }
  1048. static void
  1049. OutputRepAsFreeInstCall(
  1050. ISTREAM * pStream,
  1051. char * pTransmitTypeName )
  1052. {
  1053. pStream->Write( pTransmitTypeName );
  1054. pStream->Write( "_free_inst( " );
  1055. OutputCastedPtr( pStream, pTransmitTypeName,
  1056. PSTUB_MESSAGE_PAR_NAME"->pTransmitType );" );
  1057. }
  1058. void
  1059. CCB::OutputRepAsQuintuple(
  1060. void * pQuintupleContext
  1061. )
  1062. /*++
  1063. Routine description:
  1064. This routine emits the following helper routines for a transmit as type:
  1065. static void __RPC_API
  1066. <trans_type>_RepAsFromLocal_<index>( PMIDL_STUB_MESSAGE pStubMsg )
  1067. {
  1068. <trans_type>_from_local(
  1069. (<pres_type> *) pStubMsg->pPresentedType,
  1070. (<tran_type> * *) &pStubMsg->pTransmitType );
  1071. }
  1072. static void __RPC_API
  1073. <trans_type>_RepAsToLocal_<index>( PMIDL_STUB_MESSAGE pStubMsg )
  1074. {
  1075. <trans_type>_to_local(
  1076. (<tran_type> *) pStubMsg->pTransmitType,
  1077. (<pres_type> *) pStubMsg->pPresentedType );
  1078. }
  1079. static void __RPC_API
  1080. <trans_type>_RepAsFreeInst_<index>( PMIDL_STUB_MESSAGE pStubMsg )
  1081. {
  1082. <trans_type>_free_inst(
  1083. (<tran_type> *) pStubMsg-p>TransmitType );
  1084. }
  1085. static void __RPC_API
  1086. <trans_type>_RepAsFreeLocal_<index>( PMIDL_STUB_MESSAGE pStubMsg )
  1087. {
  1088. <trans_type>_free_local(
  1089. (<pres_type> *) pStubMsg->pPresentedType );
  1090. }
  1091. --*/
  1092. {
  1093. XMIT_AS_CONTEXT * pRepAsContext = (XMIT_AS_CONTEXT*) pQuintupleContext;
  1094. int i = pRepAsContext->Index;
  1095. ISTREAM * pStream = GetStream();
  1096. CG_REPRESENT_AS * pRepAsNode = (CG_REPRESENT_AS *)
  1097. pRepAsContext->pXmitNode;
  1098. char * pLocalTypeName = pRepAsNode->GetRepAsTypeName();
  1099. char * pTransmitTypeName = pRepAsNode->GetTransmittedType()->
  1100. GetSymName();
  1101. // *_RepAsTranslateToLocal
  1102. OpenXmitOrRepRoutine( pStream, MakeAnXmitName( pTransmitTypeName,
  1103. REP_TO_LOCAL,
  1104. unsigned short(i) ) );
  1105. OutputToLocalCall( pStream, pLocalTypeName, pTransmitTypeName );
  1106. CloseXmitOrRepRoutine( pStream );
  1107. // *_RepAsTranslateFromLocal
  1108. OpenXmitOrRepRoutine( pStream, MakeAnXmitName( pTransmitTypeName,
  1109. REP_FROM_LOCAL,
  1110. unsigned short(i) ) );
  1111. OutputFromLocalCall( pStream, pLocalTypeName, pTransmitTypeName );
  1112. CloseXmitOrRepRoutine( pStream );
  1113. // *_RepAsFreeInst
  1114. OpenXmitOrRepRoutine( pStream, MakeAnXmitName( pTransmitTypeName,
  1115. REP_FREE_INST,
  1116. unsigned short(i) ) );
  1117. OutputRepAsFreeInstCall( pStream, pTransmitTypeName );
  1118. CloseXmitOrRepRoutine( pStream );
  1119. // *_RepAsFreeLocal
  1120. OpenXmitOrRepRoutine( pStream, MakeAnXmitName( pTransmitTypeName,
  1121. REP_FREE_LOCAL,
  1122. unsigned short(i) ) );
  1123. pStream->Write( pTransmitTypeName );
  1124. pStream->Write( "_free_local( " );
  1125. OutputCastedPtr( pStream, pLocalTypeName, "pStubMsg->pPresentedType ); " );
  1126. CloseXmitOrRepRoutine( pStream );
  1127. }
  1128. // ========================================================================
  1129. // end of Transmit As and Represent As
  1130. // ========================================================================
  1131. BOOL
  1132. CCB::HasBindingRoutines( CG_HANDLE * pImplicitHandle )
  1133. {
  1134. return ! pGenericIndexMgr->IsEmpty() ||
  1135. (pImplicitHandle &&
  1136. pImplicitHandle->IsGenericHandle());
  1137. }
  1138. void
  1139. CCB::OutputBindingRoutines()
  1140. {
  1141. long i;
  1142. char * pName;
  1143. pStream->NewLine();
  1144. pStream->Write( "static const " BINDING_ROUTINE_TABLE_TYPE );
  1145. pStream->Write( " " BINDING_ROUTINE_TABLE_VAR
  1146. "[ " GENERIC_BINDING_TABLE_SIZE " ] = " );
  1147. pStream->IndentInc();
  1148. pStream->IndentInc();
  1149. pStream->NewLine();
  1150. pStream->Write( '{' );
  1151. pStream->NewLine();
  1152. for ( i = 1; ( pName = pGenericIndexMgr->Lookup(i) ) != 0 ; i++ )
  1153. {
  1154. if ( i != 1 )
  1155. pStream->Write( ',' );
  1156. pStream->Write( '{' );
  1157. pStream->IndentInc();
  1158. pStream->NewLine();
  1159. pStream->Write( "(" GENERIC_BINDING_ROUTINE_TYPE ")" );
  1160. pStream->Write( pName );
  1161. pStream->Write( "_bind" );
  1162. pStream->Write( ',' );
  1163. pStream->NewLine();
  1164. pStream->Write( "(" GENERIC_UNBINDING_ROUTINE_TYPE ")" );
  1165. pStream->Write( pName );
  1166. pStream->Write( "_unbind" );
  1167. pStream->IndentDec();
  1168. pStream->NewLine();
  1169. pStream->Write( " }" );
  1170. pStream->NewLine();
  1171. }
  1172. pStream->NewLine();
  1173. pStream->Write( "};" );
  1174. pStream->IndentDec();
  1175. pStream->IndentDec();
  1176. pStream->NewLine();
  1177. pStream->NewLine();
  1178. }
  1179. void
  1180. CCB::OutputMallocAndFreeStruct()
  1181. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1182. Routine Description:
  1183. Outputs the malloc and free struct for the RpcSsm connection.
  1184. This is needed only at the client side and non object interfaces.
  1185. If the [enable_allocate] affects a remote routine, the client side stub
  1186. defaults to malloc and free when unmarshalling regardless of the
  1187. compiler mode (osf vs. non-osf).
  1188. Therefore, the structure gets generated:
  1189. - always in the osf mode or
  1190. - in non-osf when at least one routine is affected by the attribute.
  1191. This is one-per-many-interfaces structure.
  1192. Because of win16 DS register problems, malloc and free have to be
  1193. accessed via wrappers with appropriate calling conventions.
  1194. To simplify, we generate wrappers for every platform.
  1195. REVIEW: win16 is gone, we should be able to get rid of the wrappers.
  1196. ----------------------------------------------------------------------------*/
  1197. {
  1198. // malloc and free wrappers.
  1199. pStream->NewLine();
  1200. pStream->Write( "static void * __RPC_USER" );
  1201. pStream->NewLine();
  1202. pStream->Write( GetInterfaceName() );
  1203. pStream->Write( "_malloc_wrapper( size_t _Size )" );
  1204. pStream->NewLine();
  1205. pStream->Write( "{" );
  1206. pStream->IndentInc();
  1207. pStream->NewLine();
  1208. pStream->Write( "return( malloc( _Size ) );" );
  1209. pStream->IndentDec();
  1210. pStream->NewLine();
  1211. pStream->Write( "}" );
  1212. pStream->NewLine();
  1213. pStream->NewLine();
  1214. pStream->Write( "static void __RPC_USER" );
  1215. pStream->NewLine();
  1216. pStream->Write( GetInterfaceName() );
  1217. pStream->Write( "_free_wrapper( void * _p )" );
  1218. pStream->NewLine();
  1219. pStream->Write( "{" );
  1220. pStream->IndentInc();
  1221. pStream->NewLine();
  1222. pStream->Write( "free( _p );" );
  1223. pStream->IndentDec();
  1224. pStream->NewLine();
  1225. pStream->Write( "}" );
  1226. pStream->NewLine();
  1227. // The structure.
  1228. pStream->NewLine();
  1229. pStream->Write( "static " MALLOC_FREE_STRUCT_TYPE_NAME );
  1230. pStream->Write( " " MALLOC_FREE_STRUCT_VAR_NAME " = ");
  1231. pStream->NewLine();
  1232. pStream->Write( "{");
  1233. pStream->IndentInc();
  1234. pStream->NewLine();
  1235. pStream->Write( GetInterfaceName() );
  1236. pStream->Write( "_malloc_wrapper," );
  1237. pStream->NewLine();
  1238. pStream->Write( GetInterfaceName() );
  1239. pStream->Write( "_free_wrapper" );
  1240. pStream->IndentDec();
  1241. pStream->NewLine();
  1242. pStream->Write( "};" );
  1243. pStream->NewLine();
  1244. }
  1245. // ========================================================================
  1246. void
  1247. CCB::OutputExternsToMultipleInterfaceTables()
  1248. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1249. Routine Description:
  1250. Generate the tables that may be common to multiple interfaces.
  1251. Arguments:
  1252. pCCB - A pointer to the code gen controller block.
  1253. Return Value:
  1254. None.
  1255. Notes:
  1256. ----------------------------------------------------------------------------*/
  1257. {
  1258. CGSIDE Side = GetCodeGenSide();
  1259. pStream->NewLine();
  1260. //
  1261. // Emit extern to the rundown routine table on the server Oi side,
  1262. // if needed.
  1263. //
  1264. if ( (Side == CGSIDE_SERVER) &&
  1265. ( GetOptimOption() & OPTIMIZE_INTERPRETER) &&
  1266. HasRundownRoutines() && ! GetRundownExternEmitted() )
  1267. {
  1268. pStream->Write( "extern const " RUNDOWN_ROUTINE_TABLE_TYPE );
  1269. pStream->Write( " " RUNDOWN_ROUTINE_TABLE_VAR "[];" );
  1270. pStream->NewLine();
  1271. SetRundownExternEmitted();
  1272. }
  1273. //
  1274. // Emit extern to the binding routine pair table on the client Oi stub
  1275. // if needed.
  1276. //
  1277. if ( (Side == CGSIDE_CLIENT) &&
  1278. GetInterpretedRoutinesUseGenHandle() &&
  1279. ! GetGenericHExternEmitted()
  1280. )
  1281. {
  1282. pStream->Write( "extern const " BINDING_ROUTINE_TABLE_TYPE );
  1283. pStream->Write( " " BINDING_ROUTINE_TABLE_VAR
  1284. "[ " GENERIC_BINDING_TABLE_SIZE " ];" );
  1285. pStream->NewLine();
  1286. SetGenericHExternEmitted();
  1287. }
  1288. //
  1289. // Emit extern to the expr eval routine table on both sides.
  1290. //
  1291. if ( HasExprEvalRoutines() && ! GetExprEvalExternEmitted() )
  1292. {
  1293. pStream->Write( "extern const " EXPR_EVAL_ROUTINE_TABLE_TYPE );
  1294. pStream->Write( " " EXPR_EVAL_ROUTINE_TABLE_VAR "[];" );
  1295. pStream->NewLine();
  1296. SetExprEvalExternEmitted();
  1297. }
  1298. //
  1299. // Emit extrn to the transmit as and rep as routine table on both sides.
  1300. //
  1301. if ( HasQuintupleRoutines() && ! GetQuintupleExternEmitted() )
  1302. {
  1303. pStream->Write( "extern const " XMIT_AS_ROUTINE_TABLE_TYPE );
  1304. pStream->Write( " " XMIT_AS_ROUTINE_TABLE_VAR
  1305. "[ " TRANSMIT_AS_TABLE_SIZE " ];" );
  1306. pStream->NewLine();
  1307. SetQuintupleExternEmitted();
  1308. }
  1309. //
  1310. // Emit extrn to the user_marshal routine table on both sides.
  1311. //
  1312. if ( HasQuadrupleRoutines() && ! GetQuadrupleExternEmitted() )
  1313. {
  1314. if ( pCommand->NeedsNDR64Run() )
  1315. {
  1316. pStream->Write( "extern const " USER_MARSHAL_ROUTINE_TABLE_TYPE );
  1317. pStream->Write( " " NDR64_USER_MARSHAL_ROUTINE_TABLE_VAR
  1318. "[ " WIRE_MARSHAL_TABLE_SIZE " ];" );
  1319. pStream->NewLine();
  1320. }
  1321. if ( pCommand->NeedsNDRRun() )
  1322. {
  1323. pStream->Write( "extern const " USER_MARSHAL_ROUTINE_TABLE_TYPE );
  1324. pStream->Write( " " USER_MARSHAL_ROUTINE_TABLE_VAR
  1325. "[ " WIRE_MARSHAL_TABLE_SIZE " ];" );
  1326. pStream->NewLine();
  1327. }
  1328. SetQuadrupleExternEmitted();
  1329. }
  1330. if ( HasCsTypes() )
  1331. {
  1332. //
  1333. // Emit the international character sizing/conversion routine table
  1334. //
  1335. OutputCsRoutineTables();
  1336. }
  1337. }
  1338. void
  1339. OutputPlatformCheck( ISTREAM * pStream )
  1340. /*++
  1341. Routine Description :
  1342. Outputs an ifdef checking if the platform usage is as expected
  1343. Arguments :
  1344. pStream - Stream to output the format string to.
  1345. --*/
  1346. {
  1347. pStream->NewLine();
  1348. if ( pCommand->GetEnv() == ENV_WIN64 )
  1349. {
  1350. pStream->Write( "#if !defined(__RPC_WIN64__)" );
  1351. }
  1352. else
  1353. pStream->Write( "#if !defined(__RPC_WIN32__)" );
  1354. pStream->NewLine();
  1355. pStream->Write( "#error Invalid build platform for this stub." );
  1356. pStream->NewLine();
  1357. pStream->Write( "#endif" );
  1358. pStream->NewLine();
  1359. }
  1360. const char * Nt51Guard[] =
  1361. {
  1362. "#if !(TARGET_IS_NT51_OR_LATER)",
  1363. "#error You need a Windows XP or later to run this stub because it uses these features:",
  1364. 0
  1365. };
  1366. const char * Nt50Guard[] =
  1367. {
  1368. "",
  1369. "#if !(TARGET_IS_NT50_OR_LATER)",
  1370. "#error You need a Windows 2000 or later to run this stub because it uses these features:",
  1371. 0
  1372. };
  1373. const char * Nt40Guard[] =
  1374. {
  1375. "",
  1376. "#if !(TARGET_IS_NT40_OR_LATER)",
  1377. "#error You need a Windows NT 4.0 or later to run this stub because it uses these features:",
  1378. 0
  1379. };
  1380. const char * Nt351win95Guard[] =
  1381. {
  1382. "",
  1383. "#if !(TARGET_IS_NT351_OR_WIN95_OR_LATER)",
  1384. "#error You need a Windows NT 3.51 or Windows95 or later to run this stub because it uses these features:",
  1385. 0
  1386. };
  1387. const char * NtGuardClose[] =
  1388. {
  1389. "#error However, your C/C++ compilation flags indicate you intend to run this app on earlier systems.",
  1390. "#error This app will die there with the RPC_X_WRONG_STUB_VERSION error.",
  1391. "#endif",
  1392. 0
  1393. };
  1394. void
  1395. OutputMultilineMessage(
  1396. ISTREAM * pStream,
  1397. const char * Message[] )
  1398. {
  1399. for (int i = 0; Message[i]; i++)
  1400. {
  1401. pStream->Write( Message[i] );
  1402. pStream->NewLine();
  1403. }
  1404. }
  1405. // should be local OutputVersion Guard but it can't.
  1406. class MessageSet
  1407. {
  1408. private:
  1409. char * Messages[10];
  1410. int MessageCount;
  1411. ISTREAM * pStream;
  1412. public:
  1413. MessageSet( ISTREAM * pIStream )
  1414. : MessageCount(0),
  1415. pStream( pIStream )
  1416. {
  1417. }
  1418. void AddMessage( char * Message )
  1419. {
  1420. if ( MessageCount < 10 )
  1421. Messages[ MessageCount++ ] = Message;
  1422. }
  1423. void PrintMessages()
  1424. {
  1425. pStream->Write( "#error " );
  1426. for (int i = 0; i < MessageCount; i++ )
  1427. {
  1428. pStream->Write( Messages[i] );
  1429. pStream->Write( (i < MessageCount -1) ? ", "
  1430. : ".\n" );
  1431. }
  1432. }
  1433. };
  1434. void
  1435. OutputNdrVersionGuard( ISTREAM * pStream )
  1436. /*++
  1437. Routine Description :
  1438. Outputs target release guards.
  1439. Arguments :
  1440. pStream - Stream to output the format string to.
  1441. --*/
  1442. {
  1443. MessageSet Features( pStream );
  1444. NdrVersionControl & VC = pCommand->GetNdrVersionControl();
  1445. if ( VC.HasNdr60Feature() )
  1446. {
  1447. OutputMultilineMessage( pStream, Nt51Guard );
  1448. if ( VC.HasStructPadN() )
  1449. Features.AddMessage( "large structure padding" );
  1450. if ( VC.HasForceAllocate() )
  1451. Features.AddMessage( "The [force_allocate] attribte" );
  1452. if ( VC.HasPartialIgnore() )
  1453. Features.AddMessage( "The [partial_ignore] attribute" );
  1454. if ( VC.HasMultiTransferSyntax() )
  1455. Features.AddMessage( "Uses -protocol all or -protocol ndr64" );
  1456. }
  1457. else if ( VC.HasNdr50Feature() )
  1458. {
  1459. OutputMultilineMessage( pStream, Nt50Guard );
  1460. if ( VC.HasAsyncHandleRpc() )
  1461. Features.AddMessage( "[async] attribute" );
  1462. if ( VC.HasNT5VTableSize() )
  1463. Features.AddMessage( "more than 110 methods in the interface" );
  1464. if ( VC.HasDOA() )
  1465. Features.AddMessage( "/robust command line switch" );
  1466. if ( VC.HasAsyncUUID() )
  1467. Features.AddMessage( "[async_uuid] attribute" );
  1468. if ( VC.HasInterpretedNotify() )
  1469. Features.AddMessage( "[notify] or [notify_flag] attribute in interpreted mode" );
  1470. if ( VC.HasContextSerialization() )
  1471. Features.AddMessage( "[serialize] or [noserialize] attribute" );
  1472. if ( VC.HasOicfPickling() )
  1473. Features.AddMessage( "[encode] or [decode] with -Oicf" );
  1474. }
  1475. else if ( VC.HasNdr20Feature() )
  1476. {
  1477. OutputMultilineMessage( pStream, Nt40Guard );
  1478. if ( VC.HasOi2() )
  1479. Features.AddMessage( "-Oif or -Oicf" );
  1480. if ( VC.HasUserMarshal() )
  1481. Features.AddMessage( "[wire_marshal] or [user_marshal] attribute" );
  1482. if ( VC.HasRawPipes() )
  1483. Features.AddMessage( "idl pipes" );
  1484. if ( VC.HasMoreThan64DelegatedProcs() )
  1485. Features.AddMessage( "more than 64 delegated procs" );
  1486. if ( VC.HasFloatOrDoubleInOi() )
  1487. Features.AddMessage( "float, double or hyper in -Oif or -Oicf" );
  1488. if ( VC.HasMessageAttr() )
  1489. Features.AddMessage( "[message] attribute" );
  1490. if ( VC.HasNT4VTableSize() )
  1491. Features.AddMessage( "more than 32 methods in the interface" );
  1492. }
  1493. else if ( VC.HasNdr11Feature() )
  1494. {
  1495. OutputMultilineMessage( pStream, Nt351win95Guard );
  1496. if ( VC.HasStublessProxies() )
  1497. Features.AddMessage( "old (-Oic) stubless proxies" );
  1498. if ( VC.HasCommFaultStatusInOi12() )
  1499. Features.AddMessage( "[comm_status] or [fault_status] in an -Oi* mode" );
  1500. }
  1501. else
  1502. return;
  1503. Features.PrintMessages();
  1504. OutputMultilineMessage( pStream, NtGuardClose );
  1505. pStream->NewLine();
  1506. }
  1507. void
  1508. CCB::OutputMultipleInterfaceTables()
  1509. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1510. Routine Description:
  1511. Generate the tables that may be common to multiple interfaces.
  1512. Arguments:
  1513. Return Value:
  1514. None.
  1515. Notes:
  1516. ----------------------------------------------------------------------------*/
  1517. {
  1518. CGSIDE Side = GetCodeGenSide();
  1519. // First, output the platform consistency check.
  1520. OutputPlatformCheck( pStream );
  1521. // Now, the ndr version guard against usage on old platforms.
  1522. if ( pCommand->GetEnv() == ENV_WIN32 )
  1523. OutputNdrVersionGuard( pStream );
  1524. MIDL_ASSERT( pCommand->IsNDRRun() || pCommand->IsNDR64Run() );
  1525. if ( pCommand->IsNDRRun() )
  1526. {
  1527. if ( pCommand->IsNDRRun() )
  1528. GetProcFormatString()->Output( pStream,
  1529. PROC_FORMAT_STRING_TYPE_NAME,
  1530. PROC_FORMAT_STRING_STRUCT_NAME,
  1531. GetRepAsPadExprDict(),
  1532. GetRepAsSizeDict() );
  1533. FixupRecPointers();
  1534. GetFormatString()->Output( pStream,
  1535. FORMAT_STRING_TYPE_NAME,
  1536. FORMAT_STRING_STRUCT_NAME,
  1537. GetRepAsPadExprDict(),
  1538. GetRepAsSizeDict() );
  1539. }
  1540. else
  1541. {
  1542. // If this is the 64bit transfer syntax run, then the proc and type format strings
  1543. // should be NULL.
  1544. MIDL_ASSERT( NULL == GetProcFormatString() );
  1545. MIDL_ASSERT( NULL == GetFormatString() );
  1546. GetNdr64Format()->Output();
  1547. }
  1548. if ( HasQuadrupleRoutines() )
  1549. {
  1550. //
  1551. // Emit the user_marshall table on both sides.
  1552. //
  1553. OutputQuadrupleTable();
  1554. }
  1555. //
  1556. // Emit the rundown routine table on the server side, if needed.
  1557. //
  1558. SetNoOutputIn2ndCodegen( this );
  1559. if ( (Side == CGSIDE_SERVER) &&
  1560. (GetOptimOption() & OPTIMIZE_INTERPRETER) &&
  1561. HasRundownRoutines()
  1562. )
  1563. {
  1564. OutputRundownRoutineTable();
  1565. }
  1566. //
  1567. // Emit the binding routine pair table on the client interpreted stub
  1568. // if needed.
  1569. //
  1570. if ( (Side == CGSIDE_CLIENT) &&
  1571. GetInterpretedRoutinesUseGenHandle() )
  1572. {
  1573. OutputBindingRoutines();
  1574. }
  1575. if ( HasExprEvalRoutines() )
  1576. {
  1577. //
  1578. // Emit the expr eval routines both sides.
  1579. //
  1580. OutputRegisteredExprEvalRoutines();
  1581. //
  1582. // Emit the expr eval routine table on both sides.
  1583. //
  1584. OutputExprEvalRoutineTable();
  1585. }
  1586. if ( HasExprFormatString() )
  1587. {
  1588. OutputExpressionFormatString();
  1589. }
  1590. if ( HasQuintupleRoutines() )
  1591. {
  1592. //
  1593. // Emit transmit as and represent as routines both sides.
  1594. //
  1595. OutputQuintupleRoutines();
  1596. //
  1597. // Emit the xmit as and rep as routine table on both sides.
  1598. //
  1599. OutputQuintupleTable();
  1600. }
  1601. if ( GetMallocAndFreeStructExternEmitted() )
  1602. {
  1603. // This is needed for the RpcSs support.
  1604. OutputMallocAndFreeStruct();
  1605. }
  1606. ResetNoOutputIn2ndCodegen( this );
  1607. }
  1608. long
  1609. CCB_RTN_INDEX_MGR::Lookup( char * pName )
  1610. {
  1611. long i;
  1612. for ( i = 1; i < NextIndex; i++ )
  1613. if ( ! strcmp(NameId[i],pName) )
  1614. return i;
  1615. //
  1616. // Insert a new entry
  1617. //
  1618. MIDL_ASSERT( NextIndex < MGR_INDEX_TABLE_SIZE );
  1619. NameId[NextIndex] = new char[strlen(pName) + 1];
  1620. strcpy(NameId[NextIndex],pName);
  1621. NextIndex++;
  1622. return NextIndex - 1;
  1623. }
  1624. char *
  1625. CCB_RTN_INDEX_MGR::Lookup( long Index )
  1626. {
  1627. if ( Index >= NextIndex )
  1628. return NULL;
  1629. return NameId[Index];
  1630. }
  1631. long
  1632. CCB_EXPR_INDEX_MGR::Lookup( char * pName )
  1633. {
  1634. long i;
  1635. for ( i = 1; i < NextIndex; i++ )
  1636. if ( ! strcmp(NameId[i],pName) )
  1637. return i;
  1638. //
  1639. // Insert a new entry
  1640. //
  1641. MIDL_ASSERT( NextIndex < MGR_INDEX_TABLE_SIZE );
  1642. NameId[NextIndex] = new char[strlen(pName) + 1];
  1643. strcpy(NameId[NextIndex],pName);
  1644. NextIndex++;
  1645. return NextIndex - 1;
  1646. }
  1647. char *
  1648. CCB_EXPR_INDEX_MGR::Lookup( long Index )
  1649. {
  1650. if ( Index >= NextIndex )
  1651. return NULL;
  1652. return NameId[Index];
  1653. }
  1654. PNAME
  1655. CCB::GenTRNameOffLastParam( char * pPrefix )
  1656. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1657. Routine Description:
  1658. Generate the name for a temporary resource.
  1659. Arguments:
  1660. pPrefix - A null terminated prefix string. If this is null, nothing is
  1661. added.
  1662. Return Value:
  1663. A freshly allocated resource name string.
  1664. Notes:
  1665. ----------------------------------------------------------------------------*/
  1666. {
  1667. char TempBuffer[ 30 ];
  1668. sprintf( TempBuffer,
  1669. "_%sM",
  1670. pPrefix ? pPrefix : ""
  1671. );
  1672. PNAME pName = (PNAME) new char [ strlen(TempBuffer) + 1 ];
  1673. strcpy( pName, TempBuffer );
  1674. return pName;
  1675. }