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.

1573 lines
45 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1993-1999 Microsoft Corporation
  3. Module Name:
  4. stndr.hxx
  5. Abstract:
  6. Contains routines for the generation of the new NDR format strings for
  7. structure types, and the new NDR marshalling and unmarshalling calls.
  8. Notes:
  9. History:
  10. DKays Oct-1993 Created.
  11. ----------------------------------------------------------------------------*/
  12. #include "becls.hxx"
  13. #pragma hdrstop
  14. void
  15. CG_STRUCT::GenNdrFormat( CCB * pCCB )
  16. /*++
  17. Routine Description :
  18. Generates the format string description for a simple, conformant,
  19. or conformant varying structure.
  20. Arguments :
  21. pCCB - pointer to the code control block.
  22. --*/
  23. {
  24. FORMAT_STRING * pFormatString;
  25. CG_NDR * pOldCGNodeContext;
  26. CG_NDR * pConformantArray;
  27. if ( GetFormatStringOffset() != -1 )
  28. return;
  29. //
  30. // Check if this structure is "complex".
  31. //
  32. if ( IsComplexStruct() )
  33. {
  34. GenNdrFormatComplex( pCCB );
  35. return;
  36. }
  37. //
  38. // Check if the structure is "hard".
  39. //
  40. if ( IsHardStruct() )
  41. {
  42. GenNdrFormatHard( pCCB );
  43. return;
  44. }
  45. Unroll();
  46. //
  47. // Temporarily set the format string offset to 0 in case this structure
  48. // has pointers to it's own type.
  49. //
  50. SetFormatStringOffset( 0 );
  51. SetInitialOffset( 0 );
  52. CG_FIELD *pOldRegionField = NULL;
  53. #if defined(NDR64_ON_DCE_HACK)
  54. if ( NULL != dynamic_cast<CG_REGION*>( this ) )
  55. {
  56. pOldRegionField = pCCB->StartRegion();
  57. }
  58. else
  59. #endif
  60. pOldCGNodeContext = pCCB->SetCGNodeContext( this );
  61. pFormatString = pCCB->GetFormatString();
  62. //
  63. // Search the fields of the structure for embedded structures and generate
  64. // the format string for these.
  65. //
  66. CG_ITERATOR Iterator;
  67. CG_FIELD * pField;
  68. CG_NDR * pMember;
  69. GetMembers( Iterator );
  70. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  71. {
  72. CG_NDR * pOldPlaceholder;
  73. pOldPlaceholder = pCCB->SetLastPlaceholderClass( pField );
  74. pMember = (CG_NDR *) pField->GetChild();
  75. //
  76. // If there is a structure or array member then generate
  77. // it's format string. We don't have to check for a union, because
  78. // that will make the struct CG_COMPLEX_STRUCT.
  79. //
  80. if ( pMember->IsStruct() || pMember->IsArray() )
  81. pMember->GenNdrFormat( pCCB );
  82. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  83. }
  84. //
  85. // If this is a conformant (varying) struct then generate the array's
  86. // description.
  87. //
  88. if ( GetCGID() == ID_CG_CONF_STRUCT ||
  89. GetCGID() == ID_CG_CONF_VAR_STRUCT )
  90. {
  91. CG_NDR * pOldPlaceholder;
  92. pOldPlaceholder =
  93. pCCB->SetLastPlaceholderClass(
  94. (CG_NDR *) ((CG_CONFORMANT_STRUCT *)this)->GetConformantField() );
  95. // Get the conformant array CG class.
  96. pConformantArray = (CG_NDR *)
  97. ((CG_CONFORMANT_STRUCT *)this)->GetConformantArray();
  98. // Generate the format string for the array.
  99. pConformantArray->GenNdrFormat( pCCB );
  100. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  101. }
  102. //
  103. // If there are pointers in the structure then before you can start
  104. // generating the format string for the structure, you must generate
  105. // the format string for all of the pointees.
  106. //
  107. if ( HasPointer() )
  108. {
  109. GenNdrStructurePointees( pCCB );
  110. }
  111. SetFormatStringOffset( pFormatString->GetCurrentOffset() );
  112. SetInitialOffset( pFormatString->GetCurrentOffset() );
  113. switch ( GetCGID() )
  114. {
  115. case ID_CG_STRUCT :
  116. pFormatString->PushFormatChar( HasPointer() ?
  117. FC_PSTRUCT : FC_STRUCT );
  118. break;
  119. case ID_CG_CONF_STRUCT :
  120. pFormatString->PushFormatChar( HasPointer() ?
  121. FC_CPSTRUCT : FC_CSTRUCT );
  122. break;
  123. case ID_CG_CONF_VAR_STRUCT :
  124. pFormatString->PushFormatChar( FC_CVSTRUCT );
  125. break;
  126. }
  127. // Set the alignment.
  128. pFormatString->PushByte( GetWireAlignment() - 1 );
  129. // Set the structure memory size.
  130. pFormatString->PushShort( (short)GetMemorySize() );
  131. //
  132. // If this is a conformant array then push the offset to the conformant
  133. // array's description.
  134. //
  135. if ( GetCGID() == ID_CG_CONF_STRUCT ||
  136. GetCGID() == ID_CG_CONF_VAR_STRUCT )
  137. {
  138. // Set the offset to the array description.
  139. pFormatString->PushShortOffset( pConformantArray->GetFormatStringOffset() -
  140. pFormatString->GetCurrentOffset() );
  141. }
  142. // Generate the pointer layout if needed.
  143. if ( HasPointer() )
  144. {
  145. GenNdrStructurePointerLayout( pCCB, FALSE, FALSE );
  146. }
  147. // Now generate the layout.
  148. GenNdrStructureLayout( pCCB );
  149. //
  150. // Now we have to fix up the offset for any recursive pointer to this
  151. // structure.
  152. //
  153. GenNdrPointerFixUp( pCCB, this );
  154. #if defined(NDR64_ON_DCE_HACK)
  155. if ( NULL != dynamic_cast<CG_REGION*>( this ) )
  156. {
  157. pCCB->EndRegion(pOldRegionField);
  158. }
  159. else
  160. #endif
  161. pCCB->SetCGNodeContext( pOldCGNodeContext );
  162. SetFormatStringEndOffset( pFormatString->GetCurrentOffset() );
  163. pFormatString->OptimizeFragment( this );
  164. SetInitialOffset( GetFormatStringOffset() );
  165. FixupEmbeddedComplex( pCCB );
  166. if ( GetDuplicatingComplex() )
  167. GetDuplicatingComplex()->FixupEmbeddedComplex( pCCB );
  168. }
  169. void
  170. CG_STRUCT::GenNdrFormatHard( CCB * pCCB )
  171. /*++
  172. Routine Description :
  173. Generates the format string description for a packed structure. The
  174. description has the same format as for a complex struct.
  175. Arguments :
  176. pCCB - pointer to the code control block.
  177. --*/
  178. {
  179. FORMAT_STRING * pFormatString;
  180. CG_NDR * pOldCGNodeContext;
  181. CG_NDR * pUnion;
  182. CG_FIELD * pFinalField;
  183. long CopySize;
  184. long MemoryIncrement;
  185. if ( GetFormatStringOffset() != -1 )
  186. return;
  187. //
  188. // Temporarily set the format string offset to 0 in case this structure
  189. // has pointers to it's own type.
  190. //
  191. SetFormatStringOffset( 0 );
  192. SetInitialOffset( 0 );
  193. pOldCGNodeContext = pCCB->SetCGNodeContext( this );
  194. pFormatString = pCCB->GetFormatString();
  195. //
  196. // Search the fields of the structure for embedded structures and generate
  197. // the format string for these.
  198. //
  199. CG_ITERATOR Iterator;
  200. CG_FIELD * pField;
  201. CG_NDR * pMember;
  202. CG_NDR * pOldPlaceholder;
  203. GetMembers( Iterator );
  204. pOldPlaceholder = pCCB->GetLastPlaceholderClass();
  205. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  206. {
  207. pMember = (CG_NDR *) pField->GetChild();
  208. //
  209. // If there is an embedded structure, array, or union then generate
  210. // it's format string.
  211. //
  212. if ( pMember->IsStruct() || pMember->IsArray() || pMember->IsUnion() )
  213. {
  214. pCCB->SetLastPlaceholderClass( pField );
  215. pMember->GenNdrFormat( pCCB );
  216. }
  217. }
  218. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  219. SetFormatStringOffset( pFormatString->GetCurrentOffset() );
  220. SetInitialOffset( pFormatString->GetCurrentOffset() );
  221. pFinalField = GetFinalField();
  222. //
  223. // See if we have a union.
  224. //
  225. if ( pFinalField->GetChild()->IsUnion() )
  226. pUnion = (CG_NDR *) pFinalField->GetChild();
  227. else
  228. pUnion = 0;
  229. //
  230. // Determine the copy size and memory increment for the copy.
  231. //
  232. if ( pUnion )
  233. {
  234. CG_STRUCT * pStruct;
  235. pStruct = this;
  236. CopySize = 0;
  237. for ( ;; )
  238. {
  239. pStruct->GetMembers( Iterator );
  240. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  241. ;
  242. CopySize += pField->GetWireOffset();
  243. pMember = (CG_NDR *) pField->GetChild();
  244. if ( pMember->IsStruct() )
  245. {
  246. pStruct = (CG_STRUCT *) pMember;
  247. continue;
  248. }
  249. else
  250. break;
  251. }
  252. MemoryIncrement = GetMemorySize() - pUnion->GetMemorySize();
  253. }
  254. else
  255. {
  256. CopySize = GetWireSize();
  257. MemoryIncrement = GetMemorySize();
  258. }
  259. //
  260. // Format string generation.
  261. //
  262. pFormatString->PushFormatChar( FC_HARD_STRUCT );
  263. // The alignment.
  264. pFormatString->PushByte( GetWireAlignment() - 1 );
  265. // The structure's memory size.
  266. pFormatString->PushShort( (short)GetMemorySize() );
  267. // Reserved for future use.
  268. pFormatString->PushLong( 0 );
  269. //
  270. // Offset to enum in struct.
  271. //
  272. if ( GetNumberOfEnum16s() == 1 )
  273. pFormatString->PushShort( GetEnum16Offset() );
  274. else
  275. pFormatString->PushShort( (short) -1 );
  276. //
  277. // Copy size and memory increment.
  278. //
  279. pFormatString->PushShort( CopySize );
  280. pFormatString->PushShort( MemoryIncrement );
  281. //
  282. // Offset to union's format string description.
  283. //
  284. if ( pUnion )
  285. {
  286. pOldPlaceholder = pCCB->GetLastPlaceholderClass();
  287. pCCB->SetLastPlaceholderClass( pFinalField );
  288. pFormatString->PushShort( (short)
  289. (pUnion->GetFormatStringOffset() -
  290. pFormatString->GetCurrentOffset()) );
  291. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  292. }
  293. else
  294. pFormatString->PushShort( (short) 0 );
  295. // Now generate the layout.
  296. GenNdrStructureLayout( pCCB );
  297. //
  298. // Now we have to fix up the offset for any recursive pointer to this
  299. // structure.
  300. //
  301. GenNdrPointerFixUp( pCCB, this );
  302. pCCB->SetCGNodeContext( pOldCGNodeContext );
  303. SetFormatStringEndOffset( pFormatString->GetCurrentOffset() );
  304. pFormatString->OptimizeFragment( this );
  305. SetInitialOffset( GetFormatStringOffset() );
  306. FixupEmbeddedComplex( pCCB );
  307. }
  308. void
  309. CG_STRUCT::GenNdrFormatComplex( CCB * pCCB )
  310. /*++
  311. Routine Description :
  312. Generates the format string description for a packed structure. The
  313. description has the same format as for a complex struct.
  314. Arguments :
  315. pCCB - pointer to the code control block.
  316. --*/
  317. {
  318. CG_CLASS * pConfField;
  319. CG_COMPLEX_STRUCT * pComplex;
  320. if ( (GetCGID() == ID_CG_CONF_STRUCT) ||
  321. (GetCGID() == ID_CG_CONF_VAR_STRUCT) )
  322. pConfField = ((CG_CONFORMANT_STRUCT *)this)->GetConformantField();
  323. else
  324. pConfField = 0;
  325. //
  326. // Do the old duplication trick.
  327. //
  328. pComplex = new CG_COMPLEX_STRUCT( this, pConfField );
  329. SetDuplicatingComplex( pComplex );
  330. //
  331. // Now temporarily set our format string offset to 0 to handle recursive
  332. // definitions.
  333. //
  334. SetFormatStringOffset( 0 );
  335. SetInitialOffset( 0 );
  336. //
  337. // This call will set our format string offset correctly.
  338. //
  339. pComplex->GenNdrFormat( pCCB );
  340. // Don't delete since the expression evaluator might need this.
  341. // delete( pComplex );
  342. }
  343. bool IsEnum16UnionAlignBug( CG_STRUCT *pStruct )
  344. {
  345. // Comment from old hack wacked on stub.
  346. // The NT 3.50 stubs had a problem with union alignment that affects
  347. // structs with 16b enum and a union as the only other thing.
  348. // The old, incorrect alignment was 2 (code 1), the correct alignment is 4 (code 3).
  349. // All the compilers since NT 3.51, i.e. MIDL 2.0.102 generate correct code,
  350. // however we needed to introduce the wrong alignment into newly compiled stubs
  351. // to get interoperability with the released dhcp client and server binaries.
  352. if ( 4 != pStruct->GetWireAlignment())
  353. return false;
  354. CG_ITERATOR StructElements;
  355. pStruct->GetMembers( StructElements );
  356. ITERATOR_INIT( StructElements );
  357. size_t Elements = ITERATOR_GETCOUNT( StructElements );
  358. if ( 2 != Elements )
  359. return false;
  360. ITERATOR_INIT( StructElements );
  361. CG_FIELD *pField1 = NULL;
  362. ITERATOR_GETNEXT( StructElements, pField1 );
  363. MIDL_ASSERT( NULL != pField1);
  364. // Is the first field a enum16?
  365. CG_ENUM *pEnum = dynamic_cast<CG_ENUM*>( pField1->GetChild() );
  366. if ( ( NULL == pEnum ) || pEnum->IsEnumLong() )
  367. return false;
  368. // Is the second field a union
  369. CG_FIELD *pField2 = NULL;
  370. ITERATOR_GETNEXT( StructElements, pField2 );
  371. MIDL_ASSERT( NULL != pField2 );
  372. if ( ! pField2->GetChild()->IsUnion())
  373. return false;
  374. // Ok. We have a 2 field structure were the first field is an enum16 and the second field is
  375. // and union.
  376. return true;
  377. }
  378. void
  379. CG_COMPLEX_STRUCT::GenNdrFormat( CCB * pCCB )
  380. /*++
  381. Routine Description :
  382. Generates the format string description for a complex structure.
  383. Arguments :
  384. pCCB - pointer to the code control block.
  385. --*/
  386. {
  387. FORMAT_STRING * pFormatString;
  388. CG_NDR * pOldCGNodeContext;
  389. CG_NDR * pConformantArray;
  390. long PointerLayoutOffset;
  391. if ( GetFormatStringOffset() != -1 )
  392. return;
  393. pFormatString = pCCB->GetFormatString();
  394. //
  395. // Temporarily set the format string offset to 0 in case this structure
  396. // has pointers to it's own type.
  397. //
  398. SetFormatStringOffset( 0 );
  399. SetInitialOffset( 0 );
  400. pOldCGNodeContext = pCCB->SetCGNodeContext( this );
  401. //
  402. // Search the fields of the structure for imbeded structures, arrays, and
  403. // and unions and generate the format string for these.
  404. //
  405. CG_ITERATOR Iterator;
  406. CG_FIELD * pField;
  407. CG_NDR * pMember;
  408. GetMembers( Iterator );
  409. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  410. {
  411. pMember = (CG_NDR *) pField->GetChild();
  412. //
  413. // If the field is anything other than a base type or a
  414. // non-interface pointer then generate it's description.
  415. //
  416. if ( ! pMember->IsSimpleType() &&
  417. ! ( pMember->IsPointer() &&
  418. !pMember->IsInterfacePointer() ) &&
  419. (pMember->GetCGID() != ID_CG_IGN_PTR) ||
  420. pMember->GetRangeAttribute() )
  421. {
  422. CG_NDR * pOldPlaceholder;
  423. pOldPlaceholder = pCCB->SetLastPlaceholderClass( pField );
  424. pMember->GenNdrFormat( pCCB );
  425. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  426. }
  427. }
  428. // Generate pointee format strings.
  429. GenNdrStructurePointees( pCCB );
  430. // Generate conformant array description.
  431. if ( ( pConformantArray = (CG_NDR *) GetConformantArray() ) != 0 )
  432. {
  433. CG_NDR * pOldPlaceholder;
  434. pOldPlaceholder = pCCB->SetLastPlaceholderClass(
  435. (CG_NDR *) GetConformantField() );
  436. pConformantArray->GenNdrFormat( pCCB );
  437. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  438. }
  439. // Now set the struct's format string offset.
  440. SetFormatStringOffset( pFormatString->GetCurrentOffset() );
  441. SetInitialOffset( pFormatString->GetCurrentOffset() );
  442. //
  443. // Set the duplicated struct's format string offset if we were duplicated.
  444. //
  445. if ( GetDuplicatedStruct() )
  446. {
  447. GetDuplicatedStruct()->SetFormatStringOffset( GetFormatStringOffset() );
  448. GetDuplicatedStruct()->SetInitialOffset( GetFormatStringOffset() );
  449. }
  450. pFormatString->PushFormatChar( FC_BOGUS_STRUCT );
  451. WarnAboutEmbeddedComplexStruct();
  452. //
  453. // Set the wire alignment.
  454. //
  455. if ( pCommand->WireCompat( WIRE_COMPAT_ENUM16UNIONALIGN ) &&
  456. IsEnum16UnionAlignBug(this) )
  457. {
  458. // Comment from old hack wacked on stub.
  459. // The NT 3.50 stubs had a problem with union alignment that affects
  460. // structs with 16b enum and a union as the only other thing.
  461. // The old, incorrect alignment was 2 (code 1), the correct alignment is 4 (code 3).
  462. // All the compilers since NT 3.51, i.e. MIDL 2.0.102 generate correct code,
  463. // however we needed to introduce the wrong alignment into newly compiled stubs
  464. // to get interoperability with the released dhcp client and server binaries.
  465. pFormatString->AddComment( pFormatString->GetCurrentOffset(), "/* 3 */ /* enum16unionalign Bug Compatibility */" );
  466. pFormatString->PushByte( 1 );
  467. }
  468. else
  469. pFormatString->PushByte( GetWireAlignment() - 1 );
  470. // Set the structure memory size.
  471. pFormatString->PushShort( (short)GetMemorySize() );
  472. // Array description.
  473. if ( pConformantArray )
  474. pFormatString->PushShortOffset( pConformantArray->GetFormatStringOffset() -
  475. pFormatString->GetCurrentOffset() );
  476. else
  477. pFormatString->PushShort( (short) 0 );
  478. //
  479. // Remember where the offset_to_pointer_layout<> field will go and push
  480. // some space for it.
  481. //
  482. PointerLayoutOffset = pFormatString->GetCurrentOffset();
  483. pFormatString->PushShortOffset( 0 );
  484. // Now generate the structure's layout.
  485. GenNdrStructureLayout( pCCB );
  486. //
  487. // Now see if we have any plain pointer fields and if so generate a
  488. // pointer layout. We can't use the HasAtLeastOnePointer() method
  489. // because this tells us TRUE if we have any embedded arrays, structs,
  490. // or unions which have pointers. For complex structs we're only
  491. // interested in actual pointer fields.
  492. //
  493. GetMembers( Iterator );
  494. //
  495. // Fill in the offset_to_pointer_layout<2> field and generate a
  496. // pointer_layout<> if we have any pointer fields. Interface pointers
  497. // do not reside in the pointer layout.
  498. //
  499. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  500. if ( pField->GetChild()->IsPointer() &&
  501. !pField->IsInterfacePointer() )
  502. {
  503. // This is an internal offset within the struct descriptor, namely
  504. // to the pointer layout field, not the offset to a type.
  505. // Surprisingly, this code may produce an offset to an array etc.
  506. // Hence, we push an offset to be backward compatible.
  507. pFormatString->PushShortOffset(
  508. pFormatString->GetCurrentOffset() - PointerLayoutOffset,
  509. PointerLayoutOffset );
  510. GenNdrStructurePointerLayout( pCCB );
  511. break;
  512. }
  513. pFormatString->Align();
  514. //
  515. // Now we have to fix up the offset for any recursive pointer to this
  516. // structure.
  517. //
  518. GenNdrPointerFixUp( pCCB, GetDuplicatedStruct() ? GetDuplicatedStruct() : this );
  519. pCCB->SetCGNodeContext( pOldCGNodeContext );
  520. SetFormatStringEndOffset( pFormatString->GetCurrentOffset() );
  521. pFormatString->OptimizeFragment( this );
  522. SetInitialOffset( GetFormatStringOffset() );
  523. if ( GetDuplicatedStruct() )
  524. GetDuplicatedStruct()->SetFormatStringOffset( GetFormatStringOffset() );
  525. FixupEmbeddedComplex( pCCB );
  526. if ( GetDuplicatedStruct() )
  527. GetDuplicatedStruct()->FixupEmbeddedComplex( pCCB );
  528. // There is no call to the string optimizer here. If we wanted to put it in,
  529. // the code should check if the optimization is possible or not by checking the
  530. // result of GenNdrEmbeddedPointers via GenNdrStructurePointerLayout call.
  531. }
  532. void
  533. CG_COMPLEX_STRUCT::GenNdrStructurePointerLayout( CCB * pCCB )
  534. /*++
  535. Routine Description :
  536. Generates the format string pointer layout section for a complex
  537. structure.
  538. Arguments :
  539. pCCB - pointer to the code control block.
  540. --*/
  541. {
  542. CG_ITERATOR Iterator;
  543. CG_FIELD * pField;
  544. CG_NDR * pMember;
  545. GetMembers( Iterator );
  546. while( ITERATOR_GETNEXT( Iterator, pField ) )
  547. {
  548. CG_NDR * pOldPlaceholder;
  549. pOldPlaceholder = pCCB->SetLastPlaceholderClass( pField );
  550. pMember = (CG_NDR *) pField->GetChild();
  551. if ( pMember->IsPointer() &&
  552. !pMember->IsInterfacePointer())
  553. {
  554. CG_POINTER * pPointer;
  555. pPointer = (CG_POINTER *) pMember;
  556. // The pointer description.
  557. pPointer->GenNdrFormatEmbedded( pCCB );
  558. }
  559. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  560. } // while
  561. }
  562. //---------------------------------------------------------------------------
  563. // Methods shared by all or most structure classes.
  564. //---------------------------------------------------------------------------
  565. void
  566. CG_STRUCT::GenNdrStructurePointerLayout( CCB * pCCB,
  567. BOOL fNoPP,
  568. BOOL fNoType )
  569. /*++
  570. Routine Description :
  571. Generates the format string pointer layout section for a structure.
  572. This is the default routine for this used by the structure classes.
  573. Only CG_COMPLEX_STRUCT redefines this virtual method.
  574. Arguments :
  575. pCCB - pointer to the code control block.
  576. fNoPP - TRUE if no FC_PP or FC_END should be emitted
  577. fNoType - TRUE only the bare offset and description should be emitted
  578. for each pointer
  579. --*/
  580. {
  581. CG_ITERATOR Iterator;
  582. FORMAT_STRING * pFormatString;
  583. CG_FIELD * pField;
  584. CG_NDR * pMember;
  585. long ImbedingMemSize;
  586. long ImbedingBufSize;
  587. pFormatString = pCCB->GetFormatString();
  588. // Get/Save the current imbeding sizes.
  589. ImbedingMemSize = pCCB->GetImbedingMemSize();
  590. ImbedingBufSize = pCCB->GetImbedingBufSize();
  591. if ( ! fNoPP )
  592. {
  593. pFormatString->PushFormatChar( FC_PP );
  594. pFormatString->PushFormatChar( FC_PAD );
  595. }
  596. GetMembers( Iterator );
  597. while( ITERATOR_GETNEXT( Iterator, pField ) )
  598. {
  599. CG_NDR * pOldPlaceholder;
  600. pOldPlaceholder = pCCB->SetLastPlaceholderClass( pField );
  601. pMember = (CG_NDR *) pField->GetChild();
  602. if ( pMember->IsPointer() &&
  603. !pMember->IsInterfacePointer() )
  604. {
  605. CG_POINTER * pPointer;
  606. pPointer = (CG_POINTER *) pMember;
  607. // Push the instance type.
  608. if ( ! fNoType )
  609. {
  610. pFormatString->PushFormatChar( FC_NO_REPEAT );
  611. pFormatString->PushFormatChar( FC_PAD );
  612. }
  613. pFormatString->PushShort( (short)
  614. (ImbedingMemSize + pField->GetMemOffset()));
  615. pFormatString->PushShort( (short)
  616. (ImbedingBufSize + pField->GetWireOffset()));
  617. // The actual pointer description.
  618. pPointer->GenNdrFormatEmbedded( pCCB );
  619. }
  620. //
  621. // Generate pointer descriptions for all embedded arrays and structs.
  622. // We don't have to check for unions because that will make the struct
  623. // complex.
  624. //
  625. if ( pMember->IsArray() )
  626. {
  627. CG_NDR * pNdr = (CG_NDR *) pMember->GetChild();
  628. //
  629. // For arrays we set the imbeded memory size equal to the
  630. // size of the whole imbededing structure.
  631. //
  632. pCCB->SetImbedingMemSize( ImbedingMemSize + GetMemorySize() );
  633. pCCB->SetImbedingBufSize( ImbedingBufSize + GetWireSize() );
  634. if ( (pNdr->IsPointer() &&
  635. !pNdr->IsInterfacePointer() )
  636. ||
  637. ( pNdr->IsStruct() && ((CG_COMP *)pNdr)->HasPointer() ) )
  638. ((CG_ARRAY *)pMember)->GenNdrFormatArrayPointerLayout( pCCB,
  639. TRUE );
  640. }
  641. if ( pMember->IsStruct() )
  642. if ( ((CG_STRUCT *)pMember)->HasPointer() )
  643. {
  644. //
  645. // For embedded structs we add the embedded struct's offset to
  646. // the value of the current embeddeding size.
  647. //
  648. pCCB->SetImbedingMemSize( ImbedingMemSize +
  649. pField->GetMemOffset() );
  650. pCCB->SetImbedingBufSize( ImbedingBufSize +
  651. pField->GetWireOffset() );
  652. ((CG_STRUCT *)pMember)->GenNdrStructurePointerLayout( pCCB,
  653. TRUE,
  654. fNoType );
  655. }
  656. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  657. } // while
  658. if ( ! fNoPP )
  659. pFormatString->PushFormatChar( FC_END );
  660. // Re-set the old imbeding sizes.
  661. pCCB->SetImbedingMemSize( ImbedingMemSize );
  662. pCCB->SetImbedingBufSize( ImbedingBufSize );
  663. // There is no call to the string optimizer here. If we wanted to put it in,
  664. // the code should check if the optimization is possible or not by checking the
  665. // result of GenNdrEmbeddedPointers via GenNdrStructurePointerLayout call.
  666. }
  667. CG_FIELD *
  668. CG_STRUCT::GetPreviousField( CG_FIELD * pMarkerField )
  669. /*++
  670. Routine description:
  671. Finds the field immediately preceding the given field.
  672. Argument:
  673. pMarkerField - the given field
  674. Returns:
  675. The preceding field or NULL if the given field is the first one.
  676. --*/
  677. {
  678. CG_ITERATOR Iterator;
  679. CG_FIELD *pField, *pPreviousField = 0;
  680. GetMembers( Iterator );
  681. while( ITERATOR_GETNEXT( Iterator, pField ) )
  682. {
  683. if ( pField == pMarkerField )
  684. return( pPreviousField );
  685. pPreviousField = pField;
  686. }
  687. return( 0 );
  688. }
  689. void
  690. CG_STRUCT::GenStructureMemPad( CCB * pCCB, unsigned long MemPad )
  691. /*++
  692. Routine Description :
  693. Generates the format string for memory padding in a structure layout.
  694. Arguments :
  695. pCCB - pointer to the code control block.
  696. MemPad - Amount of required padding.
  697. --*/
  698. {
  699. FORMAT_STRING * pFormatString = pCCB->GetFormatString();
  700. MIDL_ASSERT( MemPad < 0xFFFF ); // structures must be less then 64k
  701. switch( MemPad)
  702. {
  703. case 0:
  704. return; // No padding needed
  705. case 1:
  706. pFormatString->PushFormatChar( FC_STRUCTPAD1 );
  707. return;
  708. case 2:
  709. pFormatString->PushFormatChar( FC_STRUCTPAD2 );
  710. return;
  711. case 3:
  712. pFormatString->PushFormatChar( FC_STRUCTPAD3 );
  713. return;
  714. case 4:
  715. pFormatString->PushFormatChar( FC_STRUCTPAD4 );
  716. return;
  717. case 5:
  718. pFormatString->PushFormatChar( FC_STRUCTPAD5 );
  719. return;
  720. case 6:
  721. pFormatString->PushFormatChar( FC_STRUCTPAD6 );
  722. return;
  723. case 7:
  724. pFormatString->PushFormatChar( FC_STRUCTPAD7 );
  725. return;
  726. default:
  727. // NDR60 Feature
  728. // Pad an arbitrary amount
  729. // FC_STRUCTPADN 0 <unsigned short>
  730. pFormatString->Align();
  731. pFormatString->PushFormatChar( FC_STRUCTPADN );
  732. pFormatString->PushFormatChar( FC_ZERO );
  733. pFormatString->PushShort( (short)MemPad );
  734. pCommand->GetNdrVersionControl().SetHasStructPadN();
  735. }
  736. }
  737. void
  738. CG_STRUCT::GenNdrStructureLayout( CCB * pCCB )
  739. /*++
  740. Routine Description :
  741. Generates the format string layout section for a structure.
  742. Arguments :
  743. pCCB - pointer to the code control block.
  744. --*/
  745. {
  746. FORMAT_STRING * pFormatString = pCCB->GetFormatString();
  747. CG_NDR * pOldPlaceholder = pCCB->GetLastPlaceholderClass();
  748. CG_ITERATOR Iterator;
  749. GetMembers( Iterator );
  750. CG_FIELD * pField;
  751. CG_FIELD * pPrevField = NULL;
  752. unsigned long BufferOffset = 0;
  753. bool fSawUnknownRepAs = false;
  754. while( ITERATOR_GETNEXT( Iterator, pField ) )
  755. {
  756. if ( fSawUnknownRepAs && !pField->HasEmbeddedUnknownRepAs() )
  757. {
  758. switch ( pField->GetMemoryAlignment() )
  759. {
  760. case 2: pFormatString->PushFormatChar( FC_ALIGNM2 ); break;
  761. case 4: pFormatString->PushFormatChar( FC_ALIGNM4 ); break;
  762. case 8: pFormatString->PushFormatChar( FC_ALIGNM8 ); break;
  763. }
  764. }
  765. else if ( !fSawUnknownRepAs && !pField->HasEmbeddedUnknownRepAs() )
  766. {
  767. unsigned long MemPad = pField->GetMemOffset() - BufferOffset;
  768. GenStructureMemPad( pCCB, MemPad );
  769. BufferOffset += MemPad;
  770. }
  771. pCCB->SetLastPlaceholderClass( pField );
  772. CG_NDR *pMember = (CG_NDR *) pField->GetChild();
  773. while ( pMember->GetCGID() == ID_CG_TYPEDEF )
  774. {
  775. pMember = ( CG_NDR* )pMember->GetChild();
  776. }
  777. // The ending conformat array is not included in the
  778. // size of the structure.
  779. // Note that this must be the last field.
  780. if ( pMember->GetCGID() == ID_CG_CONF_ARRAY ||
  781. pMember->GetCGID() == ID_CG_CONF_VAR_ARRAY ||
  782. pMember->GetCGID() == ID_CG_CONF_STRING_ARRAY )
  783. {
  784. break;
  785. }
  786. // Generate an embedded complex for embedded things.
  787. if ( pMember->IsStruct() ||
  788. pMember->IsUnion() ||
  789. pMember->IsArray() ||
  790. pMember->IsXmitRepOrUserMarshal() ||
  791. pMember->GetRangeAttribute() ||
  792. pMember->IsInterfacePointer() )
  793. {
  794. pFormatString->PushFormatChar( FC_EMBEDDED_COMPLEX );
  795. if ( pField->HasEmbeddedUnknownRepAs() )
  796. {
  797. pCCB->GetRepAsPadExprDict()->Register(
  798. pFormatString->GetCurrentOffset(),
  799. GetType(),
  800. pField->GetType()->GetSymName(),
  801. pPrevField ? pPrevField->GetType() : 0 );
  802. pFormatString->PushByteWithPadMacro();
  803. fSawUnknownRepAs = true;
  804. }
  805. else
  806. {
  807. pFormatString->PushByte( 0 ); //Padding is generated independently
  808. }
  809. if ( pMember->GetFormatStringOffset() == -1 ||
  810. pMember->GetFormatStringOffset() == 0 )
  811. {
  812. RegisterComplexEmbeddedForFixup(
  813. pMember,
  814. pFormatString->GetCurrentOffset() - GetInitialOffset() );
  815. }
  816. pFormatString->PushShortOffset( pMember->GetFormatStringOffset() -
  817. pFormatString->GetCurrentOffset() );
  818. }
  819. else if (pMember->IsPointer() ||
  820. ( pMember->GetCGID() == ID_CG_IGN_PTR ) )
  821. {
  822. if ( pMember->IsPointer() )
  823. {
  824. if ( GetCGID() == ID_CG_COMPLEX_STRUCT )
  825. pFormatString->PushFormatChar( FC_POINTER );
  826. else
  827. {
  828. pFormatString->PushFormatChar( FC_LONG );
  829. #if !defined(NDR64_ON_DCE_HACK )
  830. MIDL_ASSERT( ! pCommand->Is64BitEnv() );
  831. #endif
  832. }
  833. }
  834. else
  835. pFormatString->PushFormatChar( FC_IGNORE );
  836. }
  837. #if defined( NDR64_ON_DCE_HACK )
  838. else if ( NULL != dynamic_cast<CG_PAD*>( pMember ) )
  839. {
  840. pFormatString->PushFormatChar( FC_BUFFER_ALIGN );
  841. pFormatString->PushByte( pMember->GetWireAlignment() - 1);
  842. }
  843. #endif
  844. else
  845. {
  846. //
  847. // Must be a CG_BASETYPE if we get here.
  848. //
  849. FORMAT_CHARACTER FormatChar = ((CG_BASETYPE *)pMember)->GetFormatChar();
  850. pFormatString->PushFormatChar( FormatChar );
  851. }
  852. BufferOffset += pField->GetMemorySize();
  853. pPrevField = pField;
  854. }
  855. // Account for padding at the end of the structure.
  856. MIDL_ASSERT( GetMemorySize() >= BufferOffset );
  857. unsigned long EndingPad = GetMemorySize() - BufferOffset;
  858. // End padding is only allow on complex struct.
  859. MIDL_ASSERT( EndingPad ? ( (GetCGID() == ID_CG_COMPLEX_STRUCT) ||
  860. IsComplexStruct() || IsHardStruct() )
  861. : true );
  862. GenStructureMemPad( pCCB, EndingPad );
  863. //
  864. // If the format string is on a short boundary right now then push
  865. // a format character so that the format string will be properly aligned
  866. // following the FC_END.
  867. //
  868. if ( ! (pFormatString->GetCurrentOffset() % 2) )
  869. pFormatString->PushFormatChar( FC_PAD );
  870. pFormatString->PushFormatChar( FC_END );
  871. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  872. }
  873. void
  874. CG_STRUCT::GenNdrStructurePointees( CCB * pCCB )
  875. {
  876. CG_ITERATOR Iterator;
  877. FORMAT_STRING * pFormatString;
  878. CG_FIELD * pField;
  879. CG_NDR * pMember;
  880. pFormatString = pCCB->GetFormatString();
  881. GetMembers( Iterator );
  882. //
  883. // We only have to check for pointer fields here, because if the structure
  884. // has a struct or array field which has pointers, this will be handled
  885. // when we generate their format strings.
  886. //
  887. while( ITERATOR_GETNEXT( Iterator, pField ) )
  888. {
  889. pMember = (CG_NDR *) pField->GetChild();
  890. if ( pMember->IsPointer() &&
  891. !pMember->IsInterfacePointer() )
  892. {
  893. CG_NDR * pOldPlaceholder;
  894. pOldPlaceholder = pCCB->SetLastPlaceholderClass( pField );
  895. //
  896. // Skip over an unattributed pointer to a simple type or string.
  897. //
  898. if ( ( pMember->GetCGID() == ID_CG_PTR &&
  899. ((CG_NDR *)pMember->GetChild())->IsSimpleType() ) ||
  900. ( pMember->GetCGID() == ID_CG_STRING_PTR ) )
  901. {
  902. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  903. continue;
  904. }
  905. ((CG_POINTER *)pMember)->GenNdrFormatPointee( pCCB );
  906. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  907. }
  908. }
  909. }
  910. BOOL
  911. CG_STRUCT::ShouldFreeOffline()
  912. {
  913. return ( (GetCGID() == ID_CG_COMPLEX_STRUCT) ||
  914. (GetCGID() == ID_CG_CONF_VAR_STRUCT) ||
  915. HasPointer() ||
  916. IsComplexStruct() ||
  917. IsHardStruct() );
  918. }
  919. void
  920. CG_STRUCT::GenFreeInline( CCB* )
  921. {
  922. }
  923. void
  924. CG_NDR::GenNdrPointerFixUp( CCB * pCCB, CG_STRUCT * pStruct )
  925. {
  926. CG_ITERATOR Iterator;
  927. CG_NDR * pMember;
  928. CG_NDR * pNdr;
  929. long Offset;
  930. if ( ! IsStruct() && ! IsArray() && ! IsUnion() )
  931. return;
  932. if ( IsInFixUp() )
  933. return;
  934. SetFixUpLock( TRUE );
  935. GetMembers( Iterator );
  936. while ( ITERATOR_GETNEXT( Iterator, pMember ) )
  937. {
  938. if ( IsStruct() )
  939. {
  940. pNdr = (CG_NDR *) pMember->GetChild();
  941. }
  942. else if ( IsUnion() )
  943. {
  944. // member of union is a case, then case->field->ndr
  945. if ( pMember->GetChild() && pMember->GetChild()->GetChild() )
  946. pNdr = (CG_NDR *) pMember->GetChild()->GetChild();
  947. else
  948. continue;
  949. }
  950. else // IsArray()
  951. {
  952. pNdr = pMember;
  953. //
  954. // See if the array's element is the structure we're looking for.
  955. //
  956. if ( pNdr == pStruct )
  957. {
  958. Offset = ((CG_ARRAY *)this)->GetElementDescriptionOffset() + 2;
  959. pCCB->GetFormatString()->PushShortOffset(
  960. pStruct->GetFormatStringOffset() - Offset,
  961. Offset );
  962. }
  963. }
  964. if (pNdr->GetCGID() == ID_CG_TYPEDEF )
  965. pNdr = (CG_NDR *)pNdr->GetChild();
  966. if ( (pNdr->GetCGID() == ID_CG_PTR) ||
  967. (pNdr->GetCGID() == ID_CG_SIZE_PTR) ||
  968. (pNdr->GetCGID() == ID_CG_SIZE_LENGTH_PTR) )
  969. {
  970. CG_POINTER * pPointer = (CG_POINTER *) pNdr;
  971. //
  972. // Check if we're ready for this guy yet.
  973. //
  974. if ( pPointer->GetFormatStringOffset() == -1 )
  975. continue;
  976. // Get the pointee.
  977. switch ( pPointer->GetCGID() )
  978. {
  979. case ID_CG_PTR :
  980. pNdr = (CG_NDR *) pPointer->GetChild();
  981. break;
  982. case ID_CG_SIZE_PTR :
  983. pNdr = ((CG_SIZE_POINTER *)pPointer)->GetPointee();
  984. break;
  985. case ID_CG_SIZE_LENGTH_PTR :
  986. pNdr = ((CG_SIZE_LENGTH_POINTER *)pPointer)->GetPointee();
  987. break;
  988. }
  989. //
  990. // If the pointer's pointee is the struct we're checking for,
  991. // then patch up the pointer's offset_to_description<2> field.
  992. //
  993. if ( pNdr == pStruct )
  994. {
  995. long PointerOffset;
  996. //
  997. // Get the offset in the format string where the
  998. // offset_to_description<2> field of the pointer is.
  999. //
  1000. PointerOffset = pPointer->GetFormatStringOffset() + 2;
  1001. /*
  1002. printf( " **MIDL_fixup: Non-Reg Actually fixing %s at %d with %d (%d)\n",
  1003. pNdr->GetSymName(),
  1004. PointerOffset,
  1005. pNdr->GetFormatStringOffset() - PointerOffset,
  1006. pNdr->GetFormatStringOffset() );
  1007. */
  1008. pCCB->GetFormatString()->PushShortOffset(
  1009. pStruct->GetFormatStringOffset() - PointerOffset,
  1010. PointerOffset );
  1011. continue;
  1012. }
  1013. }
  1014. //
  1015. // This can happen sometimes because of structs which are promoted
  1016. // to complex because of padding.
  1017. //
  1018. if ( pNdr == this )
  1019. continue;
  1020. //
  1021. // Continue the chase if necessary.
  1022. //
  1023. if ( pNdr->IsStruct() || pNdr->IsUnion() || pNdr->IsArray() )
  1024. pNdr->GenNdrPointerFixUp( pCCB, pStruct );
  1025. }
  1026. SetFixUpLock( FALSE );
  1027. }
  1028. void
  1029. CG_NDR::RegisterComplexEmbeddedForFixup(
  1030. CG_NDR * pEmbeddedComplex,
  1031. long RelativeOffset )
  1032. {
  1033. if ( GetInitialOffset() == -1 )
  1034. printf( " Internal compiler problem with recursive embeddings\n" );
  1035. MIDL_ASSERT( GetInitialOffset() != -1 );
  1036. if ( pEmbeddedComplexFixupRegistry == NULL )
  1037. {
  1038. pEmbeddedComplexFixupRegistry = new TREGISTRY;
  1039. }
  1040. // printf( "MIDL_fixup: RegisterComplex %s\n", pEmbeddedComplex->GetSymName());
  1041. EMB_COMPLEX_FIXUP * pFixup = new EMB_COMPLEX_FIXUP;
  1042. pFixup->pEmbeddedNdr = pEmbeddedComplex;
  1043. pFixup->RelativeOffset = RelativeOffset;
  1044. pEmbeddedComplexFixupRegistry->Register( (node_skl *)pFixup );
  1045. }
  1046. void
  1047. CG_NDR::FixupEmbeddedComplex(
  1048. CCB * pCCB )
  1049. {
  1050. if ( IsInComplexFixup() )
  1051. return;
  1052. SetComplexFixupLock( TRUE );
  1053. // Go down first
  1054. CG_ITERATOR Iterator;
  1055. CG_NDR * pField;
  1056. GetMembers( Iterator );
  1057. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  1058. pField->FixupEmbeddedComplex( pCCB );
  1059. // Now fix up this level description.
  1060. if ( GetEmbeddedComplexFixupRegistry() )
  1061. {
  1062. ITERATOR FixupList;
  1063. EMB_COMPLEX_FIXUP * pFixup;
  1064. long FixAtOffset;
  1065. FORMAT_STRING * pFormatString = pCCB->GetFormatString();
  1066. GetListOfEmbeddedComplex( FixupList );
  1067. while ( ITERATOR_GETNEXT( FixupList, pFixup ) )
  1068. {
  1069. FixAtOffset = GetFormatStringOffset() + pFixup->RelativeOffset;
  1070. pFormatString->PushShortOffset(
  1071. pFixup->pEmbeddedNdr->GetFormatStringOffset() - FixAtOffset,
  1072. FixAtOffset );
  1073. /*
  1074. printf( " MIDL_fixup: Reg-Cmplx Actually fixing at %d with %d\n",
  1075. FixAtOffset,
  1076. pFixup->pEmbeddedNdr->GetFormatStringOffset() - FixAtOffset );
  1077. */
  1078. }
  1079. }
  1080. // Due to duplication, the list may be at the duplicating node.
  1081. if ( IsStruct() )
  1082. {
  1083. CG_COMPLEX_STRUCT * pDuping = ((CG_STRUCT *)this)->GetDuplicatingComplex();
  1084. if ( pDuping )
  1085. pDuping->FixupEmbeddedComplex( pCCB );
  1086. }
  1087. SetComplexFixupLock( FALSE );
  1088. }
  1089. // All these different ways of fixing recursive pointers need to be cleaned up.
  1090. // The RecPointer registry seems to be the best solution in that it fixes
  1091. // the pointers once per compilation while complex embed fixup calls walk the
  1092. // tree several times recursively.
  1093. // Also, the reason the below registry is different from previously introduced
  1094. // EmbeddedComplex fixup registry is that the emb cplx fixup registry uses
  1095. // a relative pointer when fixing up while the bug we are trying to address now
  1096. // affects standalone pointers where absolute offset is appropriate.
  1097. // The basic scheme with "struct _S**" field shows up in VARIANT and LPSAFEARRAY.
  1098. // Rkk, May, 1999.
  1099. void
  1100. CCB::RegisterRecPointerForFixup(
  1101. CG_NDR * pNdr,
  1102. long AbsoluteOffset )
  1103. {
  1104. if ( pRecPointerFixupRegistry == NULL )
  1105. {
  1106. pRecPointerFixupRegistry = new TREGISTRY;
  1107. }
  1108. POINTER_FIXUP * pFixup = new POINTER_FIXUP;
  1109. // printf( "MIDL_fixup: Registering for %s at %d\n", pNdr->GetSymName(), AbsoluteOffset);
  1110. pFixup->pNdr = pNdr;
  1111. pFixup->AbsoluteOffset = AbsoluteOffset;
  1112. pFixup->fFixed = false;
  1113. pRecPointerFixupRegistry->Register( (node_skl *)pFixup );
  1114. }
  1115. void
  1116. CCB::FixupRecPointers()
  1117. {
  1118. if ( GetRecPointerFixupRegistry() )
  1119. {
  1120. ITERATOR FixupList;
  1121. POINTER_FIXUP * pFixup;
  1122. long FixAtOffset;
  1123. FORMAT_STRING * pFormatString = GetFormatString();
  1124. GetListOfRecPointerFixups( FixupList );
  1125. while ( ITERATOR_GETNEXT( FixupList, pFixup ) )
  1126. {
  1127. FixAtOffset = pFixup->AbsoluteOffset;
  1128. if ( ! pFixup->fFixed )
  1129. {
  1130. long Recorded = pFormatString->GetFormatShort(FixAtOffset) + FixAtOffset;
  1131. long NdrOffset = pFixup->pNdr->GetFormatStringOffset();
  1132. if ( 0 == Recorded && 0 != NdrOffset ||
  1133. -1 == Recorded && -1 != NdrOffset )
  1134. {
  1135. /*
  1136. printf( " MIDL_fixup: Actually fixing %s at %d with %d (%d)\n",
  1137. pFixup->pNdr->GetSymName(),
  1138. FixAtOffset,
  1139. NdrOffset - FixAtOffset,
  1140. NdrOffset );
  1141. */
  1142. pFormatString->PushShortOffset( NdrOffset - FixAtOffset,
  1143. FixAtOffset );
  1144. pFixup->fFixed = true;
  1145. }
  1146. /*
  1147. else if ( 0 != Recorded && -1 != Recorded )
  1148. {
  1149. printf( " MIDL_fixup: %s at %d was already fixed to %d (%d)\n",
  1150. pFixup->pNdr->GetSymName(),
  1151. FixAtOffset,
  1152. NdrOffset - FixAtOffset,
  1153. NdrOffset );
  1154. pFixup->fFixed = true;
  1155. }
  1156. else
  1157. {
  1158. printf( " MIDL_fixup: %s at %d has not been fixed to %d (%d)\n",
  1159. pFixup->pNdr->GetSymName(),
  1160. FixAtOffset,
  1161. NdrOffset - FixAtOffset,
  1162. NdrOffset );
  1163. }
  1164. */
  1165. } // if ! fixed
  1166. } // while
  1167. }
  1168. }
  1169. long
  1170. CG_STRUCT::FixedBufferSize( CCB * pCCB )
  1171. {
  1172. CG_ITERATOR Iterator;
  1173. CG_FIELD * pField;
  1174. CG_NDR * pNdr;
  1175. CG_NDR * pOldPlaceholder;
  1176. long TotalBufferSize;
  1177. long BufSize;
  1178. //
  1179. // Check for recursion.
  1180. //
  1181. if ( IsInFixedBufferSize() )
  1182. return -1;
  1183. if ( (GetCGID() == ID_CG_CONF_STRUCT) ||
  1184. (GetCGID() == ID_CG_CONF_VAR_STRUCT) ||
  1185. (GetCGID() == ID_CG_COMPLEX_STRUCT) ||
  1186. IsComplexStruct() )
  1187. return -1;
  1188. if ( IsHardStruct() )
  1189. {
  1190. if ( GetNumberOfUnions() == 0 )
  1191. return MAX_WIRE_ALIGNMENT + GetWireSize();
  1192. else
  1193. return -1;
  1194. }
  1195. SetInFixedBufferSize( TRUE );
  1196. MIDL_ASSERT( GetCGID() == ID_CG_STRUCT );
  1197. pOldPlaceholder = pCCB->SetLastPlaceholderClass( this );
  1198. GetMembers( Iterator );
  1199. TotalBufferSize = MAX_WIRE_ALIGNMENT + GetWireSize();
  1200. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  1201. {
  1202. pNdr = (CG_NDR *) pField->GetChild();
  1203. // skip these nodes to get to the transmitted element type.
  1204. if ( pNdr->IsXmitRepOrUserMarshal() )
  1205. pNdr = (CG_NDR *)pNdr->GetChild();
  1206. if ( pNdr->IsStruct() || pNdr->IsArray() || pNdr->IsPointer() )
  1207. {
  1208. BufSize = pNdr->FixedBufferSize( pCCB );
  1209. if ( BufSize == -1 )
  1210. {
  1211. SetInFixedBufferSize( FALSE );
  1212. return -1;
  1213. }
  1214. //
  1215. // First subtract the basic size of this thing from the struct's
  1216. // size and then add back the value it returned.
  1217. //
  1218. TotalBufferSize -= pNdr->GetWireSize();
  1219. TotalBufferSize += BufSize;
  1220. }
  1221. }
  1222. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  1223. SetInFixedBufferSize( FALSE );
  1224. // Success!
  1225. return TotalBufferSize;
  1226. }