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.

1947 lines
57 KiB

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