Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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