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.

670 lines
15 KiB

4 years ago
  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. unionndr.hxx
  5. Abstract:
  6. Contains routines for the generation of the new NDR format strings for
  7. unions, and the new NDR marshalling and unmarshalling calls.
  8. Notes:
  9. History:
  10. DKays Nov-1993 Created.
  11. ----------------------------------------------------------------------------*/
  12. #include "becls.hxx"
  13. #pragma hdrstop
  14. void
  15. CG_ENCAPSULATED_STRUCT::GenNdrFormat( CCB * pCCB )
  16. /*++
  17. Routine Description :
  18. Generates the format string for an encapsulated union.
  19. Arguments :
  20. pCCB - pointer to the code control block
  21. Return :
  22. None.
  23. --*/
  24. {
  25. FORMAT_STRING * pFormatString;
  26. CG_BASETYPE * pSwitchIsNode;
  27. CG_UNION * pUnion;
  28. unsigned long SwitchType;
  29. if ( GetFormatStringOffset() != -1 )
  30. return;
  31. pFormatString = pCCB->GetFormatString();
  32. //
  33. // The child of the struct's first field node is the switch_is node.
  34. //
  35. pSwitchIsNode = (CG_BASETYPE *) GetChild()->GetChild();
  36. //
  37. // The child of the struct's second field node is the union node.
  38. //
  39. pUnion = (CG_UNION *) GetChild()->GetSibling()->GetChild();
  40. SetFormatStringOffset( pFormatString->GetCurrentOffset() );
  41. pFormatString->PushFormatChar( FC_ENCAPSULATED_UNION );
  42. //
  43. // The switch type field in the format string has the size of the switch_is
  44. // field (including any needed pading) in the upper four bits and the
  45. // actual switch_is type in the lower four bits.
  46. //
  47. //
  48. // Get the amount to increment the memory pointer to the encapsulated
  49. // union's struct to get to the actual union. This is the total struct
  50. // size minus the union's size (this may not simply be the size of the
  51. // switch_is member because of possible padding).
  52. //
  53. CG_FIELD * pSwitchField;
  54. CG_FIELD * pUnionField;
  55. pSwitchField = (CG_FIELD *) GetChild();
  56. pUnionField = (CG_FIELD *) pSwitchField->GetSibling();
  57. //
  58. // Set the memory increment part of the SwitchType field.
  59. //
  60. SwitchType = ( pUnionField->GetMemOffset() - pSwitchField->GetMemOffset() )
  61. << 4;
  62. if ( pSwitchIsNode->GetFormatChar() == FC_ENUM16 )
  63. SwitchType |= FC_ENUM16;
  64. else
  65. SwitchType |= pSwitchIsNode->GetSignedFormatChar();
  66. pFormatString->PushByte( SwitchType );
  67. pUnion->GenNdrSizeAndArmDescriptions( pCCB );
  68. SetFormatStringEndOffset( pFormatString->GetCurrentOffset() );
  69. // SetFormatStringOffset( pFormatString->OptimizeFragment( this ) );
  70. }
  71. void
  72. CG_UNION::GenNdrFormat( CCB * pCCB )
  73. /*++
  74. Routine Description :
  75. Generates the format string for a non-encapsulated union.
  76. Arguments :
  77. pCCB - pointer to the code control block
  78. Return :
  79. None.
  80. --*/
  81. {
  82. FORMAT_STRING * pFormatString;
  83. long Offset;
  84. SetCCB( pCCB );
  85. if ( GetFormatStringOffset() != -1 )
  86. return;
  87. pFormatString = pCCB->GetFormatString();
  88. SetFormatStringOffset( pFormatString->GetCurrentOffset() );
  89. pFormatString->PushFormatChar( FC_NON_ENCAPSULATED_UNION );
  90. // The switch type's signed format char type.
  91. if (NULL == pCGSwitchType && pCommand->IsHookOleEnabled())
  92. {
  93. RpcError(NULL, 0, NO_SWITCH_IS_HOOKOLE, GetSymName());
  94. exit(NO_SWITCH_IS_HOOKOLE);
  95. }
  96. if ( ((CG_BASETYPE *)pCGSwitchType)->GetFormatChar() == FC_ENUM16 )
  97. pFormatString->PushFormatChar( FC_ENUM16 );
  98. else
  99. {
  100. FORMAT_CHARACTER SwitchTypeFc;
  101. // Note that we take the signed format character this time.
  102. SwitchTypeFc = ((CG_BASETYPE *)pCGSwitchType)->GetSignedFormatChar();
  103. #if defined(TARGET_RKK)
  104. if ( pCommand->GetTargetSystem() == NT35 &&
  105. SwitchTypeFc == FC_USMALL )
  106. {
  107. // The NT 807 NDR engine doesn't know about usmall.
  108. pFormatString->PushFormatChar( FC_BYTE );
  109. pFormatString->PushFormatChar( FC_SMALL );
  110. }
  111. else
  112. #endif
  113. pFormatString->PushFormatChar( SwitchTypeFc );
  114. }
  115. GenNdrSwitchIsDescription( pCCB );
  116. Offset = pFormatString->GetCurrentOffset();
  117. pFormatString->PushShortOffset( 0 );
  118. GenNdrSizeAndArmDescriptions( pCCB );
  119. pFormatString->PushShort( GetNdrSizeAndArmDescriptionOffset() - Offset,
  120. Offset );
  121. SetFormatStringEndOffset( pFormatString->GetCurrentOffset() );
  122. // SetFormatStringOffset( pFormatString->OptimizeFragment( this ) );
  123. }
  124. void
  125. CG_UNION::GenNdrFormatArms( CCB * pCCB )
  126. /*++
  127. Routine Description :
  128. Generates the format string for the arms of an encapsulated or a
  129. non-encapsulated union.
  130. Arguments :
  131. pCCB - pointer to the code control block
  132. Return :
  133. None.
  134. --*/
  135. {
  136. CG_ITERATOR Iterator;
  137. CG_CASE * pCase;
  138. CG_NDR * pNdr;
  139. GetMembers( Iterator );
  140. while ( ITERATOR_GETNEXT( Iterator, pCase ) )
  141. {
  142. if ( ! pCase->GetChild() )
  143. continue;
  144. //
  145. // The child of the CG_CASE is a CG_FIELD.
  146. // The child of the CG_FIELD is the actual NDR entity.
  147. //
  148. pNdr = (CG_NDR *) pCase->GetChild()->GetChild();
  149. if ( ! pNdr )
  150. continue;
  151. if ( pNdr && ! pNdr->IsSimpleType() )
  152. pNdr->GenNdrFormat( pCCB );
  153. }
  154. }
  155. void
  156. CG_UNION::GenNdrSizeAndArmDescriptions( CCB * pCCB )
  157. /*++
  158. Routine Description :
  159. Generates the memory size and arm description portion of the format
  160. string for an encapsulated or a non-encapsulated union.
  161. Arguments :
  162. pCCB - pointer to the code control block
  163. Return :
  164. None.
  165. --*/
  166. {
  167. FORMAT_STRING * pFormatString;
  168. unsigned short UnionArms;
  169. long FormatOffset;
  170. if ( GetNdrSizeAndArmDescriptionOffset() != -1 )
  171. return;
  172. pFormatString = pCCB->GetFormatString();
  173. SetNdrSizeAndArmDescriptionOffset( pFormatString->GetCurrentOffset() );
  174. //
  175. // Set aside the space for the union's description. Then we generate
  176. // the format string description for all the union's arms, and then
  177. // we go back and patch up the the union's description to have the
  178. // proper offsets. This must be done to handle self referencing union
  179. // types.
  180. //
  181. // Memory size.
  182. pFormatString->PushShort( (short) GetMemorySize() );
  183. //
  184. // union_arms<2>
  185. //
  186. UnionArms = (unsigned short) GetNumberOfArms();
  187. if ( GetUnionFlavor() == UNION_NONENCAP_MS )
  188. {
  189. //
  190. // Microsoft union support.
  191. // Set the upper four bits of the union_arm<2> field with the
  192. // the alignment of the largest aligned union arm.
  193. //
  194. UnionArms |= (CvtAlignPropertyToAlign(GetWireAlignment()) - 1) << 12;
  195. }
  196. pFormatString->PushShort( (short) UnionArms );
  197. // Get union arms again since we may have just munged it.
  198. UnionArms = (short) GetNumberOfArms();
  199. // The arms.
  200. for ( ; UnionArms-- > 0; )
  201. {
  202. pFormatString->PushLong( 0 );
  203. pFormatString->PushShortOffset( 0 );
  204. }
  205. // default_arm_description<2>
  206. pFormatString->PushShortOffset( 0 );
  207. //
  208. // Generate the format string descriptions of the arms.
  209. //
  210. GenNdrFormatArms( pCCB );
  211. // Find out where the arms' descriptions begin.
  212. FormatOffset = GetNdrSizeAndArmDescriptionOffset() + 4;
  213. CG_ITERATOR Iterator;
  214. CG_CASE * pCase;
  215. CG_NDR * pNdr;
  216. CG_NDR * pNdrDefaultCase;
  217. BOOL DefaultCaseFound;
  218. GetMembers( Iterator );
  219. pNdrDefaultCase = NULL;
  220. DefaultCaseFound = FALSE;
  221. while ( ITERATOR_GETNEXT( Iterator, pCase ) )
  222. {
  223. //
  224. // Check for the default case first.
  225. //
  226. if ( pCase->GetCGID() == ID_CG_DEFAULT_CASE )
  227. {
  228. pNdrDefaultCase = pCase->GetChild() ?
  229. (CG_NDR *) pCase->GetChild()->GetChild() : 0;
  230. DefaultCaseFound = TRUE;
  231. continue;
  232. }
  233. //
  234. // Fill in the arm's case value.
  235. //
  236. if (NULL == pCase->GetExpr())
  237. {
  238. RpcError(NULL, 0, NO_CASE_EXPR, GetSymName());
  239. exit(NO_CASE_EXPR);
  240. }
  241. pFormatString->PushLong( pCase->GetExpr()->GetValue(), FormatOffset );
  242. FormatOffset += 4;
  243. //
  244. // Check for a non-default case with an empty (;) arm.
  245. //
  246. if ( ! pCase->GetChild() || ! pCase->GetChild()->GetChild() )
  247. {
  248. //
  249. // Increment the FormatOffset past the arm description, which
  250. // simply remains zero.
  251. //
  252. FormatOffset += 2;
  253. continue;
  254. }
  255. //
  256. // Else it's a regular case with a valid arm.
  257. //
  258. pNdr = (CG_NDR *) pCase->GetChild()->GetChild();
  259. if ( pNdr && pNdr->IsSimpleType() )
  260. {
  261. short s;
  262. //
  263. // The offset in this case is the actual format character for
  264. // the base type, but with a 1 in the upper bit of the short, to
  265. // make it look negative.
  266. //
  267. s = (short) ((CG_BASETYPE *)pNdr)->GetFormatChar();
  268. s |= MAGIC_UNION_SHORT;
  269. pFormatString->PushShort( s, FormatOffset );
  270. }
  271. else
  272. {
  273. //
  274. // Remember that the offset that gets pushed here is an unsigned
  275. // short offset to the description.
  276. //
  277. pFormatString->PushShort( pNdr->GetFormatStringOffset() -
  278. FormatOffset,
  279. FormatOffset );
  280. }
  281. FormatOffset += 2;
  282. }
  283. //
  284. // Finally, handle the default case.
  285. //
  286. if ( ! DefaultCaseFound )
  287. {
  288. pFormatString->PushShort( (short) 0xffff, FormatOffset );
  289. }
  290. else
  291. {
  292. if ( ! pNdrDefaultCase )
  293. pFormatString->PushShort( (short) 0, FormatOffset );
  294. else
  295. {
  296. if ( pNdrDefaultCase->IsSimpleType() )
  297. {
  298. short s;
  299. s = (short) ((CG_BASETYPE *)pNdrDefaultCase)->GetFormatChar();
  300. s |= MAGIC_UNION_SHORT;
  301. pFormatString->PushShort( s, FormatOffset );
  302. }
  303. else
  304. pFormatString->PushShort(
  305. pNdrDefaultCase->GetFormatStringOffset() - FormatOffset,
  306. FormatOffset );
  307. }
  308. }
  309. }
  310. BOOL
  311. CG_UNION::CanUseBuffer()
  312. {
  313. CG_ITERATOR Iterator;
  314. CG_CASE * pCase;
  315. CG_NDR * pNdr;
  316. unsigned long Size;
  317. long Align;
  318. long TempBufAlign;
  319. //
  320. // We will be very strict, since there is not much room for
  321. // leeway. Only return TRUE if all arms have the same size, the same
  322. // wire alignment, and matching wire/memory alignments & sizes.
  323. //
  324. // The real scenario we're after is a union with all pointer arms or
  325. // longs. This is fairly common in NT.
  326. //
  327. GetMembers( Iterator );
  328. Size = 0;
  329. Align = 0;
  330. while ( ITERATOR_GETNEXT( Iterator, pCase ) )
  331. {
  332. if ( ! pCase->GetChild() ||
  333. ! (pNdr = (CG_NDR *) pCase->GetChild()->GetChild()) )
  334. continue;
  335. TempBufAlign = CvtAlignPropertyToAlign( pNdr->GetWireAlignment() );
  336. if ( (pNdr->GetWireSize() != pNdr->GetMemorySize()) ||
  337. (pNdr->GetMemoryAlignment() != TempBufAlign) )
  338. return FALSE;
  339. if ( ! Size )
  340. {
  341. Size = pNdr->GetWireSize();
  342. Align = TempBufAlign;
  343. continue;
  344. }
  345. if ( (Size != pNdr->GetWireSize()) || (Align != TempBufAlign) )
  346. return FALSE;
  347. }
  348. return TRUE;
  349. }
  350. void
  351. CG_UNION::GenNdrSwitchIsDescription( CCB * pCCB )
  352. /*++
  353. Routine Description :
  354. This routine generates the switch_type<1> and switch_is_description<4>
  355. field for a non-encapsulated union.
  356. Arguments :
  357. pCCB - pointer to the code control block
  358. Return :
  359. None.
  360. --*/
  361. {
  362. CG_NDR * pParamOrField;
  363. CG_FIELD * pField;
  364. expr_node * pSwitchExpr;
  365. BOOL IsPointer;
  366. pParamOrField = pCCB->GetLastPlaceholderClass();
  367. //
  368. // Get the switch is expression.
  369. //
  370. switch ( pParamOrField->GetCGID() )
  371. {
  372. case ID_CG_PARAM :
  373. pSwitchExpr = ((CG_PARAM *)pParamOrField)->GetSwitchExpr();
  374. // If it's top level param then this flag doesn't matter.
  375. IsPointer = FALSE;
  376. break;
  377. case ID_CG_FIELD :
  378. pField = (CG_FIELD *) pParamOrField;
  379. pSwitchExpr = pField->GetSwitchExpr();
  380. // Check if the field is actually a pointer to a union.
  381. IsPointer = ((CG_NDR *)pField->GetChild())->IsPointer();
  382. break;
  383. default :
  384. assert(0);
  385. }
  386. GenNdrFormatAttributeDescription( pCCB,
  387. NULL,
  388. pSwitchExpr,
  389. IsPointer,
  390. TRUE,
  391. FALSE,
  392. FALSE );
  393. }
  394. void
  395. CG_UNION::SetFormatStringOffset( long Offset )
  396. {
  397. CCB * pCCB;
  398. CG_NDR * pParamOrFieldNode;
  399. pCCB = GetCCB();
  400. pParamOrFieldNode = pCCB->GetLastPlaceholderClass();
  401. if ( pParamOrFieldNode->GetCGID() == ID_CG_PARAM )
  402. ((CG_PARAM *)pParamOrFieldNode)->SetUnionFormatStringOffset( Offset );
  403. else
  404. ((CG_FIELD *)pParamOrFieldNode)->SetUnionFormatStringOffset( Offset );
  405. }
  406. long
  407. CG_UNION::GetFormatStringOffset()
  408. {
  409. CCB * pCCB;
  410. CG_NDR * pParamOrFieldNode;
  411. pCCB = GetCCB();
  412. pParamOrFieldNode = pCCB->GetLastPlaceholderClass();
  413. if ( pParamOrFieldNode->GetCGID() == ID_CG_PARAM )
  414. return ((CG_PARAM *)pParamOrFieldNode)->GetUnionFormatStringOffset();
  415. else
  416. return ((CG_FIELD *)pParamOrFieldNode)->GetUnionFormatStringOffset();
  417. }
  418. void
  419. CG_ENCAPSULATED_STRUCT::GenNdrPointerFixUp( CCB * pCCB,
  420. CG_STRUCT * pStruct )
  421. {
  422. //
  423. // For an encapsulated struct, call this method on the actual union.
  424. // Remember that the encap struct's child is a CG_FIELD whose sibling's
  425. // child will be the actual union.
  426. //
  427. ((CG_UNION*)(GetChild()->GetSibling()->GetChild()))->
  428. GenNdrPointerFixUp( pCCB, pStruct );
  429. }
  430. void
  431. CG_UNION::GenNdrPointerFixUp( CCB * pCCB,
  432. CG_STRUCT * pStruct )
  433. {
  434. CG_ITERATOR Iterator;
  435. CG_NDR * pMember;
  436. CG_NDR * pNdr;
  437. long OffsetOffset;
  438. if ( IsInFixUp() )
  439. return;
  440. SetFixUpLock( TRUE );
  441. OffsetOffset = GetNdrSizeAndArmDescriptionOffset() + 4;
  442. GetMembers( Iterator );
  443. while ( ITERATOR_GETNEXT( Iterator, pMember ) )
  444. {
  445. if ( ! pMember->GetChild() ||
  446. ! pMember->GetChild()->GetChild() )
  447. {
  448. OffsetOffset += 6;
  449. continue;
  450. }
  451. //
  452. // Child of the case is a CG_FIELD - get it's child to get the
  453. // actual Ndr entity.
  454. //
  455. pNdr = (CG_NDR *) pMember->GetChild()->GetChild();
  456. if ( pNdr == pStruct )
  457. {
  458. //
  459. // Patch up the offset.
  460. //
  461. OffsetOffset += 4;
  462. pCCB->GetFormatString()->PushShort(
  463. pStruct->GetFormatStringOffset() - OffsetOffset,
  464. OffsetOffset );
  465. OffsetOffset += 2;
  466. continue;
  467. }
  468. if ( (pNdr->GetCGID() == ID_CG_PTR) ||
  469. (pNdr->GetCGID() == ID_CG_SIZE_PTR) ||
  470. (pNdr->GetCGID() == ID_CG_SIZE_LENGTH_PTR) )
  471. {
  472. CG_POINTER * pPointer = (CG_POINTER *) pNdr;
  473. //
  474. // Check if we're ready for this guy yet.
  475. //
  476. if ( pPointer->GetFormatStringOffset() == -1 )
  477. continue;
  478. // Get the pointee.
  479. pNdr = (CG_NDR *) pNdr->GetChild();
  480. //
  481. // If the pointer's pointee is the struct we're checking for,
  482. // then patch up the pointer's offset_to_description<2> field.
  483. //
  484. if ( pNdr == pStruct )
  485. {
  486. long PointerOffset;
  487. //
  488. // Get the offset in the format string where the
  489. // offset_to_description<2> field of the pointer is.
  490. //
  491. PointerOffset = pPointer->GetFormatStringOffset() + 2;
  492. pCCB->GetFormatString()->PushShort(
  493. pStruct->GetFormatStringOffset() - PointerOffset,
  494. PointerOffset );
  495. OffsetOffset += 6;
  496. continue;
  497. }
  498. }
  499. //
  500. // Continue the chase if necessary.
  501. //
  502. if ( pNdr->IsStruct() || pNdr->IsUnion() || pNdr->IsArray() )
  503. pNdr->GenNdrPointerFixUp( pCCB, pStruct );
  504. OffsetOffset += 6;
  505. }
  506. SetFixUpLock( FALSE );
  507. }