Leaked source code of windows server 2003
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.

1423 lines
40 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. misccls.hxx
  5. Abstract:
  6. Code generation methods for miscellaneous cg classes.
  7. Notes:
  8. History:
  9. Sep-01-1993 VibhasC Created.
  10. ----------------------------------------------------------------------------*/
  11. /****************************************************************************
  12. * include files
  13. ***************************************************************************/
  14. #include "becls.hxx"
  15. #pragma hdrstop
  16. #include "malloc.h"
  17. /****************************************************************************
  18. * local definitions
  19. ***************************************************************************/
  20. /****************************************************************************
  21. * local data
  22. ***************************************************************************/
  23. GUID_STRS TransferSyntaxGuidStrs( TRANSFER_SYNTAX_GUID_STR_1,
  24. TRANSFER_SYNTAX_GUID_STR_2,
  25. TRANSFER_SYNTAX_GUID_STR_3,
  26. TRANSFER_SYNTAX_GUID_STR_4,
  27. TRANSFER_SYNTAX_GUID_STR_5);
  28. GUID_STRS NDR64TransferSyntaxGuidStrs( NDR64_TRANSFER_SYNTAX_GUID_STR_1,
  29. NDR64_TRANSFER_SYNTAX_GUID_STR_2,
  30. NDR64_TRANSFER_SYNTAX_GUID_STR_3,
  31. NDR64_TRANSFER_SYNTAX_GUID_STR_4,
  32. NDR64_TRANSFER_SYNTAX_GUID_STR_5);
  33. GUID_STRS FakeNDR64TransferSyntaxGuidStrs(
  34. FAKE_NDR64_TRANSFER_SYNTAX_GUID_STR_1,
  35. FAKE_NDR64_TRANSFER_SYNTAX_GUID_STR_2,
  36. FAKE_NDR64_TRANSFER_SYNTAX_GUID_STR_3,
  37. FAKE_NDR64_TRANSFER_SYNTAX_GUID_STR_4,
  38. FAKE_NDR64_TRANSFER_SYNTAX_GUID_STR_5);
  39. /****************************************************************************
  40. * externs
  41. ***************************************************************************/
  42. extern CMD_ARG * pCommand;
  43. extern BOOL IsTempName( char * );
  44. /****************************************************************************/
  45. CG_INTERFACE::CG_INTERFACE(
  46. node_interface * pI,
  47. GUID_STRS GStrs,
  48. BOOL fCallbacks,
  49. BOOL fMopInfo,
  50. CG_HANDLE * pIH,
  51. CG_INTERFACE* pBaseIF
  52. ) :CG_NDR(pI, XLAT_SIZE_INFO() ),
  53. fTypeInfoInitialized( FALSE )
  54. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  55. Routine Description:
  56. The constructor for the code generation file node.
  57. Arguments:
  58. pI - A pointer to the interface node in type graph.
  59. GStrs - guid strings
  60. fCallbacks - Does the interface have any callbacks ?
  61. fMopInfo - Does the interface have any mops ?
  62. pIH - A pointer to the CG nodes for any implicit handle
  63. Return Value:
  64. Notes:
  65. ----------------------------------------------------------------------------*/
  66. {
  67. pCGBase = pBaseIF;
  68. _pCTI = NULL;
  69. char * pName = GetType()->GetSymName();
  70. GuidStrs = GStrs;
  71. GuidStrs.SetValue();
  72. fMopsPresent = fMopInfo;
  73. fCallbacksPresent = fCallbacks;
  74. pImpHdlCG = (CG_HANDLE *) pIH;
  75. CreateDispatchTables();
  76. fAllRpcSS = FALSE;
  77. fUsesRpcSS = FALSE;
  78. pIntfName = pName;
  79. fHasPipes = FALSE;
  80. fVisited = FALSE;
  81. fLocal = GetType()->FInSummary( ATTR_LOCAL );
  82. fHasMSConfStructAttr = FALSE;
  83. //
  84. // For now.
  85. //
  86. ProtSeqEPCount = 0;
  87. pStubDescName = new char[ strlen(STUB_DESC_STRUCT_VAR_NAME) +
  88. strlen(pName) + 1 ];
  89. strcpy( pStubDescName, pName );
  90. strcat( pStubDescName, STUB_DESC_STRUCT_VAR_NAME );
  91. pSyntaxInfoName = new char [strlen(MIDL_SYNTAX_INFO_VAR_NAME) +
  92. strlen(pName) + 1];
  93. strcpy( pSyntaxInfoName, pName );
  94. strcat( pSyntaxInfoName, MIDL_SYNTAX_INFO_VAR_NAME );
  95. pProxyInfoName = new char [strlen(MIDL_PROXY_INFO_VAR_NAME) +
  96. strlen(pName) + 1];
  97. strcpy( pProxyInfoName, pName );
  98. strcat( pProxyInfoName, MIDL_PROXY_INFO_VAR_NAME );
  99. }
  100. CG_STATUS
  101. CG_INTERFACE::GenClientInfo(
  102. CCB * pCCB )
  103. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  104. Routine Description:
  105. Generate code for the file node.
  106. Arguments:
  107. pCCB - a pointer to the code generation control block.
  108. Return Value:
  109. CG_OK if all is well, error otherwise.
  110. Notes:
  111. ----------------------------------------------------------------------------*/
  112. {
  113. unsigned short M,m; // for MAJOR and minor versions :-)
  114. CG_ITERATOR I;
  115. CG_PROC * pCG;
  116. CG_HANDLE * pCGHandle = GetImplicitHandle();
  117. node_skl * pID;
  118. char Buffer[_MAX_DRIVE+_MAX_DIR+_MAX_FNAME+_MAX_EXT+1];
  119. short CallbackCount;
  120. ISTREAM * pStream = pCCB->GetStream();
  121. int ProtSeqEPCount = 0;
  122. ITERATOR * pProtSeqIterator;
  123. char * pCStubPrefix;
  124. //Initialize the CCB for this interface.
  125. InitializeCCB(pCCB);
  126. pCCB->SetImplicitHandleIDNode( 0 );
  127. if( !GetMembers( I ) )
  128. {
  129. return CG_OK;
  130. }
  131. //
  132. // Emit the external variables needed.
  133. //
  134. if ( HasInterpretedCallbackProc() )
  135. Out_InterpreterServerInfoExtern( pCCB );
  136. if ( pCommand->NeedsNDR64Run() )
  137. Out_ProxyInfoExtern( pCCB );
  138. pStream->NewLine();
  139. if( pCGHandle )
  140. {
  141. pID = pCGHandle->GetHandleIDOrParam();
  142. pID->PrintType( PRT_ID_DECLARATION, pStream, 0 );
  143. }
  144. //
  145. // Emit the protseq endpoint structure if necessary. It is not
  146. // necessary if the endpoint attribute was not specified in which
  147. // case the ep count is 0.
  148. //
  149. if ( ( pProtSeqIterator = GetProtSeqEps() ) != 0 )
  150. {
  151. ProtSeqEPCount = ITERATOR_GETCOUNT( *pProtSeqIterator );
  152. Out_EP_Info( pCCB, pProtSeqIterator );
  153. }
  154. //
  155. // Emit the interface information structure.
  156. //
  157. pCCB->GetVersion( &M,&m );
  158. CallbackCount = ((node_interface *)GetType())->GetCallBackProcCount();
  159. if( CallbackCount )
  160. {
  161. sprintf( Buffer,
  162. "extern %s %s%s%s%_DispatchTable;",
  163. RPC_DISPATCH_TABLE_TYPE_NAME,
  164. pCCB->GetInterfaceName(),
  165. pCommand->IsNDR64Run()?"_NDR64_":"",
  166. pCCB->GenMangledName() );
  167. pStream->NewLine( 2 );
  168. pStream->Write( Buffer );
  169. /// NOTE:: This buffer is printed in the Out_IfInfo call !!!!
  170. sprintf( Buffer,
  171. "&%s%s%s_DispatchTable",
  172. pCCB->GetInterfaceName(),
  173. pCommand->IsNDR64Run()?"_NDR64_":"",
  174. pCCB->GenMangledName() );
  175. }
  176. //
  177. // Must set this before outputing the interface info.
  178. //
  179. pCCB->SetCodeGenSide( CGSIDE_CLIENT );
  180. Out_IFInfo( pCCB, // controller block.
  181. RPC_C_INT_INFO_TYPE_NAME, // interface info type name.
  182. RPC_C_INT_INFO_STRUCT_NAME, // variable name.
  183. SIZEOF_RPC_CLIENT_INTERFACE, // string speicifying size.
  184. GuidStrs, // Guid specified in idl
  185. M, // user specified major version
  186. m, // user specified minor version
  187. // TransferSyntaxGuidStrs, // ndr identifying guid.
  188. // NDR_UUID_MAJOR_VERSION, // ndr's version
  189. // NDR_UUID_MINOR_VERSION,
  190. CallbackCount ? Buffer : 0, // call back dispatch table name
  191. ProtSeqEPCount, // if this is 0, then the next
  192. // 2 fields are ignored by
  193. // the call.
  194. PROTSEQ_EP_TYPE_NAME, // RPC_PROTSEQ_ENDPOINT
  195. PROTSEQ_EP_VAR_NAME, // ___RpcProtSeqEndpoint
  196. pCCB->IsNoDefaultEpv(),
  197. 0, // client side
  198. HasPipes()
  199. );
  200. if ( (pCStubPrefix = pCommand->GetUserPrefix( PREFIX_CLIENT_STUB ) ) == 0 )
  201. {
  202. pCStubPrefix = "";
  203. }
  204. pStream->NewLine();
  205. sprintf( Buffer,
  206. "RPC_IF_HANDLE %s%s%s_%s = (RPC_IF_HANDLE)& %s" RPC_C_INT_INFO_STRUCT_NAME";",
  207. pCStubPrefix,
  208. pCCB->GetInterfaceName(),
  209. pCCB->GenMangledName(),
  210. ((pCCB->IsOldNames()) ? "ClientIfHandle" : "c_ifspec"),
  211. pCCB->GetInterfaceName()
  212. );
  213. pStream->Write( Buffer );
  214. //
  215. // Emit the stub descriptor extern declaration.
  216. //
  217. Out_StubDescriptorExtern( pCCB );
  218. //
  219. // Check for use of [enable_allocate]
  220. // Use in ms_ext when explicit, in osf always, to cover some weird cases.
  221. //
  222. if ( GetUsesRpcSS() || pCCB->InOSFMode() )
  223. pCCB->SetMallocAndFreeStructExternEmitted();
  224. // Emit the auto handle extern
  225. pStream->NewLine();
  226. sprintf( Buffer,
  227. "static %s %s%s;",
  228. AUTO_BH_TYPE_NAME,
  229. pCCB->GetInterfaceName(),
  230. AUTO_BH_VAR_NAME
  231. );
  232. pStream->Write( Buffer );
  233. pStream->NewLine();
  234. //
  235. // Send the message to the children to emit code.
  236. //
  237. //
  238. // for all procedure in this interface, generate code.
  239. //
  240. while( ITERATOR_GETNEXT( I, pCG ) )
  241. {
  242. pCG->GenClientStub( pCCB );
  243. }
  244. return CG_OK;
  245. }
  246. void
  247. CG_INTERFACE::Out_ProcOffsetTable( CCB *pCCB, BOOL IsForCallback )
  248. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  249. Routine Description:
  250. Output a table of offsets to procedure information in the format
  251. string/structure.
  252. Arguments:
  253. pCCB - a pointer to the code generation control block.
  254. IsForCallback - Is this is a table of callback offsets?
  255. Notes:
  256. ----------------------------------------------------------------------------*/
  257. {
  258. ISTREAM *pStream = pCCB->GetStream();
  259. if ( pCommand->IsNDR64Run() )
  260. pStream->WriteOnNewLine( "static const FormatInfoRef " );
  261. else
  262. pStream->WriteOnNewLine( "static const unsigned short " );
  263. if ( IsForCallback )
  264. pStream->Write( MIDL_CALLBACK_VAR_NAME );
  265. pStream->Write( GetSymName() );
  266. if ( pCommand->IsNDR64Run() )
  267. pStream->Write( "_Ndr64ProcTable[] =" );
  268. else
  269. pStream->Write( "_FormatStringOffsetTable[] =" );
  270. pStream->IndentInc();
  271. pStream->WriteOnNewLine( '{' );
  272. pStream->NewLine();
  273. OutputProcOffsets( pCCB, TRUE, IsForCallback );
  274. pStream->Write( "};" );
  275. pStream->IndentDec();
  276. pStream->NewLine( 2 );
  277. // If we need a table of callbacks also, recursively call ourselves
  278. if ( !IsForCallback && HasInterpretedCallbackProc() )
  279. Out_ProcOffsetTable( pCCB, TRUE );
  280. }
  281. CG_STATUS
  282. CG_INTERFACE::OutputClientStub(
  283. CCB * pCCB )
  284. {
  285. CG_ITERATOR I;
  286. if( !GetMembers( I ) )
  287. {
  288. return CG_OK;
  289. }
  290. //Initialize the CCB for this interface.
  291. InitializeCCB(pCCB);
  292. // Output a table containing the offsets of each proc description for this
  293. // interface in the format info string/struct. Output another table for
  294. // callbacks if needed.
  295. Out_ProcOffsetTable( pCCB );
  296. //
  297. // Emit the stub descriptor and all that is specific to the interface,
  298. // Generate externs to tables that may be common to several interfaces.
  299. //
  300. Out_StubDescriptor( GetImplicitHandle(), pCCB );
  301. if ( pCommand->NeedsNDR64Run() )
  302. Out_ProxyInfo( pCCB, FALSE );
  303. //
  304. // Generate the dispatch table.
  305. //
  306. short CallbackCount = ( (node_interface *) GetType() )
  307. ->GetCallBackProcCount();
  308. if( CallbackCount )
  309. {
  310. ITERATOR ProcList;
  311. GetCallbackProcedureList( ProcList, DTF_NONE );
  312. Out_DispatchTableStuff( pCCB,
  313. ProcList,
  314. CallbackCount
  315. );
  316. }
  317. if ( HasInterpretedCallbackProc() )
  318. {
  319. GenSyntaxInfo( pCCB, TRUE );
  320. Out_InterpreterServerInfo( pCCB, CGSIDE_CLIENT );
  321. }
  322. return CG_OK;
  323. }
  324. CG_STATUS
  325. CG_INTERFACE::GenServerInfo(
  326. CCB * pCCB )
  327. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  328. Routine Description:
  329. Generate code for the interface node.
  330. Arguments:
  331. pCCB - a pointer to the code generation control block.
  332. Return Value:
  333. CG_OK if all is well, error otherwise.
  334. Notes:
  335. ----------------------------------------------------------------------------*/
  336. {
  337. unsigned short M,m; // for MAJOR and minor versions :-)
  338. CG_PROC * pCG;
  339. CG_ITERATOR I;
  340. char Buffer[ _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 1 ];
  341. ISTREAM * pStream = pCCB->GetStream();
  342. ITERATOR * pProtSeqIterator;
  343. node_interface * pInterface = (node_interface *)GetType();
  344. char * pSStubPrefix;
  345. InitializeCCB(pCCB);
  346. if( !GetMembers( I ) )
  347. {
  348. return CG_OK;
  349. }
  350. //
  351. // Emit the external variables needed.
  352. //
  353. if ( HasInterpretedProc() )
  354. Out_InterpreterServerInfoExtern( pCCB );
  355. //
  356. // Emit the protseq endpoint structure if necessary. It is not
  357. // necessary if the endpoint attribute was not specified in which
  358. // case the ep count is 0.
  359. //
  360. if ( ( pProtSeqIterator = GetProtSeqEps() ) != 0 )
  361. {
  362. ProtSeqEPCount = ITERATOR_GETCOUNT( *pProtSeqIterator );
  363. Out_EP_Info( pCCB, pProtSeqIterator );
  364. }
  365. //
  366. // Emit the interface information structure.
  367. //
  368. pCCB->GetVersion( &M,&m );
  369. //
  370. // Emit the extern decl for the server's dispatch table, which goes
  371. // in the server interface structure which follows.
  372. //
  373. sprintf( Buffer,
  374. "extern %s %s%s%s_DispatchTable;",
  375. RPC_DISPATCH_TABLE_TYPE_NAME,
  376. pCCB->GetInterfaceName(),
  377. pCommand->IsNDR64Run()?"_NDR64_":"",
  378. pCCB->GenMangledName() );
  379. pStream->NewLine( 2 );
  380. pStream->Write( Buffer );
  381. //
  382. // Emit the extern decl for the server side manager epv table, which goes
  383. // in the server interface structure which follows.
  384. //
  385. if( pCCB->IsMEpV() &&
  386. !pCCB->IsNoDefaultEpv() &&
  387. (pInterface->GetProcCount() != 0) )
  388. {
  389. sprintf( Buffer,
  390. "extern %s%s_%s DEFAULT_EPV;",
  391. pCCB->GetInterfaceName(),
  392. pCCB->GenMangledName(),
  393. pCCB->IsOldNames() ? "SERVER_EPV" : "epv_t" );
  394. pStream->NewLine( 2 );
  395. pStream->Write( Buffer );
  396. }
  397. // Prepare address string for the address of the dispatch table in the
  398. // interface information structure.
  399. sprintf( Buffer,
  400. "&%s%s%s_DispatchTable",
  401. pCCB->GetInterfaceName(),
  402. pCommand->IsNDR64Run()?"_NDR64_":"",
  403. pCCB->GenMangledName()
  404. );
  405. //
  406. // Must set this before outputing the interface info.
  407. //
  408. pCCB->SetCodeGenSide( CGSIDE_SERVER );
  409. Out_IFInfo( pCCB, // controller block.
  410. RPC_S_INT_INFO_TYPE_NAME, // interface info type name.
  411. RPC_S_INT_INFO_STRUCT_NAME, // variable name.
  412. SIZEOF_RPC_SERVER_INTERFACE, // string speicifying size.
  413. GuidStrs, // Guid specified in idl
  414. M, // user specified major version
  415. m, // user specified minor version
  416. // TransferSyntaxGuidStrs, // ndr identifying guid.
  417. // NDR_UUID_MAJOR_VERSION, // ndr's version
  418. // NDR_UUID_MINOR_VERSION,
  419. Buffer,
  420. ProtSeqEPCount, // if this is 0, then the next
  421. // 2 fields are ignored by
  422. // the call.
  423. PROTSEQ_EP_TYPE_NAME, // RPC_PROTSEQ_ENDPOINT
  424. PROTSEQ_EP_VAR_NAME, // ___RpcProtSeqEndpoint
  425. pCCB->IsNoDefaultEpv(),
  426. 1,
  427. HasPipes()
  428. );
  429. if ( (pSStubPrefix = pCommand->GetUserPrefix( PREFIX_SERVER_MGR ) ) == 0 )
  430. {
  431. pSStubPrefix = "";
  432. }
  433. pStream->NewLine();
  434. sprintf( Buffer,
  435. "RPC_IF_HANDLE %s%s%s_%s = (RPC_IF_HANDLE)& %s"
  436. RPC_S_INT_INFO_STRUCT_NAME";",
  437. pSStubPrefix,
  438. pCCB->GetInterfaceName(),
  439. pCCB->GenMangledName(),
  440. ((pCCB->IsOldNames()) ? "ServerIfHandle" : "s_ifspec"),
  441. pCCB->GetInterfaceName()
  442. );
  443. pStream->Write( Buffer );
  444. //
  445. // Emit the stub descriptor extern declaration.
  446. //
  447. Out_StubDescriptorExtern( pCCB );
  448. //
  449. // Check for use of [enable_allocate]
  450. //
  451. if ( GetUsesRpcSS() && !pCCB->InOSFMode() )
  452. pCCB->SetMallocAndFreeStructExternEmitted();
  453. // has callback and Needsndr64: we need to generate proxy info for callback's
  454. // client stub.
  455. if ( HasInterpretedCallbackProc() )
  456. Out_ProxyInfoExtern( pCCB );
  457. //
  458. // Send the message to the children to emit code.
  459. //
  460. //
  461. // For all procedures in this interface, generate code.
  462. //
  463. while( ITERATOR_GETNEXT( I, pCG ) )
  464. {
  465. pCG->GenServerStub( pCCB );
  466. }
  467. return CG_OK;
  468. }
  469. CG_STATUS
  470. CG_INTERFACE::OutputServerStub(
  471. CCB * pCCB )
  472. {
  473. CG_ITERATOR I;
  474. if( !GetMembers( I ) )
  475. {
  476. return CG_OK;
  477. }
  478. short NormalProcCount;
  479. ITERATOR NormalProcList;
  480. InitializeCCB( pCCB );
  481. // For procs that return complex types (structures, floating point, etc)
  482. // we need to have a thunk that takes a pointer to where to store this
  483. // type.
  484. OutputComplexReturnThunks( pCCB );
  485. // Output a table containing the offsets of each proc description for this
  486. // interface in the format info string/struct. Output another table for
  487. // callbacks if needed.
  488. Out_ProcOffsetTable( pCCB );
  489. //
  490. // Emit the stub descriptor.
  491. //
  492. if ( HasInterpretedProc() )
  493. pCCB->SetOptimOption( unsigned short( pCCB->GetOptimOption() | OPTIMIZE_INTERPRETER ) );
  494. Out_StubDescriptor( GetImplicitHandle(), pCCB );
  495. //
  496. // Generate the dispatch table.
  497. //
  498. NormalProcCount = GetNormalProcedureList( NormalProcList,
  499. DTF_NONE
  500. );
  501. if( NormalProcCount )
  502. Out_DispatchTableStuff( pCCB,
  503. NormalProcList,
  504. NormalProcCount
  505. );
  506. // Generate the manager epv if the -use epv switch has been specified.
  507. if( pCCB->IsMEpV() && !pCCB->IsNoDefaultEpv() )
  508. {
  509. ITERATOR ProcList;
  510. short Count;
  511. Count = GetNormalProcedureList( ProcList,
  512. DTF_NONE
  513. );
  514. if( Count )
  515. {
  516. Out_ManagerEpv( pCCB, pCCB->GetInterfaceName(), ProcList, Count );
  517. }
  518. }
  519. if ( pCommand->NeedsNDR64Run() )
  520. {
  521. GenSyntaxInfo( pCCB, FALSE );
  522. if ( pCCB->GetInterfaceCG()->HasInterpretedCallbackProc() )
  523. Out_ProxyInfo( pCCB, TRUE );
  524. }
  525. if ( HasInterpretedProc() )
  526. Out_InterpreterServerInfo( pCCB, CGSIDE_SERVER );
  527. return CG_OK;
  528. }
  529. void
  530. CG_INTERFACE::OutputComplexReturnThunks(
  531. CCB * pCCB )
  532. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  533. Routine Description:
  534. For procs that return complex types (structures, floating point, etc
  535. we need to have a thunk that takes a pointer to where to store this
  536. type.
  537. Arguments:
  538. pCCB - a pointer to the code generation control block.
  539. Notes:
  540. The thunk looks like:
  541. void Proc_ComplexThunk(..., ReturnType *_RetVal)
  542. {
  543. *_RetVal = Proc(...);
  544. }
  545. REVIEW:
  546. Integrate this with NeedsServerThunk stuff
  547. ----------------------------------------------------------------------------*/
  548. {
  549. if ( CGSIDE_SERVER != pCCB->GetCodeGenSide() )
  550. return;
  551. if ( !pCommand->IsFinalProtocolRun() )
  552. return;
  553. ISTREAM *pStream = pCCB->GetStream();
  554. ITERATOR procs;
  555. CG_PROC *procCG;
  556. GetMembers( procs );
  557. while ( ITERATOR_GETNEXT( procs, procCG ) )
  558. {
  559. if ( ! procCG->HasComplexReturnType() || procCG->HasAsyncHandle() )
  560. continue;
  561. ITERATOR params;
  562. short nParams;
  563. expr_proc_call *pCall = new expr_proc_call( procCG->GetSymName() );
  564. expr_node *pExpr;
  565. CG_PARAM *param;
  566. procCG->GetMembers( params );
  567. nParams = ITERATOR_GETCOUNT( params );
  568. for ( int i = 0; i < nParams - 1; i++ )
  569. {
  570. ITERATOR_GETNEXT( params, param );
  571. pCall->SetParam( new expr_variable( param->GetResource()->GetResourceName() ) );
  572. }
  573. node_proc *proc = new node_proc( (node_proc *) procCG->GetType() );
  574. node_param *pParam;
  575. node_skl *pVoid;
  576. node_skl *pOldChild;
  577. char *pProcName = (char *) alloca(
  578. strlen( proc->GetSymName() )
  579. + sizeof( "_ComplexThunk" ) );
  580. strcpy( pProcName, proc->GetSymName() );
  581. strcat( pProcName, "_ComplexThunk" );
  582. proc->SetSymName( pProcName );
  583. // REVIEW: A lot of this is cruft, clean it up!
  584. GetBaseTypeNode( &pVoid, SIGN_UNDEF, SIZE_UNDEF, TYPE_VOID, ATTR_NONE );
  585. pParam = new node_param;
  586. pParam->SetSymName( RETURN_VALUE_VAR_NAME );
  587. pParam->SetChild( new node_pointer( proc->GetChild() ) );
  588. pParam->GetChild()->GetModifiers().SetModifier( ATTR_TAGREF );
  589. pOldChild = proc->GetChild();
  590. proc->SetChild( pVoid );
  591. // proc->SetHasComplexReturnType( FALSE );
  592. proc->RemoveAttribute( ATTR_PTR_KIND );
  593. proc->AddLastMember( pParam );
  594. pExpr = new expr_assign(new expr_variable( "*" RETURN_VALUE_VAR_NAME ), pCall );
  595. pStream->NewLine( 2 );
  596. proc->PrintType( PRT_DECL, pStream );
  597. pStream->WriteOnNewLine( "{" );
  598. pStream->IndentInc();
  599. pStream->NewLine();
  600. pExpr->PrintCall( pStream, 0, 0 );
  601. pStream->IndentDec();
  602. pStream->WriteOnNewLine( "}" );
  603. proc->RemoveLastMember();
  604. proc->SetChild( pOldChild );
  605. }
  606. }
  607. CG_STATUS
  608. CG_INTERFACE::GenHeader(
  609. CCB * pCCB )
  610. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  611. Routine Description:
  612. Generate interface header file.
  613. Arguments:
  614. pCCB - a pointer to the code generation control block.
  615. Return Value:
  616. CG_OK if all is well, error other wise.
  617. Notes:
  618. ----------------------------------------------------------------------------*/
  619. {
  620. node_interface * pInterface = (node_interface *) GetType();
  621. ITERATOR I;
  622. ITERATOR J;
  623. char Buffer[ _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 1 ];
  624. CG_HANDLE * pCGHandle = GetImplicitHandle();
  625. node_skl * pID;
  626. ISTREAM * pStream = pCCB->GetStream();
  627. unsigned short M, m;
  628. char * pCStubPrefix;
  629. char * pSStubPrefix;
  630. char * pName = pInterface->GetSymName();
  631. BOOL fAnonymous = IsTempName( pName );
  632. //Initialize the CCB for this interface.
  633. InitializeCCB(pCCB);
  634. // put out the interface guards
  635. if ( !fAnonymous )
  636. {
  637. pStream->Write("\n#ifndef __");
  638. pStream->Write( pName );
  639. pStream->Write( "_INTERFACE_DEFINED__\n" );
  640. pStream->Write( "#define __");
  641. pStream->Write( pName );
  642. pStream->Write( "_INTERFACE_DEFINED__\n" );
  643. }
  644. // Print out the declarations of the types and the procedures.
  645. // If the user defined a prefix for the cstub or sstub,
  646. // then emit prototypes with the prefix in them.
  647. pStream->NewLine();
  648. pInterface->PrintType(
  649. PRT_INTERFACE | PRT_BOTH_PREFIX | PRT_OMIT_CS_TAG_PARAMS,
  650. pStream,
  651. 0 );
  652. if( pCGHandle )
  653. {
  654. pID = pCGHandle->GetHandleIDOrParam();
  655. pStream->NewLine();
  656. pStream->Write( "extern " );
  657. pID->PrintType( PRT_ID_DECLARATION, pStream, 0 );
  658. }
  659. // Emit the declarations for user supplied routines.
  660. // Print out the dispatch table.
  661. pStream->NewLine();
  662. GetNormalProcedureList( I, DTF_NONE );
  663. if( pCCB->IsMEpV() )
  664. {
  665. if( ITERATOR_GETCOUNT(I) )
  666. Out_DispatchTableTypedef(
  667. pCCB,
  668. pCCB->GetInterfaceName(),
  669. I,
  670. 0
  671. );
  672. }
  673. GetCallbackProcedureList( J, DTF_NONE );
  674. if( ITERATOR_GETCOUNT(J ) )
  675. Out_DispatchTableTypedef(
  676. pCCB,
  677. pCCB->GetInterfaceName(),
  678. J,
  679. 1
  680. );
  681. pCCB->GetVersion( &M, &m );
  682. if ( (pCStubPrefix = pCommand->GetUserPrefix( PREFIX_CLIENT_STUB ) ) == 0 )
  683. {
  684. pCStubPrefix = 0;
  685. }
  686. if ( (pSStubPrefix = pCommand->GetUserPrefix( PREFIX_SERVER_MGR ) ) == 0 )
  687. {
  688. pSStubPrefix = 0;
  689. }
  690. // Generate the extern for the client if handle.
  691. pStream->NewLine();
  692. sprintf( Buffer, "extern RPC_IF_HANDLE %s%s%s_%s;",
  693. (pCStubPrefix == 0) ? "" : pCStubPrefix,
  694. pCCB->GetInterfaceName(),
  695. pCCB->GenMangledName(),
  696. (pCCB->IsOldNames()) ? "ClientIfHandle" : "c_ifspec" );
  697. pStream->Write( Buffer );
  698. // If a prefix is defined for cstub, generate another extern for the
  699. // non - prefixed client if handle. Remember, in the header file we need
  700. // both the externs, since the header file generated out of the -prefix
  701. // cstub invocation contains prototypes for both prefixed and non-prefix
  702. // stuff.
  703. if( pCStubPrefix )
  704. {
  705. pStream->NewLine();
  706. sprintf( Buffer, "extern RPC_IF_HANDLE %s%s%s_%s;",
  707. "",
  708. pCCB->GetInterfaceName(),
  709. pCCB->GenMangledName(),
  710. (pCCB->IsOldNames()) ? "ClientIfHandle" : "c_ifspec" );
  711. pStream->Write( Buffer );
  712. }
  713. pStream->NewLine();
  714. sprintf( Buffer, "extern RPC_IF_HANDLE %s%s%s_%s;",
  715. (pSStubPrefix == 0) ? "" : pSStubPrefix,
  716. pCCB->GetInterfaceName(),
  717. pCCB->GenMangledName(),
  718. (pCCB->IsOldNames()) ? "ServerIfHandle" : "s_ifspec" );
  719. pStream->Write( Buffer );
  720. pStream->NewLine();
  721. // put out the trailing interface guard
  722. if ( !fAnonymous )
  723. {
  724. pStream->Write( "#endif /* __");
  725. pStream->Write( pName );
  726. pStream->Write( "_INTERFACE_DEFINED__ */\n" );
  727. }
  728. return CG_OK;
  729. }
  730. ITERATOR *
  731. CG_INTERFACE::GetProtSeqEps()
  732. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  733. Routine Description:
  734. Get the protocol sequences pairs iterator.
  735. Arguments:
  736. Iterator reference.
  737. Return Value:
  738. FALSE if there are no endpoints
  739. Notes:
  740. The iterator is invalid if there are no endpoints.
  741. ----------------------------------------------------------------------------*/
  742. {
  743. node_interface * pIntf = (node_interface *) GetType();
  744. node_endpoint * pEps = (node_endpoint *)
  745. pIntf->GetAttribute( ATTR_ENDPOINT );
  746. return ( pEps ) ? &(pEps->GetEndPointPairs()) : NULL;
  747. }
  748. void
  749. CG_INTERFACE::CreateDispatchTables()
  750. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  751. Routine Description:
  752. Set up the stub dispatch tables.
  753. Arguments:
  754. None.
  755. Return Value:
  756. None.
  757. Notes:
  758. ----------------------------------------------------------------------------*/
  759. {
  760. pNormalDispatchTable = new DISPATCH_TABLE();
  761. pCallbackDispatchTable = new DISPATCH_TABLE();
  762. ppDispatchTableSaved = ppDispatchTable = &pNormalDispatchTable;
  763. }
  764. BOOL
  765. CG_INTERFACE::HasInterpretedProc()
  766. {
  767. CG_ITERATOR Iterator;
  768. CG_PROC * pProc;
  769. GetMembers( Iterator );
  770. while ( ITERATOR_GETNEXT( Iterator, pProc ) )
  771. if ( pProc->GetOptimizationFlags() & OPTIMIZE_INTERPRETER )
  772. return TRUE;
  773. return FALSE;
  774. }
  775. BOOL
  776. CG_INTERFACE::HasOnlyInterpretedProcs()
  777. {
  778. CG_ITERATOR Iterator;
  779. CG_PROC * pProc;
  780. GetMembers( Iterator );
  781. while ( ITERATOR_GETNEXT( Iterator, pProc ) )
  782. if ( (pProc->GetOptimizationFlags() & OPTIMIZE_INTERPRETER ) == 0 )
  783. return FALSE;
  784. return TRUE;
  785. }
  786. BOOL
  787. CG_OBJECT_INTERFACE::HasOnlyInterpretedMethods()
  788. {
  789. CG_ITERATOR Iterator;
  790. CG_PROC * pProc;
  791. CG_OBJECT_INTERFACE* pBaseCG = (CG_OBJECT_INTERFACE*) GetBaseInterfaceCG();
  792. if ( pBaseCG && !pBaseCG->HasOnlyInterpretedMethods() )
  793. return FALSE;
  794. GetMembers( Iterator );
  795. while ( ITERATOR_GETNEXT( Iterator, pProc ) )
  796. if ( (pProc->GetOptimizationFlags() & OPTIMIZE_INTERPRETER ) == 0 )
  797. return FALSE;
  798. return TRUE;
  799. }
  800. BOOL
  801. CG_INTERFACE::HasItsOwnOi2()
  802. {
  803. CG_ITERATOR Iterator;
  804. CG_PROC * pProc;
  805. GetMembers( Iterator );
  806. while ( ITERATOR_GETNEXT( Iterator, pProc ) )
  807. if ( (pProc->GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2) )
  808. return TRUE;
  809. return FALSE;
  810. }
  811. void
  812. CG_INTERFACE::EvaluateVersionControl()
  813. {
  814. if ( HasItsOwnOi2() )
  815. {
  816. GetNdrVersionControl().SetHasOi2();
  817. }
  818. }
  819. BOOL
  820. CG_OBJECT_INTERFACE::HasItsOwnStublessProxies()
  821. {
  822. CG_ITERATOR Iterator;
  823. CG_PROC * pProc;
  824. GetMembers( Iterator );
  825. while ( ITERATOR_GETNEXT( Iterator, pProc ) )
  826. if (pProc->GetOptimizationFlags() & OPTIMIZE_STUBLESS_CLIENT )
  827. return TRUE;
  828. return FALSE;
  829. }
  830. void
  831. CG_OBJECT_INTERFACE::EvaluateVersionControl()
  832. {
  833. CG_OBJECT_INTERFACE* pBaseCG = (CG_OBJECT_INTERFACE*) GetBaseInterfaceCG();
  834. if ( pBaseCG )
  835. {
  836. pBaseCG->EvaluateVersionControl();
  837. }
  838. if ( HasItsOwnStublessProxies() ||
  839. pBaseCG && pBaseCG->HasStublessProxies() )
  840. {
  841. GetNdrVersionControl().SetHasStublessProxies();
  842. }
  843. if ( HasItsOwnOi2() ||
  844. pBaseCG && pBaseCG->HasOi2() )
  845. {
  846. GetNdrVersionControl().SetHasOi2();
  847. }
  848. }
  849. BOOL
  850. CG_INTERFACE::HasInterpretedCallbackProc()
  851. {
  852. CG_ITERATOR Iterator;
  853. CG_PROC * pProc;
  854. GetMembers( Iterator );
  855. while ( ITERATOR_GETNEXT( Iterator, pProc ) )
  856. if ( pProc->GetCGID() == ID_CG_CALLBACK_PROC &&
  857. pProc->GetOptimizationFlags() & OPTIMIZE_INTERPRETER )
  858. return TRUE;
  859. return FALSE;
  860. }
  861. BOOL
  862. CG_INTERFACE::HasClientInterpretedCommOrFaultProc( CCB * pCCB )
  863. {
  864. CG_ITERATOR Iterator;
  865. CG_PROC * pProc;
  866. CGSIDE Side;
  867. Side = pCCB->GetCodeGenSide();
  868. GetMembers( Iterator );
  869. while ( ITERATOR_GETNEXT( Iterator, pProc ) )
  870. if ( (pProc->GetOptimizationFlags() & OPTIMIZE_INTERPRETER) &&
  871. pProc->HasStatuses() &&
  872. ( ((pProc->GetCGID() == ID_CG_PROC) && (Side == CGSIDE_CLIENT)) ||
  873. ((pProc->GetCGID() == ID_CG_CALLBACK_PROC) && (Side == CGSIDE_SERVER)) ) )
  874. return TRUE;
  875. return FALSE;
  876. }
  877. CG_STATUS
  878. CG_INTERFACE::InitializeCCB( CCB * pCCB )
  879. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  880. Routine Description:
  881. Initialize the CCB for this interface.
  882. Arguments:
  883. pCCB - a pointer to the code generation control block.
  884. Return Value:
  885. CG_OK if all is well, error otherwise.
  886. Notes:
  887. ----------------------------------------------------------------------------*/
  888. {
  889. unsigned short Major,minor;
  890. node_interface *pInterface = (node_interface *) GetType();
  891. pInterface->GetVersionDetails(&Major, &minor);
  892. pCCB->SetVersion(Major, minor);
  893. pCCB->SetInterfaceName(pInterface->GetSymName());
  894. pCCB->SetInterfaceCG(this);
  895. return CG_OK;
  896. }
  897. void
  898. CG_INTERFACE::OutputProcOffsets( CCB * pCCB, BOOL fLast, BOOL IsForCallback )
  899. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  900. Routine Description:
  901. Output a list of offsets (from the beginning of the proc format info)
  902. to each proc in the interface
  903. Arguments:
  904. pCCB - a pointer to the code generation control block.
  905. fLast -
  906. IsForCallback -
  907. Notes:
  908. For Ndr32 the list is a table of shorts that offset from the beginning
  909. of the proc format string.
  910. For Ndr64 it is a table of longs that is the offset from the format info
  911. structure.
  912. ----------------------------------------------------------------------------*/
  913. {
  914. CG_PROC * pProc;
  915. CG_ITERATOR Iterator;
  916. ISTREAM * pStream = pCCB->GetStream();
  917. CGSIDE Side;
  918. long Offset;
  919. // IUnknown doesn't get entries in the proc offsets table
  920. if ( IsIUnknown() )
  921. {
  922. if ( fLast )
  923. {
  924. pStream->Write( '0' );
  925. pStream->NewLine();
  926. }
  927. return;
  928. }
  929. Side = pCCB->GetCodeGenSide();
  930. if ( IsObject() )
  931. {
  932. CG_OBJECT_INTERFACE * pObjInterface;
  933. pObjInterface = (CG_OBJECT_INTERFACE *) this;
  934. if ( pObjInterface->GetBaseInterfaceCG() )
  935. {
  936. pObjInterface->GetBaseInterfaceCG()->OutputProcOffsets( pCCB, FALSE, IsForCallback );
  937. }
  938. }
  939. GetMembers( Iterator );
  940. BOOL fNoOffsetsEmitted = TRUE;
  941. while ( ITERATOR_GETNEXT( Iterator, pProc ) )
  942. {
  943. if ( (Side == CGSIDE_CLIENT) &&
  944. ( IsForCallback ? ( pProc->GetCGID() != ID_CG_CALLBACK_PROC ) :
  945. (pProc->GetCGID() == ID_CG_CALLBACK_PROC) ) )
  946. continue;
  947. if ( (Side == CGSIDE_SERVER) &&
  948. ( ( IsForCallback ? ( pProc->GetCGID() != ID_CG_CALLBACK_PROC ) :
  949. ( pProc->GetCGID() == ID_CG_CALLBACK_PROC ) )
  950. || (pProc->GetCGID() == ID_CG_TYPE_ENCODE_PROC ) ) )
  951. continue;
  952. CG_PROC *pTargetProc = pProc;
  953. if ( fLocal )
  954. pTargetProc = pProc->GetCallAsCG();
  955. // type encode procs are not real procs
  956. if ( dynamic_cast<CG_TYPE_ENCODE_PROC *>(pTargetProc) )
  957. continue;
  958. fNoOffsetsEmitted = FALSE;
  959. // REVIEW: If Offset is -1 (dce) or 0 (ndr64) then we haven't generated
  960. // format info for the proc. This can only happen in certain
  961. // conditions ([nocode], methods in parent interface). There
  962. // should be an assert.
  963. if ( pCommand->IsNDR64Run() )
  964. {
  965. Offset = 0;
  966. if ( pTargetProc )
  967. Offset = (long) (size_t) pCCB->GetNdr64Format()->GetRoot()
  968. ->LookupFragmentID( pTargetProc );
  969. if ( 0 == Offset )
  970. pStream->Write( "(FormatInfoRef) -1" );
  971. else
  972. pStream->WriteNumber( "&__midl_frag%d", Offset );
  973. }
  974. else
  975. {
  976. Offset = -1;
  977. if ( pTargetProc )
  978. Offset = pTargetProc->GetFormatStringOffset();
  979. if ( -1 == Offset )
  980. pStream->Write( "(unsigned short) -1" );
  981. else
  982. pStream->WriteNumber( "%d", Offset );
  983. }
  984. if ( pProc->GetSibling() || !fLast )
  985. pStream->Write( ',' );
  986. pStream->NewLine();
  987. }
  988. if ( fNoOffsetsEmitted && fLast )
  989. {
  990. pStream->Write( '0' );
  991. pStream->NewLine();
  992. }
  993. }
  994. void
  995. CG_INTERFACE::OutputThunkTableEntries( CCB * pCCB, BOOL fLast )
  996. {
  997. CG_PROC * pProc;
  998. CG_ITERATOR Iterator;
  999. ISTREAM * pStream = pCCB->GetStream();
  1000. CGSIDE Side = pCCB->GetCodeGenSide();
  1001. char * pIntfName = GetType()->GetSymName();
  1002. // IUnknown doesn't get entries in the thunk table
  1003. if ( IsIUnknown() )
  1004. {
  1005. if ( fLast )
  1006. {
  1007. pStream->Write( '0' );
  1008. pStream->NewLine();
  1009. }
  1010. return;
  1011. }
  1012. if ( IsObject() )
  1013. {
  1014. CG_OBJECT_INTERFACE * pObjInterface;
  1015. pObjInterface = (CG_OBJECT_INTERFACE *) this;
  1016. if ( pObjInterface->GetBaseInterfaceCG() )
  1017. {
  1018. pObjInterface->GetBaseInterfaceCG()->OutputThunkTableEntries( pCCB, FALSE );
  1019. }
  1020. }
  1021. GetMembers( Iterator );
  1022. while ( ITERATOR_GETNEXT( Iterator, pProc ) )
  1023. {
  1024. if ( (Side == CGSIDE_CLIENT) &&
  1025. (pProc->GetCGID() != ID_CG_CALLBACK_PROC) )
  1026. continue;
  1027. if ( (Side == CGSIDE_SERVER) &&
  1028. (pProc->GetCGID() == ID_CG_CALLBACK_PROC) )
  1029. continue;
  1030. if ( pProc->NeedsServerThunk( pCCB, Side ) && !pProc->IsDelegated() )
  1031. {
  1032. pStream->Write( pIntfName );
  1033. pStream->Write( '_' );
  1034. pStream->Write( pProc->GetType()->GetSymName() );
  1035. // if( IsObject() )
  1036. pStream->Write( "_Thunk" );
  1037. }
  1038. else
  1039. pStream->Write( '0' );
  1040. if ( pProc->GetSibling() || !fLast )
  1041. pStream->Write( ',' );
  1042. pStream->NewLine();
  1043. }
  1044. }
  1045. void
  1046. CG_INTERFACE::OutputInterfaceIdComment( CCB * pCCB )
  1047. {
  1048. char TmpBuf[40];
  1049. unsigned short Major, Minor;
  1050. ISTREAM * pStream = pCCB->GetStream();
  1051. char * pIfKind = IsObject() ? "Object"
  1052. : HasPicklingStuffOnly() ? "Pickling"
  1053. : "Standard";
  1054. pStream->NewLine(2);
  1055. sprintf( TmpBuf, "/* %s interface: ", pIfKind );
  1056. pStream->Write( TmpBuf );
  1057. pStream->Write( GetInterfaceName() );
  1058. ((node_interface *) GetType())->GetVersionDetails( &Major, &Minor );
  1059. sprintf( TmpBuf, ", ver. %d.%d,\n GUID=", Major, Minor );
  1060. pStream->Write( TmpBuf );
  1061. Out_Guid( pCCB, GetGuidStrs() );
  1062. pStream->Write( " */" );
  1063. pStream->NewLine();
  1064. }