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.

2401 lines
59 KiB

4 years ago
  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1993 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. const
  15. PSIZE_ROUTINE SizeRoutinesTable[] =
  16. {
  17. NdrPointerBufferSize,
  18. NdrPointerBufferSize,
  19. NdrPointerBufferSize,
  20. NdrPointerBufferSize,
  21. NdrSimpleStructBufferSize,
  22. NdrSimpleStructBufferSize,
  23. NdrConformantStructBufferSize,
  24. NdrConformantStructBufferSize,
  25. NdrConformantVaryingStructBufferSize,
  26. NdrComplexStructBufferSize,
  27. NdrConformantArrayBufferSize,
  28. NdrConformantVaryingArrayBufferSize,
  29. NdrFixedArrayBufferSize,
  30. NdrFixedArrayBufferSize,
  31. NdrVaryingArrayBufferSize,
  32. NdrVaryingArrayBufferSize,
  33. NdrComplexArrayBufferSize,
  34. NdrConformantStringBufferSize,
  35. NdrConformantStringBufferSize,
  36. NdrConformantStringBufferSize,
  37. NdrConformantStringBufferSize,
  38. NdrNonConformantStringBufferSize,
  39. NdrNonConformantStringBufferSize,
  40. NdrNonConformantStringBufferSize,
  41. NdrNonConformantStringBufferSize,
  42. NdrEncapsulatedUnionBufferSize,
  43. NdrNonEncapsulatedUnionBufferSize,
  44. NdrByteCountPointerBufferSize,
  45. NdrXmitOrRepAsBufferSize, // transmit as
  46. NdrXmitOrRepAsBufferSize, // represent as
  47. NdrInterfacePointerBufferSize,
  48. NdrContextHandleSize,
  49. // New Post NT 3.5 token serviced from here on.
  50. NdrHardStructBufferSize,
  51. NdrXmitOrRepAsBufferSize, // transmit as ptr
  52. NdrXmitOrRepAsBufferSize, // represent as ptr
  53. NdrUserMarshalBufferSize
  54. };
  55. const
  56. PSIZE_ROUTINE * pfnSizeRoutines = &SizeRoutinesTable[-FC_RP];
  57. #if defined( DOS ) && !defined( WIN )
  58. #pragma code_seg( "NDR20_7" )
  59. #endif
  60. void RPC_ENTRY
  61. NdrPointerBufferSize(
  62. PMIDL_STUB_MESSAGE pStubMsg,
  63. uchar * pMemory,
  64. PFORMAT_STRING pFormat )
  65. /*++
  66. Routine Description :
  67. Computes the needed buffer size for a top level pointer to anything.
  68. Pointers embedded in structures, arrays, or unions call
  69. NdrpPointerBufferSize directly.
  70. Used for FC_RP, FC_UP, FC_FP, FC_OP.
  71. Arguments :
  72. pStubMsg - Pointer to the stub message.
  73. pMemory - Pointer to the data being sized.
  74. pFormat - Pointer's format string description.
  75. Return :
  76. None.
  77. --*/
  78. {
  79. //
  80. // Add 4 bytes for a unique or full pointer.
  81. //
  82. if ( *pFormat != FC_RP )
  83. {
  84. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  85. pStubMsg->BufferLength += 4;
  86. }
  87. NdrpPointerBufferSize( pStubMsg,
  88. pMemory,
  89. pFormat );
  90. }
  91. void
  92. NdrpPointerBufferSize(
  93. PMIDL_STUB_MESSAGE pStubMsg,
  94. uchar * pMemory,
  95. PFORMAT_STRING pFormat )
  96. /*++
  97. Routine Description :
  98. Private routine for sizing a pointer to anything. This is the entry
  99. point for pointers embedded in structures, arrays, or unions.
  100. Used for FC_RP, FC_UP, FC_FP, FC_OP.
  101. Arguments :
  102. pStubMsg - Pointer to the stub message.
  103. pMemory - Pointer to the data being sized.
  104. pFormat - Pointer's format string description.
  105. Return :
  106. None.
  107. --*/
  108. {
  109. if ( ! pMemory )
  110. return;
  111. if ( *pFormat == FC_FP )
  112. {
  113. //
  114. // Check if we have already sized this full pointer.
  115. //
  116. if ( NdrFullPointerQueryPointer( pStubMsg->FullPtrXlatTables,
  117. pMemory,
  118. FULL_POINTER_BUF_SIZED,
  119. 0 ) )
  120. return;
  121. }
  122. if ( ! SIMPLE_POINTER(pFormat[1]) )
  123. {
  124. //
  125. // Pointer to complex type.
  126. //
  127. if ( POINTER_DEREF(pFormat[1]) )
  128. pMemory = *((uchar **)pMemory);
  129. pFormat += 2;
  130. pFormat += *((signed short *)pFormat);
  131. }
  132. else
  133. {
  134. switch ( pFormat[2] )
  135. {
  136. case FC_C_CSTRING :
  137. case FC_C_BSTRING :
  138. case FC_C_WSTRING :
  139. case FC_C_SSTRING :
  140. // Increment to the string description.
  141. pFormat += 2;
  142. break;
  143. default :
  144. //
  145. // Pointer to simple type. Make an upper bound estimate.
  146. //
  147. SIMPLE_TYPE_BUF_INCREMENT(pStubMsg->BufferLength, pFormat[2]);
  148. return;
  149. }
  150. }
  151. (*pfnSizeRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  152. pMemory,
  153. pFormat );
  154. }
  155. void RPC_ENTRY
  156. NdrSimpleStructBufferSize(
  157. PMIDL_STUB_MESSAGE pStubMsg,
  158. uchar * pMemory,
  159. PFORMAT_STRING pFormat )
  160. /*++
  161. Routine Description :
  162. Computes the buffer size needed for a simple structure.
  163. Used for FC_STRUCT and FC_PSTRUCT.
  164. Arguments :
  165. pStubMsg - Pointer to the stub message.
  166. pMemory - Pointer to the structure being sized.
  167. pFormat - Structure's format string description.
  168. Return :
  169. None.
  170. --*/
  171. {
  172. LENGTH_ALIGN(pStubMsg->BufferLength,pFormat[1]);
  173. // Add size of the structure.
  174. pStubMsg->BufferLength += (ulong) *((ushort *)(pFormat + 2));
  175. //
  176. // Add size of embedded pointers.
  177. //
  178. if ( *pFormat == FC_PSTRUCT )
  179. {
  180. NdrpEmbeddedPointerBufferSize( pStubMsg,
  181. pMemory,
  182. pFormat + 4 );
  183. }
  184. }
  185. void RPC_ENTRY
  186. NdrConformantStructBufferSize(
  187. PMIDL_STUB_MESSAGE pStubMsg,
  188. uchar * pMemory,
  189. PFORMAT_STRING pFormat )
  190. /*++
  191. Routine Description :
  192. Computes the buffer size needed for a conformant structure.
  193. Used for FC_CSTRUCT and FC_CPSTRUCT.
  194. Arguments :
  195. pStubMsg - Pointer to the stub message.
  196. pMemory - Pointer to the structure being sized.
  197. pFormat - Structure's format string description.
  198. Return :
  199. None.
  200. --*/
  201. {
  202. PFORMAT_STRING pFormatArray;
  203. ulong FlatSize;
  204. // Align and add size for conformance count.
  205. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  206. pStubMsg->BufferLength += 4;
  207. // Align if needed on an 8 byte boundary.
  208. if ( pFormat[1] == 0x7 )
  209. LENGTH_ALIGN(pStubMsg->BufferLength,0x7);
  210. FlatSize = (ulong) *((ushort *)(pFormat + 2));
  211. pStubMsg->BufferLength += FlatSize;
  212. // Increment to the offset to array description.
  213. pFormat += 4;
  214. pFormatArray = pFormat + *((signed short *)pFormat);
  215. //
  216. // Size our array - pass a memory pointer to the conformant array.
  217. //
  218. NdrpConformantArrayBufferSize( pStubMsg,
  219. pMemory + FlatSize,
  220. pFormatArray );
  221. pFormat += 2;
  222. if ( *pFormat == FC_PP )
  223. {
  224. NdrpEmbeddedPointerBufferSize( pStubMsg,
  225. pMemory,
  226. pFormat );
  227. }
  228. }
  229. void RPC_ENTRY
  230. NdrConformantVaryingStructBufferSize(
  231. PMIDL_STUB_MESSAGE pStubMsg,
  232. uchar * pMemory,
  233. PFORMAT_STRING pFormat )
  234. /*++
  235. Routine Description :
  236. Computes the buffer size needed for a conformant varying structure.
  237. Used for FC_CVSTRUCT.
  238. Arguments :
  239. pStubMsg - Pointer to the stub message.
  240. pMemory - Pointer to the structure being sized.
  241. pFormat - Structure's format string description.
  242. Return :
  243. None.
  244. --*/
  245. {
  246. PPRIVATE_SIZE_ROUTINE pfnSize;
  247. PFORMAT_STRING pFormatArray;
  248. ulong FlatSize;
  249. // Align and add size for conformance count.
  250. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  251. pStubMsg->BufferLength += 4;
  252. // Align on 8 byte boundary if needed.
  253. if ( pFormat[1] == 0x7 )
  254. LENGTH_ALIGN(pStubMsg->BufferLength,0x7);
  255. FlatSize = (ulong) *((ushort *)(pFormat + 2));
  256. pStubMsg->BufferLength += FlatSize;
  257. // Increment to the offset to array description.
  258. pFormat += 4;
  259. pFormatArray = pFormat + *((signed short *)pFormat);
  260. switch ( *pFormatArray )
  261. {
  262. case FC_CVARRAY :
  263. pfnSize = NdrpConformantVaryingArrayBufferSize;
  264. break;
  265. default :
  266. pfnSize = NdrpConformantStringBufferSize;
  267. break;
  268. }
  269. (*pfnSize)( pStubMsg,
  270. pMemory + FlatSize,
  271. pFormatArray );
  272. pFormat += 2;
  273. if ( *pFormat == FC_PP )
  274. {
  275. NdrpEmbeddedPointerBufferSize( pStubMsg,
  276. pMemory,
  277. pFormat );
  278. }
  279. }
  280. void RPC_ENTRY
  281. NdrHardStructBufferSize(
  282. PMIDL_STUB_MESSAGE pStubMsg,
  283. uchar * pMemory,
  284. PFORMAT_STRING pFormat )
  285. /*++
  286. Routine Description :
  287. Computes the buffer size needed for a hard structure.
  288. Used for FC_HARD_STRUCT.
  289. Arguments :
  290. pStubMsg - Pointer to the stub message.
  291. pMemory - Pointer to the structure being sized.
  292. pFormat - Structure's format string description.
  293. Return :
  294. None.
  295. --*/
  296. {
  297. LENGTH_ALIGN(pStubMsg->BufferLength,pFormat[1]);
  298. pStubMsg->BufferLength += *((ushort *)&pFormat[10]);
  299. if ( *((short *)&pFormat[14]) )
  300. {
  301. pFormat += 12;
  302. pMemory += *((ushort *)pFormat)++;
  303. pFormat += *((short *)pFormat);
  304. (*pfnSizeRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  305. pMemory,
  306. pFormat );
  307. }
  308. }
  309. void RPC_ENTRY
  310. NdrComplexStructBufferSize(
  311. PMIDL_STUB_MESSAGE pStubMsg,
  312. uchar * pMemory,
  313. PFORMAT_STRING pFormat )
  314. /*++
  315. Routine Description :
  316. Computes the buffer size needed for a complex structure.
  317. Used for FC_BOGUS_STRUCT.
  318. Arguments :
  319. pStubMsg - Pointer to the stub message.
  320. pMemory - Pointer to the structure being sized.
  321. pFormat - Structure's format string description.
  322. Return :
  323. None.
  324. --*/
  325. {
  326. uchar * pMemorySave;
  327. PFORMAT_STRING pFormatPointers;
  328. PFORMAT_STRING pFormatArray;
  329. PFORMAT_STRING pFormatComplex;
  330. long Alignment;
  331. long Align8Mod;
  332. #if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
  333. long Align4Mod;
  334. #endif
  335. pMemorySave = pStubMsg->Memory;
  336. //
  337. // This is used when computing the count(s) for size_is or length_is
  338. // pointers.
  339. //
  340. pStubMsg->Memory = pMemory;
  341. Alignment = pFormat[1];
  342. //
  343. // This is used for support of structs with doubles passed on an
  344. // i386 stack, and of struct with longs on 16 bit platforms.
  345. //
  346. Align8Mod = (long) pMemory % 8;
  347. #if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
  348. Align4Mod = (long) pMemory % 4;
  349. #endif
  350. pFormat += 4;
  351. // Get conformant array description.
  352. if ( *((ushort *)pFormat) )
  353. {
  354. pFormatArray = pFormat + *((signed short *)pFormat);
  355. //
  356. // Align and add size of conformance count(s).
  357. //
  358. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  359. pStubMsg->BufferLength += NdrpArrayDimensions(pFormatArray,FALSE) * 4;
  360. }
  361. else
  362. pFormatArray = 0;
  363. pFormat += 2;
  364. // Get pointer layout description.
  365. if ( *((ushort *)pFormat) )
  366. pFormatPointers = pFormat + *((ushort *)pFormat);
  367. else
  368. pFormatPointers = 0;
  369. pFormat += 2;
  370. LENGTH_ALIGN(pStubMsg->BufferLength,Alignment);
  371. //
  372. // Size the structure member by member.
  373. //
  374. for ( ; ; pFormat++ )
  375. {
  376. switch ( *pFormat )
  377. {
  378. //
  379. // simple types
  380. //
  381. case FC_CHAR :
  382. case FC_BYTE :
  383. case FC_SMALL :
  384. case FC_WCHAR :
  385. case FC_SHORT :
  386. case FC_LONG :
  387. case FC_FLOAT :
  388. case FC_HYPER :
  389. case FC_DOUBLE :
  390. case FC_ENUM16 :
  391. case FC_ENUM32 :
  392. case FC_IGNORE :
  393. LENGTH_ALIGN( pStubMsg->BufferLength,
  394. SIMPLE_TYPE_ALIGNMENT(*pFormat) );
  395. pStubMsg->BufferLength += SIMPLE_TYPE_BUFSIZE(*pFormat);
  396. pMemory += SIMPLE_TYPE_MEMSIZE(*pFormat);
  397. break;
  398. case FC_POINTER :
  399. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  400. pStubMsg->BufferLength += 4;
  401. if ( ! pStubMsg->IgnoreEmbeddedPointers )
  402. {
  403. NdrpPointerBufferSize( pStubMsg,
  404. *((uchar **)pMemory),
  405. pFormatPointers );
  406. pFormatPointers += 4;
  407. //
  408. // We align the buffer length back to the alignment of
  409. // the structure. Since we're sizing pointers in parallel
  410. // with the flat part of the struct, instead of after,
  411. // we need to do this to make sure we account for any
  412. // wierd alignment juxtapositions correctly.
  413. //
  414. LENGTH_ALIGN(pStubMsg->BufferLength,Alignment);
  415. }
  416. pMemory += PTR_MEM_SIZE;
  417. break;
  418. //
  419. // Embedded complex types.
  420. //
  421. case FC_EMBEDDED_COMPLEX :
  422. // Add padding.
  423. pMemory += pFormat[1];
  424. pFormat += 2;
  425. // Get the type's description.
  426. pFormatComplex = pFormat + *((signed short UNALIGNED *)pFormat);
  427. (*pfnSizeRoutines[ROUTINE_INDEX(*pFormatComplex)])
  428. ( pStubMsg,
  429. (*pFormatComplex == FC_IP) ? *(uchar **)pMemory : pMemory,
  430. pFormatComplex );
  431. pMemory = NdrpMemoryIncrement( pStubMsg,
  432. pMemory,
  433. pFormatComplex );
  434. //
  435. // Increment the main format string one byte. The loop
  436. // will increment it one more byte past the offset field.
  437. //
  438. pFormat++;
  439. break;
  440. case FC_ALIGNM2 :
  441. ALIGN( pMemory, 0x1 );
  442. break;
  443. case FC_ALIGNM4 :
  444. #if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
  445. //
  446. // We have to play some tricks for the dos and win16
  447. // to handle the case when an 4 byte aligned structure
  448. // is passed by value. The alignment of the struct on
  449. // the stack is not guaranteed to be on an 4 byte boundary.
  450. //
  451. pMemory -= Align4Mod;
  452. ALIGN( pMemory, 0x3 );
  453. pMemory += Align4Mod;
  454. #else
  455. ALIGN( pMemory, 0x3 );
  456. #endif
  457. break;
  458. case FC_ALIGNM8 :
  459. //
  460. // We have to play some tricks for the i386 to handle the case
  461. // when an 8 byte aligned structure is passed by value. The
  462. // alignment of the struct on the stack is not guaranteed to be
  463. // on an 8 byte boundary.
  464. //
  465. pMemory -= Align8Mod;
  466. ALIGN( pMemory, 0x7 );
  467. pMemory += Align8Mod;
  468. break;
  469. case FC_STRUCTPAD1 :
  470. case FC_STRUCTPAD2 :
  471. case FC_STRUCTPAD3 :
  472. case FC_STRUCTPAD4 :
  473. case FC_STRUCTPAD5 :
  474. case FC_STRUCTPAD6 :
  475. case FC_STRUCTPAD7 :
  476. //
  477. // Increment memory pointer by amount of padding.
  478. //
  479. pMemory += (*pFormat - FC_STRUCTPAD1) + 1;
  480. break;
  481. case FC_PAD :
  482. break;
  483. //
  484. // Done with layout.
  485. //
  486. case FC_END :
  487. goto ComplexBufferSizeEnd;
  488. default :
  489. NDR_ASSERT(0,"NdrComplexStructBufferSize : bad format char");
  490. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  491. return;
  492. } // switch
  493. } // for
  494. ComplexBufferSizeEnd:
  495. //
  496. // Size any conformant array.
  497. //
  498. if ( pFormatArray )
  499. {
  500. PPRIVATE_SIZE_ROUTINE pfnSize;
  501. switch ( *pFormatArray )
  502. {
  503. case FC_CARRAY :
  504. pfnSize = NdrpConformantArrayBufferSize;
  505. break;
  506. case FC_CVARRAY :
  507. pfnSize = NdrpConformantVaryingArrayBufferSize;
  508. break;
  509. case FC_BOGUS_ARRAY :
  510. pfnSize = NdrpComplexArrayBufferSize;
  511. break;
  512. case FC_C_WSTRING :
  513. ALIGN(pMemory,0x1);
  514. // fall through
  515. // case FC_C_CSTRING :
  516. // case FC_C_BSTRING :
  517. // case FC_C_SSTRING :
  518. default :
  519. pfnSize = NdrpConformantStringBufferSize;
  520. goto BufferSizeConfArray;
  521. }
  522. BufferSizeConfArray:
  523. (*pfnSize)( pStubMsg,
  524. pMemory,
  525. pFormatArray );
  526. }
  527. //
  528. // Fix for DHCP until I figure out what's really going on.
  529. //
  530. if ( ! pStubMsg->IgnoreEmbeddedPointers )
  531. {
  532. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  533. pStubMsg->BufferLength += 4;
  534. }
  535. pStubMsg->Memory = pMemorySave;
  536. }
  537. void RPC_ENTRY
  538. NdrFixedArrayBufferSize(
  539. PMIDL_STUB_MESSAGE pStubMsg,
  540. uchar * pMemory,
  541. PFORMAT_STRING pFormat )
  542. /*++
  543. Routine Description :
  544. Computes the buffer size needed for a fixed array of any number of
  545. dimensions.
  546. Used for FC_SMFARRAY and FC_LGFARRAY.
  547. Arguments :
  548. pStubMsg - Pointer to the stub message.
  549. pMemory - Pointer to the array being sized.
  550. pFormat - Array's format string description.
  551. Return :
  552. None.
  553. --*/
  554. {
  555. LENGTH_ALIGN(pStubMsg->BufferLength,pFormat[1]);
  556. if ( *pFormat == FC_SMFARRAY )
  557. {
  558. pFormat += 2;
  559. pStubMsg->BufferLength += *((ushort *)pFormat)++;
  560. }
  561. else
  562. {
  563. pFormat += 2;
  564. pStubMsg->BufferLength += *((ulong UNALIGNED *)pFormat)++;
  565. }
  566. if ( *pFormat == FC_PP )
  567. {
  568. NdrpEmbeddedPointerBufferSize( pStubMsg,
  569. pMemory,
  570. pFormat );
  571. }
  572. }
  573. void RPC_ENTRY
  574. NdrConformantArrayBufferSize(
  575. PMIDL_STUB_MESSAGE pStubMsg,
  576. uchar * pMemory,
  577. PFORMAT_STRING pFormat )
  578. /*++
  579. Routine Description :
  580. Computes the buffer size needed for a top level one dimensional conformant
  581. array.
  582. Used for FC_CARRAY.
  583. Arguments :
  584. pStubMsg - Pointer to the stub message.
  585. pMemory - Pointer to the array being sized.
  586. pFormat - Array's format string description.
  587. Return :
  588. None.
  589. --*/
  590. {
  591. //
  592. // Align and add size for conformance count.
  593. //
  594. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  595. pStubMsg->BufferLength += 4;
  596. NdrpConformantArrayBufferSize( pStubMsg,
  597. pMemory,
  598. pFormat );
  599. }
  600. void
  601. NdrpConformantArrayBufferSize(
  602. PMIDL_STUB_MESSAGE pStubMsg,
  603. uchar * pMemory,
  604. PFORMAT_STRING pFormat )
  605. /*++
  606. Routine Description :
  607. Private routine for computing the buffer size needed for a one dimensional
  608. conformant array. This is the entry point for unmarshalling an embedded
  609. conformant array.
  610. Used for FC_CARRAY.
  611. Arguments :
  612. pStubMsg - Pointer to the stub message.
  613. pMemory - Pointer to the array being sized.
  614. pFormat - Array's format string description.
  615. Return :
  616. None.
  617. --*/
  618. {
  619. ulong ConformanceCount;
  620. ConformanceCount = NdrpComputeConformance( pStubMsg,
  621. pMemory,
  622. pFormat );
  623. if ( ((long)ConformanceCount) < 0 )
  624. RpcRaiseException( RPC_X_INVALID_BOUND );
  625. if ( ! ConformanceCount )
  626. return;
  627. LENGTH_ALIGN(pStubMsg->BufferLength,pFormat[1]);
  628. pFormat += 2;
  629. // Add array size.
  630. pStubMsg->BufferLength += *((ushort *)pFormat) * ConformanceCount;
  631. pFormat += 6;
  632. if ( *pFormat == FC_PP )
  633. {
  634. NdrpEmbeddedPointerBufferSize( pStubMsg,
  635. pMemory,
  636. pFormat );
  637. }
  638. }
  639. void RPC_ENTRY
  640. NdrConformantVaryingArrayBufferSize(
  641. PMIDL_STUB_MESSAGE pStubMsg,
  642. uchar * pMemory,
  643. PFORMAT_STRING pFormat )
  644. /*++
  645. Routine Description :
  646. Computes the buffer size needed for a top level one dimensional conformant
  647. varying array.
  648. Used for FC_CVARRAY.
  649. Arguments :
  650. pStubMsg - Pointer to the stub message.
  651. pMemory - Pointer to the array being sized.
  652. pFormat - Array's format string description.
  653. Return :
  654. None.
  655. --*/
  656. {
  657. //
  658. // Align and add size for conformance count.
  659. //
  660. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  661. pStubMsg->BufferLength += 4;
  662. NdrpConformantVaryingArrayBufferSize( pStubMsg,
  663. pMemory,
  664. pFormat );
  665. }
  666. void
  667. NdrpConformantVaryingArrayBufferSize(
  668. PMIDL_STUB_MESSAGE pStubMsg,
  669. uchar * pMemory,
  670. PFORMAT_STRING pFormat )
  671. /*++
  672. Routine Description :
  673. Private routine for computing the buffer size needed for a one dimensional
  674. conformant varying array. This is the entry point for buffer sizing an
  675. embedded conformant varying array.
  676. Used for FC_CVARRAY.
  677. Arguments :
  678. pStubMsg - Pointer to the stub message.
  679. pMemory - Pointer to the array being sized.
  680. pFormat - Array's format string description.
  681. Return :
  682. None.
  683. --*/
  684. {
  685. ulong ConformanceCount;
  686. //
  687. // Align and add size for offset and actual count.
  688. //
  689. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  690. pStubMsg->BufferLength += 8;
  691. NdrpComputeVariance( pStubMsg,
  692. pMemory,
  693. pFormat );
  694. if ( pStubMsg->fCheckBounds )
  695. {
  696. ConformanceCount = NdrpComputeConformance( pStubMsg,
  697. pMemory,
  698. pFormat );
  699. if ( ( ((long)ConformanceCount) < 0 ) ||
  700. ( ((long)pStubMsg->ActualCount) < 0 ) ||
  701. ( ((long)pStubMsg->Offset) < 0 ) ||
  702. ( (pStubMsg->Offset + pStubMsg->ActualCount) > ConformanceCount ) )
  703. RpcRaiseException( RPC_X_INVALID_BOUND );
  704. }
  705. if ( ! pStubMsg->ActualCount )
  706. return;
  707. // Align on 8 byte boundary if needed.
  708. if ( pFormat[1] == 0x7 )
  709. LENGTH_ALIGN(pStubMsg->BufferLength,0x7);
  710. pFormat += 2;
  711. // Add array size.
  712. pStubMsg->BufferLength += *((ushort *)pFormat) * pStubMsg->ActualCount;
  713. pFormat += 10;
  714. if ( *pFormat == FC_PP )
  715. {
  716. //
  717. // MaxCount must contain the number of shipped elements in the array
  718. // before sizing embedded pointers.
  719. //
  720. pStubMsg->MaxCount = pStubMsg->ActualCount;
  721. NdrpEmbeddedPointerBufferSize( pStubMsg,
  722. pMemory,
  723. pFormat );
  724. }
  725. }
  726. void RPC_ENTRY
  727. NdrVaryingArrayBufferSize(
  728. PMIDL_STUB_MESSAGE pStubMsg,
  729. uchar * pMemory,
  730. PFORMAT_STRING pFormat )
  731. /*++
  732. Routine Description :
  733. Computes the buffer size needed for a top level or embedded one
  734. dimensional varying array.
  735. Used for FC_SMVARRAY and FC_LGVARRAY.
  736. Arguments :
  737. pStubMsg - Pointer to the stub message.
  738. pMemory - Pointer to the array being sized.
  739. pFormat - Array's format string description.
  740. Return :
  741. None.
  742. Arguments :
  743. pMemory - pointer to the parameter to size
  744. pFormat - pointer to the format string description of the parameter
  745. --*/
  746. {
  747. ulong Elements;
  748. ulong ElementSize;
  749. //
  750. // Align and add size for offset and actual count.
  751. //
  752. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  753. pStubMsg->BufferLength += 8;
  754. NdrpComputeVariance( pStubMsg,
  755. pMemory,
  756. pFormat );
  757. if ( pStubMsg->fCheckBounds )
  758. {
  759. Elements =
  760. (*pFormat == FC_SMVARRAY) ?
  761. *((ushort *)(pFormat + 4)) : *((ulong UNALIGNED *)(pFormat + 6));
  762. if ( ( ((long)pStubMsg->ActualCount) < 0 ) ||
  763. ( ((long)pStubMsg->Offset) < 0 ) ||
  764. ( (pStubMsg->Offset + pStubMsg->ActualCount) > Elements ) )
  765. RpcRaiseException( RPC_X_INVALID_BOUND );
  766. }
  767. if ( ! pStubMsg->ActualCount )
  768. return;
  769. // Align on 8 byte boundary if needed.
  770. if ( pFormat[1] == 0x7 )
  771. LENGTH_ALIGN(pStubMsg->BufferLength,0x7);
  772. if (*pFormat == FC_SMVARRAY)
  773. {
  774. ElementSize = *((ushort *)(pFormat + 6));
  775. pFormat += 12;
  776. }
  777. else
  778. {
  779. ElementSize = *((ushort *)(pFormat + 10));
  780. pFormat += 16;
  781. }
  782. pStubMsg->BufferLength += ElementSize * pStubMsg->ActualCount;
  783. if ( *pFormat == FC_PP )
  784. {
  785. //
  786. // MaxCount must contain the number of shipped elements in the array
  787. // before sizing embedded pointers.
  788. //
  789. pStubMsg->MaxCount = pStubMsg->ActualCount;
  790. NdrpEmbeddedPointerBufferSize( pStubMsg,
  791. pMemory,
  792. pFormat );
  793. }
  794. }
  795. void RPC_ENTRY
  796. NdrComplexArrayBufferSize(
  797. PMIDL_STUB_MESSAGE pStubMsg,
  798. uchar * pMemory,
  799. PFORMAT_STRING pFormat )
  800. /*++
  801. Routine Description :
  802. Computes the buffer size needed for a top level complex array.
  803. Used for FC_BOGUS_STRUCT.
  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. //
  813. // Add in conformance sizes if we are the outermost dimension.
  814. //
  815. if ( pStubMsg->pArrayInfo == 0 )
  816. {
  817. //
  818. // Align and add size for any conformance count(s).
  819. //
  820. if ( *((long UNALIGNED *)(pFormat + 4)) != 0xffffffff )
  821. {
  822. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  823. pStubMsg->BufferLength += NdrpArrayDimensions( pFormat, FALSE ) * 4;
  824. }
  825. }
  826. NdrpComplexArrayBufferSize( pStubMsg,
  827. pMemory,
  828. pFormat );
  829. }
  830. void
  831. NdrpComplexArrayBufferSize(
  832. PMIDL_STUB_MESSAGE pStubMsg,
  833. uchar * pMemory,
  834. PFORMAT_STRING pFormat )
  835. /*++
  836. Routine Description :
  837. Private routine for determing the buffer size of a complex array. This
  838. is the entry point for buffer sizing an embedded complex array.
  839. Arguments :
  840. pStubMsg - Pointer to the stub message.
  841. pMemory - Pointer to the array being sized.
  842. pFormat - Array's format string description.
  843. Return :
  844. None.
  845. --*/
  846. {
  847. ARRAY_INFO ArrayInfo;
  848. PARRAY_INFO pArrayInfo;
  849. PSIZE_ROUTINE pfnSize;
  850. PFORMAT_STRING pFormatStart;
  851. ulong Elements;
  852. ulong Offset, Count;
  853. ulong MemoryElementSize;
  854. long Dimension;
  855. uchar Alignment;
  856. //
  857. // Lots of setup if we are the outer dimension.
  858. //
  859. if ( ! pStubMsg->pArrayInfo )
  860. {
  861. pStubMsg->pArrayInfo = &ArrayInfo;
  862. ArrayInfo.Dimension = 0;
  863. //
  864. // Set this to 0 so that NdrpMemoryIncrement will know to call
  865. // NdrpComputeConformance when computing our size.
  866. //
  867. ArrayInfo.BufferConformanceMark = 0;
  868. ArrayInfo.MaxCountArray = (unsigned long *) pStubMsg->MaxCount;
  869. ArrayInfo.OffsetArray = (unsigned long *) pStubMsg->Offset;
  870. ArrayInfo.ActualCountArray = (unsigned long *) pStubMsg->ActualCount;
  871. }
  872. pFormatStart = pFormat;
  873. pArrayInfo = pStubMsg->pArrayInfo;
  874. Dimension = pArrayInfo->Dimension;
  875. // Get the array alignment.
  876. Alignment = pFormat[1];
  877. pFormat += 2;
  878. // Get the number of elements (0 if conformance present).
  879. Elements = *((ushort *)pFormat)++;
  880. //
  881. // Check for conformance description.
  882. //
  883. if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
  884. {
  885. Elements = NdrpComputeConformance( pStubMsg,
  886. pMemory,
  887. pFormatStart );
  888. }
  889. pFormat += 4;
  890. //
  891. // Check for variance description.
  892. //
  893. if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
  894. {
  895. NdrpComputeVariance( pStubMsg,
  896. pMemory,
  897. pFormatStart );
  898. Offset = pStubMsg->Offset;
  899. Count = pStubMsg->ActualCount;
  900. if ( Dimension == 0 )
  901. {
  902. //
  903. // Align and add in size of variance count(s).
  904. //
  905. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  906. pStubMsg->BufferLength +=
  907. NdrpArrayDimensions( pFormatStart, TRUE ) * 8;
  908. }
  909. }
  910. else
  911. {
  912. Offset = 0;
  913. Count = Elements;
  914. }
  915. pFormat += 4;
  916. if ( pStubMsg->fCheckBounds )
  917. {
  918. if ( ( ((long)Elements) < 0 ) ||
  919. ( ((long)Count) < 0 ) ||
  920. ( ((long)Offset) < 0 ) ||
  921. ( (Offset + Count) > Elements ) )
  922. RpcRaiseException( RPC_X_INVALID_BOUND );
  923. }
  924. if ( ! Count )
  925. goto ComplexArrayBufSizeEnd;
  926. LENGTH_ALIGN(pStubMsg->BufferLength,Alignment);
  927. switch ( *pFormat )
  928. {
  929. case FC_EMBEDDED_COMPLEX :
  930. pFormat += 2;
  931. pFormat += *((signed short *)pFormat);
  932. pfnSize = pfnSizeRoutines[ROUTINE_INDEX(*pFormat)];
  933. pArrayInfo->Dimension = Dimension + 1;
  934. MemoryElementSize = NdrpMemoryIncrement( pStubMsg,
  935. pMemory,
  936. pFormat ) - pMemory;
  937. break;
  938. case FC_RP :
  939. case FC_UP :
  940. case FC_FP :
  941. case FC_OP :
  942. if ( pStubMsg->IgnoreEmbeddedPointers )
  943. goto ComplexArrayBufSizeEnd;
  944. pfnSize = (PSIZE_ROUTINE) NdrpPointerBufferSize;
  945. // Need this in case we have a variant offset.
  946. MemoryElementSize = PTR_MEM_SIZE;
  947. break;
  948. case FC_IP :
  949. if ( pStubMsg->IgnoreEmbeddedPointers )
  950. return;
  951. pfnSize = NdrInterfacePointerBufferSize;
  952. // Need this in case we have a variant offset.
  953. MemoryElementSize = PTR_MEM_SIZE;
  954. break;
  955. default :
  956. NDR_ASSERT( IS_SIMPLE_TYPE(*pFormat),
  957. "NdrpComplexArrayBufferSize : bad format char" );
  958. pStubMsg->BufferLength += Count * SIMPLE_TYPE_BUFSIZE(*pFormat);
  959. goto ComplexArrayBufSizeEnd;
  960. }
  961. //
  962. // If there is variance then increment the memory pointer to the first
  963. // element actually being sized.
  964. //
  965. if ( Offset )
  966. pMemory += Offset * MemoryElementSize;
  967. if ( (pfnSize == (PSIZE_ROUTINE) NdrpPointerBufferSize) ||
  968. (pfnSize == NdrInterfacePointerBufferSize) )
  969. {
  970. pStubMsg->pArrayInfo = 0;
  971. if ( pfnSize == (PSIZE_ROUTINE) NdrpPointerBufferSize )
  972. {
  973. for ( ; Count--; )
  974. {
  975. NdrpPointerBufferSize( pStubMsg,
  976. *((uchar **)pMemory)++,
  977. pFormat );
  978. }
  979. }
  980. else
  981. {
  982. for ( ; Count--; )
  983. {
  984. NdrInterfacePointerBufferSize( pStubMsg,
  985. *((uchar **)pMemory)++,
  986. pFormat );
  987. }
  988. }
  989. goto ComplexArrayBufSizeEnd;
  990. }
  991. //
  992. // Array of complex types.
  993. //
  994. if ( ! IS_ARRAY_OR_STRING(*pFormat) )
  995. pStubMsg->pArrayInfo = 0;
  996. for ( ; Count--; )
  997. {
  998. // Keep track of multidimensional array dimension.
  999. if ( IS_ARRAY_OR_STRING(*pFormat) )
  1000. pArrayInfo->Dimension = Dimension + 1;
  1001. (*pfnSize)( pStubMsg,
  1002. pMemory,
  1003. pFormat );
  1004. pMemory += MemoryElementSize;
  1005. }
  1006. ComplexArrayBufSizeEnd:
  1007. // pArrayInfo must be zero when not valid.
  1008. pStubMsg->pArrayInfo = (Dimension == 0) ? 0 : pArrayInfo;
  1009. }
  1010. void RPC_ENTRY
  1011. NdrNonConformantStringBufferSize(
  1012. PMIDL_STUB_MESSAGE pStubMsg,
  1013. uchar * pMemory,
  1014. PFORMAT_STRING pFormat )
  1015. /*++
  1016. Routine Description :
  1017. Computes the buffer size needed for a non conformant string.
  1018. Used for FC_CSTRING, FC_WSTRING, FC_SSTRING, and FC_BSTRING (NT Beta2
  1019. compatability only).
  1020. Arguments :
  1021. pStubMsg - Pointer to the stub message.
  1022. pMemory - Pointer to the array being sized.
  1023. pFormat - Array's format string description.
  1024. Return :
  1025. None.
  1026. --*/
  1027. {
  1028. long MaxSize;
  1029. long Length;
  1030. // Align and add size for variance counts.
  1031. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  1032. pStubMsg->BufferLength += 8;
  1033. switch ( *pFormat )
  1034. {
  1035. case FC_CSTRING :
  1036. case FC_BSTRING :
  1037. Length = MIDL_ascii_strlen(pMemory) + 1;
  1038. break;
  1039. case FC_WSTRING :
  1040. Length = (MIDL_wchar_strlen((wchar_t *)pMemory) + 1) * 2;
  1041. break;
  1042. case FC_SSTRING :
  1043. Length = NdrpStringStructLen( pMemory, pFormat[1] ) + 1;
  1044. Length *= pFormat[1];
  1045. break;
  1046. default :
  1047. NDR_ASSERT(0,"NdrNonConformantStringBufferSize : Bad format type");
  1048. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  1049. return;
  1050. }
  1051. if ( pStubMsg->fCheckBounds )
  1052. {
  1053. MaxSize = *((ushort *)(pFormat + 2));
  1054. switch ( *pFormat )
  1055. {
  1056. case FC_WSTRING :
  1057. MaxSize *= 2;
  1058. break;
  1059. case FC_SSTRING :
  1060. MaxSize *= pFormat[1];
  1061. break;
  1062. default :
  1063. break;
  1064. }
  1065. if ( Length > MaxSize )
  1066. RpcRaiseException(RPC_X_INVALID_BOUND);
  1067. }
  1068. pStubMsg->BufferLength += Length;
  1069. }
  1070. void RPC_ENTRY
  1071. NdrConformantStringBufferSize(
  1072. PMIDL_STUB_MESSAGE pStubMsg,
  1073. uchar * pMemory,
  1074. PFORMAT_STRING pFormat )
  1075. /*++
  1076. Routine Description :
  1077. Computes the buffer size needed for a top level conformant string.
  1078. Used for FC_C_CSTRING, FC_C_WSTRING, FC_C_SSTRING, and FC_C_BSTRING
  1079. (NT Beta2 compatability only).
  1080. Arguments :
  1081. pStubMsg - Pointer to the stub message.
  1082. pMemory - Pointer to the array being sized.
  1083. pFormat - Array's format string description.
  1084. Return :
  1085. None.
  1086. --*/
  1087. {
  1088. //
  1089. // Add in size for conformance marshalling only if this string is not
  1090. // in a multidimensional array.
  1091. //
  1092. if ( pStubMsg->pArrayInfo == 0 )
  1093. {
  1094. // Align and add size for conformance count.
  1095. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  1096. pStubMsg->BufferLength += 4;
  1097. }
  1098. NdrpConformantStringBufferSize( pStubMsg,
  1099. pMemory,
  1100. pFormat );
  1101. }
  1102. void
  1103. NdrpConformantStringBufferSize(
  1104. PMIDL_STUB_MESSAGE pStubMsg,
  1105. uchar * pMemory,
  1106. PFORMAT_STRING pFormat )
  1107. /*++
  1108. Routine Description :
  1109. Private routine for computing the buffer size needed for a conformant
  1110. string. This is the entry point for an embedded conformant string.
  1111. Used for FC_C_CSTRING, FC_C_WSTRING, FC_C_SSTRING, and FC_C_BSTRING
  1112. (NT Beta2 compatability only).
  1113. Arguments :
  1114. pStubMsg - Pointer to the stub message.
  1115. pMemory - Pointer to the array being sized.
  1116. pFormat - Array's format string description.
  1117. Return :
  1118. None.
  1119. --*/
  1120. {
  1121. long MaxSize;
  1122. long Length;
  1123. // Align and add size for variance.
  1124. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  1125. pStubMsg->BufferLength += 8;
  1126. switch ( *pFormat )
  1127. {
  1128. case FC_C_CSTRING :
  1129. case FC_C_BSTRING :
  1130. Length = MIDL_ascii_strlen(pMemory) + 1;
  1131. break;
  1132. case FC_C_WSTRING :
  1133. Length = (MIDL_wchar_strlen((wchar_t *)pMemory) + 1) * 2;
  1134. break;
  1135. case FC_C_SSTRING :
  1136. Length = NdrpStringStructLen( pMemory, pFormat[1] ) + 1;
  1137. Length *= pFormat[1];
  1138. break;
  1139. default :
  1140. NDR_ASSERT(0,"NdrpConformantStringBufferSize : Bad format type");
  1141. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  1142. return;
  1143. }
  1144. //
  1145. // Do bounds checking if needed.
  1146. //
  1147. if ( pStubMsg->fCheckBounds )
  1148. {
  1149. if ( ((*pFormat != FC_C_SSTRING) && (pFormat[1] == FC_STRING_SIZED)) ||
  1150. ((*pFormat == FC_C_SSTRING) && (pFormat[2] == FC_STRING_SIZED)) )
  1151. {
  1152. MaxSize = NdrpComputeConformance( pStubMsg,
  1153. pMemory,
  1154. pFormat );
  1155. switch ( *pFormat )
  1156. {
  1157. case FC_C_WSTRING :
  1158. MaxSize *= 2;
  1159. break;
  1160. case FC_C_SSTRING :
  1161. MaxSize *= pFormat[1];
  1162. break;
  1163. default :
  1164. break;
  1165. }
  1166. if ( (MaxSize < 0) || (Length > MaxSize) )
  1167. RpcRaiseException(RPC_X_INVALID_BOUND);
  1168. }
  1169. }
  1170. pStubMsg->BufferLength += Length;
  1171. }
  1172. void RPC_ENTRY
  1173. NdrEncapsulatedUnionBufferSize(
  1174. PMIDL_STUB_MESSAGE pStubMsg,
  1175. uchar * pMemory,
  1176. PFORMAT_STRING pFormat )
  1177. /*++
  1178. Routine Description :
  1179. Computes the buffer size needed for an encapsulated union.
  1180. Used for FC_ENCAPSULATED_UNION.
  1181. Arguments :
  1182. pStubMsg - Pointer to the stub message.
  1183. pMemory - Pointer to the union being sized.
  1184. pFormat - Union's format string description.
  1185. Return :
  1186. None.
  1187. --*/
  1188. {
  1189. long SwitchIs;
  1190. uchar SwitchType;
  1191. SwitchType = LOW_NIBBLE(pFormat[1]);
  1192. switch ( SwitchType )
  1193. {
  1194. case FC_SMALL :
  1195. case FC_CHAR :
  1196. SwitchIs = (long) *((char *)pMemory);
  1197. break;
  1198. case FC_USMALL :
  1199. SwitchIs = (long) *((uchar *)pMemory);
  1200. break;
  1201. case FC_ENUM16 :
  1202. #if defined(__RPC_MAC__)
  1203. SwitchIs = (long) *((short *)(pMemory+2));
  1204. break;
  1205. #endif
  1206. // non-Mac: fall to short
  1207. case FC_SHORT :
  1208. SwitchIs = (long) *((short *)pMemory);
  1209. break;
  1210. case FC_USHORT :
  1211. case FC_WCHAR :
  1212. SwitchIs = (long) *((ushort *)pMemory);
  1213. break;
  1214. case FC_LONG :
  1215. case FC_ULONG :
  1216. case FC_ENUM32 :
  1217. SwitchIs = *((long *)pMemory);
  1218. break;
  1219. default :
  1220. NDR_ASSERT(0,"NdrEncapsulatedBufferSize : bad switch type");
  1221. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  1222. return;
  1223. }
  1224. // Increment memory pointer to the union.
  1225. pMemory += HIGH_NIBBLE(pFormat[1]);
  1226. NdrpUnionBufferSize( pStubMsg,
  1227. pMemory,
  1228. pFormat + 2,
  1229. SwitchIs,
  1230. SwitchType );
  1231. }
  1232. void RPC_ENTRY
  1233. NdrNonEncapsulatedUnionBufferSize(
  1234. PMIDL_STUB_MESSAGE pStubMsg,
  1235. uchar * pMemory,
  1236. PFORMAT_STRING pFormat )
  1237. /*++
  1238. Routine Description :
  1239. Computes the buffer size needed for a non encapsulated union.
  1240. Used for FC_NON_ENCAPSULATED_UNION.
  1241. Arguments :
  1242. pStubMsg - Pointer to the stub message.
  1243. pMemory - Pointer to the union being sized.
  1244. pFormat - Union's format string description.
  1245. Return :
  1246. None.
  1247. --*/
  1248. {
  1249. long SwitchIs;
  1250. uchar SwitchType;
  1251. SwitchType = pFormat[1];
  1252. SwitchIs = NdrpComputeSwitchIs( pStubMsg,
  1253. pMemory,
  1254. pFormat );
  1255. //
  1256. // Set the format string to the memory size and arm description.
  1257. //
  1258. pFormat += 6;
  1259. pFormat += *((signed short *)pFormat);
  1260. NdrpUnionBufferSize( pStubMsg,
  1261. pMemory,
  1262. pFormat,
  1263. SwitchIs,
  1264. SwitchType );
  1265. }
  1266. void
  1267. NdrpUnionBufferSize(
  1268. PMIDL_STUB_MESSAGE pStubMsg,
  1269. uchar * pMemory,
  1270. PFORMAT_STRING pFormat,
  1271. long SwitchIs,
  1272. uchar SwitchType )
  1273. /*++
  1274. Routine Description :
  1275. Private routine for computing the buffer size needed for a union. This
  1276. routine is used for sizing both encapsulated and non-encapsulated unions.
  1277. Arguments :
  1278. pStubMsg - Pointer to the stub message.
  1279. pMemory - Pointer to the union being sized.
  1280. pFormat - Union's format string description.
  1281. SwitchIs - The union's switch is.
  1282. SwitchType - The union's switch type.
  1283. Return :
  1284. None.
  1285. --*/
  1286. {
  1287. long Arms;
  1288. long Alignment;
  1289. //
  1290. // Size the switch_is.
  1291. //
  1292. LENGTH_ALIGN(pStubMsg->BufferLength,SIMPLE_TYPE_ALIGNMENT(SwitchType));
  1293. pStubMsg->BufferLength += SIMPLE_TYPE_BUFSIZE(SwitchType);
  1294. // Skip the memory size field.
  1295. pFormat += 2;
  1296. //
  1297. // Get the union alignment (0 if this is a DCE union) and align the
  1298. // buffer on this alignment.
  1299. //
  1300. Alignment = (uchar) ( *((ushort *)pFormat) >> 12 );
  1301. LENGTH_ALIGN(pStubMsg->BufferLength,Alignment);
  1302. Arms = (long) ( *((ushort *)pFormat)++ & 0x0fff );
  1303. //
  1304. // Search for the arm.
  1305. //
  1306. for ( ; Arms; Arms-- )
  1307. {
  1308. if ( *((long UNALIGNED *)pFormat)++ == SwitchIs )
  1309. {
  1310. //
  1311. // Found the right arm, break out.
  1312. //
  1313. break;
  1314. }
  1315. // Else increment format string.
  1316. pFormat += 2;
  1317. }
  1318. //
  1319. // Check if we took the default arm and no default arm is specified.
  1320. //
  1321. if ( ! Arms && (*((ushort *)pFormat) == (ushort) 0xffff) )
  1322. {
  1323. RpcRaiseException( RPC_S_INVALID_TAG );
  1324. }
  1325. //
  1326. // Return if the arm is empty.
  1327. //
  1328. if ( ! *((ushort *)pFormat) )
  1329. return;
  1330. //
  1331. // Get the arm's description.
  1332. //
  1333. // We need a real solution after beta for simple type arms. This could
  1334. // break if we have a format string larger than about 32K.
  1335. //
  1336. if ( IS_MAGIC_UNION_BYTE(pFormat) )
  1337. {
  1338. // Re-align again, only does something usefull for DCE unions.
  1339. unsigned char FcType;
  1340. #if defined(__RPC_MAC__)
  1341. FcType = pFormat[1];
  1342. #else
  1343. FcType = pFormat[0];
  1344. #endif
  1345. LENGTH_ALIGN( pStubMsg->BufferLength, SIMPLE_TYPE_ALIGNMENT( FcType ));
  1346. pStubMsg->BufferLength += SIMPLE_TYPE_BUFSIZE( FcType );
  1347. return;
  1348. }
  1349. pFormat += *((signed short *)pFormat);
  1350. //
  1351. // If the union arm we take is a pointer, we have to dereference the
  1352. // current memory pointer since we're passed a pointer to the union
  1353. // (regardless of whether the actual parameter was a by-value union
  1354. // or a pointer to a union).
  1355. //
  1356. if ( IS_POINTER_TYPE(*pFormat) )
  1357. {
  1358. //
  1359. // If we're ignoring pointers then just add in the size of a pointer
  1360. // here and return.
  1361. //
  1362. if ( pStubMsg->IgnoreEmbeddedPointers )
  1363. {
  1364. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  1365. pStubMsg->BufferLength += 4;
  1366. return;
  1367. }
  1368. pMemory = *((uchar **)pMemory);
  1369. }
  1370. // Call the appropriate sizing routine
  1371. (*pfnSizeRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  1372. pMemory,
  1373. pFormat );
  1374. }
  1375. void RPC_ENTRY
  1376. NdrByteCountPointerBufferSize(
  1377. PMIDL_STUB_MESSAGE pStubMsg,
  1378. uchar * pMemory,
  1379. PFORMAT_STRING pFormat )
  1380. /*++
  1381. Routine Description :
  1382. Computes the buffer size needed for a byte count pointer.
  1383. Arguments :
  1384. pStubMsg - Pointer to the stub message.
  1385. pMemory - The byte count pointer being sized.
  1386. pFormat - Byte count pointer's format string description.
  1387. Return :
  1388. None.
  1389. --*/
  1390. {
  1391. //
  1392. // We don't do anything special here. Just pass things on to the
  1393. // right sizing routine.
  1394. //
  1395. if ( pFormat[1] != FC_PAD )
  1396. {
  1397. SIMPLE_TYPE_BUF_INCREMENT(pStubMsg->BufferLength, pFormat[1]);
  1398. }
  1399. else
  1400. {
  1401. pFormat += 6;
  1402. pFormat += *((signed short *)pFormat);
  1403. (*pfnSizeRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  1404. pMemory,
  1405. pFormat );
  1406. }
  1407. }
  1408. // This has been introduced because of C compiler problems.
  1409. #if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
  1410. #pragma optimize( "", off )
  1411. #endif
  1412. void RPC_ENTRY
  1413. NdrXmitOrRepAsBufferSize(
  1414. PMIDL_STUB_MESSAGE pStubMsg,
  1415. uchar * pMemory,
  1416. PFORMAT_STRING pFormat )
  1417. /*++
  1418. Routine Description :
  1419. Computes the buffer size needed for a transmit as or represent as object.
  1420. See mrshl.c for the description of the FC layout.
  1421. Arguments :
  1422. pStubMsg - Pointer to the stub message.
  1423. pMemory - Pointer to the transmit/represent as object being sized.
  1424. pFormat - Object's format string description.
  1425. Return :
  1426. None.
  1427. --*/
  1428. {
  1429. const XMIT_ROUTINE_QUINTUPLE * pQuintuple;
  1430. unsigned short QIndex, XmitTypeSize;
  1431. BOOL fXmitByPtr = *pFormat == FC_TRANSMIT_AS_PTR ||
  1432. *pFormat == FC_REPRESENT_AS_PTR;
  1433. // Fetch the QuintupleIndex.
  1434. QIndex = *(unsigned short *)(pFormat + 2);
  1435. // We size the transmitted object, of course.
  1436. pFormat += 6;
  1437. XmitTypeSize = *((unsigned short *)pFormat);
  1438. pQuintuple = pStubMsg->StubDesc->aXmitQuintuple;
  1439. if ( XmitTypeSize )
  1440. {
  1441. // lower nibble of the flag word has the alignment
  1442. unsigned long Align = LOW_NIBBLE(*(pFormat - 5));
  1443. LENGTH_ALIGN( pStubMsg->BufferLength, Align );
  1444. pStubMsg->BufferLength += XmitTypeSize;
  1445. }
  1446. else
  1447. {
  1448. // We have to create an object to size it.
  1449. unsigned char __RPC_FAR * pTransmittedType;
  1450. // First translate the presented type into the transmitted type.
  1451. // This includes an allocation of a transmitted type object.
  1452. pStubMsg->pPresentedType = pMemory;
  1453. pStubMsg->pTransmitType = NULL;
  1454. pQuintuple[ QIndex ].pfnTranslateToXmit( pStubMsg );
  1455. // bufsize the transmitted type.
  1456. pFormat += 2;
  1457. pFormat = pFormat + *(short *)pFormat;
  1458. pTransmittedType = pStubMsg->pTransmitType;
  1459. // If transmitted type is a pointer, dereference it.
  1460. (*pfnSizeRoutines[ ROUTINE_INDEX(*pFormat) ])
  1461. ( pStubMsg,
  1462. fXmitByPtr ? *(uchar **)pTransmittedType
  1463. : pTransmittedType,
  1464. pFormat );
  1465. pStubMsg->pTransmitType = pTransmittedType;
  1466. // Free the temporary transmitted object (it was alloc'ed by the user).
  1467. pQuintuple[ QIndex ].pfnFreeXmit( pStubMsg );
  1468. }
  1469. }
  1470. #if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
  1471. #pragma optimize( "", on )
  1472. #endif
  1473. void RPC_ENTRY
  1474. NdrUserMarshalBufferSize(
  1475. PMIDL_STUB_MESSAGE pStubMsg,
  1476. uchar * pMemory,
  1477. PFORMAT_STRING pFormat )
  1478. /*++
  1479. Routine Description :
  1480. Computes the buffer size needed for a usr_marshall object.
  1481. See mrshl.c for the description of the FC layout and wire layout.
  1482. Arguments :
  1483. pStubMsg - Pointer to the stub message.
  1484. pMemory - Pointer to the usr_marshall object to buffer size.
  1485. pFormat - Object's format string description.
  1486. Return :
  1487. None.
  1488. --*/
  1489. {
  1490. const USER_MARSHAL_ROUTINE_QUADRUPLE * pQuadruple;
  1491. unsigned short QIndex;
  1492. unsigned long UserOffset;
  1493. USER_MARSHAL_CB UserMarshalCB;
  1494. // Align for the flat object or a pointer to the user object.
  1495. LENGTH_ALIGN( pStubMsg->BufferLength, LOW_NIBBLE(pFormat[1]) );
  1496. // Check if the object is embedded.
  1497. // Pointer buffer mark is set only when in a complex struct or array.
  1498. // For unions, when the union is embedded in a complex struct or array.
  1499. // If the union is top level, it's the same like a top level object.
  1500. // For unique pointers we don't have to check embedding, we always add 4.
  1501. // For ref pointer we need to check embedding.
  1502. if ( pFormat[1] & USER_MARSHAL_POINTER )
  1503. {
  1504. if ( (pFormat[1] & USER_MARSHAL_UNIQUE) ||
  1505. ((pFormat[1] & USER_MARSHAL_REF) && pStubMsg->PointerBufferMark) )
  1506. {
  1507. pStubMsg->BufferLength += 4;
  1508. }
  1509. // Ignore flag is off when called to do a regular buffer sizing.
  1510. // Ignore flag is on when called from within complex struct or array
  1511. // while marshalling to calculate the end of the complex struct.
  1512. if ( pStubMsg->IgnoreEmbeddedPointers )
  1513. return;
  1514. // For pointers we always call the user to size his stuff,
  1515. // Even if the unique pointer is null (he then may add nothing).
  1516. pStubMsg->BufferLength += 8;
  1517. }
  1518. // We are here to size a flat object or a pointee object.
  1519. // Optimization: if we know the wire size, don't call the user to size it.
  1520. if ( *(unsigned short *)(pFormat + 6) != 0 )
  1521. {
  1522. pStubMsg->BufferLength += *(unsigned short *)(pFormat + 6);
  1523. return;
  1524. }
  1525. // Unknown wire size: Call the user to size his stuff.
  1526. UserMarshalCB.Flags = USER_CALL_CTXT_MASK( pStubMsg->dwDestContext );
  1527. UserMarshalCB.pStubMsg = pStubMsg;
  1528. if ( pFormat[1] & USER_MARSHAL_IID )
  1529. {
  1530. UserMarshalCB.pReserve = pFormat + 10;
  1531. }
  1532. else
  1533. {
  1534. UserMarshalCB.pReserve = 0;
  1535. }
  1536. UserOffset = pStubMsg->BufferLength;
  1537. QIndex = *(unsigned short *)(pFormat + 2);
  1538. pQuadruple = pStubMsg->StubDesc->aUserMarshalQuadruple;
  1539. UserOffset = pQuadruple[ QIndex ].pfnBufferSize( (ulong*) &UserMarshalCB,
  1540. UserOffset,
  1541. pMemory );
  1542. pStubMsg->BufferLength = UserOffset;
  1543. }
  1544. void RPC_ENTRY
  1545. NdrInterfacePointerBufferSize (
  1546. PMIDL_STUB_MESSAGE pStubMsg,
  1547. uchar * pMemory,
  1548. PFORMAT_STRING pFormat )
  1549. /*++
  1550. Routine Description :
  1551. Computes the buffer size needed for an interface pointer.
  1552. Arguments :
  1553. pStubMsg - Pointer to the stub message.
  1554. pMemory - The interface pointer being sized.
  1555. pFormat - Interface pointer's format string description.
  1556. Return :
  1557. None.
  1558. --*/
  1559. {
  1560. #if !defined( NDR_OLE_SUPPORT )
  1561. NDR_ASSERT(0, "Unimplemented");
  1562. #else //NT or Chicago
  1563. IID iid;
  1564. IID *piid;
  1565. unsigned long size = 0;
  1566. HRESULT hr;
  1567. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  1568. pStubMsg->BufferLength += (sizeof(void *));
  1569. //
  1570. // This means that the interface pointer is embedded in a structure
  1571. // and we are computing the flat size of the structure.
  1572. //
  1573. if ( pStubMsg->IgnoreEmbeddedPointers )
  1574. return;
  1575. // If the pointer is null, we counted everything.
  1576. if ( pMemory == 0 )
  1577. return;
  1578. //
  1579. // Get an IID pointer.
  1580. //
  1581. if ( pFormat[1] != FC_CONSTANT_IID )
  1582. {
  1583. //
  1584. // We do it same way as we compute variance with a long.
  1585. //
  1586. piid = (IID *) NdrpComputeIIDPointer( pStubMsg,
  1587. pMemory,
  1588. pFormat );
  1589. if(piid == 0)
  1590. RpcRaiseException( RPC_S_INVALID_ARG );
  1591. }
  1592. else
  1593. {
  1594. //
  1595. // The IID may not be aligned properly in the format string,
  1596. // so we copy it to a local variable.
  1597. //
  1598. piid = &iid;
  1599. RpcpMemoryCopy( &iid, &pFormat[2], sizeof(iid) );
  1600. }
  1601. // Allocate space for the length and array bounds.
  1602. pStubMsg->BufferLength += sizeof(unsigned long) + sizeof(unsigned long);
  1603. if(pMemory)
  1604. {
  1605. hr = (*pfnCoGetMarshalSizeMax)(&size, piid, (IUnknown *)pMemory, pStubMsg->dwDestContext, pStubMsg->pvDestContext, 0);
  1606. if(FAILED(hr))
  1607. {
  1608. RpcRaiseException(hr);
  1609. }
  1610. pStubMsg->BufferLength += size;
  1611. }
  1612. #endif //NT or Chicago
  1613. }
  1614. void
  1615. NdrpEmbeddedPointerBufferSize (
  1616. PMIDL_STUB_MESSAGE pStubMsg,
  1617. uchar * pMemory,
  1618. PFORMAT_STRING pFormat )
  1619. /*++
  1620. Routine Description :
  1621. Private routine for computing the buffer size needed for a structure's
  1622. or array's embedded pointers.
  1623. Arguments :
  1624. pStubMsg - Pointer to the stub message.
  1625. pMemory - Pointer to the embedding structure or array.
  1626. pFormat - Format string pointer layout description.
  1627. Return :
  1628. None.
  1629. --*/
  1630. {
  1631. void ** ppMemPtr;
  1632. uchar * pMemorySave;
  1633. long MaxCountSave, OffsetSave;
  1634. MaxCountSave = pStubMsg->MaxCount;
  1635. OffsetSave = pStubMsg->Offset;
  1636. if ( pStubMsg->IgnoreEmbeddedPointers )
  1637. return;
  1638. pMemorySave = pStubMsg->Memory;
  1639. // Set new memory context.
  1640. pStubMsg->Memory = pMemory;
  1641. //
  1642. // Increment past the FC_PP and pad.
  1643. //
  1644. pFormat += 2;
  1645. for (;;)
  1646. {
  1647. if ( *pFormat == FC_END )
  1648. {
  1649. pStubMsg->Memory = pMemorySave;
  1650. return;
  1651. }
  1652. //
  1653. // Check for FC_FIXED_REPEAT or FC_VARIABLE_REPEAT.
  1654. //
  1655. if ( *pFormat != FC_NO_REPEAT )
  1656. {
  1657. pStubMsg->MaxCount = MaxCountSave;
  1658. pStubMsg->Offset = OffsetSave;
  1659. NdrpEmbeddedRepeatPointerBufferSize( pStubMsg,
  1660. pMemory,
  1661. &pFormat );
  1662. // Continue to the next pointer.
  1663. continue;
  1664. }
  1665. // Compute the pointer to the pointer in memory to size.
  1666. ppMemPtr = (void **) (pMemory + *((signed short *)(pFormat + 2)));
  1667. // Increment to the pointer description.
  1668. pFormat += 6;
  1669. NdrpPointerBufferSize( pStubMsg,
  1670. *ppMemPtr,
  1671. pFormat );
  1672. // Increment past pointer description.
  1673. pFormat += 4;
  1674. }
  1675. }
  1676. void
  1677. NdrpEmbeddedRepeatPointerBufferSize (
  1678. PMIDL_STUB_MESSAGE pStubMsg,
  1679. uchar * pMemory,
  1680. PFORMAT_STRING * ppFormat )
  1681. /*++
  1682. Routine Description :
  1683. Private routine for computing the buffer size needed for an array's
  1684. embedded pointers.
  1685. Arguments :
  1686. pStubMsg - Pointer to the stub message.
  1687. pMemory - Pointer to the embedding array.
  1688. pFormat - The array's format string pointer layout description.
  1689. Return :
  1690. None.
  1691. --*/
  1692. {
  1693. uchar ** ppMemPtr;
  1694. PFORMAT_STRING pFormat;
  1695. PFORMAT_STRING pFormatSave;
  1696. uchar * pMemorySave;
  1697. ulong RepeatCount, RepeatIncrement, Pointers, PointersSave;
  1698. pMemorySave = pStubMsg->Memory;
  1699. // Get current format string pointer.
  1700. pFormat = *ppFormat;
  1701. switch ( *pFormat )
  1702. {
  1703. case FC_FIXED_REPEAT :
  1704. // Increment past the FC_FIXED_REPEAT and FC_PAD.
  1705. pFormat += 2;
  1706. // Get the total number of times to repeat the pointer marshall.
  1707. RepeatCount = *((ushort *)pFormat)++;
  1708. break;
  1709. case FC_VARIABLE_REPEAT :
  1710. // Get the total number of times to repeat the pointer marshall.
  1711. RepeatCount = pStubMsg->MaxCount;
  1712. //
  1713. // Check if this variable repeat instance also has a variable
  1714. // offset (this would be the case for a conformant varying array
  1715. // of pointers). If so then increment the memory pointer to point
  1716. // to the actual first array element which is being marshalled.
  1717. //
  1718. if ( pFormat[1] == FC_VARIABLE_OFFSET )
  1719. pMemory += *((ushort *)(pFormat + 2)) * pStubMsg->Offset;
  1720. // else pFormat[1] == FC_FIXED_OFFSET - do nothing
  1721. // Increment past the FC_VARIABLE_REPEAT and FC_PAD.
  1722. pFormat += 2;
  1723. break;
  1724. default :
  1725. NDR_ASSERT(0,"NdrpEmbeddedRepeatPointerMarshall : bad format char");
  1726. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  1727. return;
  1728. }
  1729. // Get the increment amount between successive pointers.
  1730. RepeatIncrement = *((ushort *)pFormat)++;
  1731. //
  1732. // Add the offset to the beginning of this array to the Memory
  1733. // pointer. This is the offset from any currently embedding structure
  1734. // to the array whose pointers we're marshalling.
  1735. //
  1736. pStubMsg->Memory += *((ushort *)pFormat)++;
  1737. // Get the number of pointers in this repeat instance.
  1738. PointersSave = Pointers = *((ushort *)pFormat)++;
  1739. pFormatSave = pFormat;
  1740. //
  1741. // Loop over the number of elements in the array.
  1742. //
  1743. for ( ; RepeatCount--;
  1744. pMemory += RepeatIncrement,
  1745. pStubMsg->Memory += RepeatIncrement )
  1746. {
  1747. pFormat = pFormatSave;
  1748. Pointers = PointersSave;
  1749. //
  1750. // Loop over the number of pointers in each array element (this can
  1751. // be greater than one if we have an array of structures).
  1752. //
  1753. for ( ; Pointers--; )
  1754. {
  1755. // Pointer to the pointer in memory.
  1756. ppMemPtr = (uchar **)(pMemory + *((signed short *)pFormat));
  1757. // Increment to pointer description.
  1758. pFormat += 4;
  1759. NdrpPointerBufferSize( pStubMsg,
  1760. *ppMemPtr,
  1761. pFormat );
  1762. // Increment to the next pointer description.
  1763. pFormat += 4;
  1764. }
  1765. }
  1766. // Update format string pointer past this repeat pointer description.
  1767. *ppFormat = pFormatSave + PointersSave * 8;
  1768. pStubMsg->Memory = pMemorySave;
  1769. }
  1770. void RPC_ENTRY
  1771. NdrContextHandleSize(
  1772. PMIDL_STUB_MESSAGE pStubMsg,
  1773. uchar * pMemory,
  1774. PFORMAT_STRING pFormat )
  1775. /*++
  1776. Routine Description :
  1777. Computes the buffer size needed for a context handle.
  1778. Arguments :
  1779. pStubMsg - Pointer to the stub message.
  1780. pMemory - Ignored.
  1781. pFormat - Ignored.
  1782. Return :
  1783. None.
  1784. --*/
  1785. {
  1786. LENGTH_ALIGN(pStubMsg->BufferLength,0x3);
  1787. pStubMsg->BufferLength += 20;
  1788. }