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.

2912 lines
75 KiB

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