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.

866 lines
24 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name :
  4. mrshlp.c
  5. Abstract :
  6. This file contains the routines for marshalling an array's or a structure's
  7. embedded pointers and for computing conformance and variance counts and
  8. union switch values.
  9. Author :
  10. David Kays dkays September 1993.
  11. Revision History :
  12. ---------------------------------------------------------------------*/
  13. #include "ndrp.h"
  14. #include "attack.h"
  15. #include "interp2.h"
  16. #include "mulsyntx.h"
  17. #include "asyncu.h"
  18. #include "pointerq.h"
  19. PFORMAT_STRING
  20. NdrpEmbeddedPointerMarshall(
  21. PMIDL_STUB_MESSAGE pStubMsg,
  22. uchar * pMemory,
  23. PFORMAT_STRING pFormat )
  24. /*++
  25. Routine Description :
  26. Marshalls an array's or a structure's embedded pointers.
  27. Arguments :
  28. pStubMsg - Pointer to the stub message.
  29. pMemory - Pointer to the structure or array whose embedded pointers
  30. are being marshalled.
  31. pFormat - The format string pointer layout. Should point to the
  32. pointer layout's beginning FC_PP character upon entry.
  33. Return :
  34. Format string pointer after the pointer layout.
  35. --*/
  36. {
  37. uchar ** ppMemPtr;
  38. uchar * pBufPtr;
  39. uchar * pBufferMark;
  40. uchar * pMemorySave;
  41. ULONG_PTR MaxCountSave;
  42. long OffsetSave;
  43. MaxCountSave = pStubMsg->MaxCount;
  44. OffsetSave = pStubMsg->Offset;
  45. POINTER_BUFFER_SWAP_CONTEXT SwapContext(pStubMsg);
  46. pMemorySave = pStubMsg->Memory;
  47. // This is where the embedding structure or array begins in the buffer.
  48. pBufferMark = pStubMsg->BufferMark;
  49. //
  50. // The Memory field in the stub message keeps track of the pointer to
  51. // the current embedding structure or array. This is needed to handle
  52. // size/length pointers, so that we can get a pointer to the current
  53. // embedding struct when computing conformance and variance.
  54. //
  55. pStubMsg->Memory = pMemory;
  56. // Skip FC_PP and FC_PAD.
  57. pFormat += 2;
  58. for (;;)
  59. {
  60. if ( *pFormat == FC_END )
  61. {
  62. pStubMsg->Memory = pMemorySave;
  63. return pFormat;
  64. }
  65. //
  66. // Check for FC_FIXED_REPEAT and FC_VARIABLE_REPEAT.
  67. //
  68. if ( *pFormat != FC_NO_REPEAT )
  69. {
  70. pStubMsg->MaxCount = MaxCountSave;
  71. pStubMsg->Offset = OffsetSave;
  72. pStubMsg->BufferMark = pBufferMark;
  73. pFormat = NdrpEmbeddedRepeatPointerMarshall( pStubMsg,
  74. pMemory,
  75. pFormat );
  76. // Continue to the next pointer.
  77. continue;
  78. }
  79. // Compute the pointer to the pointer to marshall.
  80. ppMemPtr = (uchar **)(pMemory + *((signed short *)(pFormat + 2)));
  81. //
  82. // Compute the location in the buffer where the pointer's value will be
  83. // marshalled. Needed for full pointers.
  84. //
  85. pBufPtr = pBufferMark + *((signed short *)(pFormat + 4));
  86. // Increment to the pointer description.
  87. pFormat += 6;
  88. //
  89. // Now marshall the pointer.
  90. //
  91. NdrpPointerMarshall( pStubMsg,
  92. pBufPtr,
  93. *ppMemPtr,
  94. pFormat );
  95. // Increment to the next pointer description.
  96. pFormat += 4;
  97. } // for
  98. }
  99. PFORMAT_STRING
  100. NdrpEmbeddedRepeatPointerMarshall(
  101. PMIDL_STUB_MESSAGE pStubMsg,
  102. uchar * pMemory,
  103. PFORMAT_STRING pFormat )
  104. /*++
  105. Routine Description :
  106. Marshalls an array's embedded pointers.
  107. Arguments :
  108. pStubMsg - Pointer to the stub message.
  109. pMemory - Array whose embedded pointers are being marshalled.
  110. pFormat - Pointer layout format string description.
  111. Return :
  112. Format string pointer after the pointer layout.
  113. --*/
  114. {
  115. uchar ** ppMemPtr;
  116. uchar * pBufPtr;
  117. PFORMAT_STRING pFormatSave;
  118. uchar * pMemorySave;
  119. uchar * pBufferMark;
  120. ulong RepeatCount, RepeatIncrement, Pointers, PointersSave;
  121. pMemorySave = pStubMsg->Memory;
  122. //
  123. // This is where the current embedding structure or array begins in
  124. // the buffer.
  125. //
  126. pBufferMark = pStubMsg->BufferMark;
  127. // Get the number of shipped elements in the array.
  128. switch ( *pFormat )
  129. {
  130. case FC_FIXED_REPEAT :
  131. pFormat += 2;
  132. RepeatCount = *((ushort *)pFormat);
  133. break;
  134. case FC_VARIABLE_REPEAT :
  135. RepeatCount = (ulong)pStubMsg->MaxCount;
  136. //
  137. // Check if this variable repeat instance also has a variable
  138. // offset (this would be the case for a conformant varying array
  139. // of pointers). If so then increment the memory pointer by the
  140. // increment size time the variance offset.
  141. //
  142. if ( pFormat[1] == FC_VARIABLE_OFFSET )
  143. pMemory += *((ushort *)(pFormat + 2)) * pStubMsg->Offset;
  144. // else pFormat[1] == FC_FIXED_OFFSET - do nothing
  145. break;
  146. default :
  147. NDR_ASSERT(0,"NdrpEmbeddedRepeatPointerMarshall : bad format char");
  148. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  149. return 0;
  150. }
  151. // Increment format string to increment field.
  152. pFormat += 2;
  153. // Get the increment amount between successive pointers.
  154. // This is actually an increment over the array element.
  155. RepeatIncrement = *((ushort * &)pFormat)++;
  156. //
  157. // Add the offset to the beginning of this array to the Memory
  158. // pointer. This is the offset from the current embedding structure
  159. // or array to the array whose pointers we're marshalling.
  160. //
  161. pStubMsg->Memory += *((ushort * &)pFormat)++;
  162. // Get the number of pointers in this repeat instance.
  163. PointersSave = Pointers = *((ushort * &)pFormat)++;
  164. pFormatSave = pFormat;
  165. //
  166. // Loop over the number of shipped elements of the array.
  167. //
  168. for ( ; RepeatCount--;
  169. pBufferMark += RepeatIncrement,
  170. pMemory += RepeatIncrement,
  171. pStubMsg->Memory += RepeatIncrement )
  172. {
  173. pFormat = pFormatSave;
  174. Pointers = PointersSave;
  175. //
  176. // Loop over the number of pointer per array element (could be
  177. // greater than one for an array of structures).
  178. //
  179. for ( ; Pointers--; )
  180. {
  181. ppMemPtr = (uchar **)(pMemory + *((signed short * &)pFormat)++);
  182. pBufPtr = pBufferMark + *((signed short * &)pFormat)++;
  183. NdrpPointerMarshall( pStubMsg,
  184. pBufPtr,
  185. *ppMemPtr,
  186. pFormat );
  187. // Increment to the next pointer's offset_in_memory.
  188. pFormat += 4;
  189. }
  190. }
  191. pStubMsg->Memory = pMemorySave;
  192. // Return the format string pointer past the pointer descriptions.
  193. return pFormatSave + PointersSave * 8;
  194. }
  195. ULONG_PTR
  196. NdrpComputeConformance (
  197. PMIDL_STUB_MESSAGE pStubMsg,
  198. uchar * pMemory,
  199. PFORMAT_STRING pFormat )
  200. /*++
  201. Routine Description :
  202. This routine computes the conformant size for an array or the switch_is
  203. value for a union.
  204. Arguments :
  205. pStubMsg - Pointer to the stub message.
  206. pMemory - Pointer to the array, string, or union whose size or switch_is
  207. is being computed. This is ignored for top level parameters.
  208. pFormat - Format string description of the array, string, or union.
  209. Return :
  210. The array or string size or the union switch_is.
  211. Note:
  212. Async splitting:
  213. The only thing that the compiler should generate with the FC_SPLIT_* operations
  214. should be top level conformance.
  215. Expr evaluation routines and top level multi-dim sizing is not supported with
  216. the async uuid split.
  217. Note64:
  218. On 64b platform this routine is can return 8 bytes of a iid_is pointer.
  219. However, the MaxCount field does not need to keep it and it stays as a ulong.
  220. --*/
  221. {
  222. void * pCount;
  223. LONG_PTR Count;
  224. unsigned char FormatCopy[4];
  225. BOOL fAsyncSplit = FALSE;
  226. static uchar Increments[] =
  227. {
  228. 4, // Conformant array.
  229. 4, // Conformant varying array.
  230. 0, 0, // Fixed arrays - unused.
  231. 0, 0, // Varying arrays - unused.
  232. 4, // Complex array.
  233. 2, // Conformant char string.
  234. 2, // Conformant byte string.
  235. 4, // Conformant stringable struct.
  236. 2, // Conformant wide char string.
  237. 0, 0, 0, 0, // Non-conformant strings - unused.
  238. 0, // Encapsulated union - unused.
  239. 2, // Non-encapsulated union.
  240. 2, // Byte count pointer.
  241. 0, 0, // Xmit/Rep as - unused.
  242. 2 // Interface pointer.
  243. };
  244. //
  245. // Advance the format string to the size_is, switch_is, iid_is, or
  246. // byte count description.
  247. //
  248. pFormat += Increments[*pFormat - FC_CARRAY];
  249. pCount = 0;
  250. //
  251. // First check if this is a callback.
  252. //
  253. if ( pFormat[1] == FC_CALLBACK )
  254. {
  255. uchar * pOldStackTop;
  256. ushort Index;
  257. // Index into expression callback routines table.
  258. Index = *((ushort *)(pFormat + 2));
  259. NDR_ASSERT(pStubMsg->StubDesc->apfnExprEval != 0,
  260. "NdrpComputeConformance : no expr eval routines");
  261. NDR_ASSERT(pStubMsg->StubDesc->apfnExprEval[Index] != 0,
  262. "NdrpComputeConformance : bad expr eval routine index");
  263. pOldStackTop = pStubMsg->StackTop;
  264. //
  265. // The callback routine uses the StackTop field of the stub message
  266. // to base it's offsets from. So if this is a complex attribute for
  267. // an embedded field of a structure then set StackTop equal to the
  268. // pointer to the structure.
  269. //
  270. if ( (*pFormat & 0xf0) != FC_TOP_LEVEL_CONFORMANCE )
  271. {
  272. if ( (*pFormat & 0xf0) == FC_POINTER_CONFORMANCE )
  273. pMemory = pStubMsg->Memory;
  274. pStubMsg->StackTop = pMemory;
  275. }
  276. //
  277. // This call puts the result in pStubMsg->MaxCount.
  278. //
  279. (*pStubMsg->StubDesc->apfnExprEval[Index])( pStubMsg );
  280. pStubMsg->StackTop = pOldStackTop;
  281. return pStubMsg->MaxCount;
  282. }
  283. if ( (*pFormat & 0xf0) == FC_NORMAL_CONFORMANCE )
  284. {
  285. // Get the address where the conformance variable is in the struct.
  286. pCount = pMemory + *((signed short *)(pFormat + 2));
  287. goto ComputeConformantGetCount;
  288. }
  289. // See if this is an async split
  290. if ( pFormat[1] & 0x20 )
  291. {
  292. fAsyncSplit = TRUE;
  293. RpcpMemoryCopy( & FormatCopy[0], pFormat, 4 );
  294. pFormat = (PFORMAT_STRING) & FormatCopy[0];
  295. // Remove the async marker
  296. FormatCopy[1] = pFormat[1] & (unsigned char)~0x20;
  297. }
  298. //
  299. // Get a pointer to the conformance describing variable.
  300. //
  301. if ( (*pFormat & 0xf0) == FC_TOP_LEVEL_CONFORMANCE )
  302. {
  303. //
  304. // Top level conformance. For /Os stubs, the stubs put the max
  305. // count in the stub message. For /Oi stubs, we get the max count
  306. // via an offset from the stack top.
  307. //
  308. if ( pStubMsg->StackTop )
  309. {
  310. if ( fAsyncSplit )
  311. {
  312. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg;
  313. pAsyncMsg = (PNDR_DCOM_ASYNC_MESSAGE) pStubMsg->pAsyncMsg;
  314. pCount = pAsyncMsg->BeginStack + *((ushort *)(pFormat + 2));
  315. }
  316. else
  317. pCount = pStubMsg->StackTop + *((ushort *)(pFormat + 2));
  318. goto ComputeConformantGetCount;
  319. }
  320. else
  321. {
  322. //
  323. // If this is top level conformance with /Os then we don't have
  324. // to do anything, the proper conformance count is placed in the
  325. // stub message inline in the stubs.
  326. //
  327. return pStubMsg->MaxCount;
  328. }
  329. }
  330. //
  331. // If we're computing the size of an embedded sized pointer then we
  332. // use the memory pointer in the stub message, which points to the
  333. // beginning of the embedding structure.
  334. //
  335. if ( (*pFormat & 0xf0) == FC_POINTER_CONFORMANCE )
  336. {
  337. pMemory = pStubMsg->Memory;
  338. pCount = pMemory + *((signed short *)(pFormat + 2));
  339. goto ComputeConformantGetCount;
  340. }
  341. //
  342. // Check for constant size/switch.
  343. //
  344. if ( (*pFormat & 0xf0) == FC_CONSTANT_CONFORMANCE )
  345. {
  346. //
  347. // The size/switch is contained in the lower three bytes of the
  348. // long currently pointed to by pFormat.
  349. //
  350. Count = (LONG_PTR) ((ulong)pFormat[1] << 16);
  351. Count |= (LONG_PTR) *((ushort *)(pFormat + 2));
  352. goto ComputeConformanceEnd;
  353. }
  354. //
  355. // Check for conformance of a multidimensional array element in
  356. // a -Os stub.
  357. //
  358. if ( (*pFormat & 0xf0) == FC_TOP_LEVEL_MULTID_CONFORMANCE )
  359. {
  360. long Dimension;
  361. if ( fAsyncSplit )
  362. RpcRaiseException( RPC_X_WRONG_STUB_VERSION );
  363. //
  364. // If pArrayInfo is non-null than we have a multi-D array. If it
  365. // is null then we have multi-leveled sized pointers.
  366. //
  367. if ( pStubMsg->pArrayInfo )
  368. {
  369. Dimension = pStubMsg->pArrayInfo->Dimension;
  370. pStubMsg->MaxCount = pStubMsg->pArrayInfo->MaxCountArray[Dimension];
  371. }
  372. else
  373. {
  374. Dimension = *((ushort *)(pFormat + 2));
  375. pStubMsg->MaxCount = pStubMsg->SizePtrCountArray[Dimension];
  376. }
  377. return pStubMsg->MaxCount;
  378. }
  379. NDR_ASSERT(0, "NdrpComputeConformance:, Invalid Conformance type");
  380. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  381. return 0; //bogus return
  382. ComputeConformantGetCount:
  383. //
  384. // Must check now if there is a dereference op.
  385. //
  386. if ( pFormat[1] == FC_DEREFERENCE )
  387. {
  388. pCount = *(void **)pCount;
  389. }
  390. //
  391. // Now get the conformance count.
  392. //
  393. switch ( *pFormat & 0x0f )
  394. {
  395. case FC_HYPER :
  396. // iid_is on 64b platforms only.
  397. Count = *((LONG_PTR *)pCount);
  398. break;
  399. case FC_ULONG :
  400. Count = (LONG_PTR)*((ulong *)pCount);
  401. break;
  402. case FC_LONG :
  403. Count = *((long *)pCount);
  404. break;
  405. case FC_ENUM16:
  406. case FC_USHORT :
  407. Count = (long) *((ushort *)pCount);
  408. break;
  409. case FC_SHORT :
  410. Count = (long) *((short *)pCount);
  411. break;
  412. case FC_USMALL :
  413. Count = (long) *((uchar *)pCount);
  414. break;
  415. case FC_SMALL :
  416. Count = (long) *((char *)pCount);
  417. break;
  418. default :
  419. NDR_ASSERT(0,"NdrpComputeConformance : bad count type");
  420. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  421. return 0;
  422. }
  423. //
  424. // Check the operator.
  425. //
  426. switch ( pFormat[1] )
  427. {
  428. case FC_DIV_2 :
  429. Count /= 2;
  430. break;
  431. case FC_MULT_2 :
  432. Count *= 2;
  433. break;
  434. case FC_SUB_1 :
  435. Count -= 1;
  436. break;
  437. case FC_ADD_1 :
  438. Count += 1;
  439. break;
  440. default :
  441. // OK
  442. break;
  443. }
  444. ComputeConformanceEnd:
  445. // Max count is not used for iid_is.
  446. pStubMsg->MaxCount = (ulong) Count;
  447. return (ULONG_PTR) Count;
  448. }
  449. void
  450. NdrpComputeVariance (
  451. PMIDL_STUB_MESSAGE pStubMsg,
  452. uchar * pMemory,
  453. PFORMAT_STRING pFormat )
  454. /*++
  455. Routine Description :
  456. Computes the variance (offset and actual count) for an array.
  457. Arguments :
  458. pStubMsg - Pointer to the stub message.
  459. pMemory - Pointer to the array whose variance is being computed. This
  460. is unused for a top level parameter.
  461. pFormat - Format string description of the array.
  462. Return :
  463. None.
  464. --*/
  465. {
  466. void * pLength;
  467. LONG_PTR Length;
  468. unsigned char FormatCopy[4];
  469. BOOL fAsyncSplit = FALSE;
  470. uchar FcType = *pFormat;
  471. //
  472. // Advance the format string to the variance description.
  473. //
  474. static uchar Increments[] = { 8, // Conformant varying array.
  475. 0, 0, // Fixed arrays - unsed.
  476. 8, 12, // Varying array.
  477. 8 // Complex array.
  478. };
  479. pFormat += Increments[ FcType - FC_CVARRAY];
  480. if (FcType == FC_CVARRAY || FcType == FC_BOGUS_ARRAY)
  481. {
  482. CORRELATION_DESC_INCREMENT( pFormat );
  483. }
  484. pLength = 0;
  485. //
  486. // First check if this is a callback.
  487. //
  488. if ( pFormat[1] == FC_CALLBACK )
  489. {
  490. ULONG_PTR OldMaxCount;
  491. uchar * pOldStackTop;
  492. ushort Index;
  493. Index = *((ushort *)(pFormat + 2));
  494. NDR_ASSERT(pStubMsg->StubDesc->apfnExprEval != 0,
  495. "NdrpComputeConformance : no expr eval routines");
  496. NDR_ASSERT(pStubMsg->StubDesc->apfnExprEval[Index] != 0,
  497. "NdrpComputeConformance : bad expr eval routine index");
  498. pOldStackTop = pStubMsg->StackTop;
  499. // This gets trampled by the callback routine.
  500. OldMaxCount = pStubMsg->MaxCount;
  501. //
  502. // The callback routine uses the StackTop field of the stub message
  503. // to base it's offsets from. So if this is a complex attribute for
  504. // an embedded field of a structure then set StackTop equal to the
  505. // pointer to the structure.
  506. //
  507. if ( (*pFormat & 0xf0) != FC_TOP_LEVEL_CONFORMANCE )
  508. {
  509. if ( (*pFormat & 0xf0) == FC_POINTER_VARIANCE )
  510. pMemory = pStubMsg->Memory;
  511. pStubMsg->StackTop = pMemory;
  512. }
  513. //
  514. // This puts the computed offset in pStubMsg->Offset and the length
  515. // in pStubMsg->MaxCount.
  516. //
  517. (*pStubMsg->StubDesc->apfnExprEval[Index])( pStubMsg );
  518. // Put the length in the proper field.
  519. pStubMsg->ActualCount = (ulong)pStubMsg->MaxCount;
  520. pStubMsg->MaxCount = OldMaxCount;
  521. pStubMsg->StackTop = pOldStackTop;
  522. return;
  523. }
  524. if ( (*pFormat & 0xf0) == FC_NORMAL_VARIANCE )
  525. {
  526. // Get the address where the variance variable is in the struct.
  527. pLength = pMemory + *((signed short *)(pFormat + 2));
  528. goto ComputeVarianceGetCount;
  529. }
  530. // See if this is an async split
  531. if ( pFormat[1] & 0x20 )
  532. {
  533. fAsyncSplit = TRUE;
  534. RpcpMemoryCopy( & FormatCopy[0], pFormat, 4 );
  535. pFormat = (PFORMAT_STRING) & FormatCopy[0];
  536. // Remove the async marker
  537. FormatCopy[1] = pFormat[1] & 0xdf;
  538. }
  539. //
  540. // Get a pointer to the variance variable.
  541. //
  542. if ( (*pFormat & 0xf0) == FC_TOP_LEVEL_VARIANCE )
  543. {
  544. //
  545. // Top level variance. For /Os stubs, the stubs put the actual
  546. // count and offset in the stub message. For /Oi stubs, we get the
  547. // actual count via an offset from the stack top. The first_is must
  548. // be zero if we get here.
  549. //
  550. if ( pStubMsg->StackTop )
  551. {
  552. if ( fAsyncSplit )
  553. {
  554. PNDR_DCOM_ASYNC_MESSAGE pAsyncMsg;
  555. pAsyncMsg = (PNDR_DCOM_ASYNC_MESSAGE) pStubMsg->pAsyncMsg;
  556. pLength = pAsyncMsg->BeginStack + *((signed short *)(pFormat + 2));
  557. }
  558. else
  559. pLength = pStubMsg->StackTop + *((signed short *)(pFormat + 2));
  560. goto ComputeVarianceGetCount;
  561. }
  562. else
  563. {
  564. //
  565. // If this is top level variance with /Os then we don't have
  566. // to do anything, the proper variance values are placed in the
  567. // stub message inline in the stubs.
  568. //
  569. return;
  570. }
  571. }
  572. //
  573. // If we're computing the length of an embedded size/length pointer then we
  574. // use the memory pointer in the stub message, which points to the
  575. // beginning of the embedding structure.
  576. //
  577. if ( (*pFormat & 0xf0) == FC_POINTER_VARIANCE )
  578. {
  579. pMemory = pStubMsg->Memory;
  580. pLength = pMemory + *((signed short *)(pFormat + 2));
  581. goto ComputeVarianceGetCount;
  582. }
  583. //
  584. // Check for constant length.
  585. //
  586. if ( (*pFormat & 0xf0) == FC_CONSTANT_VARIANCE )
  587. {
  588. //
  589. // The length is contained in the lower three bytes of the
  590. // long currently pointed to by pFormat.
  591. //
  592. Length = (LONG_PTR) ((ulong)pFormat[1] << 16);
  593. Length |= (LONG_PTR) *((ushort *)(pFormat + 2));
  594. goto ComputeVarianceEnd;
  595. }
  596. //
  597. // Check for variance of a multidimensional array element in
  598. // a -Os stub.
  599. //
  600. if ( (*pFormat & 0xf0) == FC_TOP_LEVEL_MULTID_CONFORMANCE )
  601. {
  602. long Dimension;
  603. if ( fAsyncSplit )
  604. RpcRaiseException( RPC_X_WRONG_STUB_VERSION );
  605. //
  606. // If pArrayInfo is non-null than we have a multi-D array. If it
  607. // is null then we have multi-leveled sized pointers.
  608. //
  609. if ( pStubMsg->pArrayInfo )
  610. {
  611. Dimension = pStubMsg->pArrayInfo->Dimension;
  612. pStubMsg->Offset =
  613. pStubMsg->pArrayInfo->OffsetArray[Dimension];
  614. pStubMsg->ActualCount =
  615. pStubMsg->pArrayInfo->ActualCountArray[Dimension];
  616. }
  617. else
  618. {
  619. Dimension = *((ushort *)(pFormat + 2));
  620. pStubMsg->Offset = pStubMsg->SizePtrOffsetArray[Dimension];
  621. pStubMsg->ActualCount = pStubMsg->SizePtrLengthArray[Dimension];
  622. }
  623. return;
  624. }
  625. ComputeVarianceGetCount:
  626. //
  627. // Must check now if there is a dereference op.
  628. //
  629. if ( pFormat[1] == FC_DEREFERENCE )
  630. {
  631. pLength = *(void **)pLength;
  632. }
  633. //
  634. // Now get the conformance count.
  635. //
  636. switch ( *pFormat & 0x0f )
  637. {
  638. case FC_ULONG :
  639. Length = (LONG_PTR)*((ulong *)pLength);
  640. break;
  641. case FC_LONG :
  642. Length = *((long *)pLength);
  643. break;
  644. case FC_USHORT :
  645. Length = (long) *((ushort *)pLength);
  646. break;
  647. case FC_SHORT :
  648. Length = (long) *((short *)pLength);
  649. break;
  650. case FC_USMALL :
  651. Length = (long) *((uchar *)pLength);
  652. break;
  653. case FC_SMALL :
  654. Length = (long) *((char *)pLength);
  655. break;
  656. default :
  657. NDR_ASSERT(0,"NdrpComputeVariance : bad format");
  658. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  659. return;
  660. }
  661. //
  662. // Check the operator.
  663. //
  664. switch ( pFormat[1] )
  665. {
  666. case FC_DIV_2 :
  667. Length /= 2;
  668. break;
  669. case FC_MULT_2 :
  670. Length *= 2;
  671. break;
  672. case FC_SUB_1 :
  673. Length -= 1;
  674. break;
  675. case FC_ADD_1 :
  676. Length += 1;
  677. break;
  678. default :
  679. // OK
  680. break;
  681. }
  682. ComputeVarianceEnd:
  683. // Get here if the length was computed directly.
  684. pStubMsg->Offset = 0;
  685. pStubMsg->ActualCount = (ulong) Length;
  686. }