Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1774 lines
44 KiB

4 years ago
  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. arrayndr.cxx
  5. Abstract:
  6. Contains routines for the generation of the new NDR format strings for
  7. array 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. //*************************************************************************
  15. // CG_ARRAY
  16. //*************************************************************************
  17. BOOL
  18. CG_ARRAY::GenNdrFormatArrayProlog( CCB * pCCB )
  19. /*++
  20. Routine Description :
  21. Handles some common tasks for array Ndr format string generation.
  22. Arguments :
  23. pCCB - pointer to code control block
  24. Return :
  25. TRUE if format string generation should continue, FALSE if the format
  26. string for the array has already been generated.
  27. --*/
  28. {
  29. FORMAT_STRING * pFormatString;
  30. CG_NDR * pChild;
  31. if ( GetFormatStringOffset() != -1 )
  32. return FALSE;
  33. pFormatString = pCCB->GetFormatString();
  34. pChild = (CG_NDR *) GetChild();
  35. if ( pChild->IsArray() )
  36. {
  37. SetIsInMultiDim( TRUE );
  38. ((CG_ARRAY *)pChild)->SetIsInMultiDim( TRUE );
  39. }
  40. //
  41. // If the array's element type is a structure, pointer, or another array
  42. // then generate either it's description (structure/array) or it's
  43. // pointee's description (pointer).
  44. //
  45. if ( pChild->IsStruct() ||
  46. pChild->IsArray() ||
  47. pChild->IsUnion() ||
  48. (pChild->GetCGID() == ID_CG_INTERFACE_PTR) ||
  49. pChild->IsXmitRepOrUserMarshal() )
  50. {
  51. pChild->GenNdrFormat( pCCB );
  52. }
  53. if ( pChild->IsPointer() && (pChild->GetCGID() != ID_CG_INTERFACE_PTR) )
  54. {
  55. // Only generate the pointee format string if the pointee is not a
  56. // base type or non-sized string pointer.
  57. if ( ! pChild->IsPointerToBaseType() &&
  58. (pChild->GetCGID() != ID_CG_STRING_PTR) )
  59. ((CG_POINTER *)pChild)->GenNdrFormatPointee( pCCB );
  60. }
  61. SetFormatStringOffset( pFormatString->GetCurrentOffset() );
  62. //
  63. // For an array which has [unique] or [ptr] applied to it, we generate
  64. // a format string description of a pointer to the array.
  65. //
  66. if ( GetPtrType() != PTR_REF )
  67. {
  68. pFormatString->PushFormatChar( GetPtrType() == PTR_UNIQUE ?
  69. FC_UP : FC_FP );
  70. pFormatString->PushByte( 0 );
  71. pFormatString->PushShortOffset( (short) 2 );
  72. }
  73. //
  74. // Check if this is a complex array.
  75. //
  76. if ( IsComplex() )
  77. {
  78. GenNdrFormatComplex( pCCB );
  79. return FALSE;
  80. }
  81. // Push the type.
  82. switch ( GetCGID() )
  83. {
  84. case ID_CG_ARRAY :
  85. case ID_CG_VAR_ARRAY :
  86. //
  87. // Fixed and varying array's fill this in later when they know
  88. // their size.
  89. //
  90. pFormatString->PushByte( 0 );
  91. break;
  92. case ID_CG_CONF_ARRAY :
  93. pFormatString->PushFormatChar( FC_CARRAY );
  94. break;
  95. case ID_CG_CONF_VAR_ARRAY :
  96. pFormatString->PushFormatChar( FC_CVARRAY );
  97. break;
  98. }
  99. //
  100. // Push the correct alignment value.
  101. //
  102. pFormatString->PushByte(
  103. CvtAlignPropertyToAlign( pChild->IsUnion()
  104. ? AL_1
  105. : pChild->GetWireAlignment() ) - 1 );
  106. return TRUE;
  107. }
  108. void
  109. CG_ARRAY::GenNdrFormatArrayLayout( CCB * pCCB )
  110. {
  111. FORMAT_STRING * pFormatString;
  112. CG_NDR * pChild;
  113. pFormatString = pCCB->GetFormatString();
  114. pChild = (CG_NDR *) GetChild();
  115. //
  116. // See if we need to generate a pointer layout.
  117. //
  118. if ( (pChild->IsPointer() && (pChild->GetCGID() != ID_CG_INTERFACE_PTR)) ||
  119. (pChild->IsStruct() && ((CG_STRUCT *)pChild)->HasPointer()) )
  120. {
  121. //
  122. // Not home free yet. Even if the array has pointers, we only
  123. // output a pointer layout if one of the following is true :
  124. // 1. The array is a top level parameter.
  125. // 2. The array is really a fabrication of a size or size length
  126. // pointer (of structures which contain pointers).
  127. // 3. The array is embedded in a complex or hard struct.
  128. // Otherwise the array's pointer description will be in its structure's
  129. // pointer layout.
  130. //
  131. // We also never generate a pointer layout for complex arrays.
  132. //
  133. // We know if it was fabricated from a size or size-length pointer
  134. // if IsDupedSizePtr() is TRUE.
  135. //
  136. CG_NDR * pParent;
  137. pParent = pCCB->GetCGNodeContext();
  138. if ( pParent->IsProc() ||
  139. (pParent->GetCGID() == ID_CG_COMPLEX_STRUCT) ||
  140. (pParent->IsStruct() &&
  141. ((CG_STRUCT *)pParent)->IsHardStruct()) ||
  142. IsDupedSizePtr()
  143. )
  144. {
  145. if ( ! IsComplex() )
  146. GenNdrFormatArrayPointerLayout( pCCB,
  147. FALSE );
  148. }
  149. }
  150. SetElementDescriptionOffset( pFormatString->GetCurrentOffset() );
  151. //
  152. // Now generate the element description.
  153. //
  154. if ( pChild->IsStruct() ||
  155. pChild->IsArray() ||
  156. pChild->IsUnion() ||
  157. (pChild->GetCGID() == ID_CG_INTERFACE_PTR) ||
  158. pChild->IsXmitRepOrUserMarshal() )
  159. {
  160. pFormatString->PushFormatChar( FC_EMBEDDED_COMPLEX );
  161. // Not used.
  162. pFormatString->PushByte( 0 );
  163. // if embedded complex member has an offset zero, it
  164. // almost certainly means that it is in a recursion
  165. // that is not resolved yet. See structs for a solution.
  166. //
  167. // BUGBUG: this should work like for structs but
  168. // I have no time to setup arrays correctly for the
  169. // method fixing all such places.
  170. // So, it needs to wait for better times.
  171. //
  172. // if ( pMember->GetFormatStringOffset() == 0 )
  173. // {
  174. // RegisterComplexEmbeddedForFixup(
  175. // pMember,
  176. // pFormatString->GetCurrentOffset() - GetInitialOffset() );
  177. // }
  178. //
  179. pFormatString->PushShortOffset( pChild->GetFormatStringOffset() -
  180. pFormatString->GetCurrentOffset() );
  181. }
  182. if ( pChild->IsPointer() && (pChild->GetCGID() != ID_CG_INTERFACE_PTR) )
  183. {
  184. //
  185. // For complex arrays of pointers we put the actual pointer description
  186. // in the layout, otherwise we put a long.
  187. //
  188. if ( IsComplex() )
  189. {
  190. ((CG_POINTER *)pChild)->GenNdrFormatAlways( pCCB );
  191. }
  192. else
  193. {
  194. pFormatString->PushFormatChar( FC_LONG );
  195. }
  196. }
  197. if ( pChild->IsSimpleType() )
  198. {
  199. pChild->GenNdrFormat( pCCB );
  200. }
  201. // Possibly align the format string and spit out the FC_END.
  202. if ( ! (pFormatString->GetCurrentOffset() % 2) )
  203. pFormatString->PushFormatChar( FC_PAD );
  204. pFormatString->PushFormatChar( FC_END );
  205. SetFormatStringEndOffset( pFormatString->GetCurrentOffset() );
  206. }
  207. void
  208. CG_ARRAY::GenNdrFormatArrayPointerLayout( CCB * pCCB,
  209. BOOL fNoPP )
  210. /*++
  211. Routine Description :
  212. Generates the Ndr format string pointer layout for a conformant array.
  213. Arguments :
  214. pCCB - pointer to the code control block
  215. fNoPP - TRUE if no FC_PP or FC_END should be generated
  216. --*/
  217. {
  218. ITERATOR Iterator;
  219. FORMAT_STRING * pFormatString;
  220. CG_STRUCT * pStruct;
  221. CG_NDR * pImbedingNode;
  222. unsigned long MemOffsetToArray;
  223. unsigned long BufOffsetToArray;
  224. long ImbedingMemSize;
  225. long ImbedingBufSize;
  226. // Get the current imbeding sizes.
  227. ImbedingMemSize = pCCB->GetImbedingMemSize();
  228. ImbedingBufSize = pCCB->GetImbedingBufSize();
  229. pFormatString = pCCB->GetFormatString();
  230. pImbedingNode = pCCB->GetCGNodeContext();
  231. MemOffsetToArray = ImbedingMemSize;
  232. BufOffsetToArray = ImbedingBufSize;
  233. if ( pImbedingNode->IsStruct() )
  234. {
  235. pStruct = (CG_STRUCT *) pImbedingNode;
  236. if ( GetCGID() == ID_CG_CONF_ARRAY ||
  237. GetCGID() == ID_CG_CONF_VAR_ARRAY )
  238. {
  239. ; // Do nothing, imbeding sizes set offset right.
  240. }
  241. else // GetCGID() == ID_CG_ARRAY || ID_CG_VAR_ARRAY
  242. {
  243. CG_FIELD * pField;
  244. //
  245. // If we're embedded in a complex struct then we do nothing - our
  246. // offset will end up being 0.
  247. //
  248. if ( pStruct->GetCGID() != ID_CG_COMPLEX_STRUCT )
  249. {
  250. pField = pStruct->GetArrayField( this );
  251. //
  252. // If we don't find the array's field, that's because the
  253. // array must have been contained within a union which was
  254. // part of a Hard Structure.
  255. //
  256. if ( pField )
  257. {
  258. //
  259. // What has to be done here is to actually subract the
  260. // difference between the struct's sizes and the field's
  261. // offsets, since the array appears somewhere inside the
  262. // struct whose size has already been added to the
  263. // imbeding sizes.
  264. //
  265. MemOffsetToArray -= pStruct->GetMemorySize() -
  266. pField->GetMemOffset();
  267. BufOffsetToArray -= pStruct->GetWireSize() -
  268. pField->GetWireOffset();
  269. }
  270. }
  271. }
  272. }
  273. if ( ! fNoPP )
  274. {
  275. pFormatString->PushFormatChar( FC_PP );
  276. pFormatString->PushFormatChar( FC_PAD );
  277. }
  278. //
  279. // Stuff for fixed arrays.
  280. //
  281. if ( GetCGID() == ID_CG_ARRAY )
  282. {
  283. pFormatString->PushFormatChar( FC_FIXED_REPEAT );
  284. pFormatString->PushFormatChar( FC_PAD );
  285. pFormatString->PushShort( (short)
  286. ((CG_FIXED_ARRAY *)this)->GetNumOfElements() );
  287. }
  288. //
  289. // Stuff for conformant arrays.
  290. //
  291. if ( GetCGID() == ID_CG_CONF_ARRAY )
  292. {
  293. pFormatString->PushFormatChar( FC_VARIABLE_REPEAT );
  294. pFormatString->PushFormatChar( FC_FIXED_OFFSET );
  295. }
  296. //
  297. // Stuff for conformant varying and varying arrays.
  298. //
  299. if ( GetCGID() == ID_CG_CONF_VAR_ARRAY ||
  300. GetCGID() == ID_CG_VAR_ARRAY )
  301. {
  302. pFormatString->PushFormatChar( FC_VARIABLE_REPEAT );
  303. pFormatString->PushFormatChar( FC_VARIABLE_OFFSET );
  304. }
  305. if ( GetChild()->IsPointer() &&
  306. (GetChild()->GetCGID() != ID_CG_INTERFACE_PTR) )
  307. {
  308. CG_POINTER * pPointer;
  309. pPointer = (CG_POINTER *) GetChild();
  310. //
  311. // Push the increment amount between successive pointers. In this
  312. // case it's always 4.
  313. //
  314. pFormatString->PushShort( (short) sizeof(void *) );
  315. // offset_to_array<2>
  316. pFormatString->PushShort( (short) MemOffsetToArray );
  317. // number_of_pointers<2>
  318. pFormatString->PushShort( (short) 1 );
  319. // offset_to_pointer_in_memory<2>
  320. pFormatString->PushShort( (short) MemOffsetToArray );
  321. // offset_to_pointer_in_buffer<2>
  322. pFormatString->PushShort( (short) BufOffsetToArray );
  323. // Push the pointer description.
  324. pPointer->GenNdrFormatEmbedded( pCCB );
  325. }
  326. if ( GetChild()->IsStruct() )
  327. {
  328. ITERATOR Iterator;
  329. CG_STRUCT * pStruct;
  330. pStruct = (CG_STRUCT *) GetChild();
  331. //
  332. // Increment between successive pointers is the memory size of
  333. // the structure.
  334. //
  335. pFormatString->PushShort( (short) pStruct->GetMemorySize() );
  336. // offset_to_array<2>
  337. pFormatString->PushShort( (short) MemOffsetToArray );
  338. // number_of_pointers<2>
  339. pFormatString->PushShort( (short) pStruct->GetNumberOfPointers() );
  340. pStruct->GenNdrStructurePointerLayout( pCCB, TRUE, TRUE );
  341. }
  342. if ( GetChild()->IsUnion() )
  343. assert(0);
  344. if ( GetChild()->IsArray() )
  345. assert(0);
  346. if ( ! fNoPP )
  347. pFormatString->PushFormatChar( FC_END );
  348. SetFormatStringEndOffset( pFormatString->GetCurrentOffset() );
  349. }
  350. void
  351. CG_ARRAY::GenNdrFormatComplex( CCB * pCCB )
  352. {
  353. FORMAT_STRING * pFormatString;
  354. CG_NDR * pChild;
  355. pFormatString = pCCB->GetFormatString();
  356. pChild = (CG_NDR *) GetChild();
  357. pFormatString->PushFormatChar( FC_BOGUS_ARRAY );
  358. // Alignment.
  359. pFormatString->PushByte(
  360. CvtAlignPropertyToAlign( pChild->IsUnion()
  361. ? AL_1
  362. : pChild->GetWireAlignment() ) - 1 );
  363. //
  364. // Number of elements - 0 if conformant.
  365. //
  366. switch ( GetCGID() )
  367. {
  368. case ID_CG_ARRAY :
  369. pFormatString->PushShort( (short)
  370. ((CG_FIXED_ARRAY *)this)->GetNumOfElements() );
  371. break;
  372. case ID_CG_VAR_ARRAY :
  373. pFormatString->PushShort( (short)
  374. ((CG_VARYING_ARRAY *)this)->GetNumOfElements() );
  375. break;
  376. default :
  377. pFormatString->PushShort( (short) 0 );
  378. break;
  379. }
  380. //
  381. // Conformance description.
  382. //
  383. switch ( GetCGID() )
  384. {
  385. case ID_CG_CONF_ARRAY :
  386. ((CG_CONFORMANT_ARRAY *)this)->
  387. GenFormatStringConformanceDescription( pCCB,
  388. IsDupedSizePtr(),
  389. IsInMultiDim() );
  390. break;
  391. case ID_CG_CONF_VAR_ARRAY :
  392. ((CG_CONFORMANT_VARYING_ARRAY *)this)->
  393. GenFormatStringConformanceDescription( pCCB,
  394. IsDupedSizePtr(),
  395. IsInMultiDim() );
  396. break;
  397. default :
  398. pFormatString->PushLong( 0xffffffff );
  399. break;
  400. }
  401. //
  402. // Variance description.
  403. //
  404. switch ( GetCGID() )
  405. {
  406. case ID_CG_CONF_VAR_ARRAY :
  407. ((CG_CONFORMANT_VARYING_ARRAY *)this)->
  408. GenFormatStringVarianceDescription( pCCB,
  409. IsDupedSizePtr(),
  410. FALSE,
  411. IsInMultiDim() );
  412. break;
  413. case ID_CG_VAR_ARRAY :
  414. ((CG_VARYING_ARRAY *)this)->
  415. GenFormatStringVarianceDescription( pCCB,
  416. FALSE,
  417. TRUE,
  418. IsInMultiDim() );
  419. break;
  420. default :
  421. pFormatString->PushLong( 0xffffffff );
  422. break;
  423. }
  424. GenNdrFormatArrayLayout( pCCB );
  425. // optimize away duplicates
  426. pFormatString->OptimizeFragment( this );
  427. // This call needs some preparation that I have no time for.
  428. // FixupEmbeddedComplex( pCCB );
  429. }
  430. long
  431. CG_ARRAY::GetElementSize()
  432. {
  433. CG_NDR * pChild;
  434. pChild = (CG_NDR *) GetChild();
  435. if ( pChild->IsSimpleType() )
  436. {
  437. // Cheat a little. Size is equal to wire alignment value.
  438. return CvtAlignPropertyToAlign( pChild->GetWireAlignment() );
  439. }
  440. if ( pChild->IsPointer() )
  441. return sizeof( void * );
  442. if ( pChild->IsStruct() )
  443. return ((CG_STRUCT *)pChild)->GetMemorySize();
  444. if ( pChild->IsArray() )
  445. {
  446. assert ( pChild->GetCGID() == ID_CG_ARRAY );
  447. CG_FIXED_ARRAY * pArray = (CG_FIXED_ARRAY *) pChild;
  448. return pArray->GetElementSize() * pArray->GetNumOfElements();
  449. }
  450. if ( pChild->GetCGID() == ID_CG_INTERFACE_PTR )
  451. return sizeof( void * );
  452. assert(0);
  453. return 0; // for the compiler
  454. }
  455. BOOL
  456. CG_ARRAY::IsComplex()
  457. {
  458. //
  459. // If this is a conformant and/or varying array, then it becomes
  460. // complex if it is part of a multidimensional array (but not a multi
  461. // level sized pointer).
  462. //
  463. if ( (GetCGID() == ID_CG_CONF_ARRAY) ||
  464. (GetCGID() == ID_CG_CONF_VAR_ARRAY) ||
  465. (GetCGID() == ID_CG_VAR_ARRAY) )
  466. {
  467. if ( IsInMultiDim() && ! IsDupedSizePtr() )
  468. return TRUE;
  469. }
  470. //
  471. // Is the array complex by Ndr Engine standards. Any array of complex
  472. // or hard structs, encapsulated unions, transmit_as or represent_as,
  473. // enums, ref pointers, or another complex array, is complex.
  474. //
  475. // Any multidimensional array with at least one dimension with conformance
  476. // or variance is complex as well.
  477. //
  478. switch ( ((CG_NDR *)GetChild())->GetCGID() )
  479. {
  480. case ID_CG_STRUCT :
  481. return( ((CG_STRUCT *)GetChild())->IsComplexStruct() ||
  482. ((CG_STRUCT *)GetChild())->IsHardStruct() ||
  483. GetWireSize() != GetMemorySize() );
  484. case ID_CG_ARRAY :
  485. switch ( GetCGID() )
  486. {
  487. case ID_CG_CONF_ARRAY :
  488. case ID_CG_CONF_VAR_ARRAY :
  489. case ID_CG_VAR_ARRAY :
  490. return TRUE;
  491. default :
  492. //
  493. // The array is complex if the next lower fixed array
  494. // dimension is complex.
  495. //
  496. return ((CG_ARRAY *) GetChild())->IsComplex();
  497. }
  498. case ID_CG_COMPLEX_STRUCT :
  499. case ID_CG_ENCAP_STRUCT :
  500. case ID_CG_CONF_ARRAY :
  501. case ID_CG_CONF_VAR_ARRAY :
  502. case ID_CG_VAR_ARRAY :
  503. case ID_CG_STRING_ARRAY :
  504. case ID_CG_CONF_STRING_ARRAY :
  505. case ID_CG_TRANSMIT_AS :
  506. case ID_CG_REPRESENT_AS :
  507. case ID_CG_USER_MARSHAL :
  508. case ID_CG_INTERFACE_PTR :
  509. return TRUE;
  510. case ID_CG_ENUM :
  511. //
  512. // The array is complex only if this
  513. // is an array of enum16.
  514. //
  515. return ! ((CG_ENUM *)GetChild())->IsEnumLong();
  516. case ID_CG_CONF_STRUCT :
  517. case ID_CG_CONF_VAR_STRUCT :
  518. //
  519. // These two are not possible and
  520. // should be caught by the front end.
  521. //
  522. assert(0);
  523. default :
  524. //
  525. // Make a final check for an array of ref pointers.
  526. //
  527. return GetChild()->IsPointer() &&
  528. (((CG_POINTER *)GetChild())->GetPtrType() == PTR_REF);
  529. }
  530. }
  531. BOOL
  532. CG_ARRAY::IsMultiConfOrVar()
  533. {
  534. CG_NDR * pNdr;
  535. switch ( GetCGID() )
  536. {
  537. case ID_CG_CONF_ARRAY :
  538. case ID_CG_CONF_VAR_ARRAY :
  539. case ID_CG_VAR_ARRAY :
  540. break;
  541. default :
  542. return FALSE;
  543. }
  544. //
  545. // Search for an inner dimension array other than fixed.
  546. //
  547. pNdr = (CG_NDR *) GetChild();
  548. for ( ; pNdr && pNdr->IsArray(); pNdr = (CG_NDR *) pNdr->GetChild() )
  549. {
  550. if ( pNdr->GetCGID() == ID_CG_ARRAY )
  551. continue;
  552. else
  553. return TRUE;
  554. }
  555. return FALSE;
  556. }
  557. BOOL
  558. CG_ARRAY::ShouldFreeOffline()
  559. {
  560. CG_NDR * pChild;
  561. pChild = (CG_NDR *) GetChild();
  562. switch ( GetCGID() )
  563. {
  564. case ID_CG_STRING_ARRAY :
  565. case ID_CG_CONF_STRING_ARRAY :
  566. return FALSE;
  567. default :
  568. if ( pChild->IsSimpleType() )
  569. return FALSE;
  570. if ( pChild->IsStruct() )
  571. return ((CG_STRUCT *)pChild)->ShouldFreeOffline();
  572. if ( pChild->IsArray() )
  573. return ((CG_ARRAY *)pChild)->ShouldFreeOffline();
  574. return TRUE;
  575. }
  576. }
  577. void
  578. CG_ARRAY::GenFreeInline( CCB * pCCB )
  579. {
  580. CG_PARAM * pParam;
  581. BOOL fFree;
  582. fFree = FALSE;
  583. pParam = (CG_PARAM *) pCCB->GetLastPlaceholderClass();
  584. //
  585. // Don't free a [unique] or [ptr] array inline.
  586. //
  587. if ( GetPtrType() != PTR_REF )
  588. return;
  589. if ( IsComplex() )
  590. {
  591. //
  592. // If the array is complex then we must free it unless it is a
  593. // fixed or varying array of ref pointers or an [out] fixed or varying
  594. // array.
  595. //
  596. if ( ! pParam->IsParamIn() || GetBasicCGClass()->IsPointer() )
  597. fFree = (GetCGID() == ID_CG_CONF_ARRAY) ||
  598. (GetCGID() == ID_CG_CONF_VAR_ARRAY);
  599. else
  600. fFree = TRUE;
  601. }
  602. else
  603. {
  604. //
  605. // For non complex arrays the rules are :
  606. // Fixed - never free, we use the buffer.
  607. // Conformant - free if [out] only.
  608. // Conformant Varying - always free.
  609. // Varying - free if [in] or [in,out].
  610. //
  611. // String array - free always.
  612. // Conformant string array - free if sized.
  613. //
  614. switch ( GetCGID() )
  615. {
  616. case ID_CG_ARRAY :
  617. break;
  618. case ID_CG_CONF_ARRAY :
  619. fFree = ! pParam->IsParamIn();
  620. break;
  621. case ID_CG_CONF_VAR_ARRAY :
  622. fFree = TRUE;
  623. break;
  624. case ID_CG_VAR_ARRAY :
  625. fFree = pParam->IsParamIn();
  626. break;
  627. case ID_CG_STRING_ARRAY :
  628. fFree = TRUE;
  629. break;
  630. case ID_CG_CONF_STRING_ARRAY :
  631. fFree = GetSizeIsExpr() != 0;
  632. break;
  633. }
  634. }
  635. if ( fFree )
  636. Out_FreeParamInline( pCCB );
  637. }
  638. //*************************************************************************
  639. // CG_FIXED_ARRAY
  640. //*************************************************************************
  641. void
  642. CG_FIXED_ARRAY::GenNdrFormat( CCB * pCCB )
  643. /*++
  644. Routine Description :
  645. Generates the Ndr format string for a fixed array.
  646. Arguments :
  647. pCCB - pointer to the code control block
  648. --*/
  649. {
  650. FORMAT_STRING * pFormatString = pCCB->GetFormatString();
  651. unsigned long ArraySize;
  652. if ( ! GenNdrFormatArrayProlog( pCCB ) )
  653. return;
  654. assert( GetSizeIsExpr()->IsConstant() );
  655. ArraySize = GetNumOfElements() * GetElementSize();
  656. //
  657. // If the array size is >= 64K then the format is different.
  658. //
  659. if ( ArraySize >= (64 * 1024) )
  660. {
  661. pFormatString->PushFormatChar( FC_LGFARRAY,
  662. pFormatString->GetCurrentOffset() - 2 );
  663. pFormatString->PushLong( ArraySize );
  664. }
  665. else
  666. {
  667. pFormatString->PushFormatChar( FC_SMFARRAY,
  668. pFormatString->GetCurrentOffset() - 2 );
  669. pFormatString->PushShort( (short) ArraySize );
  670. }
  671. GenNdrFormatArrayLayout( pCCB );
  672. // optimize away duplicates
  673. pFormatString->OptimizeFragment( this );
  674. }
  675. long
  676. CG_FIXED_ARRAY::FixedBufferSize( CCB * pCCB )
  677. {
  678. CG_NDR * pNdr;
  679. long BufSize;
  680. long TotalSize;
  681. pNdr = (CG_NDR *)GetChild();
  682. // skip these nodes to get to the transmitted element type.
  683. if ( pNdr->IsXmitRepOrUserMarshal() )
  684. pNdr = (CG_NDR *)pNdr->GetChild();
  685. if ( pNdr->IsPointer() && ((CG_POINTER *)pNdr)->IsPointerToBaseType() )
  686. {
  687. CG_POINTER * pPointer;
  688. //
  689. // Special case arrays of pointers to base types so that we
  690. // don't grossly overestimate the buffer size.
  691. //
  692. pPointer = (CG_POINTER *) pNdr;
  693. pNdr = (CG_NDR *) pNdr->GetChild();
  694. BufSize = (pPointer->GetPtrType() == PTR_REF) ? 0 : 4;
  695. BufSize += pNdr->GetWireSize();
  696. return 8 + (GetNumOfElements() * BufSize);
  697. }
  698. if ( pNdr->IsStruct() || pNdr->IsArray() || pNdr->IsPointer() )
  699. {
  700. BufSize = pNdr->FixedBufferSize( pCCB );
  701. if ( BufSize == -1 )
  702. return -1;
  703. // Success!
  704. TotalSize = GetNumOfElements() * BufSize;
  705. }
  706. else
  707. {
  708. // Fixed array of basetypes.
  709. TotalSize = 8 + GetWireSize();
  710. }
  711. return TotalSize;
  712. }
  713. //*************************************************************************
  714. // CG_CONFORMANT_ARRAY
  715. //*************************************************************************
  716. void
  717. CG_CONFORMANT_ARRAY::GenNdrFormat( CCB * pCCB )
  718. /*++
  719. Routine Description :
  720. Generates the Ndr format string for a conformant or array.
  721. Arguments :
  722. pCCB - pointer to the code control block
  723. --*/
  724. {
  725. FORMAT_STRING * pFormatString = pCCB->GetFormatString();
  726. long ElementSize;
  727. if ( ! GenNdrFormatArrayProlog( pCCB ) )
  728. return;
  729. ElementSize = GetElementSize();
  730. if ( ElementSize >= (64 * 1024) )
  731. {
  732. fprintf(stderr,
  733. "ERROR : Conformant array element too large for NDR engine.\n");
  734. assert(0);
  735. }
  736. pFormatString->PushShort( ElementSize );
  737. GenFormatStringConformanceDescription( pCCB,
  738. IsDupedSizePtr(),
  739. IsInMultiDim() );
  740. GenNdrFormatArrayLayout( pCCB );
  741. // optimize away duplicates
  742. pFormatString->OptimizeFragment( this );
  743. }
  744. //*************************************************************************
  745. // CG_CONFORMANT_VARYING_ARRAY
  746. //*************************************************************************
  747. void CG_CONFORMANT_VARYING_ARRAY::GenNdrFormat( CCB * pCCB )
  748. /*++
  749. Routine Description :
  750. Generates the Ndr format string for a conformant varying array.
  751. Arguments :
  752. pCCB - pointer to the code control block
  753. --*/
  754. {
  755. FORMAT_STRING * pFormatString = pCCB->GetFormatString();
  756. long ElementSize;
  757. if ( ! GenNdrFormatArrayProlog( pCCB ) )
  758. return;
  759. ElementSize = GetElementSize();
  760. if ( ElementSize >= (64 * 1024) )
  761. {
  762. fprintf(stderr, "ERROR : Conformant varying array "
  763. "element too large for NDR engine.\n");
  764. assert(0);
  765. }
  766. pFormatString->PushShort( ElementSize );
  767. GenFormatStringConformanceDescription( pCCB,
  768. IsDupedSizePtr(),
  769. IsInMultiDim() );
  770. GenFormatStringVarianceDescription( pCCB,
  771. IsDupedSizePtr(),
  772. FALSE,
  773. IsInMultiDim() );
  774. GenNdrFormatArrayLayout( pCCB );
  775. // optimize away duplicates
  776. pFormatString->OptimizeFragment( this );
  777. }
  778. void CG_VARYING_ARRAY::GenNdrFormat( CCB * pCCB )
  779. /*++
  780. Routine Description :
  781. Generates the Ndr format string for a varying array.
  782. Arguments :
  783. pCCB - pointer to the code control block
  784. --*/
  785. {
  786. FORMAT_STRING * pFormatString = pCCB->GetFormatString();
  787. long Elements;
  788. long ElementSize;
  789. long ArraySize;
  790. if ( ! GenNdrFormatArrayProlog( pCCB ) )
  791. return;
  792. //
  793. // Size must be constant.
  794. //
  795. if ( ! GetSizeIsExpr()->IsConstant() )
  796. assert(0);
  797. Elements = GetNumOfElements();
  798. ElementSize = GetElementSize();
  799. ArraySize = Elements * ElementSize;
  800. //
  801. // Check if this is a large varying array.
  802. //
  803. if ( ArraySize >= (64 * 1024) )
  804. {
  805. pFormatString->PushFormatChar( FC_LGVARRAY,
  806. pFormatString->GetCurrentOffset() - 2 );
  807. pFormatString->PushLong( ArraySize );
  808. pFormatString->PushLong( Elements );
  809. }
  810. else
  811. {
  812. pFormatString->PushFormatChar( FC_SMVARRAY,
  813. pFormatString->GetCurrentOffset() - 2 );
  814. pFormatString->PushShort( ArraySize );
  815. pFormatString->PushShort( Elements );
  816. }
  817. pFormatString->PushShort( ElementSize );
  818. GenFormatStringVarianceDescription( pCCB,
  819. FALSE,
  820. TRUE,
  821. FALSE );
  822. GenNdrFormatArrayLayout( pCCB );
  823. // optimize away duplicates
  824. pFormatString->OptimizeFragment( this );
  825. }
  826. //*************************************************************************
  827. // CG_STRING_ARRAY
  828. //*************************************************************************
  829. void CG_STRING_ARRAY::GenNdrFormat( CCB * pCCB )
  830. /*++
  831. Routine Description :
  832. Generates the Ndr format string for a string array.
  833. Arguments :
  834. pCCB - pointer to the code control block
  835. --*/
  836. {
  837. FORMAT_STRING * pFormatString;
  838. if ( GetFormatStringOffset() != -1 )
  839. return;
  840. pFormatString = pCCB->GetFormatString();
  841. SetFormatStringOffset( pFormatString->GetCurrentOffset() );
  842. if ( IsStringableStruct() )
  843. {
  844. pFormatString->PushFormatChar( FC_SSTRING );
  845. pFormatString->PushByte( ((CG_NDR *)GetChild())->GetWireSize() );
  846. }
  847. else
  848. {
  849. switch ( ((CG_BASETYPE *)GetChild())->GetFormatChar() )
  850. {
  851. case FC_CHAR :
  852. case FC_BYTE :
  853. pFormatString->PushFormatChar( FC_CSTRING );
  854. break;
  855. case FC_WCHAR :
  856. pFormatString->PushFormatChar( FC_WSTRING );
  857. break;
  858. default :
  859. assert(0);
  860. }
  861. pFormatString->PushFormatChar( FC_PAD );
  862. }
  863. assert( GetSizeIsExpr()->IsConstant() );
  864. pFormatString->PushShort( GetSizeIsExpr()->GetValue() );
  865. // optimize away duplicates
  866. SetFormatStringEndOffset( pFormatString->GetCurrentOffset() );
  867. pFormatString->OptimizeFragment( this );
  868. }
  869. void CG_CONFORMANT_STRING_ARRAY::GenNdrFormat( CCB * pCCB )
  870. /*++
  871. Routine Description :
  872. Generates the Ndr format string for a conformant string array.
  873. Arguments :
  874. pCCB - pointer to the code control block
  875. --*/
  876. {
  877. FORMAT_STRING * pFormatString;
  878. if ( GetFormatStringOffset() != -1 )
  879. return;
  880. pFormatString = pCCB->GetFormatString();
  881. SetFormatStringOffset( pFormatString->GetCurrentOffset() );
  882. if ( IsStringableStruct() )
  883. {
  884. pFormatString->PushFormatChar( FC_C_SSTRING );
  885. pFormatString->PushByte( ((CG_NDR *)GetChild())->GetWireSize() );
  886. }
  887. else
  888. {
  889. switch ( ((CG_BASETYPE *)GetChild())->GetFormatChar() )
  890. {
  891. case FC_CHAR :
  892. case FC_BYTE :
  893. pFormatString->PushFormatChar( FC_C_CSTRING );
  894. break;
  895. case FC_WCHAR :
  896. pFormatString->PushFormatChar( FC_C_WSTRING );
  897. break;
  898. default :
  899. assert(0);
  900. }
  901. }
  902. if ( GetSizeIsExpr() )
  903. {
  904. pFormatString->PushFormatChar( FC_STRING_SIZED );
  905. if ( IsStringableStruct() )
  906. pFormatString->PushFormatChar( FC_PAD );
  907. //
  908. // Set the IsPointer parameter to FALSE.
  909. //
  910. GenFormatStringConformanceDescription( pCCB, FALSE, IsInMultiDim() );
  911. }
  912. else
  913. {
  914. if ( ! IsStringableStruct() )
  915. pFormatString->PushFormatChar( FC_PAD );
  916. }
  917. // optimize away duplicates
  918. SetFormatStringEndOffset( pFormatString->GetCurrentOffset() );
  919. pFormatString->OptimizeFragment( this );
  920. }
  921. //*************************************************************************
  922. // Alignment methods.
  923. //*************************************************************************
  924. void
  925. CG_ARRAY::SetNextNdrAlignment( CCB * pCCB )
  926. {
  927. CG_NDR * pChild;
  928. if ( IsComplex() )
  929. {
  930. pCCB->SetNdrAlignment( NDR_ALWC1 );
  931. return;
  932. }
  933. if ( GetCGID() == ID_CG_ARRAY )
  934. {
  935. if ( HasPointer() )
  936. pCCB->SetNdrAlignment( NDR_ALWC1 );
  937. else
  938. pCCB->SetNextNdrAlignment( GetWireSize() );
  939. return;
  940. }
  941. pChild = (CG_NDR *) GetChild();
  942. pCCB->SetNdrAlignment( NDR_ALWC4 );
  943. pCCB->NdrAlignmentAction( GetWireAlignment() );
  944. pChild->SetNextNdrAlignment( pCCB );
  945. }
  946. void
  947. CG_STRING_ARRAY::SetNextNdrAlignment( CCB * pCCB )
  948. {
  949. CG_BASETYPE * pChild = (CG_BASETYPE *) GetChild();
  950. pCCB->SetNdrAlignment( pChild->GetFormatChar() == FC_WCHAR ?
  951. NDR_ALWC2 : NDR_ALWC1 );
  952. }
  953. void
  954. CG_CONFORMANT_STRING_ARRAY::SetNextNdrAlignment( CCB * pCCB )
  955. {
  956. CG_BASETYPE * pChild = (CG_BASETYPE *) GetChild();
  957. pCCB->SetNdrAlignment( pChild->GetFormatChar() == FC_WCHAR ?
  958. NDR_ALWC2 : NDR_ALWC1 );
  959. }
  960. //*************************************************************************
  961. // CG_CONF_ATTRIBUTE
  962. //*************************************************************************
  963. void
  964. CG_CONF_ATTRIBUTE::GenFormatStringConformanceDescription(
  965. CCB * pCCB,
  966. BOOL IsPointer,
  967. BOOL IsMultiDArray )
  968. /*++
  969. Routine Description :
  970. Generates the conformace description field for a conformant (varying)
  971. array.
  972. Arguments :
  973. pCCB - pointer to the code control block
  974. --*/
  975. {
  976. GenNdrFormatAttributeDescription( pCCB,
  977. GetMinIsExpr(),
  978. GetSizeIsExpr(),
  979. IsPointer,
  980. FALSE,
  981. FALSE,
  982. IsMultiDArray );
  983. }
  984. //*************************************************************************
  985. // CG_VARY_ATTRIBUTE
  986. //*************************************************************************
  987. void
  988. CG_VARY_ATTRIBUTE::GenFormatStringVarianceDescription(
  989. CCB * pCCB,
  990. BOOL IsPointer,
  991. BOOL IsVaryingArray,
  992. BOOL IsMultiDArray )
  993. /*++
  994. Routine Description :
  995. Generates the variance description for a (conformant) varying array.
  996. Arguments :
  997. pCCB - pointer to the code control block
  998. IsPointer - TRUE if the array is actually a length_is pointer
  999. IsVaryingArray - TRUE if the array is varying only
  1000. --*/
  1001. {
  1002. GenNdrFormatAttributeDescription( pCCB,
  1003. GetFirstIsExpr(),
  1004. GetLengthIsExpr(),
  1005. IsPointer,
  1006. FALSE,
  1007. IsVaryingArray,
  1008. IsMultiDArray );
  1009. }
  1010. void
  1011. GenNdrFormatAttributeDescription( CCB * pCCB,
  1012. expr_node * pMinExpr,
  1013. expr_node * pSizeExpr,
  1014. BOOL IsPointer,
  1015. BOOL IsUnion,
  1016. BOOL IsVaryingArray,
  1017. BOOL IsMultiDArray )
  1018. /*++
  1019. Routine Description :
  1020. Generates the conformance, variance, switch_is, or iid_is description for
  1021. an array, pointer, union, or interface pointer.
  1022. Arguments :
  1023. pCCB - Pointer to code control block.
  1024. pMinExpr - Either the min_is expression (conformance), first_is
  1025. expression (variance), or 0 for a switch_is (union)
  1026. or iid_is (interface pointer).
  1027. pSizeExpr - Either the size_is (conformance), length_is (variance),
  1028. switch_is (union), or iid_is (interface pointer) expression.
  1029. IsPointer - Is the conformance or variance a pointer attribute.
  1030. IsUnion - Are we generating a switch_is description.
  1031. --*/
  1032. {
  1033. FORMAT_STRING * pFormatString;
  1034. node_skl * pAttributeNodeType;
  1035. long Offset;
  1036. FORMAT_CHARACTER Op;
  1037. unsigned char Type;
  1038. pFormatString = pCCB->GetFormatString();
  1039. //
  1040. // Make sure the min_is() or first_is() is constant 0.
  1041. // The pMinExpr is NULL if we're handling a union's switch_is.
  1042. //
  1043. if ( pMinExpr )
  1044. {
  1045. if ( ! pMinExpr->IsConstant() )
  1046. goto ComplexAttribute;
  1047. else
  1048. if ( ((expr_constant *)pMinExpr)->GetValue() != 0 )
  1049. goto ComplexAttribute;
  1050. }
  1051. if ( pSizeExpr->IsConstant() )
  1052. {
  1053. long Size;
  1054. pFormatString->PushByte( FC_CONSTANT_CONFORMANCE );
  1055. Size = ((expr_constant *)pSizeExpr)->GetValue();
  1056. //
  1057. // We push the lower 24 bits of the constant size.
  1058. //
  1059. pFormatString->PushByte( (char) ((Size & 0x00ff0000) >> 16) );
  1060. pFormatString->PushShort( (short) (Size & 0x0000ffff) );
  1061. return;
  1062. }
  1063. if ( pSizeExpr->IsAVariable() )
  1064. {
  1065. Op = FC_ZERO;
  1066. pAttributeNodeType = pSizeExpr->GetType();
  1067. }
  1068. else
  1069. {
  1070. expr_node * pLeftExpr;
  1071. expr_node * pRightExpr;
  1072. OPERATOR Operator;
  1073. if ( pSizeExpr->IsBinaryOperator() )
  1074. {
  1075. pLeftExpr = ((expr_op_binary *)pSizeExpr)->GetLeft();
  1076. pRightExpr = ((expr_op_binary *)pSizeExpr)->GetRight();
  1077. }
  1078. else
  1079. if ( pSizeExpr->IsUnaryOperator() )
  1080. pLeftExpr = ((expr_op_unary *)pSizeExpr)->GetLeft();
  1081. else
  1082. goto ComplexAttribute;
  1083. switch ( Operator = ((expr_operator *)pSizeExpr)->GetOperator() )
  1084. {
  1085. case OP_SLASH :
  1086. case OP_STAR :
  1087. if ( pLeftExpr->IsAVariable() &&
  1088. pRightExpr->IsConstant() &&
  1089. ((expr_constant *)pRightExpr)->GetValue() == 2 )
  1090. {
  1091. Op = ((Operator == OP_SLASH) ? FC_DIV_2 : FC_MULT_2);
  1092. pAttributeNodeType = pLeftExpr->GetType();
  1093. }
  1094. else
  1095. {
  1096. goto ComplexAttribute;
  1097. }
  1098. break;
  1099. case OP_PLUS :
  1100. case OP_MINUS :
  1101. if ( ( pLeftExpr->IsAVariable() &&
  1102. pRightExpr->IsConstant() &&
  1103. ((expr_constant *)pRightExpr)->GetValue() == 1 ) ||
  1104. ( pRightExpr->IsAVariable() &&
  1105. pLeftExpr->IsConstant() &&
  1106. ((expr_constant *)pLeftExpr)->GetValue() == 1 ) )
  1107. {
  1108. Op = ((Operator == OP_PLUS) ? FC_ADD_1 : FC_SUB_1);
  1109. pAttributeNodeType = pLeftExpr->GetType();
  1110. }
  1111. else
  1112. {
  1113. goto ComplexAttribute;
  1114. }
  1115. break;
  1116. case OP_UNARY_INDIRECTION :
  1117. if ( ! pLeftExpr->IsAVariable() )
  1118. goto ComplexAttribute;
  1119. pAttributeNodeType = pLeftExpr->GetType();
  1120. Op = FC_DEREFERENCE;
  1121. break;
  1122. default :
  1123. goto ComplexAttribute;
  1124. }
  1125. }
  1126. // Will hold the switch_is node.
  1127. CG_NDR * pSwitchNode;
  1128. //
  1129. // Check if this is top level conformance.
  1130. //
  1131. if ( pCCB->GetCGNodeContext()->IsProc() )
  1132. {
  1133. CG_PROC * pProc;
  1134. CG_PARAM * pParam;
  1135. CG_ITERATOR Iterator;
  1136. pProc = (CG_PROC *) pCCB->GetCGNodeContext();
  1137. if ( (pProc->GetOptimizationFlags() & OPTIMIZE_SIZE) &&
  1138. IsMultiDArray )
  1139. Type = FC_TOP_LEVEL_MULTID_CONFORMANCE;
  1140. else
  1141. Type = FC_TOP_LEVEL_CONFORMANCE;
  1142. pProc->GetMembers( Iterator );
  1143. //
  1144. // Find out the type of the attribute descriptor.
  1145. //
  1146. while ( ITERATOR_GETNEXT( Iterator, pParam ) )
  1147. {
  1148. pSwitchNode = (CG_NDR *) pParam->GetChild();
  1149. if ( pParam->GetType() == pAttributeNodeType )
  1150. {
  1151. //
  1152. // Get the actual base type if the attribute is a dereference.
  1153. //
  1154. if ( Op == FC_DEREFERENCE )
  1155. pSwitchNode = (CG_NDR *) pSwitchNode->GetChild();
  1156. //
  1157. // Iid_is check.
  1158. //
  1159. if ( pSwitchNode->IsPointer() )
  1160. {
  1161. Type |= FC_LONG;
  1162. break;
  1163. }
  1164. Type |= ((CG_BASETYPE *)pSwitchNode)->GetSignedFormatChar();
  1165. break;
  1166. }
  1167. }
  1168. if ( IsPointer && IsMultiDArray &&
  1169. (pProc->GetOptimizationFlags() & OPTIMIZE_SIZE) )
  1170. {
  1171. CG_QUALIFIED_POINTER * pSizePointer;
  1172. pSizePointer = pCCB->GetCurrentSizePointer();
  1173. pFormatString->PushByte( Type );
  1174. pFormatString->PushFormatChar( Op );
  1175. pFormatString->PushShort( pSizePointer->GetDimension() );
  1176. }
  1177. else
  1178. {
  1179. pFormatString->PushByte( Type );
  1180. pFormatString->PushFormatChar( Op );
  1181. pFormatString->PushShortStackOffset(
  1182. (short) pParam->GetStackOffset( pCCB, I386_STACK_SIZING ),
  1183. (short) pParam->GetStackOffset( pCCB, ALPHA_STACK_SIZING ),
  1184. (short) pParam->GetStackOffset( pCCB, MIPS_STACK_SIZING ),
  1185. (short) pParam->GetStackOffset( pCCB, PPC_STACK_SIZING ),
  1186. (short) pParam->GetStackOffset( pCCB, MAC_STACK_SIZING )
  1187. );
  1188. }
  1189. }
  1190. else // structure cg class
  1191. {
  1192. CG_STRUCT * pStruct;
  1193. CG_FIELD * pField;
  1194. CG_ITERATOR Iterator;
  1195. if ( IsPointer )
  1196. Type = FC_POINTER_CONFORMANCE;
  1197. else
  1198. Type = FC_NORMAL_CONFORMANCE;
  1199. pStruct = (CG_STRUCT *) pCCB->GetCGNodeContext();
  1200. pStruct->GetMembers( Iterator );
  1201. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  1202. {
  1203. pSwitchNode = (CG_NDR *) pField->GetChild();
  1204. if ( (pField->GetType() == pAttributeNodeType) &&
  1205. ! pField->GetSizeIsDone() )
  1206. {
  1207. pField->SetSizeIsDone( TRUE );
  1208. //
  1209. // Get the actual base type if the attribute is a dereference.
  1210. //
  1211. if ( Op == FC_DEREFERENCE )
  1212. pSwitchNode = (CG_NDR *) pSwitchNode->GetChild();
  1213. //
  1214. // Iid_is check.
  1215. //
  1216. if ( pSwitchNode->IsPointer() )
  1217. {
  1218. Type |= FC_LONG;
  1219. break;
  1220. }
  1221. Type |= ((CG_BASETYPE *)pSwitchNode)->GetSignedFormatChar();
  1222. break;
  1223. }
  1224. }
  1225. //
  1226. // Offset to the attribute field in the structure. Below are
  1227. // the three possible ways to compute the offset, with the order
  1228. // of precedence.
  1229. //
  1230. // For pointers (either sized pointers, or a pointer to a union)
  1231. // this is a positive offset from the beginning of the structure.
  1232. // For imbeded unions this is the offset from the union's position
  1233. // in the structure to the attribute's position.
  1234. // For conformant (varying) arrays it's a negative offset from the
  1235. // end of the structure.
  1236. //
  1237. if ( IsPointer )
  1238. Offset = pField->GetMemOffset();
  1239. else
  1240. {
  1241. if ( IsUnion || IsVaryingArray )
  1242. {
  1243. CG_FIELD * pUnionField;
  1244. pUnionField = (CG_FIELD *) pCCB->GetLastPlaceholderClass();
  1245. Offset = pField->GetMemOffset() -
  1246. pUnionField->GetMemOffset();
  1247. }
  1248. else
  1249. {
  1250. Offset = pField->GetMemOffset() -
  1251. pStruct->GetMemorySize();
  1252. }
  1253. }
  1254. pFormatString->PushByte( Type );
  1255. pFormatString->PushFormatChar( Op );
  1256. pFormatString->PushShort( Offset );
  1257. }
  1258. return;
  1259. ComplexAttribute:
  1260. char * PrintPrefix = "";
  1261. CG_NDR * pNdr;
  1262. pNdr = pCCB->GetCGNodeContext();
  1263. //
  1264. // If this is a top level attribute and we're compiling /Os then we
  1265. // don't need the callback since the expression is computed inline in
  1266. // the stub.
  1267. //
  1268. if ( pNdr->IsProc() &&
  1269. (((CG_PROC *)pNdr)->GetOptimizationFlags() & OPTIMIZE_SIZE) )
  1270. {
  1271. pFormatString->PushByte(
  1272. IsMultiDArray ?
  1273. FC_TOP_LEVEL_MULTID_CONFORMANCE : FC_TOP_LEVEL_CONFORMANCE );
  1274. pFormatString->PushByte( 0 );
  1275. pFormatString->PushShort( (short) 0 );
  1276. }
  1277. else
  1278. {
  1279. long Displacement;
  1280. if ( pCCB->GetCGNodeContext()->IsProc() )
  1281. Displacement = 0;
  1282. else
  1283. {
  1284. CG_STRUCT * pStruct;
  1285. CG_FIELD * pField;
  1286. CG_NDR * pNdr;
  1287. // Get the imbeding struct.
  1288. pStruct = (CG_STRUCT *) pCCB->GetCGNodeContext();
  1289. // Get the field whose attribute we're handling.
  1290. pField = (CG_FIELD *) pCCB->GetLastPlaceholderClass();
  1291. //
  1292. // Set the PrintPrefix string correctly.
  1293. //
  1294. PrintPrefix = pField->GetPrintPrefix();
  1295. pNdr = (CG_NDR *) pField->GetChild();
  1296. switch ( pNdr->GetCGID() )
  1297. {
  1298. case ID_CG_CONF_ARRAY :
  1299. case ID_CG_CONF_VAR_ARRAY :
  1300. case ID_CG_CONF_STRING_ARRAY :
  1301. // Displacement is imbeding struct's size.
  1302. Displacement = pStruct->GetMemorySize();
  1303. break;
  1304. case ID_CG_VAR_ARRAY :
  1305. case ID_CG_STRING_ARRAY :
  1306. case ID_CG_ENCAP_STRUCT :
  1307. case ID_CG_UNION :
  1308. // Displacement is imbeded node's offset in the struct.
  1309. Displacement = pField->GetMemOffset();
  1310. break;
  1311. default :
  1312. Displacement = 0;
  1313. break;
  1314. }
  1315. }
  1316. GenNdrFormatComplexAttributeDescription( pCCB,
  1317. pMinExpr,
  1318. pSizeExpr,
  1319. Displacement,
  1320. PrintPrefix,
  1321. IsPointer );
  1322. }
  1323. }
  1324. void
  1325. GenNdrFormatComplexAttributeDescription( CCB * pCCB,
  1326. expr_node * pMinExpr,
  1327. expr_node * pSizeExpr,
  1328. long StackTopDisplacement,
  1329. char * PrintPrefix,
  1330. BOOL IsPointer )
  1331. /*++
  1332. Routine description:
  1333. This routine generates
  1334. - an auxuliary routine that evaluates a complicated expression.
  1335. - a description of the callback call into the current code stream.
  1336. The routine has the following signature:
  1337. void <name>( PMIDL_STUB_MESSAGE pStubMsg );
  1338. The description is as follows (takes 4 bytes):
  1339. 0, FC_CALLBACK, <<routine_index>>
  1340. The naming convention for the routine is currently as follows
  1341. <name> is <proc_or_struct_name>exprEval_<routine_index>
  1342. Routine generation is postponed by using a Registry object.
  1343. Arguments:
  1344. pCCB - ptr to the code control block
  1345. pMinExpr - pointer to an expression tree, relates to min_is, first_is
  1346. pSizeExpr - pointer to an expression tree, relates to size_is, max_is etc.
  1347. StackTopDisplacement - For an attribute expression on a field in a
  1348. a structure, this is the number of bytes to
  1349. subtract from StackTop to get the proper
  1350. structure pointer.
  1351. PrinfPrefix - The prefix to print after "pS->" when accessing a field.
  1352. IsPointer - Is this a description for an attribute on a pointer
  1353. The interpretation of the two input expressions (pMinExpr and pSizeExpr)
  1354. is such that when both of them are present, it is enough to take
  1355. the difference to come up with the proper sizing.
  1356. The algorithm used here is thus as follows:
  1357. pMin pSize
  1358. NULL NULL impossible (assert)
  1359. !=NULL NULL impossible (assert)
  1360. NULL !=NULL Generate a routine that evaluates the following:
  1361. pStubMsg->Offset = 0
  1362. pStubMsg->MaxCount = eval(pSize)
  1363. !=NULL !=NULL Generate a routine that evaluates the following:
  1364. pStubMsg->Offset = eval(pMin)
  1365. pStubMsg->MaxCount = eval(pSize) - pStubMsg->Offset
  1366. Returns:
  1367. --*/
  1368. {
  1369. assert( pSizeExpr != NULL );
  1370. // Make the name of the routine and put it into the table.
  1371. // Each call to the routine we are in right now will create a new entry
  1372. // in the ExprEval routine table.
  1373. CG_NDR * pContainer = pCCB->GetCGNodeContext();
  1374. unsigned short Index = (unsigned short)
  1375. (pCCB->GetExprEvalIndexMgr()->GetIndex() - 1);
  1376. char * pContainerName = pContainer->GetType()->GetSymName();
  1377. char * pName = new char[ strlen(pCCB->GetInterfaceName()) +
  1378. 1 + // "_"
  1379. strlen(pContainerName) +
  1380. sizeof("ExprEval_0000") + 1 ];
  1381. strcpy( pName, pCCB->GetInterfaceName() );
  1382. strcat( pName, "_" );
  1383. strcat( pName, pContainerName );
  1384. strcat( pName, "ExprEval_" );
  1385. char * pBuf = pName + strlen(pName);
  1386. sprintf( pBuf, "%04x", Index );
  1387. pCCB->GetExprEvalIndexMgr()->Lookup( pName );
  1388. // generate the description of the callback
  1389. // If this is a top level attribute we note that in the description.
  1390. if ( pCCB->GetCGNodeContext()->IsProc() )
  1391. pCCB->GetFormatString()->PushByte(FC_TOP_LEVEL_CONFORMANCE);
  1392. else
  1393. if ( IsPointer )
  1394. pCCB->GetFormatString()->PushByte(FC_POINTER_CONFORMANCE);
  1395. else
  1396. pCCB->GetFormatString()->PushByte(0);
  1397. pCCB->GetFormatString()->PushFormatChar( FC_CALLBACK );
  1398. pCCB->GetFormatString()->PushShort( (short) Index );
  1399. // Register the routine to be generated for future use.
  1400. EXPR_EVAL_CONTEXT * pExprEvalContext = new EXPR_EVAL_CONTEXT;
  1401. pExprEvalContext->pContainer = pContainer;
  1402. pExprEvalContext->pMinExpr = pMinExpr;
  1403. pExprEvalContext->pSizeExpr = pSizeExpr;
  1404. pExprEvalContext->pRoutineName = pName;
  1405. pExprEvalContext->pPrintPrefix = PrintPrefix;
  1406. pExprEvalContext->Displacement = StackTopDisplacement;
  1407. pCCB->RegisterExprEvalRoutine( (node_skl *) pExprEvalContext );
  1408. }