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.

1954 lines
52 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. filecls.hxx
  5. Abstract:
  6. Code generation methods for file cg classes.
  7. Notes:
  8. History:
  9. Sep-01-1993 VibhasC Created.
  10. ----------------------------------------------------------------------------*/
  11. #pragma warning ( disable : 4238 4239 )
  12. /****************************************************************************
  13. * include files
  14. ***************************************************************************/
  15. #include "becls.hxx"
  16. #pragma hdrstop
  17. /****************************************************************************
  18. * local definitions
  19. ***************************************************************************/
  20. /****************************************************************************
  21. * local data
  22. ***************************************************************************/
  23. /****************************************************************************
  24. * externs
  25. ***************************************************************************/
  26. extern CMD_ARG * pCommand;
  27. char* GetRpcNdrHVersionGuard( char* );
  28. char* GetRpcProxyHVersionGuard( char* );
  29. extern BOOL IsTempName( char * );
  30. /****************************************************************************/
  31. void
  32. CG_FILE::EmitFileHeadingBlock(
  33. CCB * pCCB,
  34. char * CommentStr,
  35. char * CommentStr2,
  36. bool fDualFile )
  37. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  38. Routine Description:
  39. Emit double platform ifdef as needed and the opening comment to the file.
  40. Arguments:
  41. pCCB - a pointer to the code generation control block.
  42. CommentStr - a comment customizing the file.
  43. CommentStr2 - optional comment used in *_i.c
  44. fDualFile - true for client stub, server stub and froxy file
  45. false for the header file
  46. ----------------------------------------------------------------------------*/
  47. {
  48. ISTREAM * pStream = pCCB->GetStream();
  49. // A guard for double, i.e. 32b-64b, files.
  50. pStream->NewLine();
  51. pStream->Write( "#pragma warning( disable: 4049 ) /* more than 64k source lines */");
  52. // Comment customizing the file.
  53. pStream->NewLine(2);
  54. pStream->Write( "/* this ALWAYS GENERATED file contains " );
  55. pStream->Write( CommentStr );
  56. pStream->Write( " */" );
  57. pStream->NewLine(2);
  58. if ( CommentStr2 )
  59. {
  60. pStream->Write( "/* " );
  61. pStream->Write( CommentStr2 );
  62. pStream->Write( " */" );
  63. pStream->NewLine(2);
  64. }
  65. EmitStandardHeadingBlock( pCCB );
  66. if ( fDualFile )
  67. {
  68. pStream->NewLine();
  69. if ( pCommand->Is64BitEnv() )
  70. pStream->Write( "#if defined(_M_IA64) || defined(_M_AMD64)" );
  71. else if ( pCommand->Is32BitEnv() )
  72. {
  73. pStream->Write( "#if !defined(_M_IA64) && !defined(_M_AMD64)" );
  74. }
  75. }
  76. }
  77. void
  78. CG_FILE::EmitFileClosingBlock(
  79. CCB * pCCB,
  80. bool fDualFile )
  81. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  82. Routine Description:
  83. Emit an endif matching the one emitted in EmitFileHeadingBlock
  84. Arguments:
  85. pCCB - a pointer to the code generation control block.
  86. CommentStr - a comment customizing the file.
  87. fDualFile - true for client stub, server stub and froxy file
  88. false for the header file
  89. ----------------------------------------------------------------------------*/
  90. {
  91. ISTREAM * pStream = pCCB->GetStream();
  92. if ( fDualFile )
  93. {
  94. pStream->NewLine(2);
  95. if ( pCommand->Is64BitEnv() )
  96. pStream->Write( "#endif /* defined(_M_IA64) || defined(_M_AMD64)*/" );
  97. else if ( pCommand->Is32BitEnv() )
  98. {
  99. pStream->Write( "#endif /* !defined(_M_IA64) && !defined(_M_AMD64)*/" );
  100. }
  101. }
  102. pStream->NewLine(2);
  103. }
  104. void
  105. CG_FILE::EmitStandardHeadingBlock(
  106. CCB * pCCB )
  107. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  108. Routine Description:
  109. Emit standard block comment file heading portion.
  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. ISTREAM * pStream = pCCB->GetStream();
  118. pStream->NewLine();
  119. pStream->Write(" /* File created by MIDL compiler version ");
  120. pStream->Write( pCommand->GetCompilerVersion() );
  121. pStream->Write(" */");
  122. pStream->NewLine();
  123. if ( !pCommand->IsSwitchDefined( SWITCH_NO_STAMP ) )
  124. {
  125. pStream->Write("/* at ");
  126. pStream->Write( pCommand->GetCompileTime() );
  127. pStream->Write(" */");
  128. pStream->NewLine();
  129. }
  130. // Emit command line switches information.
  131. pCommand->EmitConfirm( pStream );
  132. // Write this remnant of the reparsing scheme for our testers.
  133. pStream->Write( "//@@MIDL_FILE_HEADING( )" );
  134. pStream->NewLine();
  135. }
  136. void
  137. CG_FILE::Out_TransferSyntaxDefs(
  138. CCB * pCCB )
  139. {
  140. ISTREAM *pStream = pCCB->GetStream();
  141. // NDR transfer syntax id is needed for
  142. if ( pCommand->NeedsNDRRun() )
  143. {
  144. // BUGBUG: transfer syntax guids should be in rpcrt4.lib or something
  145. pStream->WriteOnNewLine("static " TRANSFER_SYNTAX_TYPE_NAME " ");
  146. pStream->Write( NDR_TRANSFER_SYNTAX_VAR_NAME );
  147. pStream->Write( " = ");
  148. pStream->NewLine();
  149. Out_TransferSyntax( pCCB,
  150. TransferSyntaxGuidStrs,
  151. NDR_UUID_MAJOR_VERSION,
  152. NDR_UUID_MINOR_VERSION );
  153. pStream->Write( ';' );
  154. pStream->NewLine();
  155. }
  156. if ( pCommand->NeedsNDR64Run() )
  157. {
  158. pStream->WriteOnNewLine("static " TRANSFER_SYNTAX_TYPE_NAME " ");
  159. pStream->Write( NDR64_TRANSFER_SYNTAX_VAR_NAME );
  160. pStream->Write( " = ");
  161. pStream->NewLine();
  162. if ( pCommand->IsSwitchDefined( SWITCH_INTERNAL ) &&
  163. pCommand->GetEnv() == ENV_WIN32 )
  164. Out_TransferSyntax( pCCB,
  165. FakeNDR64TransferSyntaxGuidStrs,
  166. NDR64_UUID_MAJOR_VERSION,
  167. NDR64_UUID_MINOR_VERSION );
  168. else
  169. Out_TransferSyntax( pCCB,
  170. NDR64TransferSyntaxGuidStrs,
  171. NDR64_UUID_MAJOR_VERSION,
  172. NDR64_UUID_MINOR_VERSION );
  173. pStream->Write( ';' );
  174. pStream->NewLine();
  175. }
  176. }
  177. void
  178. CG_FILE::EmitFormatStringTypedefs(
  179. CCB * pCCB )
  180. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  181. Routine Description:
  182. Emit dummy #defines with sizes for the format string structs,
  183. then emit typedefs for the type and proc format string structs.
  184. Sets the context position in the file node for later use.
  185. Additional tables serviced here:
  186. transmit_as, element is a quad
  187. wire_marshal element is a quad
  188. Arguments:
  189. pCCB - a pointer to the code generation control block.
  190. Notes:
  191. The typedefs are going to be fixed later by a call to
  192. EmitFixupToFormatStringTypedefs. This is needed for ANSI.
  193. The dummies would work for ANSI non-compliant code.
  194. --------------------------------------------------------------------------*/
  195. {
  196. ISTREAM * pStream = pCCB->GetStream();
  197. // we'll only generate this once in the first run.
  198. if ( pCommand->Is2ndCodegenRun() )
  199. return;
  200. pStream->NewLine(2);
  201. if ( pCommand->NeedsNDRRun() )
  202. {
  203. pStream->Write( "#define TYPE_FORMAT_STRING_SIZE " );
  204. SetOptionalTableSizePosition( TypeFormatStringSizePosition,
  205. pStream->GetCurrentPosition() );
  206. pStream->Write( " " );
  207. pStream->NewLine();
  208. pStream->Write( "#define PROC_FORMAT_STRING_SIZE " );
  209. SetOptionalTableSizePosition( ProcFormatStringSizePosition,
  210. pStream->GetCurrentPosition() );
  211. pStream->Write( " " );
  212. pStream->NewLine();
  213. }
  214. pStream->Write( "#define " TRANSMIT_AS_TABLE_SIZE " " );
  215. SetOptionalTableSizePosition( TransmitAsSizePosition,
  216. pStream->GetCurrentPosition() );
  217. pStream->Write( " " );
  218. pStream->NewLine();
  219. pStream->Write( "#define " WIRE_MARSHAL_TABLE_SIZE " " );
  220. SetOptionalTableSizePosition( WireMarshalSizePosition,
  221. pStream->GetCurrentPosition() );
  222. pStream->Write( " " );
  223. pStream->NewLine();
  224. if ( pCommand->NeedsNDRRun() )
  225. {
  226. pStream->NewLine();
  227. pStream->Write( "typedef struct _" FORMAT_STRING_TYPE_NAME );
  228. pStream->IndentInc();
  229. pStream->NewLine();
  230. pStream->Write( "{" );
  231. pStream->NewLine();
  232. pStream->Write( "short Pad;" );
  233. pStream->NewLine();
  234. pStream->Write( "unsigned char Format[ TYPE_FORMAT_STRING_SIZE ];" );
  235. pStream->NewLine();
  236. pStream->Write( "} " FORMAT_STRING_TYPE_NAME ";" );
  237. pStream->IndentDec();
  238. pStream->NewLine(2);
  239. pStream->Write( "typedef struct _" PROC_FORMAT_STRING_TYPE_NAME );
  240. pStream->IndentInc();
  241. pStream->NewLine();
  242. pStream->Write( "{" );
  243. pStream->NewLine();
  244. pStream->Write( "short Pad;" );
  245. pStream->NewLine();
  246. pStream->Write( "unsigned char Format[ PROC_FORMAT_STRING_SIZE ];" );
  247. pStream->NewLine();
  248. pStream->Write( "} " PROC_FORMAT_STRING_TYPE_NAME ";" );
  249. pStream->IndentDec();
  250. pStream->NewLine(2);
  251. }
  252. }
  253. void
  254. CG_FILE::EmitFixupToFormatStringTypedefs(
  255. CCB * pCCB )
  256. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  257. Routine Description:
  258. Fixes he dummy #defines emitted by EmitFormatStringTypedefs.
  259. Arguments:
  260. pCCB - a pointer to the code generation control block.
  261. pContext - a pointer to the position context
  262. --------------------------------------------------------------------------*/
  263. {
  264. char Buffer[20];
  265. ISTREAM * pStream = pCCB->GetStream();
  266. long EofPosition;
  267. EofPosition = pStream->GetCurrentPosition();
  268. if ( !pCommand->Is2ndCodegenRun() )
  269. {
  270. pStream->SetCurrentPosition(
  271. GetOptionalTableSizePosition( TransmitAsSizePosition ) );
  272. sprintf( Buffer, "%d", pCCB->GetQuintupleDictionary()->GetCount() );
  273. pStream->Write( Buffer );
  274. pStream->SetCurrentPosition(
  275. GetOptionalTableSizePosition( WireMarshalSizePosition ) );
  276. sprintf( Buffer, "%d", pCCB->GetQuadrupleDictionary()->GetCount() );
  277. pStream->Write( Buffer );
  278. }
  279. if ( pCommand->IsNDRRun() )
  280. {
  281. pStream->SetCurrentPosition(
  282. GetOptionalTableSizePosition( TypeFormatStringSizePosition ) );
  283. sprintf( Buffer, "%d", pCCB->GetFormatString()->GetCurrentOffset() + 1);
  284. pStream->Write( Buffer );
  285. pStream->SetCurrentPosition(
  286. GetOptionalTableSizePosition( ProcFormatStringSizePosition ) );
  287. sprintf( Buffer, "%d", pCCB->GetProcFormatString()->GetCurrentOffset() + 1);
  288. pStream->Write( Buffer );
  289. #ifdef PRINT_METRICS
  290. printf (
  291. "Format string sizes %16d, %16d, %s\n",
  292. pCCB->GetFormatString()->GetCurrentOffset() + 1,
  293. pCCB->GetProcFormatString()->GetCurrentOffset() + 1,
  294. GetFileName()
  295. );
  296. #endif
  297. }
  298. pStream->SetCurrentPosition( EofPosition );
  299. }
  300. void
  301. CG_FILE::EmitOptionalClientTableSizeTypedefs(
  302. CCB * pCCB )
  303. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  304. Routine Description:
  305. Emit dummy #defines with sizes for the optional tables:
  306. generic handles, element is a pair
  307. Tables serviced in the EmitFormStringtypedefs routine:
  308. transmit_as
  309. wire_marshal
  310. Arguments:
  311. pCCB - a pointer to the code generation control block.
  312. Notes:
  313. The typedefs are going to be fixed later by a call to
  314. EmitFixupToOptionalTableSizeTypedefs. This is needed for ANSI.
  315. Note that we have the following tables that are not affected
  316. by the ANSI issue because element is not a struct:
  317. context rundown routine table
  318. expression evaluation table
  319. notify table
  320. --------------------------------------------------------------------------*/
  321. {
  322. ISTREAM * pStream = pCCB->GetStream();
  323. pStream->NewLine(2);
  324. pStream->Write( "#define " GENERIC_BINDING_TABLE_SIZE " " );
  325. SetOptionalTableSizePosition( GenericHandleSizePosition,
  326. pStream->GetCurrentPosition() );
  327. pStream->Write( " " );
  328. pStream->NewLine();
  329. }
  330. void
  331. CG_FILE::EmitFixupToOptionalClientTableSizeTypedefs(
  332. CCB * pCCB )
  333. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  334. Routine Description:
  335. Emit dummy #defines with sizes for the optional tables:
  336. generic handles,
  337. Arguments:
  338. pCCB - a pointer to the code generation control block.
  339. Notes:
  340. The typedefs are going to be fixed later by a call to
  341. EmitFixupOptionalTableSizeTpedefs. This is needed for ANSI.
  342. --------------------------------------------------------------------------*/
  343. {
  344. char Buffer[20];
  345. ISTREAM * pStream = pCCB->GetStream();
  346. long EofPosition = pStream->GetCurrentPosition();
  347. pStream->SetCurrentPosition(
  348. GetOptionalTableSizePosition( GenericHandleSizePosition ) );
  349. sprintf( Buffer, "%d", pCCB->GetGenericIndexMgr()->GetIndex() - 1 );
  350. pStream->Write( Buffer );
  351. pStream->SetCurrentPosition( EofPosition );
  352. }
  353. CG_STATUS
  354. CG_SOURCE::GenCode(
  355. CCB * pCCB )
  356. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  357. Routine Description:
  358. Generate code for the source node.
  359. Arguments:
  360. pCCB - a pointer to the code generation control block.
  361. Return Value:
  362. CG_OK if all is well, error otherwise.
  363. Notes:
  364. ----------------------------------------------------------------------------*/
  365. {
  366. CG_ITERATOR I;
  367. CG_FILE * pCG;
  368. //
  369. // for all files nodes in this interface, generate code.
  370. //
  371. GetMembers( I );
  372. while( ITERATOR_GETNEXT( I, pCG ) )
  373. {
  374. pCG->GenCode( pCCB );
  375. }
  376. return CG_OK;
  377. }
  378. CG_STATUS
  379. CG_CSTUB_FILE::GenCode(
  380. CCB * pCCB )
  381. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  382. Routine Description:
  383. Generate code for the file node.
  384. Arguments:
  385. pCCB - a pointer to the code generation control block.
  386. Return Value:
  387. CG_OK if all is well, error otherwise.
  388. Notes:
  389. ----------------------------------------------------------------------------*/
  390. {
  391. CG_ITERATOR I;
  392. CG_NDR * pCG;
  393. char Buffer[ _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 1 ];
  394. char Drive[ _MAX_DRIVE ];
  395. char Path[ _MAX_DIR ];
  396. char Name[ _MAX_FNAME ];
  397. char Ext[ _MAX_EXT ];
  398. if( !GetMembers( I ) )
  399. {
  400. return CG_OK;
  401. }
  402. ISTREAM Stream( GetFileName(), 4 );
  403. ISTREAM * pStream = &Stream;
  404. pCCB->SetStream( pStream, this );
  405. // Set HasStublessProxies and HasOi2 for each interface.
  406. EvaluateVersionControl();
  407. EmitFileHeadingBlock( pCCB, "the RPC client stubs" );
  408. SetNoOutputIn2ndCodegen( pCCB );
  409. // Emit the hash includes.
  410. Out_IncludeOfFile( pCCB, STRING_H_INC_FILE_NAME, TRUE );
  411. pStream->NewLine();
  412. // rpcssm puts a reference to malloc and free in the stub_c.c.
  413. // So, we have to emit the appropriate include.
  414. // In ms_ext when explicit, in osf always, to cover some weird cases.
  415. while( ITERATOR_GETNEXT( I, pCG ) )
  416. {
  417. if ( ( ((CG_INTERFACE *)pCG)->GetUsesRpcSS() || (pCCB->GetMode() == 0) ))
  418. {
  419. Out_IncludeOfFile( pCCB, "malloc.h", TRUE );
  420. break;
  421. }
  422. }
  423. _splitpath( GetHeaderFileName(), Drive, Path, Name, Ext );
  424. strcpy( Buffer, Name );
  425. strcat( Buffer, Ext );
  426. Out_IncludeOfFile( pCCB, Buffer, FALSE );
  427. EmitFormatStringTypedefs( pCCB );
  428. Out_TransferSyntaxDefs( pCCB );
  429. //
  430. // Emit the external variables needed.
  431. //
  432. pStream->NewLine();
  433. //
  434. // Emit the format string extern declarations.
  435. //
  436. Out_FormatInfoExtern( pCCB );
  437. Out_TypeFormatStringExtern( pCCB );
  438. Out_ProcFormatStringExtern( pCCB );
  439. EmitOptionalClientTableSizeTypedefs( pCCB );
  440. pCCB->ClearOptionalExternFlags();
  441. pCCB->SetFileCG(this);
  442. MIDL_ASSERT( pCommand->IsNDR64Run() || pCommand->IsNDRRun() );
  443. if ( pCommand->IsNDR64Run() )
  444. {
  445. pCCB->SetFormatString( NULL );
  446. pCCB->SetProcFormatString( NULL );
  447. pCCB->SetNdr64Format( GenNdr64Format::CreateInstance( pCCB ) );
  448. }
  449. else
  450. {
  451. //
  452. // Create a new format string object if it does not yet exist.
  453. //
  454. if ( !pCCB->GetFormatString() )
  455. {
  456. pCCB->SetFormatString( new FORMAT_STRING() );
  457. // push a dummy short 0 at the beginning. This disambiguates
  458. // the case where offset 0 means recursion and a valid offset
  459. // always push the 0 at the beginning, otherwise we'll av in
  460. // some idl files (contain VARIANT for example) if -internal
  461. // is specified.
  462. // if ( !pCommand->IsSwitchDefined( SWITCH_INTERNAL ) )
  463. // {
  464. pCCB->GetFormatString()->PushShort( ( short ) 0 );
  465. // }
  466. }
  467. if ( !pCCB->GetProcFormatString() )
  468. {
  469. pCCB->SetProcFormatString( new FORMAT_STRING() );
  470. }
  471. }
  472. //
  473. // for all interfaces in this file, generate format info.
  474. //
  475. ITERATOR_INIT( I );
  476. while( ITERATOR_GETNEXT( I, pCG ) )
  477. {
  478. switch(pCG->GetCGID())
  479. {
  480. case ID_CG_INTERFACE:
  481. ((CG_INTERFACE *)pCG)->OutputInterfaceIdComment( pCCB );
  482. ((CG_INTERFACE *)pCG)->GenClientInfo( pCCB );
  483. break;
  484. }
  485. }
  486. //
  487. // Output the tables that may be common to several interfaces.
  488. //
  489. EmitFixupToOptionalClientTableSizeTypedefs( pCCB );
  490. ResetNoOutputIn2ndCodegen( pCCB );
  491. EmitFixupToFormatStringTypedefs( pCCB );
  492. // REVIEW: The externs may not be necessary anymore
  493. pCCB->OutputExternsToMultipleInterfaceTables();
  494. pCCB->OutputMultipleInterfaceTables();
  495. OutputTypePicklingTables( pCCB );
  496. //
  497. // for all interfaces in this file, output stubs, proc tables, etc.
  498. //
  499. ITERATOR_INIT( I );
  500. while( ITERATOR_GETNEXT( I, pCG ) )
  501. {
  502. switch(pCG->GetCGID())
  503. {
  504. case ID_CG_INTERFACE:
  505. ((CG_INTERFACE *)pCG)->OutputClientStub( pCCB );
  506. break;
  507. }
  508. }
  509. EmitFileClosingBlock( pCCB );
  510. return CG_OK;
  511. }
  512. void
  513. CG_CSTUB_FILE::OutputTypePicklingTables(
  514. CCB * pCCB )
  515. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  516. Routine Description:
  517. Output tables of offsets to type information for type pickling.
  518. If this is the final run, also output the "table of tables"
  519. Arguments:
  520. pCCB - a pointer to the code generation control block.
  521. Notes:
  522. Pickled simple types don't end up in the the table. They are special
  523. cased.
  524. Tables looks like:
  525. static unsigned long DCE_TypePicklingOffsets[] =
  526. {
  527. ...
  528. };
  529. static unsigned long Ndr64_TypePicklingOffsets[] =
  530. {
  531. ...
  532. };
  533. static unsigned long * TypePicklingOffsetTable[] =
  534. {
  535. DCE_TypePicklingOffsets,
  536. Ndr64_TypePicklingOffsets
  537. }
  538. ----------------------------------------------------------------------------*/
  539. {
  540. // straight DCE mode passes the offset directly to the type pickling API
  541. if ( !pCommand->NeedsNDR64Run() )
  542. return;
  543. IndexedList PickledTypes = pCCB->GetListOfPickledTypes();
  544. if ( 0 == PickledTypes.GetCount() )
  545. return;
  546. ISTREAM *pStream = pCCB->GetStream();
  547. PNAME syntax;
  548. CG_TYPE_ENCODE *type;
  549. bool first = true;
  550. if ( pCommand->IsNDR64Run() )
  551. syntax = "FormatInfoRef Ndr64";
  552. else
  553. syntax = "unsigned long DCE";
  554. //
  555. // Output the type offset table for the current syntax
  556. //
  557. pStream->NewLine();
  558. pStream->WriteFormat(
  559. "static %s_TypePicklingOffsets[] =",
  560. syntax );
  561. pStream->WriteOnNewLine( '{' );
  562. pStream->IndentInc();
  563. ITERATOR_INIT( PickledTypes );
  564. while ( ITERATOR_GETNEXT( PickledTypes, type ) )
  565. {
  566. if ( !first )
  567. pStream->Write( ',' );
  568. pStream->NewLine();
  569. CG_NDR *pChild = (CG_NDR *) type->GetChild();
  570. ulong TypeOffset;
  571. char *format;
  572. if ( pCommand->IsNDR64Run() )
  573. {
  574. format = "&__midl_frag%d";
  575. TypeOffset = (ulong) (size_t) pCCB->GetNdr64Format()->GetRoot()
  576. ->LookupFragmentID( pChild );
  577. MIDL_ASSERT( 0 != TypeOffset );
  578. }
  579. else
  580. {
  581. format = "%d";
  582. TypeOffset = pChild->GetFormatStringOffset();
  583. MIDL_ASSERT( ((ulong) -1) != TypeOffset );
  584. }
  585. pStream->WriteFormat( format, TypeOffset );
  586. pStream->WriteFormat( " /* %s */", type->GetSymName() );
  587. first = false;
  588. }
  589. pStream->IndentDec();
  590. pStream->WriteOnNewLine( "};" );
  591. pStream->NewLine();
  592. //
  593. // If this isn't the final protocol, quit now. Otherwise output the
  594. // table of tables.
  595. //
  596. if ( !pCommand->IsFinalProtocolRun() )
  597. return;
  598. pStream->WriteOnNewLine( "static unsigned long * "
  599. "TypePicklingOffsetTable[] =" );
  600. pStream->WriteOnNewLine( "{" );
  601. pStream->IndentInc();
  602. first = true;
  603. if ( pCommand->NeedsNDRRun() )
  604. {
  605. pStream->WriteOnNewLine( "DCE_TypePicklingOffsets" );
  606. first = false;
  607. }
  608. if ( pCommand->NeedsNDR64Run() )
  609. {
  610. if ( !first ) pStream->Write( ',' );
  611. pStream->WriteOnNewLine( "(unsigned long *) Ndr64_TypePicklingOffsets" );
  612. first = false;
  613. }
  614. pStream->IndentDec();
  615. pStream->WriteOnNewLine( "};" );
  616. pStream->NewLine();
  617. }
  618. /****************************************************************************
  619. * sstub file implementation class.
  620. ***************************************************************************/
  621. CG_STATUS
  622. CG_SSTUB_FILE::GenCode(
  623. CCB * pCCB )
  624. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  625. Routine Description:
  626. Generate code for the file node.
  627. Arguments:
  628. pCCB - a pointer to the code generation control block.
  629. Return Value:
  630. CG_OK if all is well, error otherwise.
  631. Notes:
  632. ----------------------------------------------------------------------------*/
  633. {
  634. CG_ITERATOR I;
  635. CG_NDR * pCG;
  636. char Buffer[ _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 1 ];
  637. char Drive[ _MAX_DRIVE ];
  638. char Path[ _MAX_DIR ];
  639. char Name[ _MAX_FNAME ];
  640. char Ext[ _MAX_EXT ];
  641. if( !GetMembers( I ) )
  642. {
  643. return CG_OK;
  644. }
  645. ISTREAM Stream( GetFileName(), 4 );
  646. ISTREAM * pStream = &Stream;
  647. pCCB->SetStream( pStream, this );
  648. // Set HasStublessProxies and HasOi2 for each interface.
  649. EvaluateVersionControl();
  650. EmitFileHeadingBlock( pCCB, "the RPC server stubs" );
  651. //
  652. // Emit the hash includes.
  653. //
  654. SetNoOutputIn2ndCodegen( pCCB );
  655. Out_IncludeOfFile( pCCB, STRING_H_INC_FILE_NAME, TRUE );
  656. _splitpath( GetHeaderFileName(), Drive, Path, Name, Ext );
  657. strcpy( Buffer, Name );
  658. strcat( Buffer, Ext );
  659. Out_IncludeOfFile( pCCB, Buffer, FALSE );
  660. EmitFormatStringTypedefs( pCCB );
  661. Out_TransferSyntaxDefs( pCCB );
  662. //
  663. // Emit the external variables needed.
  664. //
  665. //
  666. // Emit the format string extern declarations.
  667. //
  668. Out_FormatInfoExtern( pCCB );
  669. Out_TypeFormatStringExtern( pCCB );
  670. Out_ProcFormatStringExtern( pCCB );
  671. pCCB->ClearOptionalExternFlags();
  672. pCCB->SetFileCG(this);
  673. Out_NotifyTableExtern( pCCB );
  674. MIDL_ASSERT( pCommand->IsNDR64Run() || pCommand->IsNDRRun() );
  675. if ( pCommand->IsNDR64Run() )
  676. {
  677. pCCB->SetFormatString( NULL );
  678. pCCB->SetProcFormatString( NULL );
  679. pCCB->SetNdr64Format( GenNdr64Format::CreateInstance( pCCB ) );
  680. }
  681. else
  682. {
  683. //
  684. // Create a new format string object if it does not exist.
  685. //
  686. if ( !pCCB->GetFormatString() )
  687. {
  688. pCCB->SetFormatString( new FORMAT_STRING() );
  689. // push a dummy short 0 at the beginning. This disambiguates
  690. // the case where offset 0 means recursion and a valid offset
  691. pCCB->GetFormatString()->PushShort( ( short ) 0 );
  692. }
  693. if ( !pCCB->GetProcFormatString() )
  694. {
  695. pCCB->SetProcFormatString( new FORMAT_STRING() );
  696. }
  697. }
  698. //
  699. // Send the message to the children to emit code.
  700. //
  701. //
  702. // For all interfaces in this file, generate code.
  703. //
  704. BOOL HasInterpretedProc = FALSE;
  705. while( ITERATOR_GETNEXT( I, pCG ) )
  706. {
  707. if ( pCG->GetCGID() == ID_CG_INTERFACE )
  708. {
  709. if ( ! ((CG_INTERFACE *)pCG)->HasPicklingStuffOnly() )
  710. {
  711. pCCB->SetSkipFormatStreamGeneration( FALSE );
  712. ((CG_INTERFACE *)pCG)->OutputInterfaceIdComment( pCCB );
  713. ((CG_INTERFACE *)pCG)->GenServerInfo( pCCB );
  714. if ( ((CG_INTERFACE *)pCG)->HasInterpretedProc() )
  715. HasInterpretedProc = TRUE;
  716. }
  717. }
  718. }
  719. //
  720. // Output the tables that may be common to several interfaces.
  721. pCCB->SetCodeGenSide( CGSIDE_SERVER );
  722. Out_NotifyTable( pCCB );
  723. ResetNoOutputIn2ndCodegen( pCCB );
  724. //
  725. // If there was at least one interpreted proc in the interfaces of this
  726. // file than make sure to turn the optimization bit in the CCB's
  727. // OptimOption on.
  728. //
  729. EmitFixupToFormatStringTypedefs( pCCB );
  730. if ( HasInterpretedProc )
  731. pCCB->SetOptimOption( unsigned short( pCCB->GetOptimOption() | OPTIMIZE_INTERPRETER ) );
  732. // REVIEW: The externs may not be necessary anymore
  733. pCCB->OutputExternsToMultipleInterfaceTables();
  734. pCCB->OutputMultipleInterfaceTables();
  735. ITERATOR_INIT( I );
  736. while( ITERATOR_GETNEXT( I, pCG ) )
  737. {
  738. if ( pCG->GetCGID() == ID_CG_INTERFACE )
  739. {
  740. if ( ! ((CG_INTERFACE *)pCG)->HasPicklingStuffOnly() )
  741. {
  742. ((CG_INTERFACE *)pCG)->OutputServerStub( pCCB );
  743. }
  744. }
  745. }
  746. EmitFileClosingBlock( pCCB );
  747. return CG_OK;
  748. }
  749. class GUID_DICTIONARY : public Dictionary
  750. {
  751. public:
  752. GUID_DICTIONARY()
  753. {
  754. }
  755. virtual
  756. SSIZE_T Compare (pUserType p1, pUserType p2)
  757. {
  758. INTERNAL_UUID * u1 = &( ((CG_INTERFACE *)p1)->GetGuidStrs().Value );
  759. INTERNAL_UUID * u2 = &( ((CG_INTERFACE *)p2)->GetGuidStrs().Value );
  760. return memcmp( u1, u2, 16 );
  761. }
  762. };
  763. void
  764. CG_PROXY_FILE::MakeImplementedInterfacesList( CCB* )
  765. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  766. Routine Description:
  767. Make a list of all the interfaces supported by this proxy file
  768. ( non-inherited, non-local interfaces ).
  769. Arguments:
  770. pCCB - a pointer to the code generation control block.
  771. Return Value:
  772. CG_OK if all is well, error otherwise.
  773. Notes:
  774. ----------------------------------------------------------------------------*/
  775. {
  776. CG_INTERFACE * pCG;
  777. CG_ITERATOR I;
  778. GUID_DICTIONARY GuidDict;
  779. // work directly on the real list
  780. GetMembers( I );
  781. while( ITERATOR_GETNEXT( I, pCG ) )
  782. {
  783. if ( pCG->GetCGID() != ID_CG_OBJECT_INTERFACE )
  784. continue;
  785. // Note that we don't need proxies and stubs for a pipe interface.
  786. if ( ((CG_OBJECT_INTERFACE*)pCG)->IsLocal() )
  787. continue;
  788. GuidDict.Dict_Insert( pCG );
  789. }
  790. GuidDict.Dict_GetList( ImplementedInterfaces );
  791. GuidDict.Dict_Discard();
  792. }
  793. void
  794. CG_FILE::EvaluateVersionControl()
  795. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  796. Routine Description:
  797. Calculates HasStublessProxies and Oi2 flags only through the
  798. interfaces.
  799. Arguments:
  800. pCCB - a pointer to the code generation control block.
  801. Return Value:
  802. Notes:
  803. ----------------------------------------------------------------------------*/
  804. {
  805. if ( (pCommand->GetOptimizationFlags() & OPTIMIZE_STUBLESS_CLIENT ) ||
  806. pCommand->GetNdrVersionControl().HasStublessProxies() )
  807. GetNdrVersionControl().SetHasStublessProxies();
  808. if ( (pCommand->GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 ) ||
  809. pCommand->GetNdrVersionControl().HasOi2() )
  810. GetNdrVersionControl().SetHasOi2();
  811. CG_ITERATOR I;
  812. CG_NDR * pCG;
  813. CG_INTERFACE * pIntf;
  814. if( !GetMembers( I ) )
  815. {
  816. return;
  817. }
  818. while( ITERATOR_GETNEXT( I, pCG ) )
  819. {
  820. pIntf = (CG_INTERFACE *)pCG;
  821. switch(pCG->GetCGID())
  822. {
  823. case ID_CG_INTERFACE:
  824. case ID_CG_INHERITED_OBJECT_INTERFACE:
  825. case ID_CG_OBJECT_INTERFACE:
  826. pIntf->EvaluateVersionControl();
  827. if ( pIntf->HasStublessProxies() )
  828. GetNdrVersionControl().SetHasStublessProxies();
  829. if ( pIntf->GetNdrVersionControl().HasOi2() )
  830. GetNdrVersionControl().SetHasOi2();
  831. break;
  832. default:
  833. break;
  834. }
  835. }
  836. if ( GetNdrVersionControl().HasStublessProxies() )
  837. pCommand->GetNdrVersionControl().SetHasStublessProxies();
  838. if ( GetNdrVersionControl().HasOi2() )
  839. pCommand->GetNdrVersionControl().SetHasOi2();
  840. }
  841. CG_STATUS
  842. CG_PROXY_FILE::GenCode(
  843. CCB * pCCB )
  844. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  845. Routine Description:
  846. Generate a proxy file containing the proxies and stubs for
  847. the [object] interfaces defined in the IDL file.
  848. Arguments:
  849. pCCB - a pointer to the code generation control block.
  850. Return Value:
  851. CG_OK if all is well, error otherwise.
  852. Notes:
  853. ----------------------------------------------------------------------------*/
  854. {
  855. CG_ITERATOR I;
  856. CG_NDR * pCG;
  857. char Buffer[ _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 1 ];
  858. char Drive[ _MAX_DRIVE ];
  859. char Path[ _MAX_DIR ];
  860. char Name[ _MAX_FNAME ];
  861. char Ext[ _MAX_EXT ];
  862. unsigned long index = 0;
  863. if( !GetMembers( I ) )
  864. {
  865. return CG_OK;
  866. }
  867. ISTREAM Stream( GetFileName(), 4 );
  868. ISTREAM * pStream = &Stream;
  869. pCCB->SetStream( pStream, this );
  870. // Set HasStublessProxies and HasOi2 for each interface.
  871. EvaluateVersionControl();
  872. EmitFileHeadingBlock( pCCB, "the proxy stub code" );
  873. SetNoOutputIn2ndCodegen( pCCB );
  874. //
  875. // Check if midl was invoked with -O1. This means we can create
  876. // binaries using stubless proxies (if also compiled -Oi). These
  877. // proxies will not work on 807.
  878. //
  879. if ( GetNdrVersionControl().HasStublessProxies() )
  880. {
  881. pStream->NewLine();
  882. pStream->Write( "#define USE_STUBLESS_PROXY" );
  883. pStream->NewLine();
  884. }
  885. // rpcproxy.h version guard
  886. pStream->NewLine(2);
  887. char sz[192];
  888. pStream->Write( GetRpcProxyHVersionGuard( sz ) );
  889. //
  890. // Emit the hash includes.
  891. //
  892. Out_IncludeOfFile( pCCB, "rpcproxy.h", FALSE );
  893. // rpcproxy.h version guard
  894. char *sz2 = "\n"
  895. "#ifndef __RPCPROXY_H_VERSION__\n"
  896. "#error this stub requires an updated version of <rpcproxy.h>\n"
  897. "#endif // __RPCPROXY_H_VERSION__\n\n";
  898. pStream->Write( sz2 );
  899. _splitpath( GetHeaderFileName(), Drive, Path, Name, Ext );
  900. strcpy( Buffer, Name );
  901. strcat( Buffer, Ext );
  902. Out_IncludeOfFile( pCCB, Buffer, FALSE );
  903. EmitFormatStringTypedefs( pCCB );
  904. Out_TransferSyntaxDefs( pCCB );
  905. //
  906. // Emit the external variables needed.
  907. //
  908. pStream->NewLine();
  909. //
  910. // Emit the format string extern declarations.
  911. //
  912. Out_FormatInfoExtern( pCCB );
  913. Out_TypeFormatStringExtern( pCCB );
  914. Out_ProcFormatStringExtern( pCCB );
  915. pCCB->ClearOptionalExternFlags();
  916. pStream->NewLine();
  917. pCCB->SetFileCG(this);
  918. MIDL_ASSERT( pCommand->IsNDR64Run() || pCommand->IsNDRRun() );
  919. if ( pCommand->IsNDR64Run() )
  920. {
  921. pCCB->SetFormatString( NULL );
  922. pCCB->SetProcFormatString( NULL );
  923. pCCB->SetNdr64Format( GenNdr64Format::CreateInstance( pCCB ) );
  924. }
  925. else
  926. {
  927. //
  928. // Create a new format string object if it does not yet exist.
  929. //
  930. if ( !pCCB->GetFormatString() )
  931. {
  932. pCCB->SetFormatString( new FORMAT_STRING() );
  933. // push a dummy short 0 at the beginning. This disambiguates
  934. // the case where offset 0 means recursion and a valid offset
  935. // if ( !pCommand->IsSwitchDefined( SWITCH_INTERNAL ) )
  936. // {
  937. pCCB->GetFormatString()->PushShort( ( short ) 0 );
  938. // }
  939. }
  940. if ( !pCCB->GetProcFormatString() )
  941. {
  942. pCCB->SetProcFormatString( new FORMAT_STRING() );
  943. }
  944. }
  945. // make the list of interfaces provided by this proxy file
  946. MakeImplementedInterfacesList( pCCB );
  947. //
  948. // Send the message to the children to emit code.
  949. //
  950. //
  951. // generate code for all [object] interfaces in the IDL file.
  952. //
  953. while( ITERATOR_GETNEXT( I, pCG ) )
  954. {
  955. switch(pCG->GetCGID())
  956. {
  957. case ID_CG_INHERITED_OBJECT_INTERFACE:
  958. {
  959. CG_INHERITED_OBJECT_INTERFACE * pInhObjCG =
  960. ( CG_INHERITED_OBJECT_INTERFACE * ) pCG;
  961. //
  962. // Generate format string description for all procs.
  963. //
  964. pInhObjCG->GenProxy( pCCB );
  965. break;
  966. }
  967. case ID_CG_OBJECT_INTERFACE:
  968. {
  969. CG_OBJECT_INTERFACE * pObjCG;
  970. pObjCG = (CG_OBJECT_INTERFACE *) pCG;
  971. // make no code or tables for local interfaces
  972. pObjCG->GenProxy( pCCB );
  973. if ( pObjCG->IsLocal() )
  974. break;
  975. index++; // index is index in stub/proxy buffer tables
  976. break;
  977. }
  978. default:
  979. break;
  980. }
  981. }
  982. Out_NotifyTable( pCCB );
  983. pCCB->SetSkipFormatStreamGeneration( FALSE );
  984. pStream->NewLine();
  985. // BUGBUG: figure out where to put this. yongqu
  986. // pStream->Write( "#pragma data_seg(\".rdata\")" );
  987. // pStream->NewLine();
  988. ResetNoOutputIn2ndCodegen( pCCB );
  989. pCCB->OutputExternsToMultipleInterfaceTables();
  990. EmitFixupToFormatStringTypedefs( pCCB );
  991. pCCB->OutputMultipleInterfaceTables();
  992. ITERATOR_INIT( I );
  993. while( ITERATOR_GETNEXT( I, pCG ) )
  994. {
  995. switch(pCG->GetCGID())
  996. {
  997. case ID_CG_INTERFACE:
  998. ((CG_INTERFACE *)pCG)->OutputInterfaceIdComment( pCCB );
  999. break;
  1000. case ID_CG_INHERITED_OBJECT_INTERFACE:
  1001. {
  1002. CG_INHERITED_OBJECT_INTERFACE * pInhObjCG =
  1003. ( CG_INHERITED_OBJECT_INTERFACE * ) pCG;
  1004. //
  1005. // Generate format string description for all procs.
  1006. //
  1007. pInhObjCG->OutputInterfaceIdComment( pCCB );
  1008. pInhObjCG->OutputProxy( pCCB );
  1009. // make no code or tables for local interfaces
  1010. if ( pInhObjCG->IsLocal() )
  1011. break;
  1012. //
  1013. // Both of these do nothing right now. 4/25.
  1014. //
  1015. pInhObjCG->GenInterfaceProxy( pCCB, index );
  1016. pInhObjCG->GenInterfaceStub( pCCB, index );
  1017. break;
  1018. }
  1019. case ID_CG_OBJECT_INTERFACE:
  1020. {
  1021. CG_OBJECT_INTERFACE * pObjCG;
  1022. pObjCG = (CG_OBJECT_INTERFACE *) pCG;
  1023. // make no code or tables for local interfaces
  1024. pObjCG->OutputInterfaceIdComment( pCCB );
  1025. pObjCG->OutputProxy( pCCB );
  1026. if ( pObjCG->IsLocal() )
  1027. break;
  1028. pObjCG->GenInterfaceProxy( pCCB, index ); // index is not used
  1029. pObjCG->GenInterfaceStub( pCCB, index ); // index is not used
  1030. index++; // index is index in stub/proxy buffer tables
  1031. break;
  1032. }
  1033. default:
  1034. break;
  1035. }
  1036. }
  1037. Out_StubDescriptor(0, pCCB);
  1038. if ( pCommand->IsFinalProtocolRun() )
  1039. Out_ProxyFileInfo(pCCB);
  1040. EmitFileClosingBlock( pCCB );
  1041. UpdateDLLDataFile( pCCB );
  1042. return CG_OK;
  1043. }
  1044. void
  1045. CG_HDR_FILE::OutputImportIncludes(
  1046. CCB * pCCB)
  1047. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1048. Routine Description:
  1049. Generate the header file.
  1050. Arguments:
  1051. pCCB - The code gen controller block.
  1052. Return Value:
  1053. none.
  1054. Notes:
  1055. ----------------------------------------------------------------------------*/
  1056. {
  1057. ITERATOR * pImpList = GetImportList();
  1058. node_file * pIFile;
  1059. ISTREAM * pStream = pCCB->GetStream();
  1060. char Buffer[ _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 1 ];
  1061. char Drive[ _MAX_DRIVE ];
  1062. char Path[ _MAX_DIR ];
  1063. char Name[ _MAX_FNAME ];
  1064. char Ext[ _MAX_EXT ];
  1065. if( pImpList && pImpList->NonNull() )
  1066. {
  1067. pStream->NewLine();
  1068. pStream->Write( "/* header files for imported files */" );
  1069. pImpList->Init();
  1070. while( ITERATOR_GETNEXT( (*pImportList), pIFile ) )
  1071. {
  1072. pStream->NewLine();
  1073. // if this was specified with ACF include, print out as is
  1074. if ( pIFile->IsAcfInclude() )
  1075. sprintf( Buffer, "#include \"%s\"", pIFile->GetSymName() );
  1076. else if ( pIFile->HasComClasses() )
  1077. {
  1078. _splitpath( pIFile->GetSymName(), Drive, Path, Name, Ext );
  1079. sprintf( Buffer, "#include \"%s_d.h\"", Name );
  1080. }
  1081. else
  1082. {
  1083. _splitpath( pIFile->GetSymName(), Drive, Path, Name, Ext );
  1084. sprintf( Buffer, "#include \"%s.h\"", Name );
  1085. }
  1086. pStream->Write( Buffer );
  1087. }
  1088. pStream->NewLine();
  1089. }
  1090. }
  1091. void OutputInterfaceForwards(
  1092. ISTREAM * pStream,
  1093. CG_ITERATOR & I )
  1094. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1095. Routine Description:
  1096. Generate the forwards section of the header file.
  1097. Arguments:
  1098. pCCB - The code gen controller block.
  1099. I - an iterator for the nodes to process
  1100. Return Value:
  1101. none.
  1102. Notes:
  1103. ----------------------------------------------------------------------------*/
  1104. {
  1105. CG_INTERFACE * pCG;
  1106. char * pszInterfaceName;
  1107. ID_CG id;
  1108. while( ITERATOR_GETNEXT( I, pCG ) )
  1109. {
  1110. id = pCG->GetCGID();
  1111. switch( id )
  1112. {
  1113. case ID_CG_INTERFACE:
  1114. case ID_CG_INHERITED_OBJECT_INTERFACE:
  1115. break;
  1116. case ID_CG_OBJECT_INTERFACE:
  1117. case ID_CG_DISPINTERFACE:
  1118. case ID_CG_COCLASS:
  1119. pszInterfaceName = pCG->GetType()->GetSymName();
  1120. pStream->NewLine();
  1121. // put out the interface guards
  1122. pStream->Write("\n#ifndef __");
  1123. pStream->Write( pszInterfaceName );
  1124. pStream->Write( "_FWD_DEFINED__\n" );
  1125. pStream->Write( "#define __");
  1126. pStream->Write( pszInterfaceName );
  1127. pStream->Write( "_FWD_DEFINED__\n" );
  1128. // put out the forward definition
  1129. if ( ID_CG_COCLASS == id )
  1130. {
  1131. pStream->Write("\n#ifdef __cplusplus\n");
  1132. pStream->Write("typedef class ");
  1133. pStream->Write(pszInterfaceName);
  1134. pStream->Write(' ');
  1135. pStream->Write(pszInterfaceName);
  1136. pStream->Write(';');
  1137. pStream->Write("\n#else\n");
  1138. pStream->Write("typedef struct ");
  1139. pStream->Write(pszInterfaceName);
  1140. pStream->Write(' ');
  1141. pStream->Write(pszInterfaceName);
  1142. pStream->Write(';');
  1143. pStream->Write( "\n#endif /* __cplusplus */\n");
  1144. }
  1145. else
  1146. {
  1147. pStream->Write("typedef interface ");
  1148. pStream->Write(pszInterfaceName);
  1149. pStream->Write(' ');
  1150. pStream->Write(pszInterfaceName);
  1151. pStream->Write(';');
  1152. }
  1153. // put out the trailing interface guard
  1154. pStream->Write( "\n#endif \t/* __");
  1155. pStream->Write( pszInterfaceName );
  1156. pStream->Write( "_FWD_DEFINED__ */\n" );
  1157. break;
  1158. case ID_CG_LIBRARY:
  1159. {
  1160. CG_ITERATOR Inner;
  1161. if ( pCG->GetMembers( Inner ) )
  1162. {
  1163. OutputInterfaceForwards( pStream, Inner );
  1164. }
  1165. break;
  1166. }
  1167. default:
  1168. break;
  1169. }
  1170. }
  1171. }
  1172. #define NibbleToAscii(x) ((x) >= 0x0A ? (x) + 'A' - 0x0A : (x) + '0')
  1173. #define IsAlphaNum_(x) (((x) >= '0' && (x) <= '9') || ((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z') || (x) == '_')
  1174. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1175. Routine Description:
  1176. Setup a flag (fIgnore) in STREAM no to write anything out .
  1177. Arguments:
  1178. Return Value:
  1179. none.
  1180. Notes:
  1181. This routine is called to avoid generating the same data structure twice, in
  1182. both NDR32 and NDR64 run.
  1183. ----------------------------------------------------------------------------*/
  1184. void SetNoOutputIn2ndCodegen( CCB *pCCB)
  1185. {
  1186. if ( pCommand->Is2ndCodegenRun() )
  1187. {
  1188. pCCB->GetStream()->SetIgnore();
  1189. }
  1190. }
  1191. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1192. Routine Description:
  1193. Reset Ignore flag in STREAM so Write will really write to the stream.
  1194. Arguments:
  1195. Return Value:
  1196. none.
  1197. Notes:
  1198. This routine is called to avoid generating the same data structure twice, in
  1199. both NDR32 and NDR64 run. This should be called after SetNoOutputInNdr64 to
  1200. resume regular output to stream. Current I assume we'll already generate both.
  1201. The correct checking should be Is2ndNdrRun().
  1202. ----------------------------------------------------------------------------*/
  1203. void ResetNoOutputIn2ndCodegen( CCB *pCCB)
  1204. {
  1205. if ( pCommand->Is2ndCodegenRun() )
  1206. {
  1207. pCCB->GetStream()->ResetIgnore();
  1208. }
  1209. }
  1210. void NormalizeString(
  1211. char* szSrc,
  1212. char* szNrm )
  1213. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1214. Routine Description:
  1215. Transform a string by converting spaces to underscores and other non-
  1216. alphanumerics to thier hex representation.
  1217. Arguments:
  1218. szSrc - The source string
  1219. szNrm - The normalized string
  1220. Return Value:
  1221. none.
  1222. Notes:
  1223. This routine is typically called when some generated variable is biased
  1224. by the filename. If the filename has a space or DBCS chars then the
  1225. generated variable wouldn't conform to C/C++ naming rules.
  1226. ----------------------------------------------------------------------------*/
  1227. {
  1228. for ( ; *szSrc; szSrc++ )
  1229. {
  1230. if (IsAlphaNum_(*szSrc))
  1231. {
  1232. *szNrm++ = *szSrc;
  1233. }
  1234. else if (*szSrc == ' ')
  1235. {
  1236. *szNrm++ = '_';
  1237. }
  1238. else
  1239. {
  1240. unsigned char ch;
  1241. ch = unsigned char( (*szSrc >> 4) & 0x0F );
  1242. *szNrm++ = (char) NibbleToAscii(ch);
  1243. ch = unsigned char(*szSrc & 0x0F);
  1244. *szNrm++ = (char)NibbleToAscii(ch);
  1245. }
  1246. }
  1247. *szNrm = 0;
  1248. }
  1249. CG_STATUS
  1250. CG_HDR_FILE::GenCode(
  1251. CCB * pCCB)
  1252. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1253. Routine Description:
  1254. Generate the header file.
  1255. Arguments:
  1256. pCCB - The code gen controller block.
  1257. Return Value:
  1258. CG_OK if all is well.
  1259. Notes:
  1260. ----------------------------------------------------------------------------*/
  1261. {
  1262. ISTREAM Stream( GetFileName(), 4 );
  1263. ISTREAM * pStream = pCCB->SetStream( &Stream, this );
  1264. CG_ITERATOR I;
  1265. CG_INTERFACE * pCG;
  1266. BOOL fHasPickle = FALSE;
  1267. BOOL fHasObject = FALSE;
  1268. char Buffer[ _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 1 ];
  1269. char Drive[ _MAX_DRIVE ];
  1270. char Path[ _MAX_DIR ];
  1271. char Name[ _MAX_FNAME ];
  1272. char Ext[ _MAX_EXT ];
  1273. if( !GetMembers( I ) )
  1274. {
  1275. return CG_OK;
  1276. }
  1277. if ( pCommand->Is64BitEnv() && pCommand->HasAppend64() )
  1278. {
  1279. // Don't generate the same h file definitions twice.
  1280. return CG_OK;
  1281. }
  1282. EmitFileHeadingBlock( pCCB,
  1283. "the definitions for the interfaces",
  1284. 0, // optional comment
  1285. false ); // no 64 vs.32 ifdef
  1286. while( ITERATOR_GETNEXT( I, pCG ) )
  1287. {
  1288. if ( pCG->HasPicklingStuff() )
  1289. {
  1290. fHasPickle = TRUE;
  1291. }
  1292. if ( pCG->IsObject() )
  1293. {
  1294. fHasObject = TRUE;
  1295. }
  1296. }
  1297. // rpcndr.h version guard
  1298. pStream->NewLine(2);
  1299. char sz[192];
  1300. pStream->Write( GetRpcNdrHVersionGuard( sz ) );
  1301. // Include standard files.
  1302. pStream->Write( "#include \"rpc.h\"\n#include \"rpcndr.h\"\n" );
  1303. // rpcndr.h version guard
  1304. if ( pCommand->GetNdrVersionControl().HasNdr50Feature() || fHasObject )
  1305. {
  1306. char *sz2 = "\n"
  1307. "#ifndef __RPCNDR_H_VERSION__\n"
  1308. "#error this stub requires an updated version of <rpcndr.h>\n"
  1309. "#endif // __RPCNDR_H_VERSION__\n\n";
  1310. pStream->Write( sz2 );
  1311. }
  1312. // If there is at least one pickle interface, emit the include
  1313. // of midles.h
  1314. if ( fHasPickle )
  1315. {
  1316. pStream->Write( "#include \"midles.h\"\n" );
  1317. }
  1318. if ( fHasObject )
  1319. {
  1320. pStream->Write( "#ifndef COM_NO_WINDOWS_H\n");
  1321. pStream->Write( "#include \"windows.h\"\n#include \"ole2.h\"\n" );
  1322. pStream->Write( "#endif /*COM_NO_WINDOWS_H*/\n");
  1323. }
  1324. // extract the name and the extension to create the ifdefs
  1325. _splitpath( GetFileName(), Drive, Path, Name, Ext );
  1326. char szNrmName[ _MAX_FNAME * 2 + 1 ];
  1327. char szNrmExt[ _MAX_EXT * 2 + 1 ];
  1328. NormalizeString( Name, szNrmName );
  1329. // ignore the '.' preceding the extension
  1330. if ( '.' == Ext[0] )
  1331. NormalizeString( &Ext[1], szNrmExt );
  1332. else
  1333. NormalizeString( Ext, szNrmExt );
  1334. // Write out the #ifndefs and #defines
  1335. pStream->NewLine();
  1336. sprintf( Buffer,
  1337. "#ifndef __%s_%s__\n#define __%s_%s__",
  1338. szNrmName,
  1339. szNrmExt,
  1340. szNrmName,
  1341. szNrmExt
  1342. );
  1343. pStream->Write( Buffer );
  1344. pStream->NewLine( 2 );
  1345. // Generate the #pragma once.
  1346. pStream->Write( "#if defined(_MSC_VER) && (_MSC_VER >= 1020)\n" );
  1347. pStream->Write( "#pragma once\n#endif" );
  1348. pStream->NewLine(2);
  1349. //Generate forward declarations for object interfaces.
  1350. pStream->Write("/* Forward Declarations */ ");
  1351. I.Init();
  1352. OutputInterfaceForwards( pStream, I );
  1353. pStream->NewLine();
  1354. // Include the import files.
  1355. OutputImportIncludes( pCCB );
  1356. pStream->NewLine();
  1357. // Write out the cplusplus guard.
  1358. pStream->Write( "#ifdef __cplusplus\nextern \"C\"{\n#endif " );
  1359. pStream->NewLine( 2 );
  1360. pStream->Write(
  1361. "void * __RPC_USER MIDL_user_allocate(size_t);" );
  1362. pStream->NewLine();
  1363. pStream->Write(
  1364. "void __RPC_USER MIDL_user_free( void * ); " );
  1365. pStream->NewLine();
  1366. //
  1367. // For all interfaces in this file, generate code.
  1368. //
  1369. I.Init();
  1370. while( ITERATOR_GETNEXT( I, pCG ) )
  1371. {
  1372. switch(pCG->GetCGID())
  1373. {
  1374. case ID_CG_INTERFACE:
  1375. case ID_CG_OBJECT_INTERFACE:
  1376. case ID_CG_LIBRARY:
  1377. pCG->GenHeader( pCCB );
  1378. case ID_CG_INHERITED_OBJECT_INTERFACE:
  1379. default:
  1380. break;
  1381. }
  1382. }
  1383. // put out all the prototypes that are only needed once
  1384. OutputMultipleInterfacePrototypes( pCCB );
  1385. // print out the closing endifs.
  1386. // first the cplusplus stuff.
  1387. pStream->Write( "#ifdef __cplusplus\n}\n#endif\n" );
  1388. // The endif for the file name ifndef
  1389. pStream->NewLine();
  1390. pStream->Write( "#endif" );
  1391. pStream->NewLine();
  1392. EmitFileClosingBlock( pCCB, false );
  1393. pStream->Close();
  1394. return CG_OK;
  1395. }
  1396. void
  1397. CG_HDR_FILE::OutputMultipleInterfacePrototypes(
  1398. CCB * pCCB )
  1399. {
  1400. ITERATOR I;
  1401. ITERATOR UserI;
  1402. ISTREAM * pStream = pCCB->GetStream();
  1403. pStream->NewLine();
  1404. pStream->Write("/* Additional Prototypes for ALL interfaces */");
  1405. pStream->NewLine();
  1406. // ALERT! we are using the same iterator for all different type of objects,
  1407. // so none of code below should Init the list or it'll step into something else.
  1408. // Use a new iterator if you need to rewind the list.
  1409. if( pCCB->GetListOfGenHdlTypes( I ) )
  1410. {
  1411. Out_GenHdlPrototypes( pCCB, I );
  1412. }
  1413. if( pCCB->GetListOfCtxtHdlTypes( I ) )
  1414. {
  1415. Out_CtxtHdlPrototypes( pCCB, I );
  1416. }
  1417. if( pCCB->GetListOfPresentedTypes( I ) )
  1418. {
  1419. Out_TransmitAsPrototypes( pCCB, I );
  1420. }
  1421. if( pCCB->GetListOfRepAsWireTypes( I ) )
  1422. {
  1423. Out_RepAsPrototypes( pCCB, I );
  1424. }
  1425. if( pCCB->GetQuadrupleDictionary()->GetListOfItems( UserI ) )
  1426. {
  1427. Out_UserMarshalPrototypes( pCCB, UserI );
  1428. }
  1429. Out_CSSizingAndConversionPrototypes( pCCB, pCCB->GetCsTypeList() );
  1430. if( pCCB->GetListOfTypeAlignSizeTypes( I ) )
  1431. {
  1432. Out_TypeAlignSizePrototypes( pCCB, I );
  1433. }
  1434. if( pCCB->GetListOfTypeEncodeTypes( I ) )
  1435. {
  1436. Out_TypeEncodePrototypes( pCCB, I );
  1437. }
  1438. if( pCCB->GetListOfTypeDecodeTypes( I ) )
  1439. {
  1440. Out_TypeDecodePrototypes( pCCB, I );
  1441. }
  1442. if( pCCB->GetListOfTypeFreeTypes( I ) )
  1443. {
  1444. Out_TypeFreePrototypes( pCCB, I );
  1445. }
  1446. if ( pCCB->GetListOfCallAsRoutines( I ) )
  1447. {
  1448. Out_CallAsProxyPrototypes( pCCB, I );
  1449. }
  1450. if ( pCCB->GetListOfCallAsRoutines( I ) )
  1451. {
  1452. Out_CallAsServerPrototypes( pCCB, I );
  1453. }
  1454. if( pCCB->GetListOfNotifyTableEntries( I ) )
  1455. {
  1456. Out_NotifyPrototypes( pCCB, I );
  1457. }
  1458. pStream->NewLine();
  1459. pStream->Write("/* end of Additional Prototypes */");
  1460. pStream->NewLine( 2 );
  1461. }