Windows NT 4.0 source code leak
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.

2125 lines
48 KiB

4 years ago
  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. comsrv.cxx
  5. Abstract:
  6. Generates com class server framework file
  7. Notes:
  8. History:
  9. ----------------------------------------------------------------------------*/
  10. /****************************************************************************
  11. * include files
  12. ***************************************************************************/
  13. #include "becls.hxx"
  14. #pragma hdrstop
  15. #include "buffer.hxx"
  16. /****************************************************************************
  17. * local definitions
  18. ***************************************************************************/
  19. /****************************************************************************
  20. * externs
  21. ***************************************************************************/
  22. extern CMD_ARG * pCommand;
  23. #include "szbuffer.h"
  24. CG_STATUS
  25. CG_COM_CLASS::GenComOuterUnknown(
  26. CCB * pCCB,
  27. char * pDesignatedClassName )
  28. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  29. Routine Description:
  30. Generate the COM server file code for the outer IUnknown for a COM class
  31. Arguments:
  32. pCCB - a pointer to the code generation control block.
  33. Return Value:
  34. CG_OK if all is well, error otherwise.
  35. Notes:
  36. ----------------------------------------------------------------------------*/
  37. {
  38. ISTREAM * pStream = pCCB->GetStream();
  39. char * pName = GetSymName();
  40. CG_IUNKNOWN_OBJECT_INTERFACE * pIUnknown = pCCB->GetIUnknownCG();
  41. node_object * pClass = (node_object *) GetType();
  42. MEM_ITER Iter( (node_interface *)pIUnknown->GetType() );
  43. // get pointers to all the methods
  44. named_node * pQI;
  45. named_node * pAR;
  46. named_node * pRel;
  47. while ( ( pQI = Iter.GetNext() )->NodeKind() != NODE_PROC )
  48. ;
  49. while ( ( pAR = Iter.GetNext() )->NodeKind() != NODE_PROC )
  50. ;
  51. while ( ( pRel = Iter.GetNext() )->NodeKind() != NODE_PROC )
  52. ;
  53. pStream->NewLine();
  54. pStream->Write( pDelimiterString );
  55. pStream->NewLine();
  56. pStream->Write( "// IUnknown implementation for class: " );
  57. pStream->Write( pName );
  58. pStream->NewLine(2);
  59. ////////////////////////////////////////////////////////////////////////
  60. // QueryInterface
  61. pQI->PrintType( PRT_QUALIFIED_NAME | PRT_PROC_PROTOTYPE, pStream, NULL, pClass );
  62. // print a (nearly) empty function body
  63. pStream->IndentInc();
  64. pStream->NewLine();
  65. pStream->Write( '{' );
  66. pStream->NewLine();
  67. pStream->Write("return ");
  68. if ( pDesignatedClassName )
  69. {
  70. pStream->Write( pDesignatedClassName );
  71. pStream->Write( "::" );
  72. }
  73. pStream->Write("pUnkOuter->QueryInterface( riid, ppvObject );");
  74. pStream->NewLine();
  75. pStream->Write( '}' );
  76. pStream->IndentDec();
  77. pStream->NewLine( 2 );
  78. ////////////////////////////////////////////////////////////////////////
  79. // AddRef
  80. pAR->PrintType( PRT_QUALIFIED_NAME | PRT_PROC_PROTOTYPE, pStream, NULL, pClass );
  81. // print a (nearly) empty function body
  82. pStream->IndentInc();
  83. pStream->NewLine();
  84. pStream->Write( '{' );
  85. pStream->NewLine();
  86. pStream->Write("return ");
  87. if ( pDesignatedClassName )
  88. {
  89. pStream->Write( pDesignatedClassName );
  90. pStream->Write( "::" );
  91. }
  92. pStream->Write("pUnkOuter->AddRef();");
  93. pStream->NewLine();
  94. pStream->Write( '}' );
  95. pStream->IndentDec();
  96. pStream->NewLine( 2 );
  97. ////////////////////////////////////////////////////////////////////////
  98. // Release
  99. pRel->PrintType( PRT_QUALIFIED_NAME | PRT_PROC_PROTOTYPE, pStream, NULL, pClass );
  100. // print a (nearly) empty function body
  101. pStream->IndentInc();
  102. pStream->NewLine();
  103. pStream->Write( '{' );
  104. pStream->NewLine();
  105. pStream->Write("return ");
  106. if ( pDesignatedClassName )
  107. {
  108. pStream->Write( pDesignatedClassName );
  109. pStream->Write( "::" );
  110. }
  111. pStream->Write("pUnkOuter->Release();");
  112. pStream->NewLine();
  113. pStream->Write( '}' );
  114. pStream->IndentDec();
  115. pStream->NewLine( 2 );
  116. return CG_OK;
  117. }
  118. CG_STATUS
  119. CG_COM_CLASS::GenComInnerUnknown(
  120. CCB * pCCB,
  121. char * pDesignatedClassName )
  122. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  123. Routine Description:
  124. Generate the COM server file code for the inner IUnknown for a COM class
  125. Arguments:
  126. pCCB - a pointer to the code generation control block.
  127. Return Value:
  128. CG_OK if all is well, error otherwise.
  129. Notes:
  130. ----------------------------------------------------------------------------*/
  131. {
  132. ISTREAM * pStream = pCCB->GetStream();
  133. char * pName = GetSymName();
  134. CG_IUNKNOWN_OBJECT_INTERFACE * pIUnknown = pCCB->GetIUnknownCG();
  135. node_object * pClass = (node_object *) GetType();
  136. MEM_ITER Iter( (node_interface *)pIUnknown->GetType() );
  137. ITERATOR I;
  138. CSzBuffer ExpandedName;
  139. node_object Alternate_Class = *pClass;
  140. char * pMemberQualifier = pName;
  141. BOOL fFirstItf = TRUE;
  142. CG_OBJECT_INTERFACE * pIntf;
  143. char * pItfName;
  144. // make the class name for the inner unknown
  145. ExpandedName.Append( pName );
  146. ExpandedName.Append( "_Internal_Unknown" );
  147. Alternate_Class.SetSymName( ExpandedName );
  148. // get pointers to all the methods
  149. named_node * pQI;
  150. named_node * pAR;
  151. named_node * pRel;
  152. while ( ( pQI = Iter.GetNext() )->NodeKind() != NODE_PROC )
  153. ;
  154. while ( ( pAR = Iter.GetNext() )->NodeKind() != NODE_PROC )
  155. ;
  156. while ( ( pRel = Iter.GetNext() )->NodeKind() != NODE_PROC )
  157. ;
  158. pStream->NewLine();
  159. pStream->Write( pDelimiterString );
  160. pStream->NewLine();
  161. pStream->Write( "// Internal IUnknown implementation for class: " );
  162. pStream->Write( pName );
  163. pStream->NewLine(2);
  164. if ( pDesignatedClassName )
  165. {
  166. pMemberQualifier = pDesignatedClassName;
  167. }
  168. ////////////////////////////////////////////////////////////////////////
  169. // QueryInterface
  170. pQI->PrintType( PRT_QUALIFIED_NAME | PRT_PROC_PROTOTYPE, pStream, NULL, &Alternate_Class );
  171. // print a (nearly) empty function body
  172. pStream->IndentInc();
  173. pStream->NewLine();
  174. pStream->Write( '{' );
  175. pStream->NewLine();
  176. pStream->Write("HRESULT hr = E_NOINTERFACE;");
  177. pStream->NewLine(2);
  178. pStream->Write("*ppvObject = 0;");
  179. pStream->NewLine(2);
  180. // get all provided interfaces,
  181. GetListOfUniqueBaseInterfaces( I );
  182. // now unmark them all
  183. for ( ITERATOR_INIT(I); ITERATOR_GETNEXT( I, pIntf ); pIntf->MarkVisited(FALSE) )
  184. ;
  185. // for now, just do a linear search; see OutInfoSearchRoutine for further scheme
  186. for ( ITERATOR_INIT(I); ITERATOR_GETNEXT( I, pIntf ); pIntf->MarkVisited(FALSE) )
  187. {
  188. if ( pIntf->IsIUnknown() )
  189. continue;
  190. if ( pIntf->GetCGID() == ID_CG_COM_CLASS )
  191. continue;
  192. pItfName = pIntf->GetSymName();
  193. if ( fFirstItf )
  194. {
  195. pStream->Write("if ( IsEqualGUID( riid, IID_IUnknown ) || ");
  196. fFirstItf = FALSE;
  197. }
  198. else
  199. {
  200. pStream->Write("else if ( ");
  201. }
  202. pStream->Write("IsEqualGUID( riid, IID_");
  203. pStream->Write( pItfName );
  204. pStream->Write(" ) )");
  205. pStream->IndentInc();
  206. pStream->NewLine();
  207. pStream->Write( '{' );
  208. pStream->NewLine();
  209. pStream->Write("*ppvObject = GET_MIDL_INTERFACE( ");
  210. pStream->Write( pItfName );
  211. pStream->Write( ", " );
  212. pStream->Write( pName );
  213. pStream->Write( ", ");
  214. pStream->Write( pMemberQualifier );
  215. pStream->Write( " );");
  216. pStream->NewLine();
  217. pStream->Write("hr = S_OK;");
  218. pStream->NewLine();
  219. pStream->Write( '}' );
  220. pStream->IndentDec();
  221. pStream->NewLine( 2 );
  222. }
  223. pStream->Write( "if ( FAILED( hr ) )");
  224. pStream->NewLine();
  225. pStream->Write( " hr = GET_MIDL_CLASS( " );
  226. pStream->Write( pName );
  227. pStream->Write( ", " );
  228. pStream->Write( pMemberQualifier );
  229. pStream->Write( " )" );
  230. pStream->NewLine();
  231. pStream->Write( " ->QueryInterfaceExtension( riid, ppvObject );" );
  232. pStream->NewLine();
  233. pStream->Write( "else" );
  234. pStream->NewLine();
  235. pStream->Write(" AddRef();");
  236. pStream->NewLine();
  237. pStream->Write("return hr;");
  238. pStream->NewLine(2);
  239. pStream->Write( '}' );
  240. pStream->IndentDec();
  241. ////////////////////////////////////////////////////////////////////////
  242. // AddRef
  243. pStream->NewLine( 2 );
  244. pAR->PrintType( PRT_QUALIFIED_NAME | PRT_PROC_PROTOTYPE, pStream, NULL, &Alternate_Class );
  245. // print a (nearly) empty function body
  246. pStream->IndentInc();
  247. pStream->NewLine();
  248. pStream->Write( '{' );
  249. pStream->NewLine();
  250. pStream->Write("IncrementRefCount( ");
  251. if ( pDesignatedClassName )
  252. {
  253. pStream->Write( pDesignatedClassName );
  254. pStream->Write( "::" );
  255. }
  256. pStream->Write("m_ulRefCnt );");
  257. pStream->NewLine();
  258. pStream->Write("return ");
  259. if ( pDesignatedClassName )
  260. {
  261. pStream->Write( pDesignatedClassName );
  262. pStream->Write( "::" );
  263. }
  264. pStream->Write("m_ulRefCnt;");
  265. pStream->NewLine();
  266. pStream->Write( '}' );
  267. pStream->IndentDec();
  268. pStream->NewLine( 2 );
  269. static STRING_BLOCK ReleaseCommonPart =
  270. {
  271. "if ( ulReturned )",
  272. " return ulReturned;",
  273. "",
  274. "// object refcount has dropped to 0",
  275. "",
  276. "//decrement the object count",
  277. "if(DecrementRefCount(gLifetimeInfo.ulObjectRefCnt) == 0)",
  278. "{",
  279. " //The last object in this module has been destroyed.",
  280. " if ( gLifetimeInfo.pfnObjectCleanUpRtn )",
  281. " (*gLifetimeInfo.pfnObjectCleanUpRtn)();",
  282. "}",
  283. "",
  284. "//decrement the module count",
  285. "if(DecrementRefCount(gLifetimeInfo.ulModuleRefCnt) == 0)",
  286. "{",
  287. " //The last object in this module has been destroyed.",
  288. " if ( gLifetimeInfo.pfnModuleCleanUpRtn )",
  289. " (*gLifetimeInfo.pfnModuleCleanUpRtn)();",
  290. "}",
  291. 0
  292. };
  293. ////////////////////////////////////////////////////////////////////////
  294. // Release
  295. pRel->PrintType( PRT_QUALIFIED_NAME | PRT_PROC_PROTOTYPE, pStream, NULL, &Alternate_Class );
  296. // print the function body
  297. pStream->IndentInc();
  298. pStream->NewLine();
  299. pStream->Write( '{' );
  300. pStream->NewLine();
  301. pStream->Write("unsigned long ulReturned = DecrementRefCount( ");
  302. if ( pDesignatedClassName )
  303. {
  304. pStream->Write( pDesignatedClassName );
  305. pStream->Write( "::" );
  306. }
  307. pStream->Write("m_ulRefCnt );");
  308. pStream->WriteBlock( ReleaseCommonPart );
  309. pStream->NewLine(2);
  310. pStream->Write("delete GET_MIDL_CLASS( ");
  311. pStream->Write( pName );
  312. pStream->Write( ", " );
  313. pStream->Write( pMemberQualifier );
  314. pStream->Write( " );" );
  315. pStream->NewLine();
  316. pStream->Write( "return 0;" );
  317. pStream->NewLine();
  318. pStream->Write( '}' );
  319. pStream->IndentDec();
  320. pStream->NewLine( 2 );
  321. return CG_OK;
  322. }
  323. CG_STATUS
  324. CG_COM_CLASS::GenComClassConstructor(
  325. CCB * pCCB,
  326. char * pDesignatedClassName )
  327. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  328. Routine Description:
  329. Generate the COM server file code for the constructor for a COM class
  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. ISTREAM * pStream = pCCB->GetStream();
  338. char * pName = GetSymName();
  339. pStream->Write( pDelimiterString );
  340. pStream->NewLine();
  341. pStream->Write("// Constructor");
  342. pStream->NewLine();
  343. pStream->Write("// Override InitInstance to do your own initialization");
  344. pStream->NewLine(2);
  345. pStream->Write( pName );
  346. pStream->Write( "::" );
  347. pStream->Write( pName );
  348. pStream->Write( "( IUnknown * pUnknownOuter )" );
  349. pStream->IndentInc();
  350. pStream->NewLine();
  351. pStream->Write( '{' );
  352. pStream->NewLine();
  353. pStream->Write( "// support aggregation");
  354. pStream->NewLine();
  355. pStream->Write( "if ( !pUnknownOuter )");
  356. pStream->IndentInc();
  357. pStream->NewLine();
  358. if ( pDesignatedClassName )
  359. {
  360. pStream->Write( pDesignatedClassName );
  361. pStream->Write( "::" );
  362. }
  363. pStream->Write( "pUnkOuter = (IUnknown*) &");
  364. if ( pDesignatedClassName )
  365. {
  366. pStream->Write( pDesignatedClassName );
  367. pStream->Write( "::" );
  368. }
  369. pStream->Write( "m_UnkInner;");
  370. pStream->IndentDec();
  371. pStream->NewLine();
  372. pStream->Write( "else");
  373. pStream->IndentInc();
  374. pStream->NewLine();
  375. if ( pDesignatedClassName )
  376. {
  377. pStream->Write( pDesignatedClassName );
  378. pStream->Write( "::" );
  379. }
  380. pStream->Write( "pUnkOuter = pUnknownOuter;");
  381. pStream->IndentDec();
  382. pStream->NewLine(2);
  383. pStream->Write( "CONSTRUCT_INNER_UNKNOWN( ");
  384. pStream->Write( pName );
  385. pStream->Write( ", " );
  386. pStream->Write( (pDesignatedClassName) ? pDesignatedClassName : pName );
  387. pStream->Write( " );" );
  388. pStream->NewLine(2);
  389. pStream->Write( '}' );
  390. pStream->IndentDec();
  391. pStream->NewLine( 2 );
  392. return CG_OK;
  393. }
  394. CG_STATUS
  395. CG_COM_CLASS::GenComClassIUnknown(
  396. CCB * pCCB )
  397. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  398. Routine Description:
  399. Generate the COM server file code for the IUnknown for a COM class
  400. Arguments:
  401. pCCB - a pointer to the code generation control block.
  402. Return Value:
  403. CG_OK if all is well, error otherwise.
  404. Notes:
  405. ----------------------------------------------------------------------------*/
  406. {
  407. ISTREAM * pStream = pCCB->GetStream();
  408. char * pName = GetSymName();
  409. pCCB->SetInterfaceCG( this );
  410. pStream->NewLine();
  411. pStream->Write( pDelimiterString );
  412. pStream->NewLine();
  413. pStream->Write( pDelimiterString );
  414. pStream->NewLine();
  415. pStream->Write( "// IUnknown implementations for class: " );
  416. pStream->Write( pName );
  417. pStream->NewLine(2);
  418. // generate the outer unknown methods that defer to the punkOuter
  419. GenComOuterUnknown( pCCB, NULL );
  420. // generate the inner unknown methods
  421. GenComInnerUnknown( pCCB, NULL );
  422. // generate the constructor
  423. GenComClassConstructor( pCCB, NULL );
  424. return CG_OK;
  425. }
  426. CG_STATUS
  427. CG_COM_CLASS::GenComClassFactory(
  428. CCB * pCCB )
  429. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  430. Routine Description:
  431. Generate the COM server file code for the class factory for a COM class
  432. Arguments:
  433. pCCB - a pointer to the code generation control block.
  434. Return Value:
  435. CG_OK if all is well, error otherwise.
  436. Notes:
  437. ----------------------------------------------------------------------------*/
  438. {
  439. ISTREAM * pStream = pCCB->GetStream();
  440. char * pName = GetSymName();
  441. pCCB->SetInterfaceCG( this );
  442. pStream->NewLine();
  443. pStream->Write( pDelimiterString );
  444. pStream->NewLine();
  445. pStream->Write( "// ClassFactory implementation for class: " );
  446. pStream->Write( pName );
  447. pStream->NewLine(2);
  448. // make the CreateInstance routine
  449. GenComClassFactoryCreateInstance( pCCB );
  450. // make the tables, and construct the object and the info
  451. GenComClassFactoryTables( pCCB );
  452. pStream->NewLine(2);
  453. return CG_OK;
  454. }
  455. CG_STATUS
  456. CG_COM_CLASS::GenComClassFactoryCreateInstance(
  457. CCB * pCCB )
  458. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  459. Routine Description:
  460. Generate the COM server file code for the class factory for a COM class
  461. Arguments:
  462. pCCB - a pointer to the code generation control block.
  463. Return Value:
  464. CG_OK if all is well, error otherwise.
  465. Notes:
  466. ----------------------------------------------------------------------------*/
  467. {
  468. ISTREAM * pStream = pCCB->GetStream();
  469. char * pName = GetSymName();
  470. CG_OBJECT_INTERFACE * pIClassf = pCCB->GetIClassfCG();
  471. node_interface * pIClassfNode = (node_interface*)pIClassf->GetType();
  472. CG_OBJECT_PROC * pCreateInstance = (CG_OBJECT_PROC *) pIClassf->GetChild();
  473. node_proc * pCreateInstNode = (node_proc*) pCreateInstance->GetType();
  474. node_call_as * pAttr;
  475. if ( pAttr = (node_call_as *) pCreateInstNode->GetAttribute( ATTR_CALL_AS ) )
  476. {
  477. pCreateInstNode = (node_proc *) pAttr->GetCallAsType();
  478. }
  479. // a new node_proc (on the stack)
  480. node_proc RenamedProc( pCreateInstNode );
  481. CSzBuffer NewName;
  482. NewName.Append( pName );
  483. NewName.Append( "_Factory_CreateInstance" );
  484. RenamedProc.SetSymName( NewName );
  485. RenamedProc.PrintType( PRT_THIS_POINTER | PRT_PROC_PROTOTYPE, pStream, NULL, pIClassfNode );
  486. // print the function body
  487. pStream->IndentInc();
  488. pStream->NewLine();
  489. pStream->Write( '{' );
  490. pStream->NewLine();
  491. pStream->Write("HRESULT hr = E_OUTOFMEMORY;");
  492. pStream->NewLine();
  493. pStream->Write( pName );
  494. pStream->Write(" * pInstance;");
  495. pStream->NewLine(2);
  496. pStream->Write("*ppvObject = 0;");
  497. pStream->NewLine(2);
  498. pStream->Write("pInstance = new ");
  499. pStream->Write( pName );
  500. pStream->Write( "( pUnkOuter );");
  501. static STRING_BLOCK CreateInstanceCommonPart =
  502. {
  503. "if ( pInstance )",
  504. " {",
  505. " hr = pInstance->InitInstance( pUnkOuter, riid, ppvObject );",
  506. " if ( FAILED( hr ) )",
  507. " {",
  508. " delete pInstance;",
  509. " return hr;",
  510. " }",
  511. "",
  512. " //increment the object count.",
  513. " //The module count will keep this process alive until all",
  514. " //objects in this module are released.",
  515. " IncrementRefCount( gLifetimeInfo.ulModuleRefCnt );",
  516. " IncrementRefCount( gLifetimeInfo.ulObjectRefCnt );",
  517. " hr = pInstance->QueryInterface( riid, (void**)ppvObject);",
  518. " }",
  519. "",
  520. "return hr;",
  521. 0
  522. };
  523. pStream->NewLine();
  524. pStream->WriteBlock( CreateInstanceCommonPart );
  525. pStream->NewLine();
  526. pStream->Write( '}' );
  527. pStream->IndentDec();
  528. pStream->NewLine( 2 );
  529. return CG_OK;
  530. }
  531. CG_STATUS
  532. CG_COM_CLASS::GenComClassFactoryTables(
  533. CCB * pCCB )
  534. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  535. Routine Description:
  536. Generate the COM server file code for the class factory for a COM class
  537. Arguments:
  538. pCCB - a pointer to the code generation control block.
  539. Return Value:
  540. CG_OK if all is well, error otherwise.
  541. Notes:
  542. ----------------------------------------------------------------------------*/
  543. {
  544. ISTREAM * pStream = pCCB->GetStream();
  545. char * pName = GetSymName();
  546. pStream->NewLine(2);
  547. pStream->Write( pDelimiterString );
  548. pStream->NewLine();
  549. pStream->Write( "// important data structures for the class factory and server" );
  550. // print the vtable
  551. pStream->NewLine(2);
  552. pStream->Write( "const struct Midl_Factory_Object_Vtbl " );
  553. pStream->Write( pName );
  554. pStream->Write( "_Factory_Object_Vtbl =" );
  555. pStream->IndentInc();
  556. pStream->NewLine();
  557. pStream->Write( '{' );
  558. pStream->NewLine();
  559. pStream->Write( "&Generic_Midl_Factory_QueryInterface," );
  560. pStream->NewLine();
  561. pStream->Write( "&Generic_Midl_Factory_AddRef," );
  562. pStream->NewLine();
  563. pStream->Write( "&Generic_Midl_Factory_Release," );
  564. pStream->NewLine();
  565. pStream->Write( '&' );
  566. pStream->Write( pName );
  567. pStream->Write( "_Factory_CreateInstance," );
  568. pStream->NewLine();
  569. pStream->Write( "&Generic_Midl_Factory_LockServer," );
  570. pStream->NewLine();
  571. pStream->Write( "};" );
  572. pStream->IndentDec();
  573. // print the object instance
  574. pStream->NewLine(2);
  575. pStream->Write( "const CMidlFactory_Object " );
  576. pStream->Write( pName );
  577. pStream->Write( "_Factory_Object =" );
  578. pStream->IndentInc();
  579. pStream->NewLine();
  580. pStream->Write( '{' );
  581. pStream->NewLine();
  582. pStream->Write( '&' );
  583. pStream->Write( pName );
  584. pStream->Write( "_Factory_Object_Vtbl," );
  585. pStream->NewLine();
  586. pStream->Write( "&gLifetimeInfo" );
  587. pStream->NewLine();
  588. pStream->Write( "};" );
  589. pStream->IndentDec();
  590. // print the object pointer instance
  591. pStream->NewLine(2);
  592. //pStream->Write( "const " );
  593. pStream->Write( pName );
  594. pStream->Write( "_Factory * p" );
  595. pStream->Write( pName );
  596. pStream->Write( "_Factory = ");
  597. pStream->IndentInc();
  598. pStream->IndentInc();
  599. pStream->IndentInc();
  600. pStream->NewLine();
  601. pStream->Write( '(' );
  602. pStream->Write( pName );
  603. pStream->Write( "_Factory *) &" );
  604. pStream->Write( pName );
  605. pStream->Write( "_Factory_Object;" );
  606. pStream->IndentDec();
  607. pStream->IndentDec();
  608. pStream->IndentDec();
  609. // print the factory info block
  610. pStream->NewLine(2);
  611. pStream->Write( "// here is the class factory info block" );
  612. pStream->NewLine();
  613. pStream->Write( "Midl_Class_Factory_Info " );
  614. pStream->Write( pName );
  615. pStream->Write( "_Factory_Info =" );
  616. pStream->IndentInc();
  617. pStream->NewLine();
  618. pStream->Write( '{' );
  619. pStream->NewLine();
  620. pStream->Write( '\"' );
  621. pStream->Write( pName );
  622. pStream->Write( "\"," );
  623. pStream->NewLine();
  624. pStream->Write( "&CLSID_" );
  625. pStream->Write( pName );
  626. pStream->Write( ',' );
  627. pStream->NewLine();
  628. pStream->Write( "(CGenericMidlClassFactory** )&p" );
  629. pStream->Write( pName );
  630. pStream->Write( "_Factory" );
  631. pStream->NewLine();
  632. pStream->Write( "};" );
  633. pStream->IndentDec();
  634. return CG_OK;
  635. }
  636. CG_STATUS
  637. CG_COM_CLASS::GenComClassServer(
  638. CCB * pCCB )
  639. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  640. Routine Description:
  641. Generate the COM server file code for the class
  642. implementation for a COM class defined in the IDL file.
  643. Arguments:
  644. pCCB - a pointer to the code generation control block.
  645. Return Value:
  646. CG_OK if all is well, error otherwise.
  647. Notes:
  648. ----------------------------------------------------------------------------*/
  649. {
  650. ISTREAM * pStream = pCCB->GetStream();
  651. const char * pName = GetSymName();
  652. CG_OBJECT_INTERFACE * pIntf;
  653. ITERATOR I;
  654. MIDL_TOKEN FlagToken( START_CLASS_TOKEN, pName );
  655. pCCB->SetInterfaceCG( this );
  656. pStream->NewLine();
  657. pStream->EmitToken( FlagToken );
  658. pStream->NewLine();
  659. pStream->Write( pDelimiterString );
  660. pStream->NewLine();
  661. pStream->Write( "// COM class server for class: " );
  662. pStream->Write( pName );
  663. pStream->NewLine();
  664. // go through all the methods, emitting shell code
  665. // for IUnknown, emit special code
  666. // for con/destructors, emit special code
  667. // go through all base interfaces, printing them and THEIR base
  668. // interfaces, avoiding duplicates...
  669. GetListOfUniqueBaseInterfaces( I );
  670. // now print them all, unmarking as we go
  671. for ( ITERATOR_INIT(I); ITERATOR_GETNEXT( I, pIntf ); pIntf->MarkVisited(FALSE) )
  672. {
  673. CSzBuffer NameBuffer;
  674. char * pIntfName;
  675. if ( pIntf->IsIUnknown() )
  676. continue;
  677. pIntfName = pIntf->GetInterfaceName();
  678. NameBuffer.Append( pName );
  679. NameBuffer.Append( "::" );
  680. NameBuffer.Append( pIntfName );
  681. pStream->NewLine( 2 );
  682. pStream->EmitToken( MIDL_TOKEN( START_CLASS_METHODS_TOKEN, NameBuffer ) );
  683. pStream->NewLine();
  684. pStream->Write( pDelimiterString );
  685. pStream->NewLine();
  686. pStream->Write("// Member functions from: ");
  687. pStream->Write( ( pIntf->GetCGID() == ID_CG_COM_CLASS ) ? "Class " : "Interface " );
  688. pStream->Write( pIntfName );
  689. pStream->NewLine();
  690. pIntf->GenComClassServerMembers( pCCB );
  691. }
  692. pStream->NewLine( 2 );
  693. pStream->Write( pDelimiterString );
  694. pStream->NewLine( 2 );
  695. pStream->EmitToken( MIDL_TOKEN( CLASS_DESTRUCTOR_TOKEN, pName ) );
  696. pStream->NewLine();
  697. pStream->Write("// virtual destructor");
  698. pStream->NewLine();
  699. pStream->Write( pName );
  700. pStream->Write( "::~" );
  701. pStream->Write( pName );
  702. pStream->Write( "()" );
  703. pStream->IndentInc();
  704. pStream->NewLine();
  705. pStream->Write( '{' );
  706. pStream->NewLine(2);
  707. pStream->Write( "// TODO: fill in any destructor action" );
  708. pStream->NewLine(2);
  709. pStream->Write( '}' );
  710. pStream->IndentDec();
  711. pStream->NewLine();
  712. pStream->NewLine();
  713. pStream->NewLine();
  714. FlagToken.SetTokenType( END_CLASS_TOKEN );
  715. pStream->EmitToken( FlagToken );
  716. pStream->Write( '\n' );
  717. return CG_OK;
  718. }
  719. CG_STATUS
  720. CG_COM_CLASS::ReGenComClassServer(
  721. CCB * pCCB )
  722. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  723. Routine Description:
  724. Generate the COM server file code for the class
  725. implementation for a COM class defined in the IDL file.
  726. Arguments:
  727. pCCB - a pointer to the code generation control block.
  728. Return Value:
  729. CG_OK if all is well, error otherwise.
  730. Notes:
  731. ----------------------------------------------------------------------------*/
  732. {
  733. RW_ISTREAM * pStream = (RW_ISTREAM *)pCCB->GetStream();
  734. const char * pName = GetSymName();
  735. CG_OBJECT_INTERFACE * pIntf;
  736. ITERATOR I;
  737. MIDL_TOKEN FoundToken;
  738. MIDL_TOKEN FlagToken( START_CLASS_TOKEN, pName );
  739. pCCB->SetInterfaceCG( this );
  740. pStream->SaveToNextMidlToken( FoundToken );
  741. if ( FoundToken.GetTokenType() != START_CLASS_TOKEN )
  742. {
  743. assert( !"bad token found" );
  744. }
  745. pStream->EmitToken( FlagToken );
  746. pStream->NewLine();
  747. // go through all the methods, emitting shell code
  748. // for IUnknown, emit special code
  749. // for con/destructors, emit special code
  750. // go through all base interfaces, printing them and THEIR base
  751. // interfaces, avoiding duplicates...
  752. GetListOfUniqueBaseInterfaces( I );
  753. // now print them all, unmarking as we go
  754. for ( ITERATOR_INIT(I); ITERATOR_GETNEXT( I, pIntf ); pIntf->MarkVisited(FALSE) )
  755. {
  756. CSzBuffer NameBuffer;
  757. char * pIntfName;
  758. if ( pIntf->IsIUnknown() )
  759. continue;
  760. pStream->SaveToNextMidlToken( FoundToken );
  761. if ( FoundToken.GetTokenType() != START_CLASS_METHODS_TOKEN )
  762. {
  763. assert( !"bad token found" );
  764. }
  765. pIntfName = pIntf->GetInterfaceName();
  766. NameBuffer.Append( pName );
  767. NameBuffer.Append( "::" );
  768. NameBuffer.Append( pIntfName );
  769. pStream->EmitToken( MIDL_TOKEN( START_CLASS_METHODS_TOKEN, NameBuffer ) );
  770. pStream->NewLine();
  771. pIntf->ReGenComClassServerMembers( pCCB );
  772. }
  773. pStream->SaveToNextMidlToken( FoundToken );
  774. if ( FoundToken.GetTokenType() != CLASS_DESTRUCTOR_TOKEN )
  775. {
  776. assert( !"bad token found" );
  777. }
  778. pStream->EmitToken( MIDL_TOKEN( CLASS_DESTRUCTOR_TOKEN, pName ) );
  779. pStream->NewLine();
  780. pStream->SaveToNextMidlToken( FoundToken );
  781. if ( FoundToken.GetTokenType() != END_CLASS_TOKEN )
  782. {
  783. assert( !"bad token found" );
  784. }
  785. FlagToken.SetTokenType( END_CLASS_TOKEN );
  786. pStream->EmitToken( FlagToken );
  787. pStream->Write( '\n' );
  788. return CG_OK;
  789. }
  790. CG_STATUS
  791. CG_OBJECT_INTERFACE::GenComClassServerMembers(
  792. CCB * pCCB )
  793. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  794. Routine Description:
  795. Generate the COM server file code for an interface inherited by a
  796. COM class defined in the IDL file.
  797. Arguments:
  798. pCCB - a pointer to the code generation control block.
  799. Return Value:
  800. CG_OK if all is well, error otherwise.
  801. Notes:
  802. ----------------------------------------------------------------------------*/
  803. {
  804. CG_ITERATOR I;
  805. CG_OBJECT_PROC * pCG;
  806. if( !GetMembers( I ) )
  807. {
  808. return CG_OK;
  809. }
  810. while( ITERATOR_GETNEXT( I, pCG ) )
  811. {
  812. pCG->GenComClassMemberFunction( pCCB );
  813. }
  814. return CG_OK;
  815. }
  816. CG_STATUS
  817. CG_OBJECT_INTERFACE::ReGenComClassServerMembers(
  818. CCB * pCCB )
  819. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  820. Routine Description:
  821. Generate the COM server file code for an interface inherited by a
  822. COM class defined in the IDL file.
  823. Arguments:
  824. pCCB - a pointer to the code generation control block.
  825. Return Value:
  826. CG_OK if all is well, error otherwise.
  827. Notes:
  828. ----------------------------------------------------------------------------*/
  829. {
  830. CG_ITERATOR I;
  831. CG_OBJECT_PROC * pCG;
  832. if( !GetMembers( I ) )
  833. {
  834. return CG_OK;
  835. }
  836. while( ITERATOR_GETNEXT( I, pCG ) )
  837. {
  838. pCG->ReGenComClassMemberFunction( pCCB );
  839. }
  840. return CG_OK;
  841. }
  842. CG_STATUS
  843. CG_OBJECT_PROC::GenComClassMemberFunction(
  844. CCB * pCCB )
  845. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  846. Routine Description:
  847. Generate the COM server file code for an interface inherited by a
  848. COM class defined in the IDL file.
  849. Arguments:
  850. pCCB - a pointer to the code generation control block.
  851. Return Value:
  852. CG_OK if all is well, error otherwise.
  853. Notes:
  854. ----------------------------------------------------------------------------*/
  855. {
  856. node_proc * pTypeNode = (node_proc *) GetType();
  857. ISTREAM * pStream = pCCB->GetStream();
  858. node_skl * pClass = pCCB->GetInterfaceCG()->GetType();
  859. CSzBuffer NameBuffer;
  860. NameBuffer.Append( pClass->GetSymName() );
  861. NameBuffer.Append( "::" );
  862. NameBuffer.Append( pTypeNode->GetSymName() );
  863. MIDL_TOKEN FlagToken( START_METHOD_TOKEN, NameBuffer );
  864. pStream->NewLine();
  865. pStream->EmitToken( FlagToken );
  866. pStream->NewLine(2);
  867. pTypeNode->PrintType( PRT_QUALIFIED_NAME | PRT_PROC_PROTOTYPE, pStream, NULL, pClass );
  868. // print a (nearly) empty function body
  869. pStream->IndentInc();
  870. pStream->NewLine(2);
  871. FlagToken.SetTokenType( START_METHOD_BODY_TOKEN );
  872. pStream->EmitToken( FlagToken );
  873. pStream->NewLine();
  874. pStream->NewLine();
  875. pStream->Write( '{' );
  876. pStream->NewLine(2);
  877. pStream->Write("// uncomment the below macro if you make calls out and may get");
  878. pStream->NewLine();
  879. pStream->Write("// a Release() while blocked on the call.");
  880. pStream->NewLine();
  881. pStream->Write("// MAKES_REENTERABLE_CALLS");
  882. pStream->NewLine(2);
  883. pStream->Write("// TODO: Fill in this method with your code");
  884. pStream->NewLine(2);
  885. pStream->Write("return S_OK;");
  886. pStream->NewLine(2);
  887. pStream->Write( '}' );
  888. pStream->IndentDec();
  889. pStream->NewLine( 2 );
  890. return CG_OK;
  891. }
  892. CG_STATUS
  893. CG_OBJECT_PROC::ReGenComClassMemberFunction(
  894. CCB * pCCB )
  895. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  896. Routine Description:
  897. Generate the COM server file code for an interface inherited by a
  898. COM class defined in the IDL file.
  899. Arguments:
  900. pCCB - a pointer to the code generation control block.
  901. Return Value:
  902. CG_OK if all is well, error otherwise.
  903. Notes:
  904. ----------------------------------------------------------------------------*/
  905. {
  906. node_proc * pTypeNode = (node_proc *) GetType();
  907. RW_ISTREAM * pStream = (RW_ISTREAM*)pCCB->GetStream();
  908. node_skl * pClass = pCCB->GetInterfaceCG()->GetType();
  909. MIDL_TOKEN FoundToken;
  910. CSzBuffer NameBuffer;
  911. NameBuffer.Append( pClass->GetSymName() );
  912. NameBuffer.Append( "::" );
  913. NameBuffer.Append( pTypeNode->GetSymName() );
  914. pStream->SaveToNextMidlToken( FoundToken );
  915. if ( FoundToken.GetTokenType() != START_METHOD_TOKEN )
  916. {
  917. assert( !"bad token found" );
  918. }
  919. MIDL_TOKEN FlagToken( START_METHOD_TOKEN, NameBuffer );
  920. pStream->EmitToken( FlagToken );
  921. pStream->NewLine(2);
  922. pTypeNode->PrintType( PRT_QUALIFIED_NAME | PRT_PROC_PROTOTYPE, pStream, NULL, pClass );
  923. // print a (nearly) empty function body
  924. pStream->IndentInc();
  925. pStream->NewLine(2);
  926. pStream->DiscardToNextMidlToken( FoundToken );
  927. if ( FoundToken.GetTokenType() != START_METHOD_BODY_TOKEN )
  928. {
  929. assert( !"bad token found" );
  930. }
  931. FlagToken.SetTokenType( START_METHOD_BODY_TOKEN );
  932. pStream->EmitToken( FlagToken );
  933. pStream->IndentDec();
  934. pStream->NewLine();
  935. return CG_OK;
  936. }
  937. CG_COM_SERVER::CG_COM_SERVER(
  938. node_com_server * pI,
  939. ITERATOR * pBCG
  940. )
  941. : CG_NDR( pI, XLAT_SIZE_INFO() )
  942. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  943. Routine Description:
  944. constructor for a com server DLL or EXE base class.
  945. Arguments:
  946. pI - a pointer to the node in the typegraph.
  947. Return Value:
  948. none.
  949. Notes:
  950. ----------------------------------------------------------------------------*/
  951. {
  952. pBaseCGList = pBCG;
  953. }
  954. CG_STATUS
  955. CG_COM_SERVER::GenClassFactoryArray(
  956. CCB * pCCB )
  957. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  958. Routine Description:
  959. Generate the data structures for the _g.cxx file.
  960. Arguments:
  961. pCCB - a pointer to the code generation control block.
  962. Return Value:
  963. CG_OK if all is well, error otherwise.
  964. Notes:
  965. ----------------------------------------------------------------------------*/
  966. {
  967. ISTREAM * pStream = pCCB->GetStream();
  968. ITERATOR * pClassList = GetClassList();
  969. CG_COM_CLASS * pClassCG;
  970. pStream->NewLine();
  971. pStream->Write( "// here are the class factories all connected together" );
  972. pStream->NewLine();
  973. pStream->Write( "const Midl_Class_Factory_Info * Midl_Class_Factory_Array[] =" );
  974. pStream->IndentInc();
  975. pStream->NewLine();
  976. pStream->Write( '{' );
  977. ITERATOR_INIT( *pClassList );
  978. while ( ITERATOR_GETNEXT ( *pClassList, pClassCG ) )
  979. {
  980. pStream->NewLine();
  981. pStream->Write( '&' );
  982. pStream->Write( pClassCG->GetSymName() );
  983. pStream->Write( "_Factory_Info," );
  984. }
  985. pStream->NewLine();
  986. pStream->Write( "0 // terminator" );
  987. pStream->NewLine();
  988. pStream->Write( "};" );
  989. pStream->IndentDec();
  990. pStream->NewLine();
  991. return CG_OK;
  992. }
  993. CG_STATUS
  994. CG_COM_SERVER_DLL::GenDataStructures(
  995. CCB * pCCB )
  996. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  997. Routine Description:
  998. Generate the data structures for the _g.cxx file.
  999. Arguments:
  1000. pCCB - a pointer to the code generation control block.
  1001. Return Value:
  1002. CG_OK if all is well, error otherwise.
  1003. Notes:
  1004. ----------------------------------------------------------------------------*/
  1005. {
  1006. ISTREAM * pStream = pCCB->GetStream();
  1007. unsigned long ulClassCnt = ITERATOR_GETCOUNT( *GetClassList() );
  1008. pStream->NewLine();
  1009. pStream->Write( "// the number of classes provided by this DLL" );
  1010. pStream->NewLine();
  1011. pStream->Write( "const unsigned long ulClassCnt = " );
  1012. pStream->WriteNumber( "%d", ulClassCnt );
  1013. pStream->Write( ";" );
  1014. pStream->NewLine(2);
  1015. GenClassFactoryArray( pCCB );
  1016. static STRING_BLOCK DataStructs =
  1017. {
  1018. "// lifetime information for the module (dll) containing this object",
  1019. "struct MidlModuleLifetimeInfo gLifetimeInfo =",
  1020. " {",
  1021. " 0, // ulModuleRefCnt",
  1022. " NULL,",
  1023. " 0, // ulObjectRefCnt",
  1024. " NULL",
  1025. " };",
  1026. "",
  1027. "HINSTANCE hProxyDll = 0;",
  1028. 0
  1029. };
  1030. pStream->NewLine();
  1031. pStream->WriteBlock( DataStructs );
  1032. pStream->NewLine(2);
  1033. return CG_OK;
  1034. }
  1035. CG_STATUS
  1036. CG_COM_SERVER_DLL::GenEntryPts(
  1037. CCB * pCCB )
  1038. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1039. Routine Description:
  1040. Generate the DllGetClassObject and DllCanUnloadNow code for an inprocserver32.
  1041. Arguments:
  1042. pCCB - a pointer to the code generation control block.
  1043. Return Value:
  1044. CG_OK if all is well, error otherwise.
  1045. Notes:
  1046. ----------------------------------------------------------------------------*/
  1047. {
  1048. ISTREAM * pStream = pCCB->GetStream();
  1049. char * pName = GetSymName();
  1050. #if 0
  1051. ITERATOR * pClassList = GetClassList();
  1052. CG_COM_CLASS * pClassCG;
  1053. #endif
  1054. static STRING_BLOCK DGCO_header =
  1055. {
  1056. " REFCLSID rclsid,",
  1057. " REFIID riid,",
  1058. " void ** ppv )",
  1059. "{",
  1060. " HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;",
  1061. " unsigned long idx;",
  1062. "",
  1063. " // lookup customized for this DLL",
  1064. 0
  1065. };
  1066. pStream->NewLine();
  1067. pStream->Write( "EXTERN_C HRESULT STDAPICALLTYPE " );
  1068. pStream->Write( pName );
  1069. pStream->Write( "_DllGetClassObject (" );
  1070. pStream->NewLine();
  1071. pStream->WriteBlock( DGCO_header );
  1072. pStream->IndentInc();
  1073. // tbd - for now, just do linear search
  1074. static STRING_BLOCK DGCO_search =
  1075. {
  1076. "for( idx = 0; idx < ulClassCnt; idx++ )",
  1077. " {",
  1078. " if ( IsEqualGUID( rclsid, *Midl_Class_Factory_Array[idx]->pFactoryID ) )",
  1079. " {",
  1080. " hr = (*Midl_Class_Factory_Array[idx]->ppFactory)->QueryInterface( riid, ppv );",
  1081. " break;",
  1082. " }",
  1083. " }",
  1084. 0
  1085. };
  1086. pStream->WriteBlock( DGCO_search );
  1087. pStream->IndentDec();
  1088. static STRING_BLOCK DGCO_trailer =
  1089. {
  1090. " // fail case",
  1091. " if ( FAILED (hr) )",
  1092. " *ppv = 0;",
  1093. " return hr;",
  1094. "}",
  1095. "",
  1096. 0
  1097. };
  1098. pStream->NewLine();
  1099. pStream->WriteBlock( DGCO_trailer );
  1100. static STRING_BLOCK DCUN =
  1101. {
  1102. "{",
  1103. " return (gLifetimeInfo.ulModuleRefCnt) ? S_FALSE : S_OK;",
  1104. "}",
  1105. 0
  1106. };
  1107. pStream->NewLine();
  1108. pStream->Write( "EXTERN_C HRESULT STDAPICALLTYPE " );
  1109. pStream->Write( pName );
  1110. pStream->Write( "_DllCanUnloadNow()" );
  1111. pStream->NewLine();
  1112. pStream->WriteBlock( DCUN );
  1113. return CG_OK;
  1114. }
  1115. CG_STATUS
  1116. CG_COM_SERVER_DLL::GenRegistryEntryPts(
  1117. CCB * pCCB )
  1118. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1119. Routine Description:
  1120. Generate the dllmain, RegisterServer and UnRegisterServer entry points.
  1121. Arguments:
  1122. pCCB - a pointer to the code generation control block.
  1123. Return Value:
  1124. CG_OK if all is well, error otherwise.
  1125. Notes:
  1126. ----------------------------------------------------------------------------*/
  1127. {
  1128. ISTREAM * pStream = pCCB->GetStream();
  1129. char * pName = GetSymName();
  1130. pStream->NewLine(2);
  1131. static STRING_BLOCK DllEntryPt =
  1132. {
  1133. " HINSTANCE hinstDLL,",
  1134. " DWORD fdwReason,",
  1135. " LPVOID lpvReserved)",
  1136. "{",
  1137. " if(fdwReason == DLL_PROCESS_ATTACH)",
  1138. " hProxyDll = hinstDLL;",
  1139. " return TRUE;",
  1140. "}",
  1141. 0
  1142. };
  1143. pStream->NewLine();
  1144. pStream->Write( "EXTERN_C BOOL WINAPI " );
  1145. pStream->Write( pName );
  1146. pStream->Write( "_DllEntryPoint(" );
  1147. pStream->NewLine();
  1148. pStream->WriteBlock( DllEntryPt );
  1149. static STRING_BLOCK DllRegSvr =
  1150. {
  1151. "{",
  1152. " return S_OK;",
  1153. " //tbd return NdrDllRegisterServer(hProxyDll, pProxyFileList, pClsID);",
  1154. "}",
  1155. 0
  1156. };
  1157. pStream->NewLine(2);
  1158. pStream->Write( "EXTERN_C HRESULT STDAPICALLTYPE " );
  1159. pStream->Write( pName );
  1160. pStream->Write( "_DllRegisterServer()" );
  1161. pStream->NewLine();
  1162. pStream->WriteBlock( DllRegSvr );
  1163. static STRING_BLOCK DllUnRegSvr =
  1164. {
  1165. "{",
  1166. " return S_OK;",
  1167. " //tbd return NdrDllUnregisterServer(hProxyDll, pProxyFileList, pClsID);",
  1168. "}",
  1169. 0
  1170. };
  1171. pStream->NewLine(2);
  1172. pStream->Write( "EXTERN_C HRESULT STDAPICALLTYPE " );
  1173. pStream->Write( pName );
  1174. pStream->Write( "_DllUnregisterServer()" );
  1175. pStream->NewLine();
  1176. pStream->WriteBlock( DllRegSvr );
  1177. pStream->NewLine(2);
  1178. return CG_OK;
  1179. }
  1180. CG_STATUS
  1181. CG_COM_SERVER_DLL::GenDllDefFile(
  1182. CCB * pCCB )
  1183. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1184. Routine Description:
  1185. Generate the def file for the InprocServer32.
  1186. Arguments:
  1187. pCCB - a pointer to the code generation control block.
  1188. Return Value:
  1189. CG_OK if all is well, error otherwise.
  1190. Notes:
  1191. ----------------------------------------------------------------------------*/
  1192. {
  1193. ISTREAM * pStream = pCCB->GetStream();
  1194. char * pName = GetSymName();
  1195. pStream->NewLine();
  1196. pStream->Write( "; to override the functionality of one of these entries, point" );
  1197. pStream->NewLine();
  1198. pStream->Write( "; the export to your routine (which may call the generated routine)" );
  1199. pStream->NewLine(2);
  1200. pStream->Write( "LIBRARY" );
  1201. pStream->NewLine( 2 );
  1202. pStream->Write( "DESCRIPTION \'" );
  1203. pStream->Write( pName );
  1204. pStream->Write( " InprocServer32 DLL\'" );
  1205. pStream->NewLine( 2 );
  1206. pStream->Write( "EXPORTS" );
  1207. pStream->IndentInc();
  1208. pStream->NewLine( 2 );
  1209. pStream->Write( "DllGetClassObject = " );
  1210. pStream->Write( pName );
  1211. pStream->Write( "_DllGetClassObject" );
  1212. pStream->NewLine();
  1213. pStream->Write( "DllCanUnloadNow = " );
  1214. pStream->Write( pName );
  1215. pStream->Write( "_DllCanUnloadNow" );
  1216. pStream->NewLine();
  1217. pStream->Write( "DllRegisterServer = " );
  1218. pStream->Write( pName );
  1219. pStream->Write( "_DllRegisterServer" );
  1220. pStream->NewLine();
  1221. pStream->Write( "DllUnregisterServer = " );
  1222. pStream->Write( pName );
  1223. pStream->Write( "_DllUnregisterServer" );
  1224. pStream->NewLine();
  1225. pStream->Write( "DllMain = " );
  1226. pStream->Write( pName );
  1227. pStream->Write( "_DllEntryPoint" );
  1228. pStream->IndentDec();
  1229. pStream->NewLine(2);
  1230. return CG_OK;
  1231. }
  1232. CG_STATUS
  1233. CG_COM_SERVER_DLL::GenCode(
  1234. CCB * pCCB )
  1235. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1236. Routine Description:
  1237. Generate the COM server file code for an interface inherited by a
  1238. COM class defined in the IDL file.
  1239. Arguments:
  1240. pCCB - a pointer to the code generation control block.
  1241. Return Value:
  1242. CG_OK if all is well, error otherwise.
  1243. Notes:
  1244. ----------------------------------------------------------------------------*/
  1245. {
  1246. GenDataStructures( pCCB );
  1247. GenEntryPts( pCCB );
  1248. GenRegistryEntryPts( pCCB );
  1249. pCCB->GetStream()->Write('\n');
  1250. return CG_OK;
  1251. }
  1252. CG_STATUS
  1253. CG_COM_SERVER_EXE::GenCode(
  1254. CCB * pCCB )
  1255. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1256. Routine Description:
  1257. Generate the COM server file code for an interface inherited by a
  1258. COM class defined in the IDL file.
  1259. Arguments:
  1260. pCCB - a pointer to the code generation control block.
  1261. Return Value:
  1262. CG_OK if all is well, error otherwise.
  1263. Notes:
  1264. ----------------------------------------------------------------------------*/
  1265. {
  1266. GenCleanupRoutines( pCCB );
  1267. GenDataStructures( pCCB );
  1268. GenIteratorClass( pCCB );
  1269. GenClassRegisterRevoke( pCCB );
  1270. GenRegistryCode( pCCB );
  1271. return CG_OK;
  1272. }
  1273. CG_STATUS
  1274. CG_COM_SERVER_EXE::GenMain(
  1275. CCB * pCCB )
  1276. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1277. Routine Description:
  1278. Generate the COM server file code for an interface inherited by a
  1279. COM class defined in the IDL file.
  1280. Arguments:
  1281. pCCB - a pointer to the code generation control block.
  1282. Return Value:
  1283. CG_OK if all is well, error otherwise.
  1284. Notes:
  1285. ----------------------------------------------------------------------------*/
  1286. {
  1287. return CG_OK;
  1288. }
  1289. CG_STATUS
  1290. CG_COM_SERVER_EXE::GenCleanupRoutines(
  1291. CCB * pCCB )
  1292. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1293. Routine Description:
  1294. Generate the clean-up routines for the _e.cxx file.
  1295. Arguments:
  1296. pCCB - a pointer to the code generation control block.
  1297. Return Value:
  1298. CG_OK if all is well, error otherwise.
  1299. Notes:
  1300. ----------------------------------------------------------------------------*/
  1301. {
  1302. ISTREAM * pStream = pCCB->GetStream();
  1303. char * pName = GetSymName();
  1304. static STRING_BLOCK CleanupRtns =
  1305. {
  1306. "///////////////////////////////////////////////////////////////",
  1307. "// cleanup-on-Release routines",
  1308. "//",
  1309. "// clean-up routine for the entire module",
  1310. "// this is called when all the objects AND all",
  1311. "// the class factories are released",
  1312. "void __stdcall ModuleUnReferenced()",
  1313. "{",
  1314. " // no factories or objects remaining, go away",
  1315. " PostQuitMessage(0);",
  1316. "}",
  1317. "",
  1318. "// clean-up routine for the objects in the module",
  1319. "// this is called when all live objects other than ",
  1320. "// the class factories are released",
  1321. "void __stdcall ObjectsUnReferenced()",
  1322. "{",
  1323. " // revoke all the registered classes",
  1324. " UnregisterAllClassFactories();",
  1325. "}",
  1326. 0
  1327. };
  1328. pStream->NewLine();
  1329. pStream->WriteBlock( CleanupRtns );
  1330. pStream->NewLine(3);
  1331. return CG_OK;
  1332. }
  1333. CG_STATUS
  1334. CG_COM_SERVER_EXE::GenDataStructures(
  1335. CCB * pCCB )
  1336. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1337. Routine Description:
  1338. Generate the data structures for the _g.cxx file.
  1339. Arguments:
  1340. pCCB - a pointer to the code generation control block.
  1341. Return Value:
  1342. CG_OK if all is well, error otherwise.
  1343. Notes:
  1344. ----------------------------------------------------------------------------*/
  1345. {
  1346. ISTREAM * pStream = pCCB->GetStream();
  1347. unsigned long ulClassCnt = ITERATOR_GETCOUNT( *GetClassList() );
  1348. pStream->NewLine();
  1349. pStream->Write( "// the number of classes provided by this DLL" );
  1350. pStream->NewLine();
  1351. pStream->Write( "const unsigned long ulClassCnt = " );
  1352. pStream->WriteNumber( "%d", ulClassCnt );
  1353. pStream->Write( ";" );
  1354. pStream->NewLine(2);
  1355. GenClassFactoryArray( pCCB );
  1356. static STRING_BLOCK DataStructs =
  1357. {
  1358. "// lifetime information for the module (dll) containing this object",
  1359. "struct MidlModuleLifetimeInfo gLifetimeInfo =",
  1360. " {",
  1361. " 0, // ulModuleRefCnt",
  1362. " &ModuleUnReferenced,",
  1363. " 0, // ulObjectRefCnt",
  1364. " &ObjectsUnReferenced",
  1365. " };",
  1366. 0
  1367. };
  1368. pStream->NewLine();
  1369. pStream->WriteBlock( DataStructs );
  1370. pStream->NewLine(2);
  1371. return CG_OK;
  1372. }
  1373. CG_STATUS
  1374. CG_COM_SERVER_EXE::GenIteratorClass(
  1375. CCB * pCCB )
  1376. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1377. Routine Description:
  1378. Generate the custom iterator class for the _e.cxx file.
  1379. Arguments:
  1380. pCCB - a pointer to the code generation control block.
  1381. Return Value:
  1382. CG_OK if all is well, error otherwise.
  1383. Notes:
  1384. ----------------------------------------------------------------------------*/
  1385. {
  1386. ISTREAM * pStream = pCCB->GetStream();
  1387. char * pName = GetSymName();
  1388. static STRING_BLOCK IterClass =
  1389. {
  1390. "// a special iterator class over these class factories",
  1391. "class Exe_Class_Iterator : public Midl_Class_Factory_Iterator",
  1392. " {",
  1393. "public:",
  1394. " // just a convenience constructor",
  1395. " Exe_Class_Iterator()",
  1396. " : Midl_Class_Factory_Iterator(",
  1397. " Midl_Class_Factory_Array, ",
  1398. " ulClassCnt )",
  1399. " {",
  1400. " }",
  1401. "",
  1402. " void Init()",
  1403. " {",
  1404. " Midl_Class_Factory_Iterator::Init(",
  1405. " Midl_Class_Factory_Array, ",
  1406. " ulClassCnt );",
  1407. " }",
  1408. "",
  1409. " };",
  1410. 0
  1411. };
  1412. pStream->NewLine();
  1413. pStream->WriteBlock( IterClass );
  1414. pStream->NewLine(2);
  1415. return CG_OK;
  1416. }
  1417. CG_STATUS
  1418. CG_COM_SERVER_EXE::GenClassRegisterRevoke(
  1419. CCB * pCCB )
  1420. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1421. Routine Description:
  1422. Generate the clean-up routines for the _e.cxx file.
  1423. Arguments:
  1424. pCCB - a pointer to the code generation control block.
  1425. Return Value:
  1426. CG_OK if all is well, error otherwise.
  1427. Notes:
  1428. ----------------------------------------------------------------------------*/
  1429. {
  1430. ISTREAM * pStream = pCCB->GetStream();
  1431. char * pName = GetSymName();
  1432. static STRING_BLOCK RegisterRevokeCode =
  1433. {
  1434. "// these are the handles returned by the CoRegisterClassObject",
  1435. "DWORD dwRegisterHandles[ulClassCnt] = {0};",
  1436. "",
  1437. "// flag to make sure we only call CoRevokeClassObject once",
  1438. "int fFactoriesRevoked = TRUE;",
  1439. "",
  1440. "// do a CoRevokeClassObject on all the live class factories",
  1441. "HRESULT __stdcall UnregisterAllClassFactories()",
  1442. "{",
  1443. " HRESULT hr;",
  1444. "",
  1445. " // if we already revoked all the objects, do nothing",
  1446. " if ( fFactoriesRevoked )",
  1447. " return S_OK;",
  1448. "",
  1449. " Exe_Class_Iterator Iter;",
  1450. " Midl_Class_Factory_Info * pCur;",
  1451. " DWORD * pdwHandle = dwRegisterHandles;",
  1452. "",
  1453. " // revoke all the class factories",
  1454. " while ( pCur = Iter.GetNext() )",
  1455. " {",
  1456. " hr = CoRevokeClassObject(*pdwHandle);",
  1457. " if ( FAILED(hr) )",
  1458. " return hr;",
  1459. " pdwHandle++;",
  1460. " }",
  1461. "",
  1462. " fFactoriesRevoked = TRUE;",
  1463. " return hr;",
  1464. "}",
  1465. "",
  1466. "// do a CoRegisterClassObject on all the class factories",
  1467. "HRESULT __stdcall RegisterAllClassFactories()",
  1468. "{",
  1469. " Exe_Class_Iterator Iter;",
  1470. " Midl_Class_Factory_Info * pCur;",
  1471. " HRESULT hr = S_OK;",
  1472. " DWORD * pdwHandle = dwRegisterHandles;",
  1473. "",
  1474. " fFactoriesRevoked = FALSE;",
  1475. "",
  1476. " // register all the valid class factories",
  1477. " while ( pCur = Iter.GetNext() )",
  1478. " {",
  1479. " hr =CoRegisterClassObject( ",
  1480. " *pCur->pFactoryID,",
  1481. " (IUnknown*)(*pCur->ppFactory),",
  1482. " CLSCTX_LOCAL_SERVER,",
  1483. " REGCLS_MULTI_SEPARATE,",
  1484. " pdwHandle);",
  1485. " if ( FAILED( hr ) )",
  1486. " return hr;",
  1487. "",
  1488. " pdwHandle++;",
  1489. " }",
  1490. "",
  1491. " return hr;",
  1492. "}",
  1493. 0
  1494. };
  1495. pStream->NewLine();
  1496. pStream->WriteBlock( RegisterRevokeCode );
  1497. pStream->NewLine(2);
  1498. return CG_OK;
  1499. }
  1500. CG_STATUS
  1501. CG_COM_SERVER_EXE::GenRegistryCode(
  1502. CCB * pCCB )
  1503. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1504. Routine Description:
  1505. Generate the clean-up routines for the _e.cxx file.
  1506. Arguments:
  1507. pCCB - a pointer to the code generation control block.
  1508. Return Value:
  1509. CG_OK if all is well, error otherwise.
  1510. Notes:
  1511. ----------------------------------------------------------------------------*/
  1512. {
  1513. ISTREAM * pStream = pCCB->GetStream();
  1514. char * pName = GetSymName();
  1515. static STRING_BLOCK RegistryCode =
  1516. {
  1517. "///////////////////////////////////////////////////////////////////////",
  1518. "// these routines maintain the registry information for these classes",
  1519. "//",
  1520. "// call UpdateServerRegistry to add all the classes to the registry",
  1521. "// call CleanupServerRegistry to remove the classes from the registry",
  1522. "",
  1523. "HRESULT __stdcall UpdateServerRegistry()",
  1524. "{",
  1525. " char szDllFileName[MAX_PATH];",
  1526. " HRESULT hr;",
  1527. "",
  1528. " // get the exe name",
  1529. " if ( !GetModuleFileNameA(NULL, szDllFileName, sizeof(szDllFileName)) )",
  1530. " return E_FAIL;",
  1531. "",
  1532. " Exe_Class_Iterator Iter;",
  1533. " Midl_Class_Factory_Info * pCur;",
  1534. "",
  1535. " // register all the clsid's",
  1536. " while ( pCur = Iter.GetNext() )",
  1537. " {",
  1538. " hr = NdrRegisterServerExe( szDllFileName, pCur );",
  1539. " if ( FAILED(hr) )",
  1540. " return hr;",
  1541. " }",
  1542. "",
  1543. " return S_OK;",
  1544. "}",
  1545. "",
  1546. "// remove the registry entries for the class here",
  1547. "HRESULT __stdcall CleanupServerRegistry()",
  1548. "{",
  1549. " HRESULT hr;",
  1550. "",
  1551. " Exe_Class_Iterator Iter;",
  1552. " Midl_Class_Factory_Info * pCur;",
  1553. "",
  1554. " // register all the clsid's",
  1555. " while ( pCur = Iter.GetNext() )",
  1556. " {",
  1557. " hr = NdrUnregisterServerExe( pCur );",
  1558. " if ( FAILED(hr) )",
  1559. " return hr;",
  1560. " }",
  1561. "",
  1562. " return S_OK;",
  1563. "}",
  1564. 0
  1565. };
  1566. pStream->NewLine();
  1567. pStream->WriteBlock( RegistryCode );
  1568. pStream->NewLine(2);
  1569. return CG_OK;
  1570. }
  1571. CG_STATUS
  1572. CG_COM_SERVER::GenHeader(
  1573. CCB * pCCB )
  1574. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1575. Routine Description:
  1576. Generate the COM server file code for an interface inherited by a
  1577. COM class defined in the IDL file.
  1578. Arguments:
  1579. pCCB - a pointer to the code generation control block.
  1580. Return Value:
  1581. CG_OK if all is well, error otherwise.
  1582. Notes:
  1583. ----------------------------------------------------------------------------*/
  1584. {
  1585. return CG_OK;
  1586. }