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.

3008 lines
77 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1993-2000 Microsoft Corporation
  3. Module Name :
  4. bufsize.c
  5. Abstract :
  6. This file contains the routines called by MIDL 2.0 stubs and the
  7. interpreter for computing the buffer size needed for a parameter.
  8. Author :
  9. David Kays dkays September 1993.
  10. Revision History :
  11. ---------------------------------------------------------------------*/
  12. #include "ndrp.h"
  13. #include "ndrole.h"
  14. #include "attack.h"
  15. #include "pointerq.h"
  16. RPCRTAPI
  17. void RPC_ENTRY
  18. NdrUDTSimpleTypeSize(
  19. PMIDL_STUB_MESSAGE pStubMsg,
  20. unsigned char * pMemory,
  21. PFORMAT_STRING pFormat
  22. );
  23. extern const
  24. PSIZE_ROUTINE SizeRoutinesTable[] =
  25. {
  26. NdrUDTSimpleTypeSize,
  27. NdrUDTSimpleTypeSize,
  28. NdrUDTSimpleTypeSize,
  29. NdrUDTSimpleTypeSize,
  30. NdrUDTSimpleTypeSize,
  31. NdrUDTSimpleTypeSize,
  32. NdrUDTSimpleTypeSize,
  33. NdrUDTSimpleTypeSize,
  34. NdrUDTSimpleTypeSize,
  35. NdrUDTSimpleTypeSize,
  36. NdrUDTSimpleTypeSize,
  37. NdrUDTSimpleTypeSize,
  38. NdrUDTSimpleTypeSize,
  39. NdrUDTSimpleTypeSize,
  40. NdrUDTSimpleTypeSize,
  41. NdrUDTSimpleTypeSize,
  42. NdrUDTSimpleTypeSize,
  43. NdrPointerBufferSize,
  44. NdrPointerBufferSize,
  45. NdrPointerBufferSize,
  46. NdrPointerBufferSize,
  47. NdrSimpleStructBufferSize,
  48. NdrSimpleStructBufferSize,
  49. NdrConformantStructBufferSize,
  50. NdrConformantStructBufferSize,
  51. NdrConformantVaryingStructBufferSize,
  52. NdrComplexStructBufferSize,
  53. NdrConformantArrayBufferSize,
  54. NdrConformantVaryingArrayBufferSize,
  55. NdrFixedArrayBufferSize,
  56. NdrFixedArrayBufferSize,
  57. NdrVaryingArrayBufferSize,
  58. NdrVaryingArrayBufferSize,
  59. NdrComplexArrayBufferSize,
  60. NdrConformantStringBufferSize,
  61. NdrConformantStringBufferSize,
  62. NdrConformantStringBufferSize,
  63. NdrConformantStringBufferSize,
  64. NdrNonConformantStringBufferSize,
  65. NdrNonConformantStringBufferSize,
  66. NdrNonConformantStringBufferSize,
  67. NdrNonConformantStringBufferSize,
  68. NdrEncapsulatedUnionBufferSize,
  69. NdrNonEncapsulatedUnionBufferSize,
  70. NdrByteCountPointerBufferSize,
  71. NdrXmitOrRepAsBufferSize, // transmit as
  72. NdrXmitOrRepAsBufferSize, // represent as
  73. NdrPointerBufferSize,
  74. NdrContextHandleSize,
  75. // New Post NT 3.5 token serviced from here on.
  76. 0, // NdrHardStructBufferSize,
  77. NdrXmitOrRepAsBufferSize, // transmit as ptr
  78. NdrXmitOrRepAsBufferSize, // represent as ptr
  79. NdrUserMarshalBufferSize,
  80. 0, // FC_PIPE
  81. 0, // FC_BLK_HOLE
  82. NdrpRangeBufferSize,
  83. 0, // FC_INT3264
  84. 0, // FC_UINT3264
  85. 0, // NdrCsArrayBufferSize,
  86. 0, // NdrCsTagBufferSize
  87. };
  88. const
  89. PSIZE_ROUTINE * pfnSizeRoutines = SizeRoutinesTable;
  90. void
  91. NdrpInterfacePointerBufferSize (
  92. PMIDL_STUB_MESSAGE pStubMsg,
  93. uchar * pMemory,
  94. PFORMAT_STRING pFormat );
  95. RPCRTAPI
  96. void RPC_ENTRY
  97. NdrTypeSize(
  98. PMIDL_STUB_MESSAGE pStubMsg,
  99. unsigned char * pMemory,
  100. PFORMAT_STRING pFormat
  101. )
  102. {
  103. (*pfnSizeRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  104. pMemory,
  105. pFormat );
  106. }
  107. void RPC_ENTRY
  108. NdrUDTSimpleTypeSize(
  109. PMIDL_STUB_MESSAGE pStubMsg,
  110. uchar * pMemory,
  111. PFORMAT_STRING pFormat )
  112. /*++
  113. Routine Description :
  114. Get the size a top level or embedded simple type.
  115. Used for VT_USERDEFINED but in fact simple types,
  116. like TKIND_ENUM and TKIND_ALIAS
  117. Arguments :
  118. pStubMsg - Pointer to the stub message.
  119. pMemory - Pointer to the data being sized.
  120. pFormat - Pointer's format string description.
  121. Return :
  122. None.
  123. --*/
  124. {
  125. LENGTH_ALIGN( pStubMsg->BufferLength,
  126. SIMPLE_TYPE_ALIGNMENT(*pFormat) );
  127. pStubMsg->BufferLength += SIMPLE_TYPE_BUFSIZE(*pFormat);
  128. pMemory += SIMPLE_TYPE_MEMSIZE(*pFormat);
  129. }
  130. void RPC_ENTRY
  131. NdrPointerBufferSize(
  132. PMIDL_STUB_MESSAGE pStubMsg,
  133. uchar * pMemory,
  134. PFORMAT_STRING pFormat )
  135. /*++
  136. Routine Description :
  137. Computes the needed buffer size for a top level pointer to anything.
  138. Pointers embedded in structures, arrays, or unions call
  139. NdrpPointerBufferSize directly.
  140. Used for FC_RP, FC_UP, FC_FP, FC_OP.
  141. Arguments :
  142. pStubMsg - Pointer to the stub message.
  143. pMemory - Pointer to the data being sized.
  144. pFormat - Pointer's format string description.
  145. Return :
  146. None.
  147. --*/
  148. {
  149. //
  150. // Add 4 bytes for a unique or full pointer.
  151. //
  152. if ( *pFormat != FC_RP )
  153. {
  154. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  155. pStubMsg->BufferLength += PTR_WIRE_SIZE;
  156. }
  157. NdrpPointerBufferSize( pStubMsg,
  158. pMemory,
  159. pFormat );
  160. }
  161. __forceinline void
  162. NdrpPointerBufferSizeInternal(
  163. PMIDL_STUB_MESSAGE pStubMsg,
  164. uchar * pMemory,
  165. PFORMAT_STRING pFormat )
  166. /*++
  167. Routine Description :
  168. Private routine for sizing a pointee. This is the entry
  169. point for pointers embedded in structures, arrays, or unions.
  170. Used for FC_RP, FC_UP, FC_FP, FC_OP.
  171. Arguments :
  172. pStubMsg - Pointer to the stub message.
  173. pMemory - Pointer to the data being sized.
  174. pFormat - Pointer's format string description.
  175. pStubMsg->BufferLength - ready for the pointee.
  176. Return :
  177. None.
  178. --*/
  179. {
  180. if ( FC_IP == *pFormat )
  181. {
  182. if ( IS_BROKEN_INTERFACE_POINTER(pStubMsg->uFlags) )
  183. {
  184. // The pointee is effectivly both the pointer
  185. // and the pointee.
  186. NdrInterfacePointerBufferSize(
  187. pStubMsg,
  188. pMemory,
  189. pFormat );
  190. return;
  191. }
  192. if ( ! pMemory )
  193. return;
  194. NdrpInterfacePointerBufferSize( pStubMsg,
  195. pMemory,
  196. pFormat );
  197. return;
  198. }
  199. uchar uFlagsSave;
  200. if ( ! pMemory )
  201. return;
  202. if ( *pFormat == FC_FP )
  203. {
  204. //
  205. // Check if we have already sized this full pointer.
  206. //
  207. if ( NdrFullPointerQueryPointer( pStubMsg->FullPtrXlatTables,
  208. pMemory,
  209. FULL_POINTER_BUF_SIZED,
  210. 0 ) )
  211. return;
  212. }
  213. if ( ! SIMPLE_POINTER(pFormat[1]) )
  214. {
  215. //
  216. // Pointer to complex type.
  217. //
  218. if ( POINTER_DEREF(pFormat[1]) )
  219. pMemory = *((uchar **)pMemory);
  220. pFormat += 2;
  221. pFormat += *((signed short *)pFormat);
  222. }
  223. else
  224. {
  225. switch ( pFormat[2] )
  226. {
  227. case FC_C_CSTRING :
  228. case FC_C_BSTRING :
  229. case FC_C_WSTRING :
  230. case FC_C_SSTRING :
  231. // Increment to the string description.
  232. pFormat += 2;
  233. break;
  234. default :
  235. //
  236. // Pointer to simple type. Make an upper bound estimate.
  237. //
  238. SIMPLE_TYPE_BUF_INCREMENT(pStubMsg->BufferLength, pFormat[2]);
  239. return;
  240. }
  241. }
  242. uFlagsSave = pStubMsg->uFlags;
  243. RESET_CONF_FLAGS_TO_STANDALONE(pStubMsg->uFlags);
  244. (*pfnSizeRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  245. pMemory,
  246. pFormat );
  247. pStubMsg->uFlags = uFlagsSave;
  248. }
  249. NDR_BUFSIZE_POINTER_QUEUE_ELEMENT::NDR_BUFSIZE_POINTER_QUEUE_ELEMENT(
  250. MIDL_STUB_MESSAGE *pStubMsg,
  251. uchar * const pMemoryNew,
  252. const PFORMAT_STRING pFormatNew) :
  253. pMemory(pMemoryNew),
  254. pFormat(pFormatNew),
  255. Memory(pStubMsg->Memory),
  256. uFlags(pStubMsg->uFlags)
  257. {
  258. }
  259. void
  260. NDR_BUFSIZE_POINTER_QUEUE_ELEMENT::Dispatch(
  261. MIDL_STUB_MESSAGE *pStubMsg)
  262. {
  263. SAVE_CONTEXT<uchar*> MemorySave( pStubMsg->Memory, Memory );
  264. SAVE_CONTEXT<uchar> uFlagsSave( pStubMsg->uFlags, uFlags );
  265. NDR_ASSERT( !pStubMsg->PointerBufferMark, "PointerBufferMark is not 0\n");
  266. NdrpPointerBufferSizeInternal( pStubMsg,
  267. pMemory,
  268. pFormat );
  269. }
  270. #if defined(DBG)
  271. void
  272. NDR_BUFSIZE_POINTER_QUEUE_ELEMENT::Print()
  273. {
  274. DbgPrint("NDR_BUFSIZE_POINTER_QUEUE_ELEMENT\n");
  275. DbgPrint("pNext: %p\n", pNext );
  276. DbgPrint("pMemory: %p\n", pMemory );
  277. DbgPrint("pFormat: %p\n", pFormat );
  278. DbgPrint("Memory: %p\n", Memory );
  279. DbgPrint("uFlags: %x\n", uFlags );
  280. }
  281. #endif
  282. void
  283. NdrpEnquePointerBufferSize(
  284. PMIDL_STUB_MESSAGE pStubMsg,
  285. uchar * pMemory,
  286. PFORMAT_STRING pFormat )
  287. {
  288. NDR32_POINTER_CONTEXT PointerContext( pStubMsg );
  289. RpcTryFinally
  290. {
  291. NDR_BUFSIZE_POINTER_QUEUE_ELEMENT *pElement =
  292. new(PointerContext.GetActiveState())
  293. NDR_BUFSIZE_POINTER_QUEUE_ELEMENT(pStubMsg,
  294. pMemory,
  295. pFormat);
  296. PointerContext.Enque( pElement );
  297. PointerContext.DispatchIfRequired();
  298. }
  299. RpcFinally
  300. {
  301. PointerContext.EndContext();
  302. }
  303. RpcEndFinally
  304. }
  305. void
  306. NdrpPointerBufferSize(
  307. PMIDL_STUB_MESSAGE pStubMsg,
  308. uchar * pMemory,
  309. PFORMAT_STRING pFormat )
  310. {
  311. if ( !NdrIsLowStack( pStubMsg ) )
  312. {
  313. NdrpPointerBufferSizeInternal( pStubMsg,
  314. pMemory,
  315. pFormat );
  316. return;
  317. }
  318. NdrpEnquePointerBufferSize(
  319. pStubMsg,
  320. pMemory,
  321. pFormat );
  322. }
  323. void RPC_ENTRY
  324. NdrpRangeBufferSize(
  325. PMIDL_STUB_MESSAGE pStubMsg,
  326. uchar * pMemory,
  327. PFORMAT_STRING pFormat )
  328. /*++
  329. Routine Description :
  330. Computes the buffer size needed for a simple type with range on it.
  331. Used for FC_RANGE.
  332. Arguments :
  333. pStubMsg - Pointer to the stub message.
  334. pMemory - Pointer to the structure being sized.
  335. pFormat - Structure's format string description.
  336. Return :
  337. None.
  338. --*/
  339. {
  340. // This routine is needed because the precomputed buf size is missing in some cases.
  341. // So it is cheaper to have the routine than to change code paths elsewhere.
  342. FORMAT_CHARACTER FcType = (FORMAT_CHARACTER)(pFormat[1] & 0x0f);
  343. LENGTH_ALIGN( pStubMsg->BufferLength, SIMPLE_TYPE_ALIGNMENT(FcType) );
  344. pStubMsg->BufferLength += SIMPLE_TYPE_BUFSIZE(FcType);
  345. }
  346. void RPC_ENTRY
  347. NdrSimpleStructBufferSize(
  348. PMIDL_STUB_MESSAGE pStubMsg,
  349. uchar * pMemory,
  350. PFORMAT_STRING pFormat )
  351. /*++
  352. Routine Description :
  353. Computes the buffer size needed for a simple structure.
  354. Used for FC_STRUCT and FC_PSTRUCT.
  355. Arguments :
  356. pStubMsg - Pointer to the stub message.
  357. pMemory - Pointer to the structure being sized.
  358. pFormat - Structure's format string description.
  359. Return :
  360. None.
  361. --*/
  362. {
  363. LENGTH_ALIGN(pStubMsg->BufferLength,pFormat[1]);
  364. // Add size of the structure.
  365. pStubMsg->BufferLength += (ulong) *((ushort *)(pFormat + 2));
  366. //
  367. // Add size of embedded pointers.
  368. //
  369. if ( *pFormat == FC_PSTRUCT )
  370. {
  371. NdrpEmbeddedPointerBufferSize( pStubMsg,
  372. pMemory,
  373. pFormat + 4 );
  374. }
  375. }
  376. void RPC_ENTRY
  377. NdrConformantStructBufferSize(
  378. PMIDL_STUB_MESSAGE pStubMsg,
  379. uchar * pMemory,
  380. PFORMAT_STRING pFormat )
  381. /*++
  382. Routine Description :
  383. Computes the buffer size needed for a conformant structure.
  384. Used for FC_CSTRUCT and FC_CPSTRUCT.
  385. Arguments :
  386. pStubMsg - Pointer to the stub message.
  387. pMemory - Pointer to the structure being sized.
  388. pFormat - Structure's format string description.
  389. Return :
  390. None.
  391. --*/
  392. {
  393. PFORMAT_STRING pFormatArray;
  394. ulong FlatSize;
  395. // set by the embedding complex struct
  396. uchar fIsEmbeddedStructSave = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  397. // accounted for by the outermost embedding complex struct
  398. if ( !fIsEmbeddedStructSave )
  399. {
  400. // Align and add size for conformance count.
  401. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  402. pStubMsg->BufferLength += 4;
  403. }
  404. // Align
  405. LENGTH_ALIGN(pStubMsg->BufferLength, pFormat[1] );
  406. FlatSize = (ulong) *((ushort *)(pFormat + 2));
  407. pStubMsg->BufferLength += FlatSize;
  408. // Increment to the offset to array description.
  409. pFormat += 4;
  410. pFormatArray = pFormat + *((signed short *)pFormat);
  411. //
  412. // Size our array - pass a memory pointer to the conformant array.
  413. //
  414. NdrpConformantArrayBufferSize( pStubMsg,
  415. pMemory + FlatSize,
  416. pFormatArray );
  417. pFormat += 2;
  418. if ( *pFormat == FC_PP )
  419. {
  420. NdrpEmbeddedPointerBufferSize( pStubMsg,
  421. pMemory,
  422. pFormat );
  423. }
  424. // Set the reverse flag to signal that array has been marshaled.
  425. if ( fIsEmbeddedStructSave )
  426. SET_CONF_ARRAY_DONE( pStubMsg->uFlags );
  427. }
  428. void RPC_ENTRY
  429. NdrConformantVaryingStructBufferSize(
  430. PMIDL_STUB_MESSAGE pStubMsg,
  431. uchar * pMemory,
  432. PFORMAT_STRING pFormat )
  433. /*++
  434. Routine Description :
  435. Computes the buffer size needed for a conformant varying structure.
  436. Used for FC_CVSTRUCT.
  437. Arguments :
  438. pStubMsg - Pointer to the stub message.
  439. pMemory - Pointer to the structure being sized.
  440. pFormat - Structure's format string description.
  441. Return :
  442. None.
  443. --*/
  444. {
  445. PPRIVATE_SIZE_ROUTINE pfnSize;
  446. PFORMAT_STRING pFormatArray;
  447. ulong FlatSize;
  448. // set by the outermost embedding complex struct
  449. uchar fIsEmbeddedStructSave = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  450. // accounted for by the outermost embedding complex struct
  451. if ( !fIsEmbeddedStructSave )
  452. {
  453. // Align
  454. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  455. pStubMsg->BufferLength += 4;
  456. }
  457. // Align
  458. LENGTH_ALIGN(pStubMsg->BufferLength, pFormat[1] );
  459. FlatSize = (ulong) *((ushort *)(pFormat + 2));
  460. pStubMsg->BufferLength += FlatSize;
  461. // Increment to the offset to array description.
  462. pFormat += 4;
  463. pFormatArray = pFormat + *((signed short *)pFormat);
  464. switch ( *pFormatArray )
  465. {
  466. case FC_CVARRAY :
  467. pfnSize = NdrpConformantVaryingArrayBufferSize;
  468. break;
  469. default :
  470. pfnSize = NdrpConformantStringBufferSize;
  471. break;
  472. }
  473. (*pfnSize)( pStubMsg,
  474. pMemory + FlatSize,
  475. pFormatArray );
  476. pFormat += 2;
  477. if ( *pFormat == FC_PP )
  478. {
  479. pStubMsg->MaxCount = pStubMsg->ActualCount;
  480. NdrpEmbeddedPointerBufferSize( pStubMsg,
  481. pMemory,
  482. pFormat );
  483. }
  484. // Set the reverse flag to signal that array has been marshaled.
  485. if ( fIsEmbeddedStructSave )
  486. SET_CONF_ARRAY_DONE( pStubMsg->uFlags );
  487. }
  488. #if 0
  489. void RPC_ENTRY
  490. NdrHardStructBufferSize(
  491. PMIDL_STUB_MESSAGE pStubMsg,
  492. uchar * pMemory,
  493. PFORMAT_STRING pFormat )
  494. /*++
  495. Routine Description :
  496. Computes the buffer size needed for a hard structure.
  497. Used for FC_HARD_STRUCT.
  498. Arguments :
  499. pStubMsg - Pointer to the stub message.
  500. pMemory - Pointer to the structure being sized.
  501. pFormat - Structure's format string description.
  502. Return :
  503. None.
  504. --*/
  505. {
  506. LENGTH_ALIGN(pStubMsg->BufferLength,pFormat[1]);
  507. pStubMsg->BufferLength += *((ushort *)&pFormat[10]);
  508. if ( *((short *)&pFormat[14]) )
  509. {
  510. pFormat += 12;
  511. pMemory += *((ushort *)pFormat)++;
  512. pFormat += *((short *)pFormat);
  513. (*pfnSizeRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  514. pMemory,
  515. pFormat );
  516. }
  517. }
  518. #endif // 0
  519. void RPC_ENTRY
  520. NdrComplexStructBufferSize(
  521. PMIDL_STUB_MESSAGE pStubMsg,
  522. uchar * pMemory,
  523. PFORMAT_STRING pFormat )
  524. /*++
  525. Routine Description :
  526. Computes the buffer size needed for a complex structure.
  527. Used for FC_BOGUS_STRUCT.
  528. Arguments :
  529. pStubMsg - Pointer to the stub message.
  530. pMemory - Pointer to the structure being sized.
  531. pFormat - Structure's format string description.
  532. Return :
  533. None.
  534. --*/
  535. {
  536. PFORMAT_STRING pFormatPointers;
  537. PFORMAT_STRING pFormatArray;
  538. PFORMAT_STRING pFormatComplex;
  539. long Alignment;
  540. long Align8Mod;
  541. BOOL fEmbedConfStructContext;
  542. uchar* pMemoryLoop;
  543. PFORMAT_STRING pFormatLoop;
  544. uchar fIsEmbeddedStructSave = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  545. uchar * pMemorySave = pStubMsg->Memory;
  546. //
  547. // If were not ignoring pointees and the the stub message PointerBufferMark field is 0,
  548. // then determine the position in the buffer where pointees will be marshalled.
  549. //
  550. // We have to do this to handle embedded pointers.
  551. //
  552. bool fSetPointerBufferMark = !pStubMsg->IgnoreEmbeddedPointers &&
  553. !pStubMsg->PointerBufferMark;
  554. if ( fSetPointerBufferMark )
  555. {
  556. pStubMsg->IgnoreEmbeddedPointers = TRUE;
  557. ulong BufferLengthSave = pStubMsg->BufferLength;
  558. NdrComplexStructBufferSize( pStubMsg,
  559. pMemory,
  560. pFormat );
  561. // If the size of the flat part is zero and this is the first item to be
  562. // marshalled, add a small offset to the buffer so that we can continue
  563. // to use PointerBufferMark as an is embedded flag.
  564. if ( !pStubMsg->BufferLength)
  565. {
  566. pStubMsg->BufferLength += NDR_MAX_BUFFER_ALIGNMENT;
  567. BufferLengthSave += NDR_MAX_BUFFER_ALIGNMENT;
  568. }
  569. pStubMsg->IgnoreEmbeddedPointers = FALSE;
  570. pStubMsg->PointerBufferMark = (uchar *) UlongToPtr(pStubMsg->BufferLength);
  571. pStubMsg->BufferLength = BufferLengthSave;
  572. }
  573. //
  574. // This is used when computing the count(s) for size_is or length_is
  575. // pointers.
  576. //
  577. pStubMsg->Memory = pMemory;
  578. Alignment = pFormat[1];
  579. //
  580. // This is used for support of structs with doubles passed on an
  581. // i386 stack, and of struct with longs on 16 bit platforms.
  582. //
  583. // A cast to long is what we need.
  584. Align8Mod = 0x7 & PtrToLong( pMemory );
  585. pFormat += 4;
  586. fEmbedConfStructContext = fIsEmbeddedStructSave;
  587. // Get conformant array description.
  588. if ( *((ushort *)pFormat) )
  589. {
  590. pFormatArray = pFormat + *((signed short *)pFormat);
  591. // mark Complex struct embedding Conformant struct case
  592. if ( FixWireRepForDComVerGTE54( pStubMsg ) )
  593. fEmbedConfStructContext = TRUE;
  594. // accounted for by the outermost embedding complex struct
  595. if ( !fIsEmbeddedStructSave )
  596. {
  597. //
  598. // Align and add size of conformance count(s).
  599. //
  600. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  601. pStubMsg->BufferLength += 4 * NdrpArrayDimensions( pStubMsg,
  602. pFormatArray,
  603. FALSE);
  604. }
  605. }
  606. else
  607. pFormatArray = 0;
  608. RESET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  609. pFormat += 2;
  610. // Get pointer layout description.
  611. if ( *((ushort *)pFormat) )
  612. pFormatPointers = pFormat + *((ushort *)pFormat);
  613. else
  614. pFormatPointers = 0;
  615. pFormat += 2;
  616. // save variables for second loop
  617. pMemoryLoop = pMemory;
  618. pFormatLoop = pFormat;
  619. LENGTH_ALIGN(pStubMsg->BufferLength,Alignment);
  620. //
  621. // size the structure member by member.
  622. //
  623. for ( ; *pFormat != FC_END; pFormat++ )
  624. {
  625. switch ( *pFormat )
  626. {
  627. //
  628. // simple types
  629. //
  630. case FC_CHAR :
  631. case FC_BYTE :
  632. case FC_SMALL :
  633. case FC_WCHAR :
  634. case FC_SHORT :
  635. case FC_LONG :
  636. #if defined(__RPC_WIN64__)
  637. case FC_INT3264:
  638. case FC_UINT3264:
  639. #endif
  640. case FC_FLOAT :
  641. case FC_HYPER :
  642. case FC_DOUBLE :
  643. case FC_ENUM16 :
  644. case FC_ENUM32 :
  645. case FC_IGNORE :
  646. LENGTH_ALIGN( pStubMsg->BufferLength,
  647. SIMPLE_TYPE_ALIGNMENT(*pFormat) );
  648. pStubMsg->BufferLength += SIMPLE_TYPE_BUFSIZE(*pFormat);
  649. pMemory += SIMPLE_TYPE_MEMSIZE(*pFormat);
  650. break;
  651. case FC_POINTER :
  652. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  653. pStubMsg->BufferLength += PTR_WIRE_SIZE;
  654. if ( !pStubMsg->IgnoreEmbeddedPointers )
  655. {
  656. POINTER_BUFFERLENGTH_SWAP_CONTEXT SwapContext( pStubMsg );
  657. NdrpPointerBufferSize( pStubMsg,
  658. *((uchar **)pMemory),
  659. pFormatPointers );
  660. }
  661. pFormatPointers += 4;
  662. pMemory += PTR_MEM_SIZE;
  663. break;
  664. //
  665. // Embedded complex types.
  666. //
  667. case FC_EMBEDDED_COMPLEX :
  668. // Add padding.
  669. pMemory += pFormat[1];
  670. pFormat += 2;
  671. // Get the type's description.
  672. pFormatComplex = pFormat + *((signed short UNALIGNED *)pFormat);
  673. if ( FC_IP == *pFormatComplex )
  674. {
  675. // Treat embedded interface pointers the same as regular pointers.
  676. LENGTH_ALIGN( pStubMsg->BufferLength, 0x3 );
  677. pStubMsg->BufferLength += PTR_WIRE_SIZE;
  678. if ( !pStubMsg->IgnoreEmbeddedPointers )
  679. {
  680. POINTER_BUFFERLENGTH_SWAP_CONTEXT SwapContext( pStubMsg );
  681. NdrpPointerBufferSize( pStubMsg,
  682. *((uchar **)pMemory),
  683. pFormatComplex);
  684. }
  685. pMemory += PTR_MEM_SIZE;
  686. pFormat++;
  687. break;
  688. }
  689. // Needed for embedded conf structs
  690. //
  691. if ( fEmbedConfStructContext )
  692. SET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  693. (*pfnSizeRoutines[ROUTINE_INDEX(*pFormatComplex)])
  694. ( pStubMsg,
  695. pMemory,
  696. pFormatComplex );
  697. pMemory = NdrpMemoryIncrement( pStubMsg,
  698. pMemory,
  699. pFormatComplex );
  700. RESET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  701. //
  702. // Increment the main format string one byte. The loop
  703. // will increment it one more byte past the offset field.
  704. //
  705. pFormat++;
  706. break;
  707. case FC_ALIGNM2 :
  708. ALIGN( pMemory, 0x1 );
  709. break;
  710. case FC_ALIGNM4 :
  711. ALIGN( pMemory, 0x3 );
  712. break;
  713. case FC_ALIGNM8 :
  714. //
  715. // We have to play some tricks for the i386 to handle the case
  716. // when an 8 byte aligned structure is passed by value. The
  717. // alignment of the struct on the stack is not guaranteed to be
  718. // on an 8 byte boundary.
  719. //
  720. pMemory -= Align8Mod;
  721. ALIGN( pMemory, 0x7 );
  722. pMemory += Align8Mod;
  723. break;
  724. case FC_STRUCTPAD1 :
  725. case FC_STRUCTPAD2 :
  726. case FC_STRUCTPAD3 :
  727. case FC_STRUCTPAD4 :
  728. case FC_STRUCTPAD5 :
  729. case FC_STRUCTPAD6 :
  730. case FC_STRUCTPAD7 :
  731. pMemory += (*pFormat - FC_STRUCTPAD1) + 1;
  732. break;
  733. case FC_STRUCTPADN :
  734. // FC_STRUCTPADN 0 <unsigned short>
  735. pMemory += *(((unsigned short *)pFormat) + 1);
  736. pFormat += 3;
  737. break;
  738. case FC_PAD :
  739. break;
  740. //
  741. // Done with layout.
  742. //
  743. case FC_END :
  744. break;
  745. default :
  746. NDR_ASSERT(0,"NdrComplexStructBufferSize : bad format char");
  747. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  748. return;
  749. } // switch
  750. } // for
  751. //
  752. // Size any conformant array.
  753. //
  754. // accounted for by the outermost embedding complex struct
  755. // .. but not when embedded and not when array done by an embeded conf struct.
  756. if ( pFormatArray && !fIsEmbeddedStructSave &&
  757. ! IS_CONF_ARRAY_DONE( pStubMsg->uFlags ) )
  758. {
  759. PPRIVATE_SIZE_ROUTINE pfnSize;
  760. switch ( *pFormatArray )
  761. {
  762. case FC_CARRAY :
  763. pfnSize = NdrpConformantArrayBufferSize;
  764. break;
  765. case FC_CVARRAY :
  766. pfnSize = NdrpConformantVaryingArrayBufferSize;
  767. break;
  768. case FC_BOGUS_ARRAY :
  769. pfnSize = NdrpComplexArrayBufferSize;
  770. break;
  771. // case FC_C_WSTRING :
  772. // case FC_C_CSTRING :
  773. // case FC_C_BSTRING :
  774. // case FC_C_SSTRING :
  775. default :
  776. pfnSize = NdrpConformantStringBufferSize;
  777. break;
  778. }
  779. (*pfnSize)( pStubMsg,
  780. pMemory,
  781. pFormatArray );
  782. }
  783. if ( fIsEmbeddedStructSave )
  784. SET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  785. else
  786. RESET_CONF_ARRAY_DONE( pStubMsg->uFlags );
  787. pStubMsg->Memory = pMemorySave;
  788. if ( fSetPointerBufferMark )
  789. {
  790. pStubMsg->BufferLength = PtrToUlong(pStubMsg->PointerBufferMark);
  791. pStubMsg->PointerBufferMark = NULL;
  792. }
  793. }
  794. void RPC_ENTRY
  795. NdrFixedArrayBufferSize(
  796. PMIDL_STUB_MESSAGE pStubMsg,
  797. uchar * pMemory,
  798. PFORMAT_STRING pFormat )
  799. /*++
  800. Routine Description :
  801. Computes the buffer size needed for a fixed array of any number of
  802. dimensions.
  803. Used for FC_SMFARRAY and FC_LGFARRAY.
  804. Arguments :
  805. pStubMsg - Pointer to the stub message.
  806. pMemory - Pointer to the array being sized.
  807. pFormat - Array's format string description.
  808. Return :
  809. None.
  810. --*/
  811. {
  812. LENGTH_ALIGN(pStubMsg->BufferLength,pFormat[1]);
  813. if ( *pFormat == FC_SMFARRAY )
  814. {
  815. pFormat += 2;
  816. pStubMsg->BufferLength += *((ushort *&)pFormat)++;
  817. }
  818. else
  819. {
  820. pFormat += 2;
  821. pStubMsg->BufferLength += *((ulong UNALIGNED *&)pFormat)++;
  822. }
  823. if ( *pFormat == FC_PP )
  824. {
  825. NdrpEmbeddedPointerBufferSize( pStubMsg,
  826. pMemory,
  827. pFormat );
  828. }
  829. }
  830. void RPC_ENTRY
  831. NdrConformantArrayBufferSize(
  832. PMIDL_STUB_MESSAGE pStubMsg,
  833. uchar * pMemory,
  834. PFORMAT_STRING pFormat )
  835. /*++
  836. Routine Description :
  837. Computes the buffer size needed for a top level one dimensional conformant
  838. array.
  839. Used for FC_CARRAY.
  840. Arguments :
  841. pStubMsg - Pointer to the stub message.
  842. pMemory - Pointer to the array being sized.
  843. pFormat - Array's format string description.
  844. Return :
  845. None.
  846. --*/
  847. {
  848. //
  849. // Align and add size for conformance count.
  850. //
  851. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  852. pStubMsg->BufferLength += 4;
  853. NdrpConformantArrayBufferSize( pStubMsg,
  854. pMemory,
  855. pFormat );
  856. }
  857. void
  858. NdrpConformantArrayBufferSize(
  859. PMIDL_STUB_MESSAGE pStubMsg,
  860. uchar * pMemory,
  861. PFORMAT_STRING pFormat )
  862. /*++
  863. Routine Description :
  864. Private routine for computing the buffer size needed for a one dimensional
  865. conformant array. This is the entry point for unmarshalling an embedded
  866. conformant array.
  867. Used for FC_CARRAY.
  868. Arguments :
  869. pStubMsg - Pointer to the stub message.
  870. pMemory - Pointer to the array being sized.
  871. pFormat - Array's format string description.
  872. Return :
  873. None.
  874. --*/
  875. {
  876. ulong ConformanceCount;
  877. ConformanceCount = (ulong) NdrpComputeConformance( pStubMsg,
  878. pMemory,
  879. pFormat );
  880. if ( ((long)ConformanceCount) < 0 )
  881. RpcRaiseException( RPC_X_INVALID_BOUND );
  882. if ( ! ConformanceCount )
  883. return;
  884. LENGTH_ALIGN(pStubMsg->BufferLength,pFormat[1]);
  885. pFormat += 2;
  886. // Add array size.
  887. pStubMsg->BufferLength += *((ushort *)pFormat) * ConformanceCount;
  888. pFormat += 6;
  889. CORRELATION_DESC_INCREMENT( pFormat );
  890. if ( *pFormat == FC_PP )
  891. {
  892. NdrpEmbeddedPointerBufferSize( pStubMsg,
  893. pMemory,
  894. pFormat );
  895. }
  896. }
  897. void RPC_ENTRY
  898. NdrConformantVaryingArrayBufferSize(
  899. PMIDL_STUB_MESSAGE pStubMsg,
  900. uchar * pMemory,
  901. PFORMAT_STRING pFormat )
  902. /*++
  903. Routine Description :
  904. Computes the buffer size needed for a top level one dimensional conformant
  905. varying array.
  906. Used for FC_CVARRAY.
  907. Arguments :
  908. pStubMsg - Pointer to the stub message.
  909. pMemory - Pointer to the array being sized.
  910. pFormat - Array's format string description.
  911. Return :
  912. None.
  913. --*/
  914. {
  915. //
  916. // Align and add size for conformance count.
  917. //
  918. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  919. pStubMsg->BufferLength += 4;
  920. NdrpConformantVaryingArrayBufferSize( pStubMsg,
  921. pMemory,
  922. pFormat );
  923. }
  924. void
  925. NdrpConformantVaryingArrayBufferSize(
  926. PMIDL_STUB_MESSAGE pStubMsg,
  927. uchar * pMemory,
  928. PFORMAT_STRING pFormat )
  929. /*++
  930. Routine Description :
  931. Private routine for computing the buffer size needed for a one dimensional
  932. conformant varying array. This is the entry point for buffer sizing an
  933. embedded conformant varying array.
  934. Used for FC_CVARRAY.
  935. Arguments :
  936. pStubMsg - Pointer to the stub message.
  937. pMemory - Pointer to the array being sized.
  938. pFormat - Array's format string description.
  939. Return :
  940. None.
  941. --*/
  942. {
  943. ulong ConformanceCount;
  944. //
  945. // Align and add size for offset and actual count.
  946. //
  947. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  948. pStubMsg->BufferLength += 8;
  949. NdrpComputeVariance( pStubMsg,
  950. pMemory,
  951. pFormat );
  952. // Check if the bounds are valid
  953. ConformanceCount = (ulong) NdrpComputeConformance( pStubMsg,
  954. pMemory,
  955. pFormat );
  956. if ( ( ((long)ConformanceCount) < 0 ) ||
  957. ( ((long)pStubMsg->ActualCount) < 0 ) ||
  958. ( ((long)pStubMsg->Offset) < 0 ) ||
  959. ( (pStubMsg->Offset + pStubMsg->ActualCount) > ConformanceCount ) )
  960. RpcRaiseException( RPC_X_INVALID_BOUND );
  961. if ( ! pStubMsg->ActualCount )
  962. return;
  963. LENGTH_ALIGN(pStubMsg->BufferLength, pFormat[1]);
  964. pFormat += 2;
  965. // Add array size.
  966. pStubMsg->BufferLength += *((ushort *)pFormat) * pStubMsg->ActualCount;
  967. pFormat += 10;
  968. CORRELATION_DESC_INCREMENT( pFormat );
  969. CORRELATION_DESC_INCREMENT( pFormat );
  970. if ( *pFormat == FC_PP )
  971. {
  972. //
  973. // MaxCount must contain the number of shipped elements in the array
  974. // before sizing embedded pointers.
  975. //
  976. pStubMsg->MaxCount = pStubMsg->ActualCount;
  977. NdrpEmbeddedPointerBufferSize( pStubMsg,
  978. pMemory,
  979. pFormat );
  980. }
  981. }
  982. void RPC_ENTRY
  983. NdrVaryingArrayBufferSize(
  984. PMIDL_STUB_MESSAGE pStubMsg,
  985. uchar * pMemory,
  986. PFORMAT_STRING pFormat )
  987. /*++
  988. Routine Description :
  989. Computes the buffer size needed for a top level or embedded one
  990. dimensional varying array.
  991. Used for FC_SMVARRAY and FC_LGVARRAY.
  992. Arguments :
  993. pStubMsg - Pointer to the stub message.
  994. pMemory - Pointer to the array being sized.
  995. pFormat - Array's format string description.
  996. Return :
  997. None.
  998. Arguments :
  999. pMemory - pointer to the parameter to size
  1000. pFormat - pointer to the format string description of the parameter
  1001. --*/
  1002. {
  1003. ulong Elements;
  1004. ulong ElementSize;
  1005. //
  1006. // Align and add size for offset and actual count.
  1007. //
  1008. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  1009. pStubMsg->BufferLength += 8;
  1010. NdrpComputeVariance( pStubMsg,
  1011. pMemory,
  1012. pFormat );
  1013. // Check if the bounds are valid
  1014. Elements =
  1015. (*pFormat == FC_SMVARRAY) ?
  1016. *((ushort *)(pFormat + 4)) : *((ulong UNALIGNED *)(pFormat + 6));
  1017. if ( ( ((long)pStubMsg->ActualCount) < 0 ) ||
  1018. ( ((long)pStubMsg->Offset) < 0 ) ||
  1019. ( (pStubMsg->Offset + pStubMsg->ActualCount) > Elements ) )
  1020. RpcRaiseException( RPC_X_INVALID_BOUND );
  1021. if ( ! pStubMsg->ActualCount )
  1022. return;
  1023. LENGTH_ALIGN(pStubMsg->BufferLength, pFormat[1]);
  1024. if (*pFormat == FC_SMVARRAY)
  1025. {
  1026. ElementSize = *((ushort *)(pFormat + 6));
  1027. pFormat += 12;
  1028. }
  1029. else
  1030. {
  1031. ElementSize = *((ushort *)(pFormat + 10));
  1032. pFormat += 16;
  1033. }
  1034. CORRELATION_DESC_INCREMENT( pFormat );
  1035. pStubMsg->BufferLength += ElementSize * pStubMsg->ActualCount;
  1036. if ( *pFormat == FC_PP )
  1037. {
  1038. //
  1039. // MaxCount must contain the number of shipped elements in the array
  1040. // before sizing embedded pointers.
  1041. //
  1042. pStubMsg->MaxCount = pStubMsg->ActualCount;
  1043. NdrpEmbeddedPointerBufferSize( pStubMsg,
  1044. pMemory,
  1045. pFormat );
  1046. }
  1047. }
  1048. void RPC_ENTRY
  1049. NdrComplexArrayBufferSize(
  1050. PMIDL_STUB_MESSAGE pStubMsg,
  1051. uchar * pMemory,
  1052. PFORMAT_STRING pFormat )
  1053. /*++
  1054. Routine Description :
  1055. Computes the buffer size needed for a top level complex array.
  1056. Used for FC_BOGUS_STRUCT.
  1057. Arguments :
  1058. pStubMsg - Pointer to the stub message.
  1059. pMemory - Pointer to the array being sized.
  1060. pFormat - Array's format string description.
  1061. Return :
  1062. None.
  1063. Note.
  1064. Array of ref pointers does not have wire representation for the pointers
  1065. themselves, regardless whether array is top level or embedded in a struct.
  1066. --*/
  1067. {
  1068. bool fSetPointerBufferMark = !pStubMsg->IgnoreEmbeddedPointers &&
  1069. (! pStubMsg->PointerBufferMark );
  1070. if ( fSetPointerBufferMark )
  1071. {
  1072. //
  1073. // Save the current conformance and variance fields. The sizing
  1074. // routine can overwrite them.
  1075. //
  1076. ULONG_PTR MaxCountSave = pStubMsg->MaxCount;
  1077. ulong OffsetSave = pStubMsg->Offset;
  1078. ulong ActualCountSave = pStubMsg->ActualCount;
  1079. ulong BufferLengthSave = pStubMsg->BufferLength;
  1080. pStubMsg->IgnoreEmbeddedPointers = TRUE;
  1081. NdrComplexArrayBufferSize( pStubMsg,
  1082. pMemory,
  1083. pFormat );
  1084. // If the size of the flat part is zero and this is the first item to be
  1085. // marshalled, add a small offset to the buffer so that we can continue
  1086. // to use PointerBufferMark as an is embedded flag.
  1087. if ( !pStubMsg->BufferLength)
  1088. {
  1089. pStubMsg->BufferLength += NDR_MAX_BUFFER_ALIGNMENT;
  1090. BufferLengthSave += NDR_MAX_BUFFER_ALIGNMENT;
  1091. }
  1092. pStubMsg->PointerBufferMark = (uchar *) UlongToPtr(pStubMsg->BufferLength);
  1093. pStubMsg->IgnoreEmbeddedPointers = FALSE;
  1094. // Restore conformance and variance fields.
  1095. pStubMsg->MaxCount = MaxCountSave;
  1096. pStubMsg->Offset = OffsetSave;
  1097. pStubMsg->ActualCount = ActualCountSave;
  1098. pStubMsg->BufferLength = BufferLengthSave;
  1099. }
  1100. //
  1101. // Add in conformance sizes if we are the outermost dimension.
  1102. //
  1103. if ( pStubMsg->pArrayInfo == 0 )
  1104. {
  1105. //
  1106. // Align and add size for any conformance count(s).
  1107. //
  1108. if ( *((long UNALIGNED *)(pFormat + 4)) != 0xffffffff )
  1109. {
  1110. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  1111. pStubMsg->BufferLength += NdrpArrayDimensions( pStubMsg, pFormat, FALSE ) * 4;
  1112. }
  1113. }
  1114. NdrpComplexArrayBufferSize( pStubMsg,
  1115. pMemory,
  1116. pFormat );
  1117. if ( fSetPointerBufferMark )
  1118. {
  1119. pStubMsg->BufferLength = PtrToUlong(pStubMsg->PointerBufferMark);
  1120. pStubMsg->PointerBufferMark = NULL;
  1121. }
  1122. }
  1123. void
  1124. NdrpComplexArrayBufferSize(
  1125. PMIDL_STUB_MESSAGE pStubMsg,
  1126. uchar * pMemory,
  1127. PFORMAT_STRING pFormat )
  1128. /*++
  1129. Routine Description :
  1130. Private routine for determing the buffer size of a complex array. This
  1131. is the entry point for buffer sizing an embedded complex array.
  1132. Arguments :
  1133. pStubMsg - Pointer to the stub message.
  1134. pMemory - Pointer to the array being sized.
  1135. pFormat - Array's format string description.
  1136. Return :
  1137. None.
  1138. --*/
  1139. {
  1140. ARRAY_INFO ArrayInfo;
  1141. PARRAY_INFO pArrayInfo;
  1142. PSIZE_ROUTINE pfnSize;
  1143. PFORMAT_STRING pFormatStart;
  1144. ulong Elements;
  1145. ulong Offset, Count;
  1146. ulong MemoryElementSize;
  1147. long Dimension;
  1148. uchar Alignment;
  1149. //
  1150. // Lots of setup if we are the outer dimension.
  1151. //
  1152. if ( ! pStubMsg->pArrayInfo )
  1153. {
  1154. pStubMsg->pArrayInfo = &ArrayInfo;
  1155. ArrayInfo.Dimension = 0;
  1156. //
  1157. // Set this to 0 so that NdrpMemoryIncrement will know to call
  1158. // NdrpComputeConformance when computing our size.
  1159. //
  1160. ArrayInfo.BufferConformanceMark = 0;
  1161. ArrayInfo.MaxCountArray = (unsigned long *) pStubMsg->MaxCount;
  1162. ArrayInfo.OffsetArray = (ulong *) UlongToPtr( pStubMsg->Offset );
  1163. ArrayInfo.ActualCountArray = (ulong *) UlongToPtr( pStubMsg->ActualCount );
  1164. }
  1165. pFormatStart = pFormat;
  1166. pArrayInfo = pStubMsg->pArrayInfo;
  1167. Dimension = pArrayInfo->Dimension;
  1168. // Get the array alignment.
  1169. Alignment = pFormat[1];
  1170. pFormat += 2;
  1171. // Get the number of elements (0 if conformance present).
  1172. Elements = *((ushort *&)pFormat)++;
  1173. //
  1174. // Check for conformance description.
  1175. //
  1176. if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
  1177. {
  1178. Elements = (ulong) NdrpComputeConformance( pStubMsg,
  1179. pMemory,
  1180. pFormatStart );
  1181. }
  1182. pFormat += 4;
  1183. CORRELATION_DESC_INCREMENT( pFormat );
  1184. //
  1185. // Check for variance description.
  1186. //
  1187. if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
  1188. {
  1189. NdrpComputeVariance( pStubMsg,
  1190. pMemory,
  1191. pFormatStart );
  1192. Offset = pStubMsg->Offset;
  1193. Count = pStubMsg->ActualCount;
  1194. if ( Dimension == 0 )
  1195. {
  1196. //
  1197. // Align and add in size of variance count(s).
  1198. //
  1199. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  1200. pStubMsg->BufferLength +=
  1201. NdrpArrayDimensions( pStubMsg, pFormatStart, TRUE ) * 8;
  1202. }
  1203. }
  1204. else
  1205. {
  1206. Offset = 0;
  1207. Count = Elements;
  1208. }
  1209. pFormat += 4;
  1210. CORRELATION_DESC_INCREMENT( pFormat );
  1211. // Check bounds
  1212. if ( ( ((long)Elements) < 0 ) ||
  1213. ( ((long)Count) < 0 ) ||
  1214. ( ((long)Offset) < 0 ) ||
  1215. ( (Offset + Count) > Elements ) )
  1216. RpcRaiseException( RPC_X_INVALID_BOUND );
  1217. if ( Count )
  1218. {
  1219. LENGTH_ALIGN( pStubMsg->BufferLength, Alignment );
  1220. if ( *pFormat == FC_EMBEDDED_COMPLEX )
  1221. {
  1222. ulong CountSave;
  1223. uchar* pMemorySave;
  1224. PFORMAT_STRING pFormatSave;
  1225. pFormat += 2;
  1226. pFormat += *((signed short *)pFormat);
  1227. if ( FC_IP == *pFormat )
  1228. goto PointerSizing;
  1229. pfnSize = pfnSizeRoutines[ROUTINE_INDEX(*pFormat)];
  1230. pArrayInfo->Dimension = Dimension + 1;
  1231. MemoryElementSize = (ulong) ( NdrpMemoryIncrement( pStubMsg,
  1232. pMemory,
  1233. pFormat ) - pMemory );
  1234. if ( ! IS_ARRAY_OR_STRING(*pFormat) )
  1235. pStubMsg->pArrayInfo = 0;
  1236. //
  1237. // If there is variance then increment the memory pointer to the first
  1238. // element actually being sized.
  1239. //
  1240. if ( Offset )
  1241. pMemory += Offset * MemoryElementSize;
  1242. pFormatSave = pFormat;
  1243. pMemorySave = pMemory;
  1244. CountSave = Count;
  1245. for ( ; Count--; )
  1246. {
  1247. // Keep track of multidimensional array dimension.
  1248. if ( IS_ARRAY_OR_STRING(*pFormat) )
  1249. pArrayInfo->Dimension = Dimension + 1;
  1250. (*pfnSize)( pStubMsg,
  1251. pMemory,
  1252. pFormat );
  1253. pMemory += MemoryElementSize;
  1254. }
  1255. pMemory += MemoryElementSize;
  1256. }
  1257. else if ( *pFormat == FC_UP || *pFormat == FC_FP || *pFormat == FC_OP || *pFormat == FC_RP ||
  1258. *pFormat == FC_IP )
  1259. {
  1260. PointerSizing:
  1261. //
  1262. // Shallow size the array
  1263. //
  1264. if ( *pFormat != FC_RP )
  1265. {
  1266. pStubMsg->BufferLength += Count * PTR_WIRE_SIZE;
  1267. }
  1268. //
  1269. // If there is variance then increment the memory pointer to the first
  1270. // element actually being sized.
  1271. //
  1272. if ( Offset )
  1273. pMemory += Offset * PTR_MEM_SIZE;
  1274. //
  1275. // size the pointees
  1276. //
  1277. if ( !pStubMsg->IgnoreEmbeddedPointers )
  1278. {
  1279. bool UseBrokenInterfacePointerRep =
  1280. (FC_IP == *pFormat) && !FixWireRepForDComVerGTE54( pStubMsg );
  1281. // If this is the broken interface pointer format, make sure we
  1282. // have enough space for both the pointer and pointee where
  1283. // the pointer should have been.
  1284. if ( UseBrokenInterfacePointerRep )
  1285. SET_BROKEN_INTERFACE_POINTER( pStubMsg->uFlags );
  1286. // Need this in case we have a variant offset.
  1287. pStubMsg->pArrayInfo = 0;
  1288. // Switch to the pointee buffer.
  1289. POINTER_BUFFERLENGTH_SWAP_CONTEXT SwapContext( pStubMsg );
  1290. for ( ; Count--; )
  1291. {
  1292. NdrpPointerBufferSize(
  1293. pStubMsg,
  1294. *((uchar **&)pMemory)++,
  1295. pFormat );
  1296. }
  1297. if ( UseBrokenInterfacePointerRep )
  1298. RESET_BROKEN_INTERFACE_POINTER( pStubMsg->uFlags );
  1299. }
  1300. }
  1301. else if (*pFormat == FC_RANGE )
  1302. {
  1303. pStubMsg->BufferLength += Count * SIMPLE_TYPE_BUFSIZE( pFormat[1] );
  1304. }
  1305. else
  1306. {
  1307. NDR_ASSERT( IS_SIMPLE_TYPE(*pFormat), "NdrpComplexArrayBufferSize : bad format char" );
  1308. pStubMsg->BufferLength += Count * SIMPLE_TYPE_BUFSIZE(*pFormat);
  1309. }
  1310. }
  1311. // pArrayInfo must be zero when not valid.
  1312. pStubMsg->pArrayInfo = (Dimension == 0) ? 0 : pArrayInfo;
  1313. }
  1314. void RPC_ENTRY
  1315. NdrNonConformantStringBufferSize(
  1316. PMIDL_STUB_MESSAGE pStubMsg,
  1317. uchar * pMemory,
  1318. PFORMAT_STRING pFormat )
  1319. /*++
  1320. Routine Description :
  1321. Computes the buffer size needed for a non conformant string.
  1322. Used for FC_CSTRING, FC_WSTRING, FC_SSTRING, and FC_BSTRING (NT Beta2
  1323. compatability only).
  1324. Arguments :
  1325. pStubMsg - Pointer to the stub message.
  1326. pMemory - Pointer to the array being sized.
  1327. pFormat - Array's format string description.
  1328. Return :
  1329. None.
  1330. --*/
  1331. {
  1332. long MaxSize;
  1333. long Length;
  1334. // Align and add size for variance counts.
  1335. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  1336. pStubMsg->BufferLength += 8;
  1337. switch ( *pFormat )
  1338. {
  1339. case FC_CSTRING :
  1340. case FC_BSTRING :
  1341. Length = strlen((char*)pMemory) + 1;
  1342. break;
  1343. case FC_WSTRING :
  1344. Length = (wcslen((wchar_t *)pMemory) + 1) * sizeof(wchar_t);
  1345. break;
  1346. case FC_SSTRING :
  1347. Length = NdrpStringStructLen( pMemory, pFormat[1] ) + 1;
  1348. Length *= pFormat[1];
  1349. break;
  1350. default :
  1351. NDR_ASSERT(0,"NdrNonConformantStringBufferSize : Bad format type");
  1352. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  1353. return;
  1354. }
  1355. // Check bounds
  1356. MaxSize = *((ushort *)(pFormat + 2));
  1357. switch ( *pFormat )
  1358. {
  1359. case FC_WSTRING :
  1360. MaxSize *= sizeof(wchar_t);
  1361. break;
  1362. case FC_SSTRING :
  1363. MaxSize *= pFormat[1];
  1364. break;
  1365. default :
  1366. break;
  1367. }
  1368. if ( Length > MaxSize )
  1369. RpcRaiseException(RPC_X_INVALID_BOUND);
  1370. pStubMsg->BufferLength += Length;
  1371. }
  1372. void RPC_ENTRY
  1373. NdrConformantStringBufferSize(
  1374. PMIDL_STUB_MESSAGE pStubMsg,
  1375. uchar * pMemory,
  1376. PFORMAT_STRING pFormat )
  1377. /*++
  1378. Routine Description :
  1379. Computes the buffer size needed for a top level conformant string.
  1380. Used for FC_C_CSTRING, FC_C_WSTRING, FC_C_SSTRING, and FC_C_BSTRING
  1381. (NT Beta2 compatability only).
  1382. Arguments :
  1383. pStubMsg - Pointer to the stub message.
  1384. pMemory - Pointer to the array being sized.
  1385. pFormat - Array's format string description.
  1386. Return :
  1387. None.
  1388. --*/
  1389. {
  1390. //
  1391. // Add in size for conformance marshalling only if this string is not
  1392. // in a multidimensional array.
  1393. //
  1394. if ( pStubMsg->pArrayInfo == 0 )
  1395. {
  1396. // Align and add size for conformance count.
  1397. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  1398. pStubMsg->BufferLength += 4;
  1399. }
  1400. NdrpConformantStringBufferSize( pStubMsg,
  1401. pMemory,
  1402. pFormat );
  1403. }
  1404. void
  1405. NdrpConformantStringBufferSize(
  1406. PMIDL_STUB_MESSAGE pStubMsg,
  1407. uchar * pMemory,
  1408. PFORMAT_STRING pFormat )
  1409. /*++
  1410. Routine Description :
  1411. Private routine for computing the buffer size needed for a conformant
  1412. string. This is the entry point for an embedded conformant string.
  1413. Used for FC_C_CSTRING, FC_C_WSTRING, FC_C_SSTRING, and FC_C_BSTRING
  1414. (NT Beta2 compatability only).
  1415. Arguments :
  1416. pStubMsg - Pointer to the stub message.
  1417. pMemory - Pointer to the array being sized.
  1418. pFormat - Array's format string description.
  1419. Return :
  1420. None.
  1421. --*/
  1422. {
  1423. long MaxSize;
  1424. long Length;
  1425. // Align and add size for variance.
  1426. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  1427. pStubMsg->BufferLength += 8;
  1428. switch ( *pFormat )
  1429. {
  1430. case FC_C_CSTRING :
  1431. case FC_C_BSTRING :
  1432. Length = strlen((char*)pMemory) + 1;
  1433. break;
  1434. case FC_C_WSTRING :
  1435. Length = (wcslen((wchar_t *)pMemory) + 1) * sizeof(wchar_t);
  1436. break;
  1437. case FC_C_SSTRING :
  1438. Length = NdrpStringStructLen( pMemory, pFormat[1] ) + 1;
  1439. Length *= pFormat[1];
  1440. break;
  1441. default :
  1442. NDR_ASSERT(0,"NdrpConformantStringBufferSize : Bad format type");
  1443. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  1444. return;
  1445. }
  1446. //
  1447. // Do bounds checking.
  1448. //
  1449. if ( ((*pFormat != FC_C_SSTRING) && (pFormat[1] == FC_STRING_SIZED)) ||
  1450. ((*pFormat == FC_C_SSTRING) && (pFormat[2] == FC_STRING_SIZED)) )
  1451. {
  1452. MaxSize = (ulong) NdrpComputeConformance( pStubMsg,
  1453. pMemory,
  1454. pFormat );
  1455. switch ( *pFormat )
  1456. {
  1457. case FC_C_WSTRING :
  1458. MaxSize *= sizeof(wchar_t);
  1459. break;
  1460. case FC_C_SSTRING :
  1461. MaxSize *= pFormat[1];
  1462. break;
  1463. default :
  1464. break;
  1465. }
  1466. if ( (MaxSize < 0) || (Length > MaxSize) )
  1467. RpcRaiseException(RPC_X_INVALID_BOUND);
  1468. }
  1469. pStubMsg->BufferLength += Length;
  1470. }
  1471. void RPC_ENTRY
  1472. NdrEncapsulatedUnionBufferSize(
  1473. PMIDL_STUB_MESSAGE pStubMsg,
  1474. uchar * pMemory,
  1475. PFORMAT_STRING pFormat )
  1476. /*++
  1477. Routine Description :
  1478. Computes the buffer size needed for an encapsulated union.
  1479. Used for FC_ENCAPSULATED_UNION.
  1480. Arguments :
  1481. pStubMsg - Pointer to the stub message.
  1482. pMemory - Pointer to the union being sized.
  1483. pFormat - Union's format string description.
  1484. Return :
  1485. None.
  1486. --*/
  1487. {
  1488. long SwitchIs;
  1489. uchar SwitchType;
  1490. NO_CORRELATION;
  1491. SwitchType = LOW_NIBBLE(pFormat[1]);
  1492. switch ( SwitchType )
  1493. {
  1494. case FC_SMALL :
  1495. case FC_CHAR :
  1496. SwitchIs = (long) *((char *)pMemory);
  1497. break;
  1498. case FC_USMALL :
  1499. SwitchIs = (long) *((uchar *)pMemory);
  1500. break;
  1501. case FC_ENUM16 :
  1502. case FC_SHORT :
  1503. SwitchIs = (long) *((short *)pMemory);
  1504. break;
  1505. case FC_USHORT :
  1506. case FC_WCHAR :
  1507. SwitchIs = (long) *((ushort *)pMemory);
  1508. break;
  1509. case FC_LONG :
  1510. case FC_ULONG :
  1511. case FC_ENUM32 :
  1512. // FC_INT3264 is mapped to FC_LONG.
  1513. SwitchIs = *((long *)pMemory);
  1514. break;
  1515. default :
  1516. NDR_ASSERT(0,"NdrEncapsulatedBufferSize : bad switch type");
  1517. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  1518. return;
  1519. }
  1520. // Increment memory pointer to the union.
  1521. pMemory += HIGH_NIBBLE(pFormat[1]);
  1522. NdrpUnionBufferSize( pStubMsg,
  1523. pMemory,
  1524. pFormat + 2,
  1525. SwitchIs,
  1526. SwitchType );
  1527. }
  1528. void RPC_ENTRY
  1529. NdrNonEncapsulatedUnionBufferSize(
  1530. PMIDL_STUB_MESSAGE pStubMsg,
  1531. uchar * pMemory,
  1532. PFORMAT_STRING pFormat )
  1533. /*++
  1534. Routine Description :
  1535. Computes the buffer size needed for a non encapsulated union.
  1536. Used for FC_NON_ENCAPSULATED_UNION.
  1537. Arguments :
  1538. pStubMsg - Pointer to the stub message.
  1539. pMemory - Pointer to the union being sized.
  1540. pFormat - Union's format string description.
  1541. Return :
  1542. None.
  1543. --*/
  1544. {
  1545. long SwitchIs;
  1546. uchar SwitchType;
  1547. SwitchType = pFormat[1];
  1548. SwitchIs = (ulong) NdrpComputeSwitchIs( pStubMsg,
  1549. pMemory,
  1550. pFormat );
  1551. //
  1552. // Set the format string to the memory size and arm description.
  1553. //
  1554. pFormat += 6;
  1555. CORRELATION_DESC_INCREMENT( pFormat );
  1556. pFormat += *((signed short *)pFormat);
  1557. NdrpUnionBufferSize( pStubMsg,
  1558. pMemory,
  1559. pFormat,
  1560. SwitchIs,
  1561. SwitchType );
  1562. }
  1563. void
  1564. NdrpUnionBufferSize(
  1565. PMIDL_STUB_MESSAGE pStubMsg,
  1566. uchar * pMemory,
  1567. PFORMAT_STRING pFormat,
  1568. long SwitchIs,
  1569. uchar SwitchType )
  1570. /*++
  1571. Routine Description :
  1572. Private routine for computing the buffer size needed for a union. This
  1573. routine is used for sizing both encapsulated and non-encapsulated unions.
  1574. Arguments :
  1575. pStubMsg - Pointer to the stub message.
  1576. pMemory - Pointer to the union being sized.
  1577. pFormat - Union's format string description.
  1578. SwitchIs - The union's switch is.
  1579. SwitchType - The union's switch type.
  1580. Return :
  1581. None.
  1582. --*/
  1583. {
  1584. long Arms;
  1585. long Alignment;
  1586. //
  1587. // Size the switch_is.
  1588. //
  1589. LENGTH_ALIGN(pStubMsg->BufferLength,SIMPLE_TYPE_ALIGNMENT(SwitchType));
  1590. pStubMsg->BufferLength += SIMPLE_TYPE_BUFSIZE(SwitchType);
  1591. // Skip the memory size field.
  1592. pFormat += 2;
  1593. //
  1594. // Get the union alignment (0 if this is a DCE union) and align the
  1595. // buffer on this alignment.
  1596. //
  1597. Alignment = (uchar) ( *((ushort *)pFormat) >> 12 );
  1598. LENGTH_ALIGN(pStubMsg->BufferLength,Alignment);
  1599. Arms = (long) ( *((ushort *&)pFormat)++ & 0x0fff );
  1600. //
  1601. // Search for the arm.
  1602. //
  1603. for ( ; Arms; Arms-- )
  1604. {
  1605. if ( *((long UNALIGNED *&)pFormat)++ == SwitchIs )
  1606. {
  1607. //
  1608. // Found the right arm, break out.
  1609. //
  1610. break;
  1611. }
  1612. // Else increment format string.
  1613. pFormat += 2;
  1614. }
  1615. //
  1616. // Check if we took the default arm and no default arm is specified.
  1617. //
  1618. if ( ! Arms && (*((ushort *)pFormat) == (ushort) 0xffff) )
  1619. {
  1620. RpcRaiseException( RPC_S_INVALID_TAG );
  1621. }
  1622. //
  1623. // Return if the arm is empty.
  1624. //
  1625. if ( ! *((ushort *)pFormat) )
  1626. return;
  1627. //
  1628. // Get the arm's description.
  1629. //
  1630. // We need a real solution after beta for simple type arms. This could
  1631. // break if we have a format string larger than about 32K.
  1632. //
  1633. if ( IS_MAGIC_UNION_BYTE(pFormat) )
  1634. {
  1635. // Re-align again, only does something usefull for DCE unions.
  1636. unsigned char FcType = pFormat[0];
  1637. LENGTH_ALIGN( pStubMsg->BufferLength, SIMPLE_TYPE_ALIGNMENT( FcType ));
  1638. pStubMsg->BufferLength += SIMPLE_TYPE_BUFSIZE( FcType );
  1639. }
  1640. else
  1641. {
  1642. pFormat += *((signed short *)pFormat);
  1643. //
  1644. // If the union arm we take is a pointer, we have to dereference the
  1645. // current memory pointer since we're passed a pointer to the union
  1646. // (regardless of whether the actual parameter was a by-value union
  1647. // or a pointer to a union).
  1648. //
  1649. if ( IS_POINTER_TYPE(*pFormat) )
  1650. {
  1651. if ( pStubMsg->IgnoreEmbeddedPointers )
  1652. {
  1653. //
  1654. // If we're ignoring pointers then just add in the size of a pointer
  1655. // here and return.
  1656. //
  1657. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  1658. pStubMsg->BufferLength += PTR_WIRE_SIZE;
  1659. return;
  1660. }
  1661. pMemory = *((uchar **)pMemory);
  1662. if ( pStubMsg->PointerBufferMark )
  1663. {
  1664. // If the union is embedded, tread it specially
  1665. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  1666. pStubMsg->BufferLength += PTR_WIRE_SIZE;
  1667. if ( !pStubMsg->IgnoreEmbeddedPointers )
  1668. {
  1669. POINTER_BUFFERLENGTH_SWAP_CONTEXT SwapContext(pStubMsg);
  1670. NdrpPointerBufferSize( pStubMsg,
  1671. pMemory,
  1672. pFormat );
  1673. }
  1674. return;
  1675. }
  1676. }
  1677. // Call the appropriate sizing routine
  1678. (*pfnSizeRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  1679. pMemory,
  1680. pFormat );
  1681. }
  1682. }
  1683. void RPC_ENTRY
  1684. NdrByteCountPointerBufferSize(
  1685. PMIDL_STUB_MESSAGE pStubMsg,
  1686. uchar * pMemory,
  1687. PFORMAT_STRING pFormat )
  1688. /*++
  1689. Routine Description :
  1690. Computes the buffer size needed for a byte count pointer.
  1691. Arguments :
  1692. pStubMsg - Pointer to the stub message.
  1693. pMemory - The byte count pointer being sized.
  1694. pFormat - Byte count pointer's format string description.
  1695. Return :
  1696. None.
  1697. --*/
  1698. {
  1699. //
  1700. // We don't do anything special here. Just pass things on to the
  1701. // right sizing routine.
  1702. //
  1703. if ( pFormat[1] != FC_PAD )
  1704. {
  1705. SIMPLE_TYPE_BUF_INCREMENT(pStubMsg->BufferLength, pFormat[1]);
  1706. }
  1707. else
  1708. {
  1709. pFormat += 6;
  1710. CORRELATION_DESC_INCREMENT( pFormat );
  1711. pFormat += *((signed short *)pFormat);
  1712. (*pfnSizeRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  1713. pMemory,
  1714. pFormat );
  1715. }
  1716. }
  1717. void RPC_ENTRY
  1718. NdrXmitOrRepAsBufferSize(
  1719. PMIDL_STUB_MESSAGE pStubMsg,
  1720. uchar * pMemory,
  1721. PFORMAT_STRING pFormat )
  1722. /*++
  1723. Routine Description :
  1724. Computes the buffer size needed for a transmit as or represent as object.
  1725. See mrshl.c for the description of the FC layout.
  1726. Arguments :
  1727. pStubMsg - Pointer to the stub message.
  1728. pMemory - Pointer to the transmit/represent as object being sized.
  1729. pFormat - Object's format string description.
  1730. Return :
  1731. None.
  1732. --*/
  1733. {
  1734. const XMIT_ROUTINE_QUINTUPLE * pQuintuple;
  1735. unsigned short QIndex, XmitTypeSize;
  1736. BOOL fXmitByPtr = *pFormat == FC_TRANSMIT_AS_PTR ||
  1737. *pFormat == FC_REPRESENT_AS_PTR;
  1738. // Fetch the QuintupleIndex.
  1739. QIndex = *(unsigned short *)(pFormat + 2);
  1740. // We size the transmitted object, of course.
  1741. pFormat += 6;
  1742. XmitTypeSize = *((unsigned short *)pFormat);
  1743. pQuintuple = pStubMsg->StubDesc->aXmitQuintuple;
  1744. if ( XmitTypeSize )
  1745. {
  1746. // lower nibble of the flag word has the alignment
  1747. unsigned long Align = LOW_NIBBLE(*(pFormat - 5));
  1748. LENGTH_ALIGN( pStubMsg->BufferLength, Align );
  1749. pStubMsg->BufferLength += XmitTypeSize;
  1750. }
  1751. else
  1752. {
  1753. // We have to create an object to size it.
  1754. unsigned char * pTransmittedType;
  1755. // First translate the presented type into the transmitted type.
  1756. // This includes an allocation of a transmitted type object.
  1757. pStubMsg->pPresentedType = pMemory;
  1758. pStubMsg->pTransmitType = NULL;
  1759. pQuintuple[ QIndex ].pfnTranslateToXmit( pStubMsg );
  1760. // bufsize the transmitted type.
  1761. pFormat += 2;
  1762. pFormat = pFormat + *(short *)pFormat;
  1763. pTransmittedType = pStubMsg->pTransmitType;
  1764. // If transmitted type is a pointer, dereference it.
  1765. {
  1766. // Set the current queue to NULL so that all the embedded
  1767. // pointers in the transmitted type will be sized together
  1768. uchar *PointerBufferMarkSave = pStubMsg->PointerBufferMark;
  1769. pStubMsg->PointerBufferMark = 0;
  1770. NDR_POINTER_QUEUE *pOldQueue = NULL;
  1771. if ( pStubMsg->pPointerQueueState )
  1772. {
  1773. pOldQueue = pStubMsg->pPointerQueueState->GetActiveQueue();
  1774. pStubMsg->pPointerQueueState->SetActiveQueue(NULL);
  1775. }
  1776. RpcTryFinally
  1777. {
  1778. (*pfnSizeRoutines[ ROUTINE_INDEX(*pFormat) ])
  1779. ( pStubMsg,
  1780. fXmitByPtr ? *(uchar **)pTransmittedType
  1781. : pTransmittedType,
  1782. pFormat );
  1783. }
  1784. RpcFinally
  1785. {
  1786. pStubMsg->PointerBufferMark = PointerBufferMarkSave;
  1787. if ( pStubMsg->pPointerQueueState )
  1788. {
  1789. pStubMsg->pPointerQueueState->SetActiveQueue(pOldQueue);
  1790. }
  1791. }
  1792. RpcEndFinally
  1793. }
  1794. pStubMsg->pTransmitType = pTransmittedType;
  1795. // Free the temporary transmitted object (it was alloc'ed by the user).
  1796. pQuintuple[ QIndex ].pfnFreeXmit( pStubMsg );
  1797. }
  1798. }
  1799. void
  1800. NdrpUserMarshalBufferSize(
  1801. PMIDL_STUB_MESSAGE pStubMsg,
  1802. uchar * pMemory,
  1803. PFORMAT_STRING pFormat )
  1804. /*++
  1805. Routine Description :
  1806. Computes the buffer size needed for a usr_marshall object.
  1807. See mrshl.c for the description of the FC layout and wire layout.
  1808. Arguments :
  1809. pStubMsg - Pointer to the stub message.
  1810. pMemory - Pointer to the usr_marshall object to buffer size.
  1811. pFormat - Object's format string description.
  1812. Return :
  1813. None.
  1814. --*/
  1815. {
  1816. const USER_MARSHAL_ROUTINE_QUADRUPLE * pQuadruple;
  1817. unsigned short QIndex;
  1818. unsigned long UserOffset;
  1819. USER_MARSHAL_CB UserMarshalCB;
  1820. if ( pFormat[1] & USER_MARSHAL_POINTER )
  1821. {
  1822. // This is an overestimate to correct the size generated
  1823. // by MIDL's state machine for sizing arguments.
  1824. // The maximum alignment gap VARIANT might consume is 11:
  1825. // 4 for the leading pad between unique pointer and wireVARIANT,
  1826. // and 7 bytes if variant is a BSTR, and following parameter is
  1827. // a CY (stuff that's aligned to 8).
  1828. // MZ: Since were overcompensating here, just make this something
  1829. // reasonable like 0x10 which is probably a good max alignment.
  1830. pStubMsg->BufferLength += 0x10;
  1831. }
  1832. // We are here to size a flat object or a pointee object.
  1833. // Optimization: if we know the wire size, don't call the user to size it.
  1834. if ( *(unsigned short *)(pFormat + 6) != 0 )
  1835. {
  1836. pStubMsg->BufferLength += *(unsigned short *)(pFormat + 6);
  1837. }
  1838. else
  1839. {
  1840. // Unknown wire size: Call the user to size his stuff.
  1841. NdrpInitUserMarshalCB( pStubMsg,
  1842. pFormat,
  1843. USER_MARSHAL_CB_BUFFER_SIZE,
  1844. & UserMarshalCB);
  1845. UserOffset = pStubMsg->BufferLength;
  1846. QIndex = *(unsigned short *)(pFormat + 2);
  1847. pQuadruple = pStubMsg->StubDesc->aUserMarshalQuadruple;
  1848. UserOffset = pQuadruple[ QIndex ].pfnBufferSize( (ulong*) &UserMarshalCB,
  1849. UserOffset,
  1850. pMemory );
  1851. pStubMsg->BufferLength = UserOffset;
  1852. }
  1853. }
  1854. void
  1855. NDR_USR_MRSHL_BUFSIZE_POINTER_QUEUE_ELEMENT::Dispatch(MIDL_STUB_MESSAGE *pStubMsg)
  1856. {
  1857. NdrpUserMarshalBufferSize( pStubMsg,
  1858. pMemory,
  1859. pFormat );
  1860. }
  1861. #if defined(DBG)
  1862. void
  1863. NDR_USR_MRSHL_BUFSIZE_POINTER_QUEUE_ELEMENT::Print()
  1864. {
  1865. DbgPrint("NDR_USR_MRSHL_BUFSIZE_POINTER_QUEUE_ELEMENT\n");
  1866. DbgPrint("pMemory: %p\n", pMemory );
  1867. DbgPrint("pFormat: %p\n", pFormat );
  1868. }
  1869. #endif
  1870. void RPC_ENTRY
  1871. NdrUserMarshalBufferSize(
  1872. PMIDL_STUB_MESSAGE pStubMsg,
  1873. uchar * pMemory,
  1874. PFORMAT_STRING pFormat )
  1875. {
  1876. // Check if the object is embedded.
  1877. // Pointer buffer mark is set only when in a complex struct or array.
  1878. // For unions, when the union is embedded in a complex struct or array.
  1879. // If the union is top level, it's the same like a top level object.
  1880. // For unique pointers we don't have to check embedding, we always add 4.
  1881. // For ref pointer we need to check embedding.
  1882. // Align for the flat object or a pointer to the user object.
  1883. LENGTH_ALIGN( pStubMsg->BufferLength, LOW_NIBBLE(pFormat[1]) );
  1884. if ( pFormat[1] & USER_MARSHAL_POINTER )
  1885. {
  1886. if ( (pFormat[1] & USER_MARSHAL_UNIQUE) ||
  1887. ((pFormat[1] & USER_MARSHAL_REF) && pStubMsg->PointerBufferMark) )
  1888. {
  1889. pStubMsg->BufferLength += PTR_WIRE_SIZE;
  1890. }
  1891. if ( pStubMsg->IgnoreEmbeddedPointers )
  1892. return;
  1893. POINTER_BUFFERLENGTH_SWAP_CONTEXT SwapContext( pStubMsg );
  1894. if ( !pStubMsg->pPointerQueueState ||
  1895. !pStubMsg->pPointerQueueState->GetActiveQueue() )
  1896. {
  1897. NdrpUserMarshalBufferSize(
  1898. pStubMsg,
  1899. pMemory,
  1900. pFormat );
  1901. }
  1902. else
  1903. {
  1904. NDR_USR_MRSHL_BUFSIZE_POINTER_QUEUE_ELEMENT*pElement =
  1905. new(pStubMsg->pPointerQueueState)
  1906. NDR_USR_MRSHL_BUFSIZE_POINTER_QUEUE_ELEMENT(pMemory,
  1907. pFormat);
  1908. pStubMsg->pPointerQueueState->GetActiveQueue()->Enque( pElement );
  1909. }
  1910. return;
  1911. }
  1912. NdrpUserMarshalBufferSize( pStubMsg,
  1913. pMemory,
  1914. pFormat );
  1915. }
  1916. void
  1917. NdrpInterfacePointerBufferSize (
  1918. PMIDL_STUB_MESSAGE pStubMsg,
  1919. uchar * pMemory,
  1920. PFORMAT_STRING pFormat )
  1921. /*++
  1922. Routine Description :
  1923. Computes the buffer size needed for an interface pointer.
  1924. Arguments :
  1925. pStubMsg - Pointer to the stub message.
  1926. pMemory - The interface pointer being sized.
  1927. pFormat - Interface pointer's format string description.
  1928. Return :
  1929. None.
  1930. --*/
  1931. {
  1932. IID iid;
  1933. IID *piid;
  1934. unsigned long size = 0;
  1935. HRESULT hr;
  1936. //
  1937. // Get an IID pointer.
  1938. //
  1939. if ( pFormat[1] != FC_CONSTANT_IID )
  1940. {
  1941. //
  1942. // We do it same way as we compute variance with a long.
  1943. //
  1944. piid = (IID *) NdrpComputeIIDPointer( pStubMsg,
  1945. pMemory,
  1946. pFormat );
  1947. if(piid == 0)
  1948. RpcRaiseException( RPC_S_INVALID_ARG );
  1949. }
  1950. else
  1951. {
  1952. //
  1953. // The IID may not be aligned properly in the format string,
  1954. // so we copy it to a local variable.
  1955. //
  1956. piid = &iid;
  1957. RpcpMemoryCopy( &iid, &pFormat[2], sizeof(iid) );
  1958. }
  1959. // Allocate space for the length and array bounds.
  1960. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  1961. pStubMsg->BufferLength += sizeof(unsigned long) + sizeof(unsigned long);
  1962. hr = (*pfnCoGetMarshalSizeMax)(&size, *piid, (IUnknown *)pMemory, pStubMsg->dwDestContext, pStubMsg->pvDestContext, 0);
  1963. if(FAILED(hr))
  1964. {
  1965. RpcRaiseException(hr);
  1966. }
  1967. pStubMsg->BufferLength += size;
  1968. }
  1969. void RPC_ENTRY
  1970. NdrInterfacePointerBufferSize (
  1971. PMIDL_STUB_MESSAGE pStubMsg,
  1972. uchar * pMemory,
  1973. PFORMAT_STRING pFormat )
  1974. {
  1975. // This function is called only for toplevel interface pointers and
  1976. // backward compatibity
  1977. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  1978. pStubMsg->BufferLength += PTR_WIRE_SIZE;
  1979. if ( pStubMsg->IgnoreEmbeddedPointers )
  1980. return;
  1981. // If the pointer is null, we counted everything.
  1982. if ( pMemory == 0 )
  1983. return;
  1984. NdrpInterfacePointerBufferSize( pStubMsg,
  1985. pMemory,
  1986. pFormat );
  1987. }
  1988. void
  1989. NdrpEmbeddedPointerBufferSize (
  1990. PMIDL_STUB_MESSAGE pStubMsg,
  1991. uchar * pMemory,
  1992. PFORMAT_STRING pFormat )
  1993. /*++
  1994. Routine Description :
  1995. Private routine for computing the buffer size needed for a structure's
  1996. or array's embedded pointers.
  1997. Arguments :
  1998. pStubMsg - Pointer to the stub message.
  1999. pMemory - Pointer to the embedding structure or array.
  2000. pFormat - Format string pointer layout description.
  2001. Return :
  2002. None.
  2003. --*/
  2004. {
  2005. if ( pStubMsg->IgnoreEmbeddedPointers )
  2006. return;
  2007. POINTER_BUFFERLENGTH_SWAP_CONTEXT SwapContext( pStubMsg );
  2008. void ** ppMemPtr;
  2009. uchar * pMemorySave;
  2010. ULONG_PTR MaxCountSave;
  2011. long OffsetSave;
  2012. MaxCountSave = pStubMsg->MaxCount;
  2013. OffsetSave = pStubMsg->Offset;
  2014. pMemorySave = pStubMsg->Memory;
  2015. // Set new memory context.
  2016. pStubMsg->Memory = pMemory;
  2017. //
  2018. // Increment past the FC_PP and pad.
  2019. //
  2020. pFormat += 2;
  2021. for (;;)
  2022. {
  2023. if ( *pFormat == FC_END )
  2024. {
  2025. pStubMsg->Memory = pMemorySave;
  2026. break;
  2027. }
  2028. //
  2029. // Check for FC_FIXED_REPEAT or FC_VARIABLE_REPEAT.
  2030. //
  2031. if ( *pFormat != FC_NO_REPEAT )
  2032. {
  2033. pStubMsg->MaxCount = MaxCountSave;
  2034. pStubMsg->Offset = OffsetSave;
  2035. NdrpEmbeddedRepeatPointerBufferSize( pStubMsg,
  2036. pMemory,
  2037. &pFormat );
  2038. // Continue to the next pointer.
  2039. continue;
  2040. }
  2041. // Compute the pointer to the pointer in memory to size.
  2042. ppMemPtr = (void **) (pMemory + *((signed short *)(pFormat + 2)));
  2043. // Increment to the pointer description.
  2044. pFormat += 6;
  2045. NdrpPointerBufferSize(
  2046. pStubMsg,
  2047. (uchar*)*ppMemPtr,
  2048. pFormat );
  2049. // Increment past pointer description.
  2050. pFormat += 4;
  2051. }
  2052. }
  2053. void
  2054. NdrpEmbeddedRepeatPointerBufferSize (
  2055. PMIDL_STUB_MESSAGE pStubMsg,
  2056. uchar * pMemory,
  2057. PFORMAT_STRING * ppFormat )
  2058. /*++
  2059. Routine Description :
  2060. Private routine for computing the buffer size needed for an array's
  2061. embedded pointers.
  2062. Arguments :
  2063. pStubMsg - Pointer to the stub message.
  2064. pMemory - Pointer to the embedding array.
  2065. pFormat - The array's format string pointer layout description.
  2066. Return :
  2067. None.
  2068. --*/
  2069. {
  2070. uchar ** ppMemPtr;
  2071. PFORMAT_STRING pFormat;
  2072. PFORMAT_STRING pFormatSave;
  2073. uchar * pMemorySave;
  2074. ulong RepeatCount,RepeatIncrement, Pointers, PointersSave;
  2075. pMemorySave = pStubMsg->Memory;
  2076. // Get current format string pointer.
  2077. pFormat = *ppFormat;
  2078. switch ( *pFormat )
  2079. {
  2080. case FC_FIXED_REPEAT :
  2081. // Increment past the FC_FIXED_REPEAT and FC_PAD.
  2082. pFormat += 2;
  2083. // Get the total number of times to repeat the pointer marshall.
  2084. RepeatCount = *((ushort *&)pFormat)++;
  2085. break;
  2086. case FC_VARIABLE_REPEAT :
  2087. // Get the total number of times to repeat the pointer marshall.
  2088. RepeatCount = (ulong)pStubMsg->MaxCount;
  2089. //
  2090. // Check if this variable repeat instance also has a variable
  2091. // offset (this would be the case for a conformant varying array
  2092. // of pointers). If so then increment the memory pointer to point
  2093. // to the actual first array element which is being marshalled.
  2094. //
  2095. if ( pFormat[1] == FC_VARIABLE_OFFSET )
  2096. pMemory += *((ushort *)(pFormat + 2)) * pStubMsg->Offset;
  2097. // else pFormat[1] == FC_FIXED_OFFSET - do nothing
  2098. // Increment past the FC_VARIABLE_REPEAT and FC_PAD.
  2099. pFormat += 2;
  2100. break;
  2101. default :
  2102. NDR_ASSERT(0,"NdrpEmbeddedRepeatPointerMarshall : bad format char");
  2103. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  2104. return;
  2105. }
  2106. // Get the increment amount between successive pointers.
  2107. RepeatIncrement = *((ushort *&)pFormat)++;
  2108. //
  2109. // Add the offset to the beginning of this array to the Memory
  2110. // pointer. This is the offset from any currently embedding structure
  2111. // to the array whose pointers we're marshalling.
  2112. //
  2113. pStubMsg->Memory += *((ushort *&)pFormat)++;
  2114. // Get the number of pointers in this repeat instance.
  2115. PointersSave = Pointers = *((ushort *&)pFormat)++;
  2116. pFormatSave = pFormat;
  2117. //
  2118. // Loop over the number of elements in the array.
  2119. //
  2120. for ( ; RepeatCount--;
  2121. pMemory += RepeatIncrement,
  2122. pStubMsg->Memory += RepeatIncrement )
  2123. {
  2124. pFormat = pFormatSave;
  2125. Pointers = PointersSave;
  2126. //
  2127. // Loop over the number of pointers in each array element (this can
  2128. // be greater than one if we have an array of structures).
  2129. //
  2130. for ( ; Pointers--; )
  2131. {
  2132. // Pointer to the pointer in memory.
  2133. ppMemPtr = (uchar **)(pMemory + *((signed short *)pFormat));
  2134. // Increment to pointer description.
  2135. pFormat += 4;
  2136. NdrpPointerBufferSize(
  2137. pStubMsg,
  2138. (uchar*)*ppMemPtr,
  2139. pFormat );
  2140. // Increment to the next pointer description.
  2141. pFormat += 4;
  2142. }
  2143. }
  2144. // Update format string pointer past this repeat pointer description.
  2145. *ppFormat = pFormatSave + PointersSave * 8;
  2146. pStubMsg->Memory = pMemorySave;
  2147. }
  2148. void RPC_ENTRY
  2149. NdrContextHandleSize(
  2150. PMIDL_STUB_MESSAGE pStubMsg,
  2151. uchar * pMemory,
  2152. PFORMAT_STRING pFormat )
  2153. /*++
  2154. Routine Description :
  2155. Computes the buffer size needed for a context handle.
  2156. Arguments :
  2157. pStubMsg - Pointer to the stub message.
  2158. pMemory - Ignored.
  2159. pFormat - Ignored.
  2160. Return :
  2161. None.
  2162. --*/
  2163. {
  2164. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  2165. pStubMsg->BufferLength += CONTEXT_HANDLE_WIRE_SIZE;
  2166. }
  2167. #ifdef _CS_CHAR_
  2168. void RPC_ENTRY
  2169. NdrCsTagBufferSize(
  2170. PMIDL_STUB_MESSAGE pStubMsg,
  2171. uchar * pMemory,
  2172. PFORMAT_STRING pFormat )
  2173. /*++
  2174. Routine Description :
  2175. Computes the buffer size needed for a cs tag param. Also copies the
  2176. sending tag value to the stub message for use by NdrCsArrayXXX.
  2177. Arguments :
  2178. pStubMsg - Pointer to the stub message.
  2179. pMemory - Pointer to the embedding array.
  2180. pFormat - Pointer to the FC_CSTAG entry in the format string.
  2181. Return :
  2182. None.
  2183. --*/
  2184. {
  2185. // We need to set the tag in the stub message so that we can properly
  2186. // size subsequent cs_char arrays.
  2187. NdrpGetSetCSTagMarshall( pStubMsg, pMemory, (NDR_CS_TAG_FORMAT *) pFormat);
  2188. LENGTH_ALIGN( pStubMsg->BufferLength, 3 );
  2189. pStubMsg->BufferLength += sizeof( unsigned long );
  2190. }
  2191. void RPC_ENTRY
  2192. NdrCsArrayBufferSize(
  2193. PMIDL_STUB_MESSAGE pStubMsg,
  2194. uchar * pMemory,
  2195. PFORMAT_STRING pFormat )
  2196. /*++
  2197. Routine Description :
  2198. Computes the buffer size needed for a cs_char array
  2199. Arguments :
  2200. pStubMsg - Pointer to the stub message.
  2201. pMemory - Pointer to the embedding array.
  2202. pFormat - Pointer to the FC_CSARRAY entry in the format string.
  2203. Return :
  2204. None.
  2205. --*/
  2206. {
  2207. NDR_CS_ARRAY_FORMAT *pCSFormat = (NDR_CS_ARRAY_FORMAT *) pFormat;
  2208. ulong Size;
  2209. ulong Length;
  2210. ulong WireSize;
  2211. NDR_ASSERT( NULL != pStubMsg->pCSInfo, "cs_char stub info not set up");
  2212. // Skip pFormat to the underlying array descriptor
  2213. pFormat += pCSFormat->DescriptionOffset;
  2214. // Leave room for the max count / offset / actual count
  2215. if ( NdrpIsVaryingArray( pFormat ) )
  2216. {
  2217. LENGTH_ALIGN( pStubMsg->BufferLength, 3 );
  2218. pStubMsg->BufferLength += 8;
  2219. }
  2220. if ( NdrpIsConformantArray( pFormat ) )
  2221. {
  2222. LENGTH_ALIGN( pStubMsg->BufferLength, 3 );
  2223. pStubMsg->BufferLength += 4;
  2224. }
  2225. // Get the base size and length
  2226. NdrpGetArraySizeLength (
  2227. pStubMsg,
  2228. pMemory,
  2229. pFormat,
  2230. 1,
  2231. (long*)&Size,
  2232. (long*)&Length,
  2233. (long*)&WireSize );
  2234. // Call XXX_net_size to estimate the buffer space required to store this
  2235. // array after conversion. For fixed or varying arrays the buffer
  2236. // space is equal to the fixed upper bound specified in the idl file.
  2237. if ( !NdrpIsVaryingArray( pFormat ) )
  2238. {
  2239. NDR_CS_SIZE_CONVERT_ROUTINES *CSRoutines;
  2240. CS_TYPE_NET_SIZE_ROUTINE SizingRoutine;
  2241. IDL_CS_CONVERT ConversionType;
  2242. error_status_t Status;
  2243. CSRoutines = pStubMsg->StubDesc->CsRoutineTables->pSizeConvertRoutines;
  2244. SizingRoutine = CSRoutines[ pCSFormat->CSRoutineIndex ].pfnNetSize;
  2245. SizingRoutine(
  2246. NULL,
  2247. pStubMsg->pCSInfo->WireCodeset,
  2248. Size,
  2249. (IDL_CS_CONVERT*)&ConversionType,
  2250. &Size,
  2251. &Status);
  2252. if (RPC_S_OK != Status)
  2253. RpcRaiseException(Status);
  2254. }
  2255. pStubMsg->BufferLength += Size;
  2256. }
  2257. #endif // _CS_CHAR_
  2258. void
  2259. NdrPartialIgnoreClientBufferSize(
  2260. PMIDL_STUB_MESSAGE pStubMsg,
  2261. void * pMemory
  2262. )
  2263. {
  2264. LENGTH_ALIGN( pStubMsg->BufferLength, 0x3 );
  2265. pStubMsg->Buffer += PTR_WIRE_SIZE;
  2266. }