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.

2857 lines
74 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. cgobject.cxx
  5. Abstract:
  6. code generation for object interfaces.
  7. CG_OBJECT_INTERFACE
  8. CG_OBJECT_PROC
  9. Notes:
  10. History:
  11. ----------------------------------------------------------------------------*/
  12. /****************************************************************************
  13. * include files
  14. ***************************************************************************/
  15. #include "becls.hxx"
  16. #pragma hdrstop
  17. #include "buffer.hxx"
  18. extern "C"
  19. {
  20. #include <fcntl.h>
  21. #include <sys\types.h>
  22. #include <sys\stat.h>
  23. #include <io.h>
  24. #include <errno.h>
  25. }
  26. #include "szbuffer.h"
  27. // Needed to time out a synchronize write to dlldata.c
  28. void MidlSleep( int time_in_sec);
  29. // number of times (1 sec delay per attempt) before quitting.
  30. #define DLLDATA_OPEN_ATTEMPT_MAX 25
  31. /****************************************************************************
  32. * externs
  33. ***************************************************************************/
  34. extern CMD_ARG * pCommand;
  35. char* GetRpcProxyHVersionGuard( char* );
  36. /****************************************************************************
  37. * global flags
  38. ***************************************************************************/
  39. BOOL fDllDataDelegating = FALSE;
  40. CG_OBJECT_INTERFACE::CG_OBJECT_INTERFACE(
  41. node_interface *pI,
  42. GUID_STRS GStrs,
  43. BOOL fCallbacks,
  44. BOOL fMopInfo,
  45. CG_OBJECT_INTERFACE * pBaseIF
  46. ) : CG_INTERFACE(pI, GStrs, fCallbacks, fMopInfo, 0, pBaseIF)
  47. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  48. Routine Description:
  49. The constructor for the code generation file node.
  50. Arguments:
  51. pI - A pointer to the interface node in type graph.
  52. GStrs - guid strings
  53. fCallbacks - Does the interface have any callbacks ?
  54. fMopInfo - Does the interface have any mops ?
  55. Return Value:
  56. Notes:
  57. ----------------------------------------------------------------------------*/
  58. {
  59. SetBaseInterfaceCG( pBaseIF );
  60. pThisDeclarator = MakePtrIDNodeFromTypeName( "This",
  61. GetType()->GetSymName() );
  62. // all object interfaces use the same stub desc name
  63. pStubDescName = "Object" STUB_DESC_STRUCT_VAR_NAME;
  64. fLocal = GetType()->FInSummary( ATTR_LOCAL );
  65. fForcedDelegation = FALSE;
  66. fVisited = FALSE;
  67. }
  68. //--------------------------------------------------------------------
  69. //
  70. // CountMemberFunctions
  71. //
  72. // Notes: This function counts the member functions in an interface,
  73. // including inherited member functions.
  74. //
  75. //
  76. //
  77. //--------------------------------------------------------------------
  78. unsigned long
  79. CG_OBJECT_INTERFACE::CountMemberFunctions()
  80. {
  81. return ((node_interface*)GetType())->GetProcCount();
  82. }
  83. BOOL
  84. CG_OBJECT_INTERFACE::IsLastObjectInterface()
  85. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  86. Routine Description:
  87. Return TRUE if there are no more object interfaces after us.
  88. Arguments:
  89. none.
  90. Return Value:
  91. TRUE if there are no more non-local object interfaces.
  92. Notes:
  93. ----------------------------------------------------------------------------*/
  94. {
  95. CG_INTERFACE * pNext = (CG_INTERFACE *) GetSibling();
  96. while ( pNext )
  97. {
  98. if ( pNext->IsObject() && !( (CG_OBJECT_INTERFACE*)pNext)->IsLocal() )
  99. return FALSE;
  100. pNext = (CG_INTERFACE *) pNext->GetSibling();
  101. }
  102. return TRUE;
  103. }
  104. CG_STATUS
  105. CG_OBJECT_INTERFACE::GenProxy(
  106. CCB * pCCB )
  107. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  108. Routine Description:
  109. Generate code for the file node.
  110. Arguments:
  111. pCCB - a pointer to the code generation control block.
  112. Return Value:
  113. CG_OK if all is well, error otherwise.
  114. Notes:
  115. ----------------------------------------------------------------------------*/
  116. {
  117. CG_ITERATOR I;
  118. CG_PROC * pCG;
  119. ISTREAM * pStream = pCCB->GetStream();
  120. //Initialize the CCB for this interface.
  121. InitializeCCB(pCCB);
  122. // do nothing for local interfaces and types-only base interfaces
  123. if( IsLocal() || !( GetMembers( I ) || GetBaseInterfaceCG() ) )
  124. {
  125. return CG_OK;
  126. }
  127. Out_StubDescriptorExtern( pCCB );
  128. // Check for use of [enable_allocate]
  129. if ( GetUsesRpcSS() )
  130. pCCB->SetMallocAndFreeStructExternEmitted();
  131. Out_InterpreterServerInfoExtern( pCCB );
  132. pStream->NewLine();
  133. pStream->WriteFormat(
  134. "extern const MIDL_STUBLESS_PROXY_INFO %s_ProxyInfo;",
  135. GetSymName() );
  136. pStream->NewLine();
  137. //
  138. // for all procedure in this interface, generate code.
  139. //
  140. while( ITERATOR_GETNEXT( I, pCG ) )
  141. {
  142. pCCB->SetCodeGenSide( CGSIDE_CLIENT );
  143. pCG->GenClientStub( pCCB );
  144. pCCB->SetCodeGenSide( CGSIDE_SERVER );
  145. pCG->GenServerStub( pCCB );
  146. }
  147. return CG_OK;
  148. }
  149. CG_STATUS
  150. CG_OBJECT_INTERFACE::OutputProxy(
  151. CCB * pCCB )
  152. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  153. Routine Description:
  154. Generate code for the file node.
  155. Arguments:
  156. pCCB - a pointer to the code generation control block.
  157. Return Value:
  158. CG_OK if all is well, error otherwise.
  159. Notes:
  160. ----------------------------------------------------------------------------*/
  161. {
  162. CG_ITERATOR I;
  163. ISTREAM * pStream = pCCB->GetStream();
  164. //Initialize the CCB for this interface.
  165. InitializeCCB(pCCB);
  166. // do nothing for local interfaces and types-only base interfaces
  167. if( IsLocal() || !( GetMembers( I ) || GetBaseInterfaceCG() ) )
  168. {
  169. return CG_OK;
  170. }
  171. pStream->NewLine();
  172. pStream->Write("#pragma code_seg(\".orpc\")");
  173. Out_ProcOffsetTable( pCCB );
  174. if ( pCommand->NeedsNDR64Run() )
  175. Out_ProxyInfo( pCCB, FALSE );
  176. else
  177. GenProxyInfo( pCCB, FALSE );
  178. Out_InterpreterServerInfo( pCCB, CGSIDE_SERVER );
  179. return CG_OK;
  180. }
  181. unsigned long
  182. CG_OBJECT_INTERFACE::PrintProxyMemberFunctions(
  183. ISTREAM * pStream,
  184. BOOL fForcesDelegation )
  185. /*++
  186. Routine Description:
  187. This function prints out the member functions of an interface proxy.
  188. The function calls itself recursively to print out inherited member functions.
  189. Arguments:
  190. pStream - Specifies the destination stream for output.
  191. --*/
  192. {
  193. CG_OBJECT_PROC * pProc;
  194. CG_ITERATOR I;
  195. CG_OBJECT_INTERFACE * pBaseInterface = (CG_OBJECT_INTERFACE *)GetBaseInterfaceCG();
  196. if(pBaseInterface)
  197. pBaseInterface->PrintProxyMemberFunctions(pStream, fForcesDelegation );
  198. else // special stuff for IUnknown
  199. {
  200. #ifdef OK_TO_HAVE_0_IN_VTABLES
  201. pStream->NewLine();
  202. pStream->Write( "0 /* QueryInterface */ ," );
  203. pStream->NewLine();
  204. pStream->Write( "0 /* AddRef */ ," );
  205. pStream->NewLine();
  206. pStream->Write( "0 /* Release */" );
  207. #else
  208. pStream->NewLine();
  209. pStream->Write( "IUnknown_QueryInterface_Proxy," );
  210. pStream->NewLine();
  211. pStream->Write( "IUnknown_AddRef_Proxy," );
  212. pStream->NewLine();
  213. pStream->Write( "IUnknown_Release_Proxy" );
  214. #endif
  215. return 0;
  216. }
  217. GetMembers( I );
  218. while( ITERATOR_GETNEXT( I, pProc ) )
  219. {
  220. pStream->Write( " ," );
  221. pStream->NewLine();
  222. pProc->OutProxyRoutineName( pStream, fForcesDelegation );
  223. }
  224. return 0;
  225. }
  226. /*
  227. This routine is used to see if we need to force proxies with a thunk for static
  228. linking. We need a thunk if the proc number is too big for the engine to handle.
  229. Method limits apply only to stubless proxies. /Oicf and /Oic but not /Oi or /Os.
  230. The engine was capable of supporting different number of methods depending on
  231. the size of the stubless client routine vtable. This is the size of the stubless
  232. client vtbl over releases:
  233. < 32 Windows NT 3.51-
  234. 32 - 110 Windows NT 4.0
  235. 110 - 512 Windows NT 4.0 SP3
  236. 128 Windows NT 5 beta2
  237. infinity Windows 2000
  238. In NT5 beta2 we put a new support for stubless client vtbl that removed any
  239. limitations. At the same time we decreased the size of the default vtbl to 128.
  240. However, we had a bug, and the support for unlimited methods didn't work, so
  241. effectively we, we are doing the same thing again with NT5 beta3 (2000 beta 3).
  242. */
  243. BOOL CG_OBJECT_PROC::IsStublessProxy()
  244. {
  245. BOOL res = TRUE;
  246. if ( ! GetCallAsName() &&
  247. ( GetOptimizationFlags() & OPTIMIZE_STUBLESS_CLIENT ) &&
  248. ( GetOptimizationFlags() & OPTIMIZE_INTERPRETER ) )
  249. {
  250. if (pCommand->GetNdrVersionControl().HasNdr50Feature())
  251. {
  252. // Temporary till we deploy a fix in NT5 beta3.
  253. // With beta3 fix, this branch should simply say
  254. // res = TRUE;
  255. res = GetProcNum() < 128;
  256. }
  257. else
  258. {
  259. unsigned int lMaxProcNumAllowed;
  260. // NT4 engine had the NDR version 2.0
  261. if (pCommand->GetNdrVersionControl().HasNdr20Feature())
  262. lMaxProcNumAllowed = 110;
  263. else
  264. lMaxProcNumAllowed = 32; // NT3.51
  265. res = GetProcNum() < lMaxProcNumAllowed;
  266. }
  267. }
  268. else
  269. res = FALSE;
  270. return res;
  271. }
  272. void
  273. CG_OBJECT_PROC::OutProxyRoutineName(
  274. ISTREAM * pStream,
  275. BOOL fForcesDelegation )
  276. {
  277. char * pszProcName;
  278. BOOL fIsStublessProxy;
  279. // In NT5, we can fill in -1 for all the non-delegation methods, and generate
  280. // a stubless proxy. For older platforms, due to limits of the support for
  281. // stubless proxies we have to generate actual name for static linking.
  282. // The name corrsponds to a thunk, or a mini-stub, calling into interpreter.
  283. // See IsStublessProxy() for vtbl limits.
  284. // Later during proxy creation in ndr engine, we'll fill in ObjectStublessProxy
  285. // vtbl with entries that we take from the default table or that we generate on fly.
  286. // In fact, for 2000 final, we don't have any limits and we could do it for all
  287. // interfaces but we do have a backward compatibility problem due to the above
  288. // limitations on old platforms.
  289. // Also, midl has been issuing a warning that NT4SP3 doesn't support more than 512
  290. // methods etc., although that's applicable to late-binding only. We are removing
  291. // this warning.
  292. fIsStublessProxy = IsStublessProxy();
  293. //
  294. // Delegated and interpreted proxies have their Vtables filled in
  295. // at proxy creation time (see ndr20\factory.c).
  296. //
  297. if ( IsDelegated () )
  298. pStream->Write( "0 /* " );
  299. if ( fIsStublessProxy )
  300. {
  301. if ( fForcesDelegation && ! IsDelegated() )
  302. pStream->Write( "0 /* forced delegation " );
  303. else
  304. pStream->Write( "(void *) (INT_PTR) -1 /* " );
  305. }
  306. if ( GetCallAsName() )
  307. pszProcName = GetCallAsName();
  308. else
  309. pszProcName = GetSymName();
  310. if ( fIsStublessProxy )
  311. {
  312. // Just a nitpicky different comment for the stubless guys.
  313. pStream->Write( GetInterfaceName() );
  314. pStream->Write( "::" );
  315. pStream->Write( pszProcName );
  316. }
  317. else
  318. {
  319. pStream->Write( GetInterfaceName() );
  320. pStream->Write( '_' );
  321. pStream->Write( pszProcName );
  322. pStream->Write( "_Proxy" );
  323. }
  324. if ( IsDelegated () || fIsStublessProxy )
  325. pStream->Write( " */" );
  326. }
  327. CG_STATUS
  328. CG_INTERFACE::GenProxyInfo( CCB *pCCB,
  329. BOOL IsForCallback )
  330. {
  331. ISTREAM * pStream = pCCB->GetStream();
  332. pStream->Write( "static const MIDL_STUBLESS_PROXY_INFO " );
  333. pStream->Write( GetSymName() );
  334. pStream->Write( "_ProxyInfo =" );
  335. pStream->IndentInc();
  336. pStream->NewLine();
  337. pStream->Write( "{" );
  338. pStream->NewLine();
  339. // Stub descriptor.
  340. pStream->Write( '&' );
  341. pStream->Write( GetStubDescName() );
  342. pStream->Write( ',' );
  343. pStream->NewLine();
  344. // Proc format string.
  345. if (pCommand->GetDefaultSyntax() == SYNTAX_NDR64 )
  346. pStream->Write( "(unsigned char *) &NDR64_MIDL_FORMATINFO" );
  347. else
  348. pStream->Write( PROC_FORMAT_STRING_STRING_FIELD );
  349. pStream->Write( ',' );
  350. pStream->NewLine();
  351. // Proc format string offset table.
  352. if (pCommand->GetDefaultSyntax() == SYNTAX_NDR64 )
  353. pStream->Write( "(unsigned short *) " );
  354. if ( IsObject() )
  355. pStream->Write( '&' );
  356. if ( IsForCallback )
  357. pStream->Write( MIDL_CALLBACK_VAR_NAME );
  358. pStream->Write( GetSymName() );
  359. if (pCommand->GetDefaultSyntax() == SYNTAX_NDR64 )
  360. pStream->Write( "_Ndr64ProcTable" );
  361. else
  362. pStream->Write( FORMAT_STRING_OFFSET_TABLE_NAME );
  363. if ( IsObject() )
  364. pStream->Write( "[-3]," );
  365. else
  366. pStream->Write( ',' );
  367. pStream->NewLine();
  368. if ( !pCommand->NeedsNDR64Run() )
  369. {
  370. pStream->Write( "0," );
  371. pStream->NewLine();
  372. pStream->Write( "0,");
  373. pStream->NewLine();
  374. pStream->Write( "0");
  375. }
  376. else
  377. {
  378. // BUGBUG: what if we let ndr64 as default?
  379. pStream->Write( '&' );
  380. if ( pCommand->GetDefaultSyntax() == SYNTAX_NDR64 )
  381. pStream->Write( NDR64_TRANSFER_SYNTAX_VAR_NAME );
  382. else
  383. pStream->Write( NDR_TRANSFER_SYNTAX_VAR_NAME );
  384. pStream->Write( ',' );
  385. pStream->NewLine();
  386. // SyntaxInfo is only generated when NDR64 is required.
  387. // MIDL_SYNTAX_INFO will be generated for each transfer syntax supported.
  388. if ( pCommand->NeedsNDRRun() )
  389. pStream->Write( "2," );
  390. else
  391. pStream->Write( "1," );
  392. pStream->NewLine();
  393. if ( IsForCallback )
  394. pStream->Write( MIDL_CALLBACK_VAR_NAME );
  395. pStream->Write( GetMulSyntaxInfoName() );
  396. pStream->NewLine();
  397. }
  398. pStream->NewLine();
  399. pStream->Write( "};" );
  400. pStream->IndentDec();
  401. pStream->NewLine();
  402. pStream->NewLine();
  403. return CG_OK;
  404. }
  405. CG_STATUS
  406. CG_INTERFACE::GenSyntaxInfo( CCB * pCCB,
  407. BOOL IsForCallback)
  408. {
  409. if ( !pCommand->NeedsNDR64Run() || !pCommand->IsFinalProtocolRun() )
  410. return CG_OK;
  411. long nCount = pCommand->NeedsNDRRun() ? 2 : 1 ;
  412. ISTREAM *pStream = pCCB->GetStream();
  413. pStream->WriteOnNewLine("static " MIDL_SYNTAX_INFO_TYPE_NAME " ");
  414. if ( IsForCallback )
  415. pStream->Write( MIDL_CALLBACK_VAR_NAME );
  416. pStream->Write( GetSymName() );
  417. pStream->Write( MIDL_SYNTAX_INFO_VAR_NAME " [ ");
  418. pStream->WriteNumber(" %d ] = ", nCount );
  419. pStream->IndentInc();
  420. pStream->WriteOnNewLine( "{" );
  421. pStream->NewLine();
  422. if ( pCommand->NeedsNDRRun() )
  423. Out_OneSyntaxInfo( pCCB, IsForCallback, SYNTAX_DCE );
  424. if ( nCount > 1 )
  425. pStream->Write( "," );
  426. if ( pCommand->NeedsNDR64Run() )
  427. Out_OneSyntaxInfo( pCCB, IsForCallback, SYNTAX_NDR64 );
  428. pStream->Write( "};" );
  429. pStream->IndentDec();
  430. pStream->NewLine(2);
  431. return CG_OK;
  432. }
  433. CG_STATUS
  434. CG_OBJECT_INTERFACE::GenInterfaceProxy(
  435. CCB *pCCB,
  436. unsigned long )
  437. {
  438. if ( !pCommand->IsFinalProtocolRun() )
  439. return CG_OK;
  440. char * pszInterfaceName = GetSymName();
  441. ISTREAM * pStream = pCCB->GetStream();
  442. BOOL fDelegates = (NULL != GetDelegatedInterface());
  443. //
  444. // Output the interface proxy.
  445. //
  446. //
  447. // If we have to delegate or if we have interpreted methods, then we
  448. // can not emit the const because in both of these instances the proxy
  449. // Vtable must be modified during proxy creation time (see
  450. // ndr20\factory.c).
  451. //
  452. if ( ! fDelegates && ! HasStublessProxies() )
  453. pStream->Write("const ");
  454. char TmpBuff[10];
  455. long Count = CountMemberFunctions();
  456. // Use a struct macro for Ansi [] compatibility.
  457. pStream->Write("CINTERFACE_PROXY_VTABLE(" );
  458. sprintf( TmpBuff, "%ld%", Count );
  459. pStream->Write( TmpBuff );
  460. pStream->Write(") _");
  461. pStream->Write(pszInterfaceName);
  462. pStream->Write("ProxyVtbl = ");
  463. pStream->NewLine();
  464. pStream->Write("{");
  465. pStream->IndentInc();
  466. //
  467. // Emit ProxyInfo field for stubless proxies
  468. // (NT 3.5 incompatible).
  469. //
  470. BOOL fForcesDelegation = HasStublessProxies() &&
  471. ! HasItsOwnStublessProxies() &&
  472. CountMemberFunctions() > 3;
  473. if ( fForcesDelegation )
  474. SetHasForcedDelegation();
  475. if ( HasStublessProxies() )
  476. {
  477. // The ProxyInfo.
  478. pStream->NewLine();
  479. if ( HasItsOwnStublessProxies() )
  480. {
  481. pStream->Write( '&' );
  482. pStream->Write( pszInterfaceName );
  483. pStream->Write( "_ProxyInfo" );
  484. }
  485. else
  486. {
  487. // In fact, we delegate for empty interfaces or interfaces
  488. // with os methods only.
  489. pStream->Write( '0' );
  490. }
  491. pStream->Write( ',' );
  492. }
  493. else if ( pCommand->GetNdrVersionControl().HasStublessProxies() )
  494. {
  495. // Add a dummy 0 for proxy info pointer for a proxy that is
  496. // oi or os in the file that has stubles proxies
  497. pStream->NewLine();
  498. pStream->Write( "0, /* dummy for table ver 2 */" );
  499. }
  500. //Write the IID
  501. pStream->NewLine();
  502. pStream->Write( "&IID_" );
  503. pStream->Write( pszInterfaceName );
  504. pStream->Write( ',' );
  505. //initialize the vtable
  506. PrintProxyMemberFunctions( pStream, fForcesDelegation );
  507. pStream->IndentDec();
  508. pStream->NewLine();
  509. pStream->Write("};");
  510. pStream->NewLine();
  511. return CG_OK;
  512. }
  513. unsigned long
  514. CG_OBJECT_INTERFACE::PrintStubMemberFunctions(
  515. ISTREAM * pStream)
  516. /*++
  517. Routine Description:
  518. This function prints out the member functions of an interface stub dispatch table
  519. The function calls itself recursively to print out inherited member functions.
  520. Arguments:
  521. pInterface - Specifies the interface node.
  522. pStream - Specifies the destination stream for output.
  523. --*/
  524. {
  525. unsigned long count = 0;
  526. CG_OBJECT_PROC * pProc;
  527. CG_ITERATOR I;
  528. CG_OBJECT_INTERFACE * pBaseInterface = (CG_OBJECT_INTERFACE *)GetBaseInterfaceCG();
  529. if ( IsIUnknown() )
  530. return 0;
  531. if ( pBaseInterface )
  532. count = pBaseInterface->PrintStubMemberFunctions(pStream);
  533. GetMembers( I );
  534. for( ; ITERATOR_GETNEXT( I, pProc ); count++ )
  535. {
  536. if ( ((node_proc*) (pProc->GetType()))->IsFinishProc() )
  537. {
  538. continue;
  539. }
  540. if( count != 0 )
  541. pStream->Write(',');
  542. pStream->NewLine();
  543. pProc->OutStubRoutineName( pStream );
  544. }
  545. return count;
  546. }
  547. void
  548. CG_OBJECT_PROC::OutStubRoutineName(
  549. ISTREAM * pStream )
  550. {
  551. node_proc* pProc = (node_proc*) GetType();
  552. if ( IsDelegated() )
  553. {
  554. pStream->Write( "STUB_FORWARDING_FUNCTION" );
  555. return;
  556. }
  557. // local procs don't need proxys and stubs
  558. if ( IsLocal() )
  559. {
  560. pStream->Write( '0' );
  561. return;
  562. }
  563. if ( pProc->IsBeginProc() )
  564. {
  565. pStream->Write( S_NDR_CALL_RTN_NAME_DCOM_ASYNC );
  566. return;
  567. }
  568. #ifndef TEMPORARY_OI_SERVER_STUBS
  569. if ( (GetOptimizationFlags() &
  570. (OPTIMIZE_INTERPRETER_V2 | OPTIMIZE_INTERPRETER)) ==
  571. (OPTIMIZE_INTERPRETER_V2 | OPTIMIZE_INTERPRETER) )
  572. {
  573. if ( HasAsyncHandle() )
  574. pStream->Write( S_OBJECT_NDR_CALL_RTN_NAME_ASYNC );
  575. else
  576. {
  577. if ( pCommand->NeedsNDR64Run() )
  578. pStream->Write( S_OBJECT_NDR64_CALL_RTN_NAME );
  579. else
  580. pStream->Write( S_OBJECT_NDR_CALL_RTN_NAME_V2 );
  581. }
  582. return;
  583. }
  584. if ( GetOptimizationFlags() & OPTIMIZE_INTERPRETER )
  585. {
  586. pStream->Write( S_OBJECT_NDR_CALL_RTN_NAME );
  587. return;
  588. }
  589. #endif // TEMPORARY_OI_SERVER_STUBS
  590. pStream->Write( GetInterfaceName() );
  591. pStream->Write( '_' );
  592. pStream->Write( GetSymName() );
  593. pStream->Write( "_Stub" );
  594. }
  595. CG_STATUS
  596. CG_OBJECT_INTERFACE::GenInterfaceStub(
  597. CCB *pCCB,
  598. unsigned long )
  599. {
  600. if ( !pCommand->IsFinalProtocolRun() )
  601. return CG_OK;
  602. node_interface * pInterface = (node_interface *) GetType();
  603. char * pszInterfaceName = pInterface->GetSymName();
  604. ISTREAM * pStream = pCCB->GetStream();
  605. unsigned long count;
  606. #ifdef TEMPORARY_OI_SERVER_STUBS
  607. BOOL fPureInterpreted = FALSE;
  608. #else // TEMPORARY_OI_SERVER_STUBS
  609. BOOL fPureInterpreted = HasOnlyInterpretedMethods();
  610. #endif // TEMPORARY_OI_SERVER_STUBS
  611. BOOL fDelegates = (NULL != GetDelegatedInterface()) || fForcedDelegation;
  612. // if any of our base interfaces are delegated, we can't be pure interpreted
  613. if ( fDelegates )
  614. fPureInterpreted = FALSE;
  615. // pure interpreted uses no dispatch table, special invoke function instead
  616. if ( !fPureInterpreted )
  617. {
  618. // Generate the dispatch table
  619. pStream->NewLine(2);
  620. pStream->Write( "static const PRPC_STUB_FUNCTION " );
  621. pStream->Write( pszInterfaceName );
  622. pStream->Write( "_table[] =" );
  623. pStream->NewLine();
  624. pStream->Write('{');
  625. pStream->IndentInc();
  626. // Print out the names of all the procedures.
  627. count = PrintStubMemberFunctions(pStream);
  628. if ( count == 0 )
  629. {
  630. // This is possible for an empty interface inheriting
  631. // directly from IUnknown. As we don't print first three
  632. // entries, the table would be empty.
  633. // We add a zero to simplify references.
  634. pStream->NewLine();
  635. pStream->Write( "0 /* a dummy for an empty interface */" );
  636. }
  637. pStream->IndentDec();
  638. pStream->NewLine();
  639. pStream->Write( "};" );
  640. pStream->NewLine();
  641. }
  642. count = CountMemberFunctions();
  643. //initialize an interface stub
  644. pStream->NewLine();
  645. if ( !fDelegates && !( ( node_interface* ) GetType() )->IsAsyncClone() )
  646. pStream->Write( "const " );
  647. pStream->Write( "CInterfaceStubVtbl _" );
  648. pStream->Write( pszInterfaceName );
  649. pStream->Write( "StubVtbl =" );
  650. pStream->NewLine();
  651. pStream->Write('{');
  652. pStream->IndentInc();
  653. //Write the IID
  654. pStream->NewLine();
  655. pStream->Write( "&IID_" );
  656. pStream->Write( pszInterfaceName );
  657. pStream->Write( "," );
  658. //
  659. // Interpreter server info fits in the middle here.
  660. //
  661. pStream->NewLine();
  662. pStream->Write( '&' );
  663. pStream->Write( pszInterfaceName );
  664. pStream->Write( SERVER_INFO_VAR_NAME );
  665. pStream->Write( ',' );
  666. //Write the count
  667. pStream->NewLine();
  668. pStream->WriteNumber( "%d", count );
  669. pStream->Write(',');
  670. //Write the pointer to dispatch table.
  671. pStream->NewLine();
  672. if ( fPureInterpreted )
  673. pStream->Write( "0, /* pure interpreted */" );
  674. else
  675. {
  676. pStream->Write( '&' );
  677. pStream->Write( pszInterfaceName );
  678. pStream->Write( "_table[-3]," );
  679. }
  680. //initialize the vtable
  681. pStream->NewLine();
  682. if ( ( ( node_interface* ) GetType() )->IsAsyncClone() )
  683. {
  684. if ( fDelegates )
  685. pStream->Write("CStdAsyncStubBuffer_DELEGATING_METHODS");
  686. else
  687. pStream->Write("CStdAsyncStubBuffer_METHODS");
  688. }
  689. else
  690. {
  691. if ( fDelegates )
  692. pStream->Write("CStdStubBuffer_DELEGATING_METHODS");
  693. else
  694. pStream->Write("CStdStubBuffer_METHODS");
  695. }
  696. pStream->IndentDec();
  697. pStream->NewLine();
  698. pStream->Write("};");
  699. pStream->NewLine();
  700. return CG_OK;
  701. }
  702. CG_STATUS
  703. CG_INHERITED_OBJECT_INTERFACE::GenProxy(
  704. CCB * )
  705. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  706. Routine Description:
  707. Generate code for the file node.
  708. Arguments:
  709. pCCB - a pointer to the code generation control block.
  710. Return Value:
  711. CG_OK if all is well, error otherwise.
  712. Notes:
  713. ----------------------------------------------------------------------------*/
  714. {
  715. /*
  716. ITERATOR I;
  717. CG_PROC * pProc;
  718. // Initialize the CCB for this interface.
  719. InitializeCCB( pCCB );
  720. if( IsLocal() || !GetMembers( I ) )
  721. {
  722. return CG_OK;
  723. }
  724. //
  725. // Send the message to the children to emit code.
  726. //
  727. //
  728. // for all procedures in this interface, generate code.
  729. //
  730. while( ITERATOR_GETNEXT( I, pProc ) )
  731. {
  732. if ( pProc->GetOptimizationFlags() & OPTIMIZE_INTERPRETER )
  733. {
  734. pProc->GenNdrFormat( pCCB );
  735. if ( pProc->NeedsServerThunk( pCCB, CGSIDE_SERVER ) )
  736. {
  737. CG_ITERATOR Iterator;
  738. CG_PARAM * pParam;
  739. CG_RETURN * pReturn;
  740. CG_NDR * pChild;
  741. node_skl * pType;
  742. node_skl * pActualType;
  743. PNAME pName;
  744. pProc->GetMembers( Iterator );
  745. while ( ITERATOR_GETNEXT( Iterator, pParam ) )
  746. {
  747. pType = pParam->GetType();
  748. pActualType = pType->GetChild();
  749. pName = pType->GetSymName();
  750. pChild = (CG_NDR *) pParam->GetChild();
  751. if( pChild->IsArray() )
  752. pActualType = MakePtrIDNode( pName, pActualType );
  753. else
  754. pActualType = MakeIDNode( pName, pActualType );
  755. pParam->SetResource( new RESOURCE( pName, pActualType ) );
  756. }
  757. if ( ( pReturn = pProc->GetReturnType() ) != 0 )
  758. {
  759. pReturn->SetResource(
  760. new RESOURCE( RETURN_VALUE_VAR_NAME,
  761. MakeIDNode( RETURN_VALUE_VAR_NAME,
  762. pReturn->GetType() ) ) );
  763. }
  764. pProc->GenNdrThunkInterpretedServerStub( pCCB );
  765. }
  766. }
  767. }
  768. */
  769. return CG_OK;
  770. }
  771. CG_STATUS
  772. CG_INHERITED_OBJECT_INTERFACE::OutputProxy(
  773. CCB * )
  774. {
  775. return CG_OK;
  776. }
  777. STATUS_T
  778. CG_OBJECT_INTERFACE::PrintVtableEntries( CCB * pCCB )
  779. /*++
  780. Routine Description:
  781. This routine prints the vtable entries for an interface.
  782. --*/
  783. {
  784. CG_OBJECT_PROC * pC;
  785. CG_OBJECT_INTERFACE* pBaseCG = (CG_OBJECT_INTERFACE*) GetBaseInterfaceCG();
  786. if( pBaseCG )
  787. pBaseCG->PrintVtableEntries( pCCB );
  788. pC = (CG_OBJECT_PROC *) GetChild();
  789. while ( pC )
  790. {
  791. pC->PrintVtableEntry( pCCB );
  792. pC = (CG_OBJECT_PROC *) pC->GetSibling();
  793. }
  794. return STATUS_OK;
  795. }
  796. CG_STATUS
  797. CG_OBJECT_PROC::C_GenProlog(
  798. CCB * pCCB )
  799. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  800. Routine Description:
  801. Generate the procedure prolog for the stub procedure.
  802. Arguments:
  803. pCCB - A pointer to the code generation controller block.
  804. Return Value:
  805. CG_OK if all is well
  806. error Otherwise
  807. Notes:
  808. Increment the stream indentation at the end of the prolog.
  809. Although we register params as param resources, we dont generate the
  810. procedure signature using the PrintType/Decl facility.
  811. We have added an explicit "this" pointer as the first parameter.
  812. ----------------------------------------------------------------------------*/
  813. {
  814. ITERATOR I;
  815. ITERATOR T;
  816. ISTREAM * pStream = pCCB->GetStream();
  817. BufferManager Buffer(10);
  818. // Output the bare procedure declaration
  819. pStream->NewLine();
  820. Out_ProxyFunctionPrototype(pCCB, 0);
  821. pStream->IndentDec();
  822. //
  823. // Write the opening brace on a new line.
  824. //
  825. pStream->WriteOnNewLine( "{" );
  826. pStream->NewLine();
  827. // Generate declarations for pre-allocated and analyser-determined locals.
  828. pCCB->GetListOfLocalResources( I );
  829. Out_ClientLocalVariables( pCCB, I );
  830. pCCB->GetListOfTransientResources( T );
  831. Out_ClientLocalVariables( pCCB, T );
  832. // If the rpc ss package is to be enabled, do so.
  833. // It would need to be enabled explicitely on the client side when
  834. // in non-osf mode, with the attribute on the operation AND
  835. // - the routine is a callback,
  836. // - the routine is not a callback and the interface doesn't
  837. // have the attribute (if it does, we optimized via stub descr.)
  838. if( pCCB->GetMode() && MustInvokeRpcSSAllocate()
  839. &&
  840. ( GetCGID() == ID_CG_CALLBACK_PROC ||
  841. GetCGID() != ID_CG_CALLBACK_PROC &&
  842. !pCCB->GetInterfaceCG()->IsAllRpcSS())
  843. )
  844. {
  845. Out_RpcSSSetClientToOsf( pCCB );
  846. }
  847. // Increment the indentation of the output stream. Reset at epilog time.
  848. Out_IndentInc( pCCB );
  849. //
  850. // Initialize all [out] unique and interface pointers to 0.
  851. //
  852. CG_ITERATOR Iterator;
  853. CG_PARAM * pParam;
  854. CG_NDR * pNdr;
  855. CG_NDR * pTopPtr = 0;
  856. long Derefs;
  857. expr_node * pSizeof;
  858. GetMembers( Iterator );
  859. for ( ; ITERATOR_GETNEXT(Iterator, pParam); )
  860. {
  861. if ( pParam->IsParamIn() )
  862. continue;
  863. pNdr = (CG_NDR *) pParam->GetChild();
  864. if ( ! pNdr->IsPointer() && ! pNdr->IsArray() )
  865. continue;
  866. Derefs = 0;
  867. //
  868. // Skip the ref pointer(s) to the pointee.
  869. //
  870. for ( ;
  871. pNdr->IsPointer() &&
  872. ((CG_POINTER *)pNdr)->GetPtrType() == PTR_REF &&
  873. !pNdr->IsInterfacePointer();
  874. Derefs++, pNdr = (CG_NDR *) pNdr->GetChild() )
  875. {
  876. if( Derefs == 0 )
  877. pTopPtr = pNdr;
  878. }
  879. // No ref, no service.
  880. if ( ! Derefs && ! pNdr->IsArray() )
  881. continue;
  882. // Ready to zero out.
  883. // Note, however, that in case where the ref checks are required,
  884. // we need to be careful and skip zeroing if ref pointers are null.
  885. // This is because we cannot raise exception immediately
  886. // as then some of the variables may not be zeroed out yet.
  887. //
  888. // Memset a struct, union or an array in case there are
  889. // embedded unique, full or interface pointers.
  890. // Same for user types of transmit_as, represent_as, user_marshal.
  891. //
  892. if ( pNdr->GetCGID() == ID_CG_TRANSMIT_AS )
  893. {
  894. pSizeof = new expr_sizeof( ((CG_TRANSMIT_AS*)pNdr)->GetPresentedType() );
  895. }
  896. else if ( pNdr->GetCGID() == ID_CG_USER_MARSHAL &&
  897. ((CG_USER_MARSHAL*)pNdr)->IsFromXmit() )
  898. {
  899. pSizeof = new expr_sizeof( ((CG_USER_MARSHAL*)pNdr)->GetRepAsType() );
  900. }
  901. else
  902. pSizeof = new expr_sizeof( pNdr->GetType() );
  903. if ( pNdr->IsStruct() || pNdr->IsUnion() || pNdr->IsArray() ||
  904. pNdr->IsXmitRepOrUserMarshal() || pNdr->IsInterfacePointer() )
  905. {
  906. if ( pCCB->MustCheckRef() )
  907. {
  908. Out_If( pCCB,
  909. new expr_variable( pParam->GetType()->GetSymName() ));
  910. }
  911. expr_proc_call * pCall;
  912. pStream->NewLine();
  913. pCall = new expr_proc_call( MIDL_MEMSET_RTN_NAME );
  914. pCall->SetParam(
  915. new expr_param(
  916. new expr_variable( pParam->GetType()->GetSymName() ) ) );
  917. pCall->SetParam(
  918. new expr_param(
  919. new expr_variable( "0" ) ) );
  920. if ( pNdr->IsInterfacePointer() )
  921. {
  922. pSizeof = new expr_sizeof( pParam->GetChild()->GetType() );
  923. }
  924. if( pTopPtr && ((CG_POINTER *)pTopPtr)->IsQualifiedPointer() &&
  925. !(pTopPtr->GetCGID() == ID_CG_STRING_PTR ) )
  926. {
  927. _expr_node * pFinalExpr;
  928. CGPHASE Ph = pCCB->GetCodeGenPhase();
  929. pCCB->SetCodeGenPhase( CGPHASE_MARSHALL );
  930. pFinalExpr = ((CG_POINTER *)pTopPtr)->FinalSizeExpression( pCCB );
  931. pSizeof = new expr_op_binary( OP_STAR, pFinalExpr, pSizeof );
  932. pCCB->SetCodeGenPhase( Ph );
  933. }
  934. pCall->SetParam(
  935. new expr_param( pSizeof ) );
  936. pCall->PrintCall( pStream, 0, 0 );
  937. if ( pCCB->MustCheckRef() )
  938. Out_Endif( pCCB );
  939. continue;
  940. }
  941. //
  942. // Are we at a non ref pointer now?
  943. //
  944. if ( ( pNdr->IsPointer() &&
  945. (((CG_POINTER *)pNdr)->GetPtrType() != PTR_REF) ) ||
  946. pNdr->IsInterfacePointer() )
  947. {
  948. if ( pCCB->MustCheckRef() )
  949. {
  950. Out_If( pCCB,
  951. new expr_variable( pParam->GetType()->GetSymName() ));
  952. }
  953. pStream->NewLine();
  954. for ( ; Derefs--; )
  955. pStream->Write( '*' );
  956. pStream->Write( pParam->GetResource()->GetResourceName() );
  957. pStream->Write( " = 0;" );
  958. if ( pCCB->MustCheckRef() )
  959. Out_Endif( pCCB );
  960. }
  961. }
  962. return CG_OK;
  963. }
  964. CG_STATUS
  965. CG_OBJECT_PROC::C_GenBind(
  966. CCB * pCCB )
  967. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  968. Routine Description:
  969. Generate code to bind to server.
  970. Arguments:
  971. pCCB - A pointer to the code generation controller block.
  972. Return Value:
  973. CG_OK if all is well
  974. error Otherwise.
  975. Notes:
  976. ----------------------------------------------------------------------------*/
  977. {
  978. ISTREAM * pStream = pCCB->GetStream();
  979. ITERATOR BindingParamList;
  980. expr_node * pExpr;
  981. expr_proc_call * pProcCall;
  982. //
  983. // collect standard arguments to the init procedure.
  984. //
  985. // The implicit "this" pointer.
  986. pExpr = new RESOURCE( "This",
  987. (node_skl *)0 );
  988. pExpr = MakeExpressionOfCastToTypeName( "void *",
  989. pExpr );
  990. ITERATOR_INSERT( BindingParamList, pExpr );
  991. // The rpc message variable.
  992. pExpr = pCCB->GetStandardResource( ST_RES_RPC_MESSAGE_VARIABLE );
  993. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  994. pExpr = MakeExpressionOfCastToTypeName( PRPC_MESSAGE_TYPE_NAME, pExpr );
  995. ITERATOR_INSERT(
  996. BindingParamList,
  997. pExpr
  998. );
  999. // The stub message variable.
  1000. pExpr = pCCB->GetStandardResource( ST_RES_STUB_MESSAGE_VARIABLE);
  1001. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  1002. pExpr = MakeExpressionOfCastToTypeName( PSTUB_MESSAGE_TYPE_NAME, pExpr );
  1003. ITERATOR_INSERT(
  1004. BindingParamList,
  1005. pExpr
  1006. );
  1007. // The stub descriptor structure variable. This is not allocated as
  1008. // a resource explicitly.
  1009. pExpr = new RESOURCE( pCCB->GetInterfaceCG()->GetStubDescName(),
  1010. (node_skl *)0 );
  1011. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  1012. pExpr = MakeExpressionOfCastToTypeName( PSTUB_DESC_STRUCT_TYPE_NAME,
  1013. pExpr );
  1014. ITERATOR_INSERT( BindingParamList, pExpr );
  1015. //
  1016. // Proc num.
  1017. //
  1018. ITERATOR_INSERT( BindingParamList,
  1019. new expr_constant( (long) GetProcNum() ) );
  1020. //Build the procedure call expression.
  1021. pProcCall = MakeProcCallOutOfParamExprList("NdrProxyInitialize", 0, BindingParamList);
  1022. pStream->NewLine();
  1023. pProcCall->PrintCall( pCCB->GetStream(), 0, 0 );
  1024. pStream->NewLine();
  1025. Out_SetOperationBits(pCCB, GetOperationBits());
  1026. pStream->NewLine();
  1027. return CG_OK;
  1028. }
  1029. CG_STATUS
  1030. CG_OBJECT_PROC::GenGetBuffer(
  1031. CCB * pCCB )
  1032. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1033. Routine Description:
  1034. Get the message buffer.
  1035. Arguments:
  1036. pCCB - A pointer to the code generation controller block.
  1037. Return Value:
  1038. CG_OK if all is well
  1039. error Otherwise.
  1040. Notes:
  1041. ----------------------------------------------------------------------------*/
  1042. {
  1043. ISTREAM *pStream = pCCB->GetStream();
  1044. CGSIDE Side = pCCB->GetCodeGenSide();
  1045. pStream->NewLine();
  1046. if(Side == CGSIDE_SERVER)
  1047. pStream->Write("NdrStubGetBuffer(This, _pRpcChannelBuffer, &_StubMsg);");
  1048. else
  1049. pStream->Write("NdrProxyGetBuffer(This, &_StubMsg);");
  1050. return CG_OK;
  1051. }
  1052. CG_STATUS
  1053. CG_OBJECT_PROC::C_GenSendReceive(
  1054. CCB * pCCB )
  1055. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1056. Routine Description:
  1057. Generate code to call IRpcChannelBuffer::SendReceive.
  1058. Arguments:
  1059. pCCB - A pointer to the code generation controller block.
  1060. Return Value:
  1061. CG_OK if all is well
  1062. error Otherwise.
  1063. Notes:
  1064. ----------------------------------------------------------------------------*/
  1065. {
  1066. ISTREAM *pStream = pCCB->GetStream();
  1067. pStream->NewLine();
  1068. pStream->Write("NdrProxySendReceive(This, &_StubMsg);");
  1069. pStream->NewLine();
  1070. return CG_OK;
  1071. }
  1072. CG_STATUS
  1073. CG_OBJECT_PROC::C_GenFreeBuffer(
  1074. CCB * pCCB )
  1075. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1076. Routine Description:
  1077. Generate code to call IRpcChannelBuffer::FreeBuffer.
  1078. Arguments:
  1079. pCCB - A pointer to the code generation controller block.
  1080. Return Value:
  1081. CG_OK if all is well
  1082. error Otherwise.
  1083. Notes:
  1084. ----------------------------------------------------------------------------*/
  1085. {
  1086. ISTREAM *pStream = pCCB->GetStream();
  1087. pStream->NewLine();
  1088. pStream->Write("NdrProxyFreeBuffer(This, &_StubMsg);");
  1089. pStream->NewLine();
  1090. return CG_OK;
  1091. }
  1092. CG_STATUS
  1093. CG_OBJECT_PROC::C_GenUnBind( CCB* )
  1094. {
  1095. return CG_OK;
  1096. }
  1097. CG_STATUS
  1098. CG_OBJECT_PROC::S_GenProlog(
  1099. CCB * pCCB )
  1100. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1101. Routine Description:
  1102. Generate the server side stub prolog.
  1103. Arguments:
  1104. pCCB - A pointer to the code generation controller block.
  1105. Return Value:
  1106. CG_OK if all is well
  1107. error Otherwise.
  1108. Notes:
  1109. Print out the signature, locals, the stub descriptor if needed and the
  1110. adjust indent in anticipation of code.
  1111. ----------------------------------------------------------------------------*/
  1112. {
  1113. ITERATOR LocalsList;
  1114. ITERATOR TransientList;
  1115. expr_proc_call * pCall;
  1116. // Collect all the params and locals into lists ready to print.
  1117. pCCB->GetListOfLocalResources( LocalsList );
  1118. pCCB->GetListOfTransientResources( TransientList );
  1119. // Print out the procedure signature and the local variables. This
  1120. // procedure will also print out the stub descriptor.
  1121. Out_ServerStubProlog( pCCB,
  1122. LocalsList,
  1123. TransientList
  1124. );
  1125. //
  1126. // Done for interpretation op. No indent needed either.
  1127. //
  1128. if ( pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER )
  1129. return CG_OK;
  1130. // Start a new indent for code.
  1131. Out_IndentInc( pCCB );
  1132. //
  1133. // Call the NdrStubInitialize routine.
  1134. //
  1135. pCall = new expr_proc_call( "NdrStubInitialize" );
  1136. pCall->SetParam( new expr_param (
  1137. new expr_variable( PRPC_MESSAGE_VAR_NAME ) ) );
  1138. pCall->SetParam( new expr_param (
  1139. new expr_u_address (
  1140. new expr_variable( STUB_MESSAGE_VAR_NAME ) ) ) );
  1141. pCall->SetParam( new expr_param (
  1142. new expr_u_address (
  1143. new expr_variable(
  1144. pCCB->GetInterfaceCG()->GetStubDescName() ) ) ) );
  1145. pCall->SetParam( new expr_param (
  1146. new expr_variable( "_pRpcChannelBuffer" ) ) );
  1147. pCall->PrintCall( pCCB->GetStream(), 0, 0 );
  1148. // if the rpc ss package is to be enabled, do so.
  1149. if( MustInvokeRpcSSAllocate() )
  1150. {
  1151. Out_RpcSSEnableAllocate( pCCB );
  1152. }
  1153. return CG_OK;
  1154. }
  1155. CG_STATUS
  1156. CG_OBJECT_PROC::S_GenInitMarshall( CCB* )
  1157. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1158. Routine Description:
  1159. Generate the server side marshall init.
  1160. Arguments:
  1161. pCCB - A pointer to the code generation controller block.
  1162. Return Value:
  1163. CG_OK if all is well,
  1164. error otherwise.
  1165. Notes:
  1166. ----------------------------------------------------------------------------*/
  1167. {
  1168. return CG_OK;
  1169. }
  1170. void
  1171. CG_OBJECT_PROC::S_PreAllocateResources(
  1172. ANALYSIS_INFO * pAna )
  1173. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1174. Routine Description:
  1175. Pre-allocate variables that are needed on the server side.
  1176. Arguments:
  1177. pAna - A pointer to the analysis block.
  1178. Return Value:
  1179. None.
  1180. Notes:
  1181. 1. The rpc message is a parameter resource allocated on the server side.
  1182. 2. All other local variables, are decided during/after the analysis phase.
  1183. ----------------------------------------------------------------------------*/
  1184. {
  1185. node_param * pInterfaceStubType = new node_param();
  1186. node_param * pChannelType = new node_param();
  1187. //pointer to interface stub
  1188. pInterfaceStubType->SetSymName( "This" );
  1189. pInterfaceStubType->SetBasicType( (node_skl *)
  1190. new node_def ("IRpcStubBuffer *") );
  1191. pInterfaceStubType->SetEdgeType( EDGE_USE );
  1192. pAna->AddParamResource( "This",
  1193. (node_skl *) pInterfaceStubType
  1194. );
  1195. //The pointer to IRpcChannelBuffer
  1196. pChannelType->SetSymName( "_pRpcChannelBuffer" );
  1197. pChannelType->SetBasicType( (node_skl *)
  1198. new node_def ("IRpcChannelBuffer *") );
  1199. pChannelType->SetEdgeType( EDGE_USE );
  1200. pAna->AddParamResource( "_pRpcChannelBuffer",
  1201. (node_skl *) pChannelType
  1202. );
  1203. CG_PROC::S_PreAllocateResources( pAna );
  1204. }
  1205. CG_STATUS
  1206. CG_OBJECT_PROC::S_GenCallManager(
  1207. CCB * pCCB )
  1208. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1209. Routine Description:
  1210. Generate a call to the manager routine.
  1211. Arguments:
  1212. pCCB - A pointer to the code generation controller block.
  1213. Return Value:
  1214. CG_OK if all is well
  1215. error otherwise.
  1216. Notes:
  1217. Make a procedure node with all the parameters that need to be passed to
  1218. the manager code. The actual expression that needs to be passed to the
  1219. actual manager code is set up during earlier passes. This is called the
  1220. result expression.
  1221. ----------------------------------------------------------------------------*/
  1222. {
  1223. CG_ITERATOR I;
  1224. PNAME pName;
  1225. expr_proc_call * pProc;
  1226. CG_PARAM * pParam;
  1227. expr_node * pExpr;
  1228. expr_node * pReturnExpr = 0;
  1229. CG_RETURN * pRT;
  1230. CSzBuffer Buffer;
  1231. ISTREAM * pStream = pCCB->GetStream();
  1232. if ( GetCallAsName() )
  1233. {
  1234. pName = (PNAME ) new char[ strlen(GetCallAsName()) +
  1235. strlen( pCCB->GetInterfaceName() )
  1236. + 7 ];
  1237. strcpy( pName, pCCB->GetInterfaceName() );
  1238. strcat( pName, "_" );
  1239. strcat( pName, GetCallAsName() );
  1240. strcat( pName, "_Stub" );
  1241. }
  1242. else
  1243. pName = (PNAME ) GetType()->GetSymName();
  1244. pProc = new expr_proc_call( pName );
  1245. //implicit this pointer.
  1246. Buffer.Append("(");
  1247. Buffer.Append(pCCB->GetInterfaceName());
  1248. Buffer.Append(" *) ((CStdStubBuffer *)This)->pvServerObject");
  1249. pProc->SetParam(
  1250. new expr_param(
  1251. new expr_variable(Buffer)));
  1252. GetMembers( I );
  1253. while( ITERATOR_GETNEXT( I, pParam ) )
  1254. {
  1255. if ( ( pExpr = pParam->GetFinalExpression() ) != 0 )
  1256. {
  1257. CG_NDR * pChild = (CG_NDR *)pParam->GetChild();
  1258. //
  1259. // We have to dereference arrays because of how they are defined
  1260. // in the stub.
  1261. //
  1262. if ( pChild->IsArray() )
  1263. pExpr = new expr_u_deref( pExpr );
  1264. pProc->SetParam( new expr_param( pExpr ) );
  1265. }
  1266. }
  1267. if ( ( pRT = GetReturnType() ) != 0 )
  1268. {
  1269. pReturnExpr = pRT->GetFinalExpression();
  1270. }
  1271. //Set flag before calling server object.
  1272. pStream->NewLine();
  1273. if ( ReturnsHRESULT() )
  1274. pStream->WriteOnNewLine("*_pdwStubPhase = STUB_CALL_SERVER;");
  1275. else
  1276. pStream->WriteOnNewLine("*_pdwStubPhase = STUB_CALL_SERVER_NO_HRESULT;");
  1277. pStream->NewLine();
  1278. // stubs with call_as must call the user routine, instead of the
  1279. // member function. The user function must then call the member function
  1280. if ( GetCallAsName() )
  1281. Out_CallManager( pCCB, pProc, pReturnExpr, FALSE );
  1282. else
  1283. Out_CallMemberFunction( pCCB, pProc, pReturnExpr, FALSE );
  1284. //Set flag before marshalling.
  1285. pStream->NewLine();
  1286. pStream->WriteOnNewLine("*_pdwStubPhase = STUB_MARSHAL;");
  1287. return CG_OK;
  1288. }
  1289. void
  1290. CG_OBJECT_PROC::GenNdrInterpretedManagerCall(
  1291. CCB * pCCB )
  1292. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1293. Routine Description:
  1294. Generate a call to the interpreted manager routine.
  1295. Arguments:
  1296. pCCB - A pointer to the code generation controller block.
  1297. Return Value:
  1298. none
  1299. Notes:
  1300. Make a procedure node with all the parameters that need to be passed to
  1301. the manager code. The actual expression that needs to be passed to the
  1302. actual manager code is set up during earlier passes. This is called the
  1303. result expression.
  1304. ----------------------------------------------------------------------------*/
  1305. {
  1306. CG_ITERATOR I;
  1307. PNAME pName;
  1308. expr_proc_call * pProc;
  1309. CG_PARAM * pParam;
  1310. expr_node * pReturnExpr = 0;
  1311. CG_RETURN * pRT;
  1312. CSzBuffer Buffer;
  1313. ISTREAM * pStream = pCCB->GetStream();
  1314. if ( GetCallAsName() )
  1315. {
  1316. pName = (PNAME ) new char[ strlen(GetCallAsName()) +
  1317. strlen( pCCB->GetInterfaceName() )
  1318. + 7 ];
  1319. strcpy( pName, pCCB->GetInterfaceName() );
  1320. strcat( pName, "_" );
  1321. strcat( pName, GetCallAsName() );
  1322. strcat( pName, "_Stub" );
  1323. }
  1324. else
  1325. pName = (PNAME ) GetType()->GetSymName();
  1326. pProc = new expr_proc_call( pName );
  1327. //implicit this pointer.
  1328. Buffer.Append("(");
  1329. Buffer.Append(pCCB->GetInterfaceName());
  1330. Buffer.Append(" *) pParamStruct->This");
  1331. pProc->SetParam(
  1332. new expr_param(
  1333. new expr_variable(Buffer)));
  1334. GetMembers( I );
  1335. while( ITERATOR_GETNEXT( I, pParam ) )
  1336. {
  1337. CG_NDR * pNdr;
  1338. char * pName;
  1339. expr_node * pExpr;
  1340. char * pPlainName = pParam->GetResource()->GetResourceName();
  1341. pNdr = (CG_NDR *) pParam->GetChild();
  1342. pName = new char[strlen(pPlainName) + strlen("pParamStruct->")+1 ];
  1343. strcpy( pName, "pParamStruct->" );
  1344. strcat( pName, pPlainName );
  1345. pExpr = new expr_variable( pName );
  1346. pProc->SetParam( new expr_param ( pExpr ) );
  1347. }
  1348. if( ( pRT = GetReturnType() ) != 0 && !HasAsyncHandle() )
  1349. {
  1350. pReturnExpr = new expr_variable(
  1351. "pParamStruct->" RETURN_VALUE_VAR_NAME );
  1352. }
  1353. pStream->WriteOnNewLine("/* Call the server */");
  1354. // stubs with call_as must call the user routine, instead of the
  1355. // member function. The user function must then call the member function
  1356. if ( GetCallAsName() )
  1357. Out_CallManager( pCCB, pProc, pReturnExpr, FALSE );
  1358. else
  1359. Out_CallMemberFunction( pCCB, pProc, pReturnExpr, TRUE );
  1360. pStream->NewLine();
  1361. return;
  1362. }
  1363. void
  1364. Out_CallCMacroFunction(
  1365. CCB * pCCB,
  1366. expr_proc_call * pProcExpr)
  1367. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1368. Routine Description:
  1369. Generate a call to the manager routine.
  1370. Arguments:
  1371. pCCB - A pointer to the code generation controller block.
  1372. pProcExpr - A pointer to the complete procedure expression.
  1373. pRet - An optional pointer to ther return variable.
  1374. Return Value:
  1375. None.
  1376. Notes:
  1377. //call proxy
  1378. (*(This)->lpVtbl -> LockServer)( This, fLock);
  1379. ----------------------------------------------------------------------------*/
  1380. {
  1381. ISTREAM * pStream = pCCB->GetStream();
  1382. // allocate the nodes on the stack
  1383. expr_variable VtblExpr( "(This)->lpVtbl" );
  1384. expr_pointsto VtblEntExpr( &VtblExpr, pProcExpr );
  1385. // expr_op_unary VtblEntExprCall( OP_UNARY_INDIRECTION, &VtblEntExpr );
  1386. pStream->IndentInc();
  1387. pStream->NewLine();
  1388. VtblEntExpr.Print( pStream );
  1389. pStream->IndentDec();
  1390. }
  1391. CG_STATUS
  1392. CG_OBJECT_PROC::GenCMacro(
  1393. CCB * pCCB )
  1394. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1395. Routine Description:
  1396. Generate a call to the proxy routine.
  1397. Arguments:
  1398. pCCB - A pointer to the code generation controller block.
  1399. Return Value:
  1400. CG_OK if all is well
  1401. error otherwise.
  1402. Notes:
  1403. Make a procedure node with all the parameters that need to be passed to
  1404. the manager code. The actual expression that needs to be passed to the
  1405. actual manager code is set up during earlier passes. This is called the
  1406. result expression.
  1407. ----------------------------------------------------------------------------*/
  1408. {
  1409. node_param * pParam;
  1410. ISTREAM * pStream = pCCB->GetStream();
  1411. node_proc * pProc = (node_proc *) GetType();
  1412. if ( SupressHeader())
  1413. return CG_OK;
  1414. if ( GetCallAsName() )
  1415. {
  1416. node_call_as * pCallAs = (node_call_as *)
  1417. pProc->GetAttribute( ATTR_CALL_AS );
  1418. pProc = (node_proc *) pCallAs->GetCallAsType();
  1419. MIDL_ASSERT ( pProc );
  1420. }
  1421. // construct all these on the stack...
  1422. MEM_ITER MemIter( pProc );
  1423. expr_proc_call Proc( pProc->GetSymName() );
  1424. expr_variable ThisVar( "This" );
  1425. expr_param ThisParam( &ThisVar );
  1426. Proc.SetParam( &ThisParam );
  1427. while ( ( pParam = (node_param *) MemIter.GetNext() ) != 0 )
  1428. {
  1429. Proc.SetParam( new expr_param(
  1430. new expr_variable( pParam->GetSymName() ) ) );
  1431. }
  1432. // print out the #define line
  1433. pStream->NewLine();
  1434. pStream->Write("#define ");
  1435. pStream->Write( pCCB->GetInterfaceName() );
  1436. pStream->Write( '_' );
  1437. Proc.Print( pStream );
  1438. pStream->Write( "\t\\" );
  1439. Out_CallCMacroFunction( pCCB, &Proc );
  1440. return CG_OK;
  1441. }
  1442. void
  1443. CG_PROXY_FILE::Out_ProxyBuffer(
  1444. CCB *pCCB,
  1445. char * pFName )
  1446. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1447. Routine Description:
  1448. Generate a CStdProxyBuffer for the [object] interfaces defined
  1449. in the IDL file.
  1450. Arguments:
  1451. pCCB - a pointer to the code generation control block.
  1452. Notes:
  1453. ----------------------------------------------------------------------------*/
  1454. {
  1455. ITERATOR & I = GetImplementedInterfacesList();
  1456. CG_OBJECT_INTERFACE * pCG;
  1457. ISTREAM * pStream = pCCB->GetStream();
  1458. pStream->NewLine();
  1459. pStream->Write("const CInterfaceProxyVtbl * _");
  1460. pStream->Write(pFName);
  1461. pStream->Write("_ProxyVtblList[] = ");
  1462. pStream->NewLine();
  1463. pStream->Write('{');
  1464. pStream->IndentInc();
  1465. //list of interface proxies.
  1466. while( ITERATOR_GETNEXT( I, pCG ) )
  1467. {
  1468. pStream->NewLine();
  1469. pStream->Write("( CInterfaceProxyVtbl *) &_");
  1470. pStream->Write(pCG->GetSymName());
  1471. pStream->Write("ProxyVtbl,");
  1472. }
  1473. pStream->NewLine();
  1474. pStream->Write('0');
  1475. pStream->IndentDec();
  1476. pStream->NewLine();
  1477. pStream->Write("};");
  1478. pStream->NewLine();
  1479. }
  1480. void
  1481. CG_PROXY_FILE::Out_StubBuffer(
  1482. CCB *pCCB,
  1483. char * pFName )
  1484. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1485. Routine Description:
  1486. Generate a CStdStubBuffer for the [object] interfaces defined
  1487. in the IDL file.
  1488. Arguments:
  1489. pCCB - a pointer to the code generation control block.
  1490. Notes:
  1491. ----------------------------------------------------------------------------*/
  1492. {
  1493. ITERATOR & I = GetImplementedInterfacesList();
  1494. CG_OBJECT_INTERFACE * pCG;
  1495. ISTREAM * pStream = pCCB->GetStream();
  1496. pStream->NewLine();
  1497. pStream->Write("const CInterfaceStubVtbl * _");
  1498. pStream->Write(pFName);
  1499. pStream->Write("_StubVtblList[] = ");
  1500. pStream->NewLine();
  1501. pStream->Write('{');
  1502. pStream->IndentInc();
  1503. //list of interface proxies.
  1504. while( ITERATOR_GETNEXT( I, pCG ) )
  1505. {
  1506. pStream->NewLine();
  1507. pStream->Write("( CInterfaceStubVtbl *) &_");
  1508. pStream->Write( pCG->GetSymName() );
  1509. pStream->Write("StubVtbl,");
  1510. }
  1511. pStream->NewLine();
  1512. pStream->Write('0');
  1513. pStream->IndentDec();
  1514. pStream->NewLine();
  1515. pStream->Write("};");
  1516. pStream->NewLine();
  1517. }
  1518. void
  1519. CG_PROXY_FILE::Out_InterfaceNamesList(
  1520. CCB *pCCB,
  1521. char * pFName )
  1522. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1523. Routine Description:
  1524. Generate an interface name list for the [object] interfaces defined
  1525. in the IDL file.
  1526. Arguments:
  1527. pCCB - a pointer to the code generation control block.
  1528. Notes:
  1529. ----------------------------------------------------------------------------*/
  1530. {
  1531. ITERATOR & I = GetImplementedInterfacesList();
  1532. CG_OBJECT_INTERFACE * pCG;
  1533. ISTREAM * pStream = pCCB->GetStream();
  1534. pStream->NewLine();
  1535. pStream->Write("PCInterfaceName const _");
  1536. pStream->Write(pFName);
  1537. pStream->Write("_InterfaceNamesList[] = ");
  1538. pStream->NewLine();
  1539. pStream->Write('{');
  1540. pStream->IndentInc();
  1541. //list of interface proxies.
  1542. while( ITERATOR_GETNEXT( I, pCG ) )
  1543. {
  1544. pStream->NewLine();
  1545. pStream->Write('\"');
  1546. pStream->Write(pCG->GetSymName());
  1547. pStream->Write("\",");
  1548. }
  1549. pStream->NewLine();
  1550. pStream->Write('0');
  1551. pStream->IndentDec();
  1552. pStream->NewLine();
  1553. pStream->Write("};");
  1554. pStream->NewLine();
  1555. }
  1556. void
  1557. CG_PROXY_FILE::Out_AsyncInterfaceTable (
  1558. CCB* pCCB,
  1559. char*
  1560. )
  1561. {
  1562. ITERATOR& I = GetImplementedInterfacesList();
  1563. CG_OBJECT_INTERFACE* pCG;
  1564. ISTREAM* pStream = pCCB->GetStream();
  1565. pStream->NewLine();
  1566. pStream->Write("static const IID * _AsyncInterfaceTable[] = ");
  1567. pStream->NewLine();
  1568. pStream->Write('{');
  1569. pStream->IndentInc();
  1570. //list of interface proxies.
  1571. while( ITERATOR_GETNEXT( I, pCG ) )
  1572. {
  1573. pStream->NewLine();
  1574. if ( ((node_interface*)pCG->GetType())->GetAsyncInterface() == 0 )
  1575. {
  1576. if ( ((node_interface*)pCG->GetType())->IsAsyncClone() )
  1577. {
  1578. pStream->Write( "(IID*) -1" );
  1579. }
  1580. else
  1581. {
  1582. pStream->Write( "(IID*) 0" );
  1583. }
  1584. }
  1585. else
  1586. {
  1587. pStream->Write( "(IID*) &IID_" );
  1588. pStream->Write(((node_interface*)pCG->GetType())->GetAsyncInterface()->GetSymName());
  1589. }
  1590. pStream->Write(",");
  1591. }
  1592. pStream->NewLine();
  1593. pStream->Write( "(IID*) 0" );
  1594. pStream->IndentDec();
  1595. pStream->NewLine();
  1596. pStream->Write("};");
  1597. pStream->NewLine();
  1598. }
  1599. void
  1600. CG_PROXY_FILE::Out_BaseIntfsList(
  1601. CCB *pCCB,
  1602. char * pFName )
  1603. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1604. Routine Description:
  1605. Generate a base interface list for the [object] interfaces defined
  1606. in the IDL file that need delegation
  1607. Arguments:
  1608. pCCB - a pointer to the code generation control block.
  1609. Notes:
  1610. ----------------------------------------------------------------------------*/
  1611. {
  1612. ITERATOR & I = GetImplementedInterfacesList();
  1613. CG_OBJECT_INTERFACE * pCG;
  1614. CG_OBJECT_INTERFACE * pBaseCG;
  1615. ISTREAM * pStream = pCCB->GetStream();
  1616. //list of interface proxies.
  1617. while( ITERATOR_GETNEXT( I, pCG ) )
  1618. {
  1619. // if we needed delegation, add it to the list
  1620. if ( ( (pBaseCG = pCG->GetDelegatedInterface() ) != 0 ) || pCG->HasForcedDelegation())
  1621. {
  1622. fDllDataDelegating = TRUE;
  1623. break;
  1624. }
  1625. }
  1626. ITERATOR_INIT( I );
  1627. // if there is no delegating, we don't need this table
  1628. if ( !fDllDataDelegating )
  1629. return;
  1630. pStream->NewLine();
  1631. pStream->Write("const IID * _");
  1632. pStream->Write(pFName);
  1633. pStream->Write("_BaseIIDList[] = ");
  1634. pStream->NewLine();
  1635. pStream->Write('{');
  1636. pStream->IndentInc();
  1637. //list of interface proxies.
  1638. while( ITERATOR_GETNEXT( I, pCG ) )
  1639. {
  1640. pStream->NewLine();
  1641. // if we needed delegation, add it to the list
  1642. if ( ( pBaseCG = pCG->GetDelegatedInterface() ) != 0 )
  1643. {
  1644. fDllDataDelegating = TRUE;
  1645. pStream->Write("&IID_");
  1646. pStream->Write( pBaseCG->GetSymName() );
  1647. pStream->Write(',');
  1648. }
  1649. else if ( pCG->HasForcedDelegation() )
  1650. {
  1651. fDllDataDelegating = TRUE;
  1652. pStream->Write("&IID_");
  1653. pStream->Write( pCG->GetBaseInterfaceCG()->GetSymName() );
  1654. pStream->Write(',');
  1655. pStream->Write(" /* forced */");
  1656. }
  1657. else
  1658. pStream->Write("0,");
  1659. }
  1660. pStream->NewLine();
  1661. pStream->Write('0');
  1662. pStream->IndentDec();
  1663. pStream->NewLine();
  1664. pStream->Write("};");
  1665. pStream->NewLine();
  1666. }
  1667. inline
  1668. unsigned char
  1669. log2( unsigned long ulVal )
  1670. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1671. Routine Description:
  1672. Compute the log base 2 (rounded down to integral) of a number
  1673. Returns 0 for 0 or 1
  1674. Arguments:
  1675. ulVal - the value to check on.
  1676. Notes:
  1677. uses binary search to find the highest set bit
  1678. to find the smallest power of 2 >= a number, use 1 << log2( 2n-1 )
  1679. ----------------------------------------------------------------------------*/
  1680. {
  1681. unsigned char result = 0;
  1682. if ( ( ulVal >>16 ) > 0 )
  1683. {
  1684. ulVal >>= 16;
  1685. result = 16;
  1686. }
  1687. if ( ( ulVal >>8 ) > 0 )
  1688. {
  1689. ulVal >>= 8;
  1690. result += 8;
  1691. }
  1692. if ( ( ulVal >>4 ) > 0 )
  1693. {
  1694. ulVal >>= 4;
  1695. result += 4;
  1696. }
  1697. if ( ( ulVal >>2 ) > 0 )
  1698. {
  1699. ulVal >>= 2;
  1700. result += 2;
  1701. }
  1702. if ( ulVal > 1 )
  1703. {
  1704. result++;
  1705. }
  1706. return result;
  1707. }
  1708. void
  1709. CG_PROXY_FILE::Out_InfoSearchRoutine(
  1710. CCB *pCCB,
  1711. char * pFName )
  1712. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1713. Routine Description:
  1714. Generate a search function for the interfaces defined in this proxy file
  1715. Arguments:
  1716. pCCB - a pointer to the code generation control block.
  1717. Notes:
  1718. ----------------------------------------------------------------------------*/
  1719. {
  1720. ITERATOR & I = GetImplementedInterfacesList();
  1721. ISTREAM * pStream = pCCB->GetStream();
  1722. unsigned long ListSize = I.GetCount();
  1723. CSzBuffer CheckIIDName;
  1724. unsigned long CurIndex;
  1725. CheckIIDName.Append("_");
  1726. CheckIIDName.Append( pFName );
  1727. CheckIIDName.Append( "_CHECK_IID" );
  1728. pStream->NewLine(2);
  1729. pStream->Write( "#define " );
  1730. pStream->Write( CheckIIDName );
  1731. pStream->Write( "(n)\tIID_GENERIC_CHECK_IID( _");
  1732. pStream->Write( pFName );
  1733. pStream->Write( ", pIID, n)");
  1734. pStream->NewLine( 2 );
  1735. pStream->Write( "int __stdcall _" );
  1736. pStream->Write( pFName );
  1737. pStream->Write( "_IID_Lookup( const IID * pIID, int * pIndex )" );
  1738. pStream->NewLine();
  1739. pStream->Write( '{' );
  1740. pStream->IndentInc();
  1741. pStream->NewLine();
  1742. if ( ListSize == 0 )
  1743. {
  1744. pStream->Write( "return 0;" );
  1745. }
  1746. else if ( ListSize < 2 )
  1747. {
  1748. expr_variable SetValue( "*pIndex" );
  1749. expr_param IndexParam( NULL );
  1750. expr_proc_call CheckIIDExpr( CheckIIDName );
  1751. CheckIIDExpr.SetParam( &IndexParam );
  1752. expr_u_not TopExpr( &CheckIIDExpr );
  1753. for ( CurIndex = 0; CurIndex < ListSize; CurIndex++ )
  1754. {
  1755. expr_constant IndexNode( CurIndex );
  1756. IndexParam.SetLeft( &IndexNode );
  1757. Out_If( pCCB, &TopExpr );
  1758. Out_Assign( pCCB, &SetValue, &IndexNode );
  1759. pStream->NewLine();
  1760. pStream->Write( "return 1;" );
  1761. Out_Endif( pCCB );
  1762. }
  1763. pStream->NewLine(2);
  1764. pStream->Write( "return 0;" );
  1765. }
  1766. else
  1767. {
  1768. unsigned long curStep = 1 << log2( ListSize - 1 );
  1769. pStream->Write( "IID_BS_LOOKUP_SETUP" );
  1770. pStream->NewLine(2);
  1771. pStream->Write( "IID_BS_LOOKUP_INITIAL_TEST( _" );
  1772. pStream->Write( pFName );
  1773. pStream->Write( ", " );
  1774. pStream->WriteNumber( "%d", ListSize );
  1775. pStream->Write( ", " );
  1776. pStream->WriteNumber( "%d", curStep );
  1777. pStream->Write( " )" );
  1778. pStream->NewLine();
  1779. for ( curStep >>= 1 ; curStep > 0 ; curStep >>= 1 )
  1780. {
  1781. pStream->Write( "IID_BS_LOOKUP_NEXT_TEST( _" );
  1782. pStream->Write( pFName );
  1783. pStream->Write( ", " );
  1784. pStream->WriteNumber( "%d", curStep );
  1785. pStream->Write( " )" );
  1786. pStream->NewLine();
  1787. }
  1788. pStream->Write( "IID_BS_LOOKUP_RETURN_RESULT( _" );
  1789. pStream->Write( pFName );
  1790. pStream->Write( ", " );
  1791. pStream->WriteNumber( "%d", ListSize );
  1792. pStream->Write( ", *pIndex )" );
  1793. pStream->NewLine();
  1794. }
  1795. pStream->IndentDec();
  1796. pStream->NewLine();
  1797. pStream->Write( '}' );
  1798. pStream->NewLine();
  1799. }
  1800. void
  1801. CG_PROXY_FILE::Out_ProxyFileInfo(
  1802. CCB *pCCB )
  1803. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1804. Routine Description:
  1805. Generate a ProxyFileInfo structure for the [object] interfaces defined
  1806. in the IDL file.
  1807. Arguments:
  1808. pCCB - a pointer to the code generation control block.
  1809. Return Value:
  1810. CG_OK if all is well, error otherwise.
  1811. Notes:
  1812. ----------------------------------------------------------------------------*/
  1813. {
  1814. ITERATOR & I = GetImplementedInterfacesList();
  1815. char BaseName[ _MAX_FNAME ];
  1816. char Name[ _MAX_FNAME ];
  1817. ISTREAM * pStream = pCCB->GetStream();
  1818. unsigned long count = 0;
  1819. //Get the IDL file name.
  1820. pCommand->GetInputFileNameComponents(NULL, NULL, BaseName, NULL );
  1821. NormalizeString( BaseName, Name);
  1822. //////////////////////////////////////////
  1823. // put out the ancilliary data structures
  1824. Out_ProxyBuffer(pCCB, Name );
  1825. Out_StubBuffer(pCCB, Name );
  1826. Out_InterfaceNamesList(pCCB, Name );
  1827. Out_BaseIntfsList(pCCB, Name);
  1828. Out_InfoSearchRoutine( pCCB, Name );
  1829. // AsyncIFTable
  1830. if ( pCommand->GetNdrVersionControl().HasAsyncUUID() )
  1831. {
  1832. Out_AsyncInterfaceTable( pCCB, Name );
  1833. }
  1834. //////////////////////////////////////////
  1835. // put out the ProxyFileInfo struct
  1836. //list of interface proxies.
  1837. count = ITERATOR_GETCOUNT( I );
  1838. pStream->NewLine();
  1839. pStream->Write("const ExtendedProxyFileInfo ");
  1840. pStream->Write(Name);
  1841. pStream->Write("_ProxyFileInfo = ");
  1842. pStream->NewLine();
  1843. pStream->Write('{');
  1844. pStream->IndentInc();
  1845. //pointer to the proxy buffer
  1846. pStream->NewLine();
  1847. pStream->Write("(PCInterfaceProxyVtblList *) & _");
  1848. pStream->Write(Name);
  1849. pStream->Write("_ProxyVtblList,");
  1850. //pointer to the stub buffer
  1851. pStream->NewLine();
  1852. pStream->Write("(PCInterfaceStubVtblList *) & _");
  1853. pStream->Write(Name);
  1854. pStream->Write("_StubVtblList,");
  1855. //pointer to the interface names list
  1856. pStream->NewLine();
  1857. pStream->Write("(const PCInterfaceName * ) & _");
  1858. pStream->Write(Name);
  1859. pStream->Write("_InterfaceNamesList,");
  1860. //pointer to the base iids list
  1861. pStream->NewLine();
  1862. // no table if no delegation
  1863. if ( fDllDataDelegating )
  1864. {
  1865. pStream->Write("(const IID ** ) & _");
  1866. pStream->Write(Name);
  1867. pStream->Write("_BaseIIDList,");
  1868. }
  1869. else
  1870. {
  1871. pStream->Write( "0, // no delegation" );
  1872. }
  1873. // IID lookup routine
  1874. pStream->NewLine();
  1875. pStream->Write( "& _" );
  1876. pStream->Write( Name );
  1877. pStream->Write( "_IID_Lookup, ");
  1878. // table size
  1879. pStream->NewLine();
  1880. pStream->WriteNumber( "%d", count );
  1881. pStream->Write( ',' );
  1882. pStream->NewLine();
  1883. // table version
  1884. unsigned short uTableVer = 1;
  1885. if ( pCommand->GetNdrVersionControl().HasStublessProxies() )
  1886. {
  1887. uTableVer = 2;
  1888. }
  1889. if ( pCommand->GetNdrVersionControl().HasAsyncUUID() )
  1890. {
  1891. uTableVer |= 4;
  1892. }
  1893. pStream->WriteNumber( "%d", uTableVer );
  1894. pStream->Write( ',' );
  1895. pStream->NewLine();
  1896. // AsyncIFTable
  1897. if ( pCommand->GetNdrVersionControl().HasAsyncUUID() )
  1898. {
  1899. pStream->Write( "(const IID**) &_AsyncInterfaceTable[0],");
  1900. }
  1901. else
  1902. {
  1903. pStream->Write( "0,");
  1904. }
  1905. pStream->Write( " /* table of [async_uuid] interfaces */" );
  1906. pStream->NewLine();
  1907. pStream->Write( "0, /* Filler1 */" );
  1908. pStream->NewLine();
  1909. pStream->Write( "0, /* Filler2 */" );
  1910. pStream->NewLine();
  1911. pStream->Write( "0 /* Filler3 */" );
  1912. pStream->IndentDec();
  1913. pStream->NewLine();
  1914. pStream->Write("};");
  1915. pStream->NewLine();
  1916. }
  1917. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1918. String constants for the DllData file
  1919. ----------------------------------------------------------------------------*/
  1920. #define DLLDATA_LIST_START "/* Start of list */\n"
  1921. #define DLLDATA_LIST_END "/* End of list */\n"
  1922. #define DLLDATA_HEADER_COMMENT \
  1923. "/*********************************************************\n" \
  1924. " DllData file -- generated by MIDL compiler \n\n" \
  1925. " DO NOT ALTER THIS FILE\n\n" \
  1926. " This file is regenerated by MIDL on every IDL file compile.\n\n" \
  1927. " To completely reconstruct this file, delete it and rerun MIDL\n" \
  1928. " on all the IDL files in this DLL, specifying this file for the\n" \
  1929. " /dlldata command line option\n\n" \
  1930. "*********************************************************/\n\n"
  1931. #define DLLDATA_HAS_DELEGATION "#define PROXY_DELEGATION\n"
  1932. #define DLLDATA_HEADER_INCLUDES \
  1933. "\n#include <rpcproxy.h>\n\n" \
  1934. "#ifdef __cplusplus\n" \
  1935. "extern \"C\" {\n" \
  1936. "#endif\n" \
  1937. "\n"
  1938. #define DLLDATA_EXTERN_CALL "EXTERN_PROXY_FILE( %s )\n"
  1939. #define DLLDATA_REFERENCE " REFERENCE_PROXY_FILE( %s ),\n"
  1940. #define DLLDATA_START "\n\nPROXYFILE_LIST_START\n" DLLDATA_LIST_START
  1941. #define DLLDATA_END DLLDATA_LIST_END "PROXYFILE_LIST_END\n"
  1942. #define DLLDATA_TRAILER \
  1943. "\n\nDLLDATA_ROUTINES( aProxyFileList, GET_DLL_CLSID )\n" \
  1944. "\n" \
  1945. "#ifdef __cplusplus\n" \
  1946. "} /*extern \"C\" */\n" \
  1947. "#endif\n" \
  1948. "\n/* end of generated dlldata file */\n"
  1949. void
  1950. DllDataParse(
  1951. FILE * pDllData,
  1952. STRING_DICT & Dict )
  1953. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1954. Routine Description:
  1955. Parse the "dlldata" file, extracting info on all the included files.
  1956. Arguments:
  1957. pCCB - a pointer to the code generation control block.
  1958. Return Value:
  1959. CG_OK if all is well, error otherwise.
  1960. Notes:
  1961. ----------------------------------------------------------------------------*/
  1962. {
  1963. const char * pStart = DLLDATA_LIST_START;
  1964. const char * pEnd = DLLDATA_LIST_END;
  1965. const char * pDelegating = DLLDATA_HAS_DELEGATION;
  1966. char Input[100];
  1967. // skip everything up to (and including) pStart
  1968. while ( !feof( pDllData ) )
  1969. {
  1970. if ( !fgets( Input, 100, pDllData ) )
  1971. break;
  1972. if ( !strcmp( Input, pDelegating ) )
  1973. {
  1974. fDllDataDelegating = TRUE;
  1975. continue;
  1976. }
  1977. if ( !strcmp( Input, pStart ) )
  1978. break;
  1979. }
  1980. // parse list (looking for pEnd)
  1981. while ( !feof( pDllData ) &&
  1982. fgets( Input, 100, pDllData ) &&
  1983. strcmp( Input, pEnd ) )
  1984. {
  1985. char * pOpenParen = strchr( Input, '(' );
  1986. char * pCloseParen = strchr( Input, ')' );
  1987. char * pSave;
  1988. if ( !pOpenParen || !pCloseParen )
  1989. {
  1990. // formatting error on this line
  1991. continue;
  1992. }
  1993. // chop off the close paren, and skip the open paren
  1994. *(pCloseParen--) = '\0';
  1995. pOpenParen++;
  1996. // delete leading and trailing spaces
  1997. while ( isspace( *pOpenParen ) )
  1998. pOpenParen++;
  1999. while ( isspace( *pCloseParen ) )
  2000. *(pCloseParen--) = '\0';
  2001. pSave = new char[ strlen( pOpenParen ) + 1 ];
  2002. strcpy( pSave, pOpenParen );
  2003. // add file name to dictionary
  2004. Dict.Dict_Insert( pSave );
  2005. }
  2006. }
  2007. void
  2008. DllDataEmit(
  2009. FILE * pDllData,
  2010. STRING_DICT & Dict )
  2011. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2012. Routine Description:
  2013. Emit a new "dlldata" file, including info on all the included files.
  2014. Arguments:
  2015. pCCB - a pointer to the code generation control block.
  2016. Return Value:
  2017. CG_OK if all is well, error otherwise.
  2018. Notes:
  2019. ----------------------------------------------------------------------------*/
  2020. {
  2021. Dict_Status Status;
  2022. char * pCur;
  2023. char Normalized[ _MAX_FNAME ];
  2024. BOOL fFirst = TRUE;
  2025. // emit header
  2026. fputs( DLLDATA_HEADER_COMMENT, pDllData );
  2027. if ( fDllDataDelegating )
  2028. fputs( DLLDATA_HAS_DELEGATION, pDllData );
  2029. // rpcproxy.h version guard
  2030. // do not generate the version guard in dlldata.c for now because
  2031. // MIDL does not regenerate the file. It adds to the existing
  2032. // dlldata.c This causes problems when the old compiler has
  2033. // generated the existing dlldata.c and vice-versa.
  2034. /*
  2035. fputs( "\n\n", pDllData );
  2036. char sz[192];
  2037. fputs( GetRpcProxyHVersionGuard( sz ), pDllData );
  2038. fputs( "\n", pDllData );
  2039. */
  2040. fputs( DLLDATA_HEADER_INCLUDES, pDllData );
  2041. // emit extern definitions
  2042. Status = Dict.Dict_Init();
  2043. while( SUCCESS == Status )
  2044. {
  2045. pCur = (char *) Dict.Dict_Curr_Item();
  2046. NormalizeString( pCur, Normalized );
  2047. fprintf( pDllData, DLLDATA_EXTERN_CALL, Normalized );
  2048. Status = Dict.Dict_Next( (pUserType)pCur );
  2049. }
  2050. // emit header for type
  2051. fputs( DLLDATA_START, pDllData );
  2052. // emit extern references, adding comma on all but the first
  2053. Status = Dict.Dict_Init();
  2054. while( SUCCESS == Status )
  2055. {
  2056. pCur = (char *) Dict.Dict_Curr_Item();
  2057. NormalizeString( pCur, Normalized );
  2058. fprintf( pDllData,
  2059. DLLDATA_REFERENCE,
  2060. Normalized );
  2061. fFirst = FALSE;
  2062. Status = Dict.Dict_Next( (pUserType)pCur );
  2063. }
  2064. // emit trailer for type
  2065. fputs( DLLDATA_END, pDllData );
  2066. // emit trailer
  2067. fputs( DLLDATA_TRAILER, pDllData );
  2068. }
  2069. void
  2070. CG_PROXY_FILE::UpdateDLLDataFile( CCB* )
  2071. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2072. Routine Description:
  2073. Update the "dlldata" file, adding info for this file if needed.
  2074. If no changes at all are required, leave the file untouched.
  2075. Arguments:
  2076. pCCB - a pointer to the code generation control block.
  2077. Return Value:
  2078. CG_OK if all is well, error otherwise.
  2079. Notes:
  2080. ----------------------------------------------------------------------------*/
  2081. {
  2082. char * pszDllDataName = pCommand->GetDllDataFName();
  2083. FILE * pDllData;
  2084. STRING_DICT ProxyFileList;
  2085. char BaseName[ _MAX_FNAME ];
  2086. char Name[ _MAX_FNAME ];
  2087. // Use sopen to make sure there always is a file to process.
  2088. // (fsopen with "r+" requires an existing file).
  2089. int DllDataHandle = _sopen( pszDllDataName,
  2090. (_O_CREAT | _O_RDWR | _O_TEXT),
  2091. _SH_DENYRW,
  2092. (_S_IREAD | _S_IWRITE ) );
  2093. // if the file exists already and/or is busy, it's ok.
  2094. if ( DllDataHandle == -1 &&
  2095. (errno != EEXIST && errno != EACCES) )
  2096. {
  2097. // unexpected error
  2098. RpcError((char *)NULL, 0, INPUT_OPEN, pszDllDataName );
  2099. return;
  2100. }
  2101. if ( DllDataHandle != -1 )
  2102. {
  2103. _close(DllDataHandle);
  2104. }
  2105. // Attempt to open the file for reading and writing.
  2106. // Because we can have a race condition when updating this file,
  2107. // we try several times before quitting.
  2108. for ( int i = 0;
  2109. (i < DLLDATA_OPEN_ATTEMPT_MAX) &&
  2110. ( ( pDllData = _fsopen( pszDllDataName, "r+t", _SH_DENYRW ) ) == 0 );
  2111. i++ )
  2112. {
  2113. printf("waiting for %s ...\n", pszDllDataName);
  2114. MidlSleep(1);
  2115. }
  2116. if ( !pDllData )
  2117. {
  2118. RpcError((char *)NULL, 0, INPUT_OPEN, pszDllDataName );
  2119. return;
  2120. }
  2121. //Get the IDL file name.
  2122. pCommand->GetInputFileNameComponents(NULL, NULL, BaseName, NULL );
  2123. NormalizeString( BaseName, Name );
  2124. // If file is empty, the following is a no op.
  2125. // skip up to the proxyfileinfo stuff and read/make sorted list of files
  2126. DllDataParse( pDllData, ProxyFileList );
  2127. // insert our file name
  2128. ProxyFileList.Dict_Insert( Name );
  2129. // re-emit everything
  2130. rewind( pDllData );
  2131. DllDataEmit( pDllData, ProxyFileList );
  2132. // close the file to give others a chance
  2133. if ( fclose( pDllData ))
  2134. {
  2135. RpcError((char *)NULL, 0, ERROR_WRITING_FILE, pszDllDataName );
  2136. }
  2137. }