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.

5266 lines
151 KiB

  1. /**********************************************************************
  2. Copyright (c) 1993-2000 Microsoft Corporation
  3. Module Name :
  4. unmrshl.cxx
  5. Abstract :
  6. This file contains the unmarshalling routines called by MIDL generated
  7. stubs and the interpreter.
  8. Author :
  9. David Kays dkays September 1993.
  10. Revision History :
  11. **********************************************************************/
  12. #include "ndrp.h"
  13. #include "hndl.h"
  14. #include "ndrole.h"
  15. #include "attack.h"
  16. #include "pointerq.h"
  17. unsigned char * RPC_ENTRY
  18. NdrUDTSimpleTypeUnmarshall1(
  19. PMIDL_STUB_MESSAGE pStubMsg,
  20. unsigned char * * ppMemory,
  21. PFORMAT_STRING pFormat,
  22. unsigned char fMustAlloc
  23. );
  24. //
  25. // Function table of unmarshalling routines.
  26. //
  27. extern const
  28. PUNMARSHALL_ROUTINE UnmarshallRoutinesTable[] =
  29. {
  30. NdrUDTSimpleTypeUnmarshall1,
  31. NdrUDTSimpleTypeUnmarshall1,
  32. NdrUDTSimpleTypeUnmarshall1,
  33. NdrUDTSimpleTypeUnmarshall1,
  34. NdrUDTSimpleTypeUnmarshall1,
  35. NdrUDTSimpleTypeUnmarshall1,
  36. NdrUDTSimpleTypeUnmarshall1,
  37. NdrUDTSimpleTypeUnmarshall1,
  38. NdrUDTSimpleTypeUnmarshall1,
  39. NdrUDTSimpleTypeUnmarshall1,
  40. NdrUDTSimpleTypeUnmarshall1,
  41. NdrUDTSimpleTypeUnmarshall1,
  42. NdrUDTSimpleTypeUnmarshall1,
  43. NdrUDTSimpleTypeUnmarshall1,
  44. NdrUDTSimpleTypeUnmarshall1,
  45. NdrUDTSimpleTypeUnmarshall1,
  46. NdrUDTSimpleTypeUnmarshall1,
  47. NdrPointerUnmarshall,
  48. NdrPointerUnmarshall,
  49. NdrPointerUnmarshall,
  50. NdrPointerUnmarshall,
  51. NdrSimpleStructUnmarshall,
  52. NdrSimpleStructUnmarshall,
  53. NdrConformantStructUnmarshall,
  54. NdrConformantStructUnmarshall,
  55. NdrConformantVaryingStructUnmarshall,
  56. NdrComplexStructUnmarshall,
  57. NdrConformantArrayUnmarshall,
  58. NdrConformantVaryingArrayUnmarshall,
  59. NdrFixedArrayUnmarshall,
  60. NdrFixedArrayUnmarshall,
  61. NdrVaryingArrayUnmarshall,
  62. NdrVaryingArrayUnmarshall,
  63. NdrComplexArrayUnmarshall,
  64. NdrConformantStringUnmarshall,
  65. NdrConformantStringUnmarshall,
  66. NdrConformantStringUnmarshall,
  67. NdrConformantStringUnmarshall,
  68. NdrNonConformantStringUnmarshall,
  69. NdrNonConformantStringUnmarshall,
  70. NdrNonConformantStringUnmarshall,
  71. NdrNonConformantStringUnmarshall,
  72. NdrEncapsulatedUnionUnmarshall,
  73. NdrNonEncapsulatedUnionUnmarshall,
  74. NdrByteCountPointerUnmarshall,
  75. NdrXmitOrRepAsUnmarshall, // transmit as
  76. NdrXmitOrRepAsUnmarshall, // represent as
  77. NdrPointerUnmarshall,
  78. NdrUnmarshallHandle,
  79. // New Post NT 3.5 tokens serviced from here on.
  80. 0, // FC_HARD_STRUCT // NdrHardStructUnmarshall,
  81. NdrXmitOrRepAsUnmarshall, // transmit as ptr
  82. NdrXmitOrRepAsUnmarshall, // represent as ptr
  83. NdrUserMarshalUnmarshall,
  84. 0, // FC_PIPE
  85. 0, // FC_BLK_HOLE
  86. NdrRangeUnmarshall,
  87. 0, // FC_INT3264
  88. 0, // FC_UINT3264
  89. 0, // NdrCsArrayUnmarshall,
  90. 0, // NdrCsTagUnmarshall
  91. };
  92. extern const
  93. PUNMARSHALL_ROUTINE * pfnUnmarshallRoutines = UnmarshallRoutinesTable;
  94. RPCRTAPI
  95. unsigned char * RPC_ENTRY
  96. NdrTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
  97. uchar ** ppMemory,
  98. PFORMAT_STRING pFormat,
  99. uchar fMustAlloc )
  100. {
  101. return
  102. (*pfnUnmarshallRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  103. ppMemory,
  104. pFormat,
  105. fMustAlloc );
  106. }
  107. __inline unsigned char * RPC_ENTRY
  108. NdrUDTSimpleTypeUnmarshall1(
  109. PMIDL_STUB_MESSAGE pStubMsg,
  110. uchar ** ppMemory,
  111. PFORMAT_STRING pFormat,
  112. uchar /* fSkipRefCheck */)
  113. {
  114. NdrSimpleTypeUnmarshall(pStubMsg,*ppMemory,*pFormat);
  115. return NULL;
  116. }
  117. void
  118. NdrpInterfacePointerUnmarshall (
  119. PMIDL_STUB_MESSAGE pStubMsg,
  120. uchar ** ppMemory,
  121. PFORMAT_STRING pFormat );
  122. void RPC_ENTRY
  123. NdrSimpleTypeUnmarshall(
  124. PMIDL_STUB_MESSAGE pStubMsg,
  125. uchar * pMemory,
  126. uchar FormatChar )
  127. /*++
  128. Routine Description :
  129. Unmarshalls a simple type.
  130. Arguments :
  131. pStubMsg - Pointer to the stub message.
  132. pMemory - Memory pointer to unmarshall into.
  133. FormatChar - Simple type format character.
  134. Return :
  135. None.
  136. --*/
  137. {
  138. switch ( FormatChar )
  139. {
  140. case FC_CHAR :
  141. case FC_BYTE :
  142. case FC_SMALL :
  143. case FC_USMALL :
  144. *pMemory = *(pStubMsg->Buffer)++;
  145. break;
  146. case FC_ENUM16 :
  147. *((ulong *)pMemory) &= 0x0000ffff;
  148. // fall through...
  149. case FC_WCHAR :
  150. case FC_SHORT :
  151. case FC_USHORT :
  152. ALIGN(pStubMsg->Buffer,1);
  153. *((ushort *)pMemory) = *((ushort * &)pStubMsg->Buffer)++;
  154. break;
  155. #if defined(__RPC_WIN64__)
  156. case FC_INT3264:
  157. ALIGN(pStubMsg->Buffer,3);
  158. // sign exted long to __int64
  159. *((__int64 *)pMemory) = *((long * &)pStubMsg->Buffer)++;
  160. break;
  161. case FC_UINT3264:
  162. ALIGN(pStubMsg->Buffer,3);
  163. *((unsigned __int64 *)pMemory) = *((ulong * &)pStubMsg->Buffer)++;
  164. break;
  165. #endif
  166. case FC_LONG :
  167. case FC_ULONG :
  168. case FC_FLOAT :
  169. case FC_ENUM32 :
  170. case FC_ERROR_STATUS_T:
  171. ALIGN(pStubMsg->Buffer,3);
  172. *((ulong *)pMemory) = *((ulong * &)pStubMsg->Buffer)++;
  173. break;
  174. case FC_HYPER :
  175. case FC_DOUBLE :
  176. ALIGN(pStubMsg->Buffer,7);
  177. //
  178. // Let's stay away from casts to doubles.
  179. //
  180. *((ulong *)pMemory) = *((ulong * &)pStubMsg->Buffer)++;
  181. *((ulong *)(pMemory + 4)) = *((ulong * &)pStubMsg->Buffer)++;
  182. break;
  183. case FC_IGNORE :
  184. break;
  185. default :
  186. NDR_ASSERT(0,"NdrSimpleTypeUnmarshall : bad format char");
  187. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  188. return;
  189. }
  190. }
  191. unsigned char * RPC_ENTRY
  192. NdrRangeUnmarshall(
  193. PMIDL_STUB_MESSAGE pStubMsg,
  194. uchar ** ppMemory,
  195. PFORMAT_STRING pFormat,
  196. uchar fMustAlloc )
  197. /*++
  198. Unmarshals a range FC_RANGE descriptor.
  199. --*/
  200. {
  201. FORMAT_CHARACTER FcType = (FORMAT_CHARACTER)(pFormat[1] & 0xf);
  202. NDR_DEF_FC_RANGE * pRange = (NDR_DEF_FC_RANGE *)pFormat;
  203. uchar * pMemory;
  204. long Value;
  205. unsigned long Low, High;
  206. ALIGN( pStubMsg->Buffer, SIMPLE_TYPE_ALIGNMENT( FcType ) );
  207. CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + SIMPLE_TYPE_BUFSIZE(FcType ) );
  208. if ( fMustAlloc )
  209. *ppMemory = (uchar*)NdrAllocate( pStubMsg, SIMPLE_TYPE_MEMSIZE(FcType) );
  210. else
  211. {
  212. if (REUSE_BUFFER(pStubMsg) && ! *ppMemory )
  213. *ppMemory = pStubMsg->Buffer;
  214. else if ( ppMemory == NULL )
  215. {
  216. NDR_ASSERT(0, "invalid range memory\n");
  217. }
  218. }
  219. pMemory= *ppMemory;
  220. switch ( FcType )
  221. {
  222. case FC_CHAR :
  223. case FC_BYTE :
  224. case FC_USMALL :
  225. Value = *pMemory = *(pStubMsg->Buffer)++;
  226. break;
  227. case FC_SMALL :
  228. Value = *(small *)pMemory = *(small *)(pStubMsg->Buffer)++;
  229. break;
  230. case FC_ENUM16 :
  231. Value = *((ulong *)pMemory) &= 0x0000ffff;
  232. // fall through...
  233. case FC_WCHAR :
  234. case FC_USHORT :
  235. ALIGN(pStubMsg->Buffer,1);
  236. Value = *((ushort *)pMemory) = *((ushort * &)pStubMsg->Buffer)++;
  237. break;
  238. case FC_SHORT :
  239. ALIGN(pStubMsg->Buffer,1);
  240. Value = *((short *)pMemory) = *((short * &)pStubMsg->Buffer)++;
  241. break;
  242. case FC_ULONG :
  243. case FC_ENUM32 :
  244. case FC_ERROR_STATUS_T:
  245. ALIGN(pStubMsg->Buffer,3);
  246. Value = *((ulong *)pMemory) = *((ulong * &)pStubMsg->Buffer)++;
  247. break;
  248. case FC_LONG :
  249. ALIGN(pStubMsg->Buffer,3);
  250. Value = *((long *)pMemory) = *((long * &)pStubMsg->Buffer)++;
  251. break;
  252. // case FC_IGNORE :
  253. // case FC_FLOAT :
  254. // case FC_HYPER :
  255. // case FC_DOUBLE :
  256. // case FC_INT3264 :
  257. // case FC_UINT3264 :
  258. default :
  259. NDR_ASSERT(0,"NdrSimpleTypeUnmarshall : bad format char");
  260. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  261. return 0;
  262. }
  263. Low = *(unsigned long UNALIGNED *)(pFormat + 2);
  264. High = *(unsigned long UNALIGNED *)(pFormat + 6);
  265. if ( FcType == FC_ULONG )
  266. {
  267. if ( (ulong)Value < Low || (ulong)Value > High )
  268. RpcRaiseException( RPC_X_INVALID_BOUND );
  269. }
  270. else
  271. if ( Value < (long)Low || Value > (long)High )
  272. RpcRaiseException( RPC_X_INVALID_BOUND );
  273. return 0;
  274. }
  275. unsigned char * RPC_ENTRY
  276. NdrPointerUnmarshall(
  277. PMIDL_STUB_MESSAGE pStubMsg,
  278. uchar ** ppMemory,
  279. PFORMAT_STRING pFormat,
  280. uchar /*fSkipRefCheck*/ )
  281. /*++
  282. Routine Description :
  283. Unmarshalls a top level pointer to anything. Pointers embedded in
  284. structures, arrays, or unions call NdrpPointerUnmarshall directly.
  285. Used for FC_RP, FC_UP, FC_FP, FC_OP.
  286. Arguments :
  287. pStubMsg - Pointer to the stub message.
  288. ppMemory - Double pointer to where to unmarshall the pointer.
  289. pFormat - Pointer's format string description.
  290. fSkipRefCheck - This is for cases like [in,out] unique to unique to ref
  291. pointer or unique to unique to structure with embedded
  292. ref pointer. Client pass in NULL and server allocate some
  293. memory back. The flag is set when fPointerAlloc is true
  294. in NdrpPointerUnmarshall.
  295. In fact, we probably should skip the check for all the
  296. ref pointer from fPointerAlloc. So we add a new flag in
  297. pStubMsg->uFlag
  298. Return :
  299. None.
  300. --*/
  301. {
  302. //
  303. // If the pointer is not a ref pointer then get a pointer to it's
  304. // incomming value's location in the buffer. If it's a ref then set
  305. // up some stack space to temporarily act as the buffer.
  306. //
  307. long * pBufferPointer;
  308. if ( *pFormat != FC_RP )
  309. {
  310. ALIGN( pStubMsg->Buffer, 3 );
  311. pBufferPointer = (long*)pStubMsg->Buffer;
  312. pStubMsg->Buffer += PTR_WIRE_SIZE;
  313. }
  314. else
  315. {
  316. //
  317. // If we're on the client unmarshalling a top level [out] ref pointer,
  318. // we have to make sure that it is non-null.
  319. //
  320. if ( pStubMsg->IsClient &&
  321. !IS_SKIP_REF_CHECK( pStubMsg->uFlags ) &&
  322. ! *ppMemory )
  323. RpcRaiseException( RPC_X_NULL_REF_POINTER );
  324. //
  325. // Do this so unmarshalling ref pointers works the same as
  326. // unmarshalling unique and ptr pointers.
  327. //
  328. pBufferPointer = NULL;
  329. }
  330. NdrpPointerUnmarshall( pStubMsg,
  331. ppMemory,
  332. *ppMemory,
  333. pBufferPointer,
  334. pFormat );
  335. return 0;
  336. }
  337. void
  338. NdrpFreeOlePointer(
  339. PMIDL_STUB_MESSAGE pStubMsg,
  340. uchar *pMemory,
  341. PFORMAT_STRING pFormat )
  342. {
  343. NDR_POINTER_QUEUE *pOldQueue;
  344. if ( pStubMsg->pPointerQueueState )
  345. {
  346. pOldQueue = pStubMsg->pPointerQueueState->GetActiveQueue();
  347. pStubMsg->pPointerQueueState->SetActiveQueue(NULL);
  348. }
  349. RpcTryFinally
  350. {
  351. NdrPointerFree( pStubMsg,
  352. pMemory,
  353. pFormat );
  354. }
  355. RpcFinally
  356. {
  357. if (pStubMsg->pPointerQueueState)
  358. {
  359. pStubMsg->pPointerQueueState->SetActiveQueue( pOldQueue );
  360. }
  361. }
  362. RpcEndFinally
  363. }
  364. NDR_ALLOC_ALL_NODES_CONTEXT *
  365. NdrpGetAllocateAllNodesContext(
  366. PMIDL_STUB_MESSAGE pStubMsg,
  367. PFORMAT_STRING pFormat )
  368. {
  369. uchar *pBuffer = pStubMsg->Buffer;
  370. // Clear memory size before calling mem size routine.
  371. pStubMsg->MemorySize = 0;
  372. //
  373. // Get the allocate all nodes memory size. Need to make sure
  374. // all the pointee as finished before continuing
  375. //
  376. {
  377. NDR_POINTER_QUEUE *pOldQueue;
  378. if ( pStubMsg->pPointerQueueState )
  379. {
  380. pOldQueue = pStubMsg->pPointerQueueState->GetActiveQueue();
  381. pStubMsg->pPointerQueueState->SetActiveQueue(NULL);
  382. }
  383. RpcTryFinally
  384. {
  385. (*pfnMemSizeRoutines[ROUTINE_INDEX(*pFormat)])
  386. ( pStubMsg,
  387. pFormat );
  388. }
  389. RpcFinally
  390. {
  391. if ( pStubMsg->pPointerQueueState )
  392. {
  393. pStubMsg->pPointerQueueState->SetActiveQueue( pOldQueue );
  394. }
  395. }
  396. RpcEndFinally
  397. }
  398. pStubMsg->Buffer = pBuffer;
  399. ulong AllocSize = pStubMsg->MemorySize;
  400. pStubMsg->MemorySize = 0;
  401. LENGTH_ALIGN( AllocSize, __alignof(NDR_ALLOC_ALL_NODES_CONTEXT) - 1);
  402. uchar *pAllocMemory =
  403. (uchar*)NdrAllocate( pStubMsg, AllocSize + sizeof(NDR_ALLOC_ALL_NODES_CONTEXT) );
  404. NDR_ALLOC_ALL_NODES_CONTEXT *pAllocContext =
  405. (NDR_ALLOC_ALL_NODES_CONTEXT*)(pAllocMemory + AllocSize);
  406. pAllocContext->AllocAllNodesMemory = pAllocMemory;
  407. pAllocContext->AllocAllNodesMemoryBegin = pAllocMemory;
  408. pAllocContext->AllocAllNodesMemoryEnd = (uchar*)pAllocContext;
  409. return pAllocContext;
  410. }
  411. __forceinline void
  412. NdrpPointerUnmarshallInternal(
  413. PMIDL_STUB_MESSAGE pStubMsg,
  414. uchar ** ppMemory, // Where allocated pointer is written
  415. uchar * pMemory,
  416. long * pBufferPointer, // Pointer to the wire rep.
  417. PFORMAT_STRING pFormat )
  418. /*++
  419. Routine Description :
  420. Private routine for unmarshalling a pointer to anything. This is the
  421. entry point for pointers embedded in structures, arrays, and unions.
  422. Used for FC_RP, FC_UP, FC_FP, FC_OP.
  423. Arguments :
  424. pStubMsg - Pointer to the stub message.
  425. ppBufferPointer - Address of the location in the buffer which holds the
  426. incomming pointer's value and will hold the final
  427. unmarshalled pointer's value.
  428. pMemory - Current memory pointer's value which we want to
  429. unmarshall into. If this value is valid the it will
  430. be copied to *ppBufferPointer and this is where stuff
  431. will get unmarshalled into.
  432. pFormat - Pointer's format string description.
  433. pStubMsg->Buffer - set to the pointee.
  434. Return :
  435. None.
  436. --*/
  437. {
  438. ulong FullPtrRefId;
  439. uchar fPointeeAlloc;
  440. int fNewAllocAllNodes;
  441. int fNewDontFreeContext;
  442. uchar uFlagsSave;
  443. fNewAllocAllNodes = FALSE;
  444. fNewDontFreeContext = FALSE;
  445. // we need to have a check here for pointer embedded in a struct,
  446. // or pointer to pointer case.
  447. CHECK_EOB_RAISE_BSD( pStubMsg->Buffer );
  448. //
  449. // Check the pointer type.
  450. //
  451. switch ( *pFormat )
  452. {
  453. case FC_RP :
  454. break;
  455. case FC_IP :
  456. // On the client side, release the [in,out] interface pointer.
  457. if ( IS_BROKEN_INTERFACE_POINTER( pStubMsg->uFlags ) )
  458. {
  459. NdrInterfacePointerUnmarshall( pStubMsg,
  460. ppMemory,
  461. pFormat,
  462. true );
  463. return;
  464. }
  465. if ((pStubMsg->IsClient == TRUE) && (pMemory != 0))
  466. {
  467. ((IUnknown*)pMemory)->Release();
  468. *ppMemory = NULL ;
  469. }
  470. if ( !*pBufferPointer ) return;
  471. NdrpInterfacePointerUnmarshall( pStubMsg,
  472. ppMemory,
  473. pFormat );
  474. if ( pBufferPointer ) *pBufferPointer = PTR_WIRE_REP(*ppMemory);
  475. return;
  476. case FC_OP :
  477. //
  478. // Burn some instructions for OLE unique pointer support.
  479. //
  480. if ( pStubMsg->IsClient )
  481. {
  482. //
  483. // It's ok if this is an [out] unique pointer. It will get
  484. // zeroed before this routine is called and NdrPointerFree
  485. // will simply return. Need to finish all the pointees before
  486. // continueing.
  487. NdrpFreeOlePointer(
  488. pStubMsg,
  489. pMemory,
  490. pFormat);
  491. // Set the current memory pointer to 0 so that we'll alloc.
  492. pMemory = 0;
  493. }
  494. // Fall through.
  495. case FC_UP :
  496. //
  497. // Check for a null incomming pointer. Routines which call this
  498. // routine insure that the memory pointer gets nulled.
  499. //
  500. if ( ! *pBufferPointer )
  501. {
  502. *ppMemory = NULL;
  503. return;
  504. }
  505. break;
  506. case FC_FP :
  507. //
  508. // We have to remember the incomming ref id because we overwrite
  509. // it during the QueryRefId call.
  510. //
  511. FullPtrRefId = *pBufferPointer;
  512. // we couldn't pass pBufferPointer to QueryRefId because it's 4bytes
  513. // on wire but 8bytes on 64bit. (and it'll have mix alignment issue)
  514. if ( 0 == FullPtrRefId )
  515. {
  516. *ppMemory = NULL;
  517. return;
  518. }
  519. //
  520. // Lookup the ref id.
  521. //
  522. if ( NdrFullPointerQueryRefId( pStubMsg->FullPtrXlatTables,
  523. FullPtrRefId,
  524. FULL_POINTER_UNMARSHALLED,
  525. (void**)ppMemory) )
  526. {
  527. // true means the RefId had been unmarshalled.
  528. *pBufferPointer = PTR_WIRE_REP( *ppMemory );
  529. return;
  530. }
  531. //
  532. // If our query returned false then check if the returned pointer
  533. // is 0. If so then we have to scribble away the ref id in the
  534. // stub message FullPtrRefId field so that we can insert the
  535. // pointer translation later, after we've allocated the pointer.
  536. // If the returned pointer was non-null then we leave the stub
  537. // message FullPtrRefId field alone so that we don't try to
  538. // re-insert the pointer to ref id translation later.
  539. //
  540. // We also copy the returned pointer value into pMemory. This
  541. // will allow our allocation decision to be made correctly.
  542. //
  543. pMemory = *ppMemory;
  544. if ( !pMemory )
  545. {
  546. //
  547. // Put the unmarshalled ref id into the stub message to
  548. // be used later in a call to NdrFullPointerInsertRefId.
  549. //
  550. pStubMsg->FullPtrRefId = FullPtrRefId;
  551. }
  552. break;
  553. default :
  554. NDR_ASSERT(0,"NdrpPointerUnmarshall : bad pointer type");
  555. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  556. return;
  557. }
  558. //
  559. // Make the initial "must allocate" decision.
  560. //
  561. // The fPointeeAlloc flag is set on the client side if the current memory
  562. // pointer is null, and on the server side it is set if the current memory
  563. // pointer has the allocate don't free attribute applied to it.
  564. //
  565. // On the client side we also set the pointer's value in the buffer equal
  566. // to the current memory pointer.
  567. //
  568. // On the server side we explicitly null out the pointer's value in the
  569. // buffer as long as it's not allocated on the stack, otherwise we set it
  570. // equal to the current memory pointer (stack allocated).
  571. //
  572. if ( pStubMsg->IsClient )
  573. {
  574. *ppMemory = pMemory;
  575. fPointeeAlloc = ! pMemory;
  576. }
  577. else
  578. {
  579. if ( ! ALLOCED_ON_STACK(pFormat[1]) )
  580. *ppMemory = 0;
  581. else
  582. *ppMemory = pMemory;
  583. //
  584. // If this is a don't free pointer or a parent pointer of this pointer
  585. // was a don't free pointer then we set the alloc flag.
  586. //
  587. if ( fPointeeAlloc = (DONT_FREE(pFormat[1])
  588. || pStubMsg->ReuseBuffer
  589. || pStubMsg->fInDontFree) )
  590. {
  591. //
  592. // If we encounter a don't free pointer which is not nested inside
  593. // of another don't free pointer then set the local and stub message
  594. // flags.
  595. //
  596. if ( ! pStubMsg->fInDontFree )
  597. {
  598. fNewDontFreeContext = TRUE;
  599. pStubMsg->fInDontFree = TRUE;
  600. }
  601. }
  602. //
  603. // We also set the alloc flag for object interface pointers.
  604. //
  605. if ( *pFormat == FC_OP )
  606. fPointeeAlloc = TRUE;
  607. }
  608. //
  609. // Pointer to complex type.
  610. //
  611. if ( ! SIMPLE_POINTER(pFormat[1]) )
  612. {
  613. PFORMAT_STRING pFormatPointee;
  614. pFormatPointee = pFormat + 2;
  615. // Set the pointee format string.
  616. // Cast must be to a signed short since some offsets are negative.
  617. pFormatPointee += *((signed short *)pFormatPointee);
  618. //
  619. // Right now the server will always allocate for allocate all nodes
  620. // when told to. Eventually we want to use the rpc buffer when
  621. // possible.
  622. //
  623. //
  624. // Check if this is an allocate all nodes pointer AND that we're
  625. // not already in an allocate all nodes context.
  626. //
  627. if ( ALLOCATE_ALL_NODES(pFormat[1]) && ! pStubMsg->pAllocAllNodesContext )
  628. {
  629. fNewAllocAllNodes = TRUE;
  630. pStubMsg->pAllocAllNodesContext =
  631. NdrpGetAllocateAllNodesContext(
  632. pStubMsg,
  633. pFormatPointee );
  634. *ppMemory = 0;
  635. fPointeeAlloc = TRUE;
  636. //
  637. // I think this is what we'll have to add to support an [in,out]
  638. // allocate all nodes full pointer ([in] only and [out] only
  639. // allocate all nodes full pointer shouldn't need any special
  640. // treatment).
  641. //
  642. // if ( *pFormat == FC_FP )
  643. // {
  644. // pStubMsg->FullPtrRefId = FullPtrRefId;
  645. // }
  646. //
  647. }
  648. if ( POINTER_DEREF(pFormat[1]) )
  649. {
  650. //
  651. // Re-align the buffer. This is to cover embedded pointer to
  652. // pointers.
  653. //
  654. ALIGN(pStubMsg->Buffer,0x3);
  655. //
  656. // We can't re-use the buffer for a pointer to a pointer
  657. // because we can't null out the pointee before we've unmarshalled
  658. // it. We need the stubs to alloc pointers to pointers on the
  659. // stack.
  660. //
  661. if ( ! *ppMemory && ! pStubMsg->IsClient )
  662. fPointeeAlloc = TRUE;
  663. if ( fPointeeAlloc )
  664. {
  665. *ppMemory = (uchar*)NdrAllocate( pStubMsg, PTR_MEM_SIZE );
  666. *((void **)*ppMemory) = 0;
  667. }
  668. if ( pStubMsg->FullPtrRefId )
  669. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  670. if ( pBufferPointer )
  671. *pBufferPointer = PTR_WIRE_REP(*ppMemory);
  672. pBufferPointer = 0;
  673. ppMemory = (uchar**)*ppMemory;
  674. }
  675. //
  676. // Now call the proper unmarshalling routine.
  677. //
  678. uFlagsSave = pStubMsg->uFlags;
  679. RESET_CONF_FLAGS_TO_STANDALONE(pStubMsg->uFlags);
  680. if ( fPointeeAlloc )
  681. SET_SKIP_REF_CHECK( pStubMsg->uFlags );
  682. (*pfnUnmarshallRoutines[ROUTINE_INDEX(*pFormatPointee)])
  683. ( pStubMsg,
  684. ppMemory,
  685. pFormatPointee,
  686. fPointeeAlloc );
  687. pStubMsg->uFlags = uFlagsSave;
  688. if ( *pFormatPointee == FC_USER_MARSHAL )
  689. {
  690. if ( pStubMsg->FullPtrRefId )
  691. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  692. }
  693. goto PointerUnmarshallEnd;
  694. }
  695. //
  696. // Else handle a pointer to a simple type, pointer, or string.
  697. //
  698. switch ( pFormat[2] )
  699. {
  700. case FC_C_CSTRING :
  701. case FC_C_BSTRING :
  702. case FC_C_WSTRING :
  703. case FC_C_SSTRING :
  704. NdrConformantStringUnmarshall( pStubMsg,
  705. ppMemory,
  706. &pFormat[2],
  707. fPointeeAlloc );
  708. goto PointerUnmarshallEnd;
  709. default :
  710. // Break to handle a simple type.
  711. break;
  712. }
  713. //
  714. // Handle pointers to simple types.
  715. //
  716. //
  717. // Align the buffer.
  718. //
  719. ALIGN(pStubMsg->Buffer,SIMPLE_TYPE_ALIGNMENT(pFormat[2]));
  720. CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + SIMPLE_TYPE_BUFSIZE(pFormat[2]) );
  721. //
  722. // We can't use the buffer for pointers to enum16 since these force
  723. // us to zero out the upper 16 bits of the memory pointer, and this
  724. // might overwrite data in the buffer that we still need!
  725. // Similar thing happens for int3264 values.
  726. //
  727. if ( pFormat[2] == FC_ENUM16
  728. #if defined(__RPC_WIN64__)
  729. || pFormat[2] == FC_INT3264 || pFormat[2] == FC_UINT3264
  730. #endif
  731. )
  732. {
  733. if ( ! pStubMsg->IsClient && ! *ppMemory )
  734. fPointeeAlloc = TRUE;
  735. }
  736. //
  737. // Check for allocation or buffer reuse.
  738. //
  739. if ( fPointeeAlloc )
  740. {
  741. *ppMemory =
  742. (uchar*)NdrAllocate( pStubMsg,
  743. SIMPLE_TYPE_MEMSIZE(pFormat[2]) );
  744. }
  745. else
  746. {
  747. if ( ! pStubMsg->IsClient && ! *ppMemory )
  748. {
  749. // Set pointer into buffer.
  750. *ppMemory = pStubMsg->Buffer;
  751. }
  752. }
  753. if ( pStubMsg->FullPtrRefId )
  754. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  755. //
  756. // We always get here for simple types. What this means is that
  757. // when we reuse the buffer on the server side we end up copying the
  758. // data with source and destination memory pointer equal. But this
  759. // way we can cover the enum and error_status_t cases without duplicating
  760. // a lot of code.
  761. //
  762. NdrSimpleTypeUnmarshall( pStubMsg,
  763. *ppMemory,
  764. pFormat[2] );
  765. PointerUnmarshallEnd:
  766. if ( fNewDontFreeContext )
  767. pStubMsg->fInDontFree = FALSE;
  768. if ( pBufferPointer )
  769. *pBufferPointer = PTR_WIRE_REP(*ppMemory);
  770. if ( fNewAllocAllNodes )
  771. pStubMsg->pAllocAllNodesContext = 0;
  772. }
  773. NDR_UNMRSHL_POINTER_QUEUE_ELEMENT::NDR_UNMRSHL_POINTER_QUEUE_ELEMENT(
  774. MIDL_STUB_MESSAGE *pStubMsg,
  775. uchar ** ppMemoryNew,
  776. uchar * pMemoryNew,
  777. long * pBufferPointerNew,
  778. PFORMAT_STRING pFormatNew ) :
  779. ppMemory(ppMemoryNew),
  780. pMemory(pMemoryNew),
  781. pBufferPointer(pBufferPointerNew),
  782. pFormat(pFormatNew),
  783. Memory(pStubMsg->Memory),
  784. uFlags(pStubMsg->uFlags),
  785. fInDontFree( pStubMsg->fInDontFree ),
  786. pAllocAllNodesContext( pStubMsg->pAllocAllNodesContext ),
  787. pCorrMemory( pStubMsg->pCorrMemory )
  788. {
  789. }
  790. void
  791. NDR_UNMRSHL_POINTER_QUEUE_ELEMENT::Dispatch(
  792. MIDL_STUB_MESSAGE *pStubMsg)
  793. {
  794. SAVE_CONTEXT<uchar*> MemorySave( pStubMsg->Memory, Memory );
  795. SAVE_CONTEXT<uchar> uFlagsSave( pStubMsg->uFlags, uFlags );
  796. NDR_ASSERT( !pStubMsg->PointerBufferMark, "PointerBufferMark is not 0\n");
  797. int fInDontFreeSave = pStubMsg->fInDontFree;
  798. pStubMsg->fInDontFree = fInDontFree;
  799. SAVE_CONTEXT<uchar*> pCorrMemorySave(pStubMsg->pCorrMemory, pCorrMemory );
  800. SAVE_CONTEXT<NDR_ALLOC_ALL_NODES_CONTEXT *>
  801. AllNodesContextSave(pStubMsg->pAllocAllNodesContext, pAllocAllNodesContext);
  802. NdrpPointerUnmarshallInternal( pStubMsg,
  803. ppMemory,
  804. pMemory,
  805. pBufferPointer,
  806. pFormat );
  807. pStubMsg->fInDontFree = fInDontFreeSave;
  808. }
  809. #if defined(DBG)
  810. void
  811. NDR_UNMRSHL_POINTER_QUEUE_ELEMENT::Print()
  812. {
  813. DbgPrint("NDR_MRSHL_POINTER_QUEUE_ELEMENT\n");
  814. DbgPrint("pNext: %p\n", pNext );
  815. DbgPrint("pMemory: %p\n", pMemory );
  816. DbgPrint("ppMemory: %p\n", ppMemory );
  817. DbgPrint("pBufferPointer: %p\n", pBufferPointer );
  818. DbgPrint("pFormat: %p\n", pFormat );
  819. DbgPrint("Memory: %p\n", Memory );
  820. DbgPrint("uFlags: %x\n", uFlags );
  821. DbgPrint("fInDontFree: %u\n", fInDontFree );
  822. DbgPrint("pAllocAllNodesContext: %p\n", pAllocAllNodesContext );
  823. DbgPrint("pCorrMemorySave: %p\n", pCorrMemory );
  824. }
  825. #endif
  826. void
  827. NdrpEnquePointerUnmarshall(
  828. PMIDL_STUB_MESSAGE pStubMsg,
  829. uchar ** ppMemory, // Where allocated pointer is written
  830. uchar * pMemory,
  831. long * pBufferPointer, // Pointer to the wire rep.
  832. PFORMAT_STRING pFormat )
  833. {
  834. NDR32_POINTER_CONTEXT PointerContext( pStubMsg );
  835. RpcTryFinally
  836. {
  837. NDR_UNMRSHL_POINTER_QUEUE_ELEMENT*pElement =
  838. new(PointerContext.GetActiveState())
  839. NDR_UNMRSHL_POINTER_QUEUE_ELEMENT(pStubMsg,
  840. ppMemory,
  841. pMemory,
  842. pBufferPointer,
  843. pFormat );
  844. PointerContext.Enque( pElement );
  845. PointerContext.DispatchIfRequired();
  846. }
  847. RpcFinally
  848. {
  849. PointerContext.EndContext();
  850. }
  851. RpcEndFinally
  852. }
  853. void
  854. NdrpPointerUnmarshall(
  855. PMIDL_STUB_MESSAGE pStubMsg,
  856. uchar ** ppMemory, // Where allocated pointer is written
  857. uchar * pMemory,
  858. long * pBufferPointer, // Pointer to the wire rep.
  859. PFORMAT_STRING pFormat )
  860. {
  861. if ( !NdrIsLowStack( pStubMsg ) )
  862. {
  863. NdrpPointerUnmarshallInternal(
  864. pStubMsg,
  865. ppMemory,
  866. pMemory,
  867. pBufferPointer,
  868. pFormat );
  869. return;
  870. }
  871. NdrpEnquePointerUnmarshall(
  872. pStubMsg,
  873. ppMemory,
  874. pMemory,
  875. pBufferPointer,
  876. pFormat );
  877. }
  878. unsigned char * RPC_ENTRY
  879. NdrSimpleStructUnmarshall(
  880. PMIDL_STUB_MESSAGE pStubMsg,
  881. uchar ** ppMemory,
  882. PFORMAT_STRING pFormat,
  883. uchar fMustAlloc )
  884. /*++
  885. Routine description :
  886. Unmarshalls a simple structure.
  887. Used for FC_STRUCT and FC_PSTRUCT.
  888. Arguments :
  889. pStubMsg - Pointer to the stub message.
  890. ppMemory - Double pointer to the structure being unmarshalled.
  891. pFormat - Structure's format string description.
  892. fMustAlloc - TRUE if the structure must be allocate, FALSE otherwise.
  893. --*/
  894. {
  895. uchar * pBufferSave;
  896. uint StructSize;
  897. CORRELATION_RESOURCE_SAVE;
  898. // Align the buffer.
  899. ALIGN(pStubMsg->Buffer,pFormat[1]);
  900. // Increment to the struct size field.
  901. pFormat += 2;
  902. // Get struct size and increment.
  903. StructSize = (ulong) *((ushort * &)pFormat)++;
  904. // Remember the current buffer position for the struct copy later.
  905. pBufferSave = pStubMsg->Buffer;
  906. // Set BufferMark to the beginning of the struct in the buffer.
  907. pStubMsg->BufferMark = pBufferSave;
  908. CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + StructSize );
  909. // Increment Buffer past struct data.
  910. pStubMsg->Buffer += StructSize;
  911. // Initialize the memory pointer if needed.
  912. if ( fMustAlloc )
  913. *ppMemory = (uchar *) NdrAllocate( pStubMsg, StructSize );
  914. else
  915. // we'll get rid of pStubMsg->ReuseBuffer given it's basically !IsClient now
  916. // we might set the flag again through compiler flag later on.
  917. if ( REUSE_BUFFER(pStubMsg) && ! *ppMemory )
  918. *ppMemory = pBufferSave;
  919. SET_CORRELATION_MEMORY( pBufferSave );
  920. // Insert full pointer to ref id translation if needed.
  921. if ( pStubMsg->FullPtrRefId )
  922. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  923. // Unmarshall embedded pointers before copying the struct.
  924. if ( *pFormat == FC_PP )
  925. {
  926. NdrpEmbeddedPointerUnmarshall( pStubMsg,
  927. *ppMemory,
  928. pFormat,
  929. fMustAlloc );
  930. }
  931. // Copy the struct if we're not using the rpc buffer.
  932. if ( *ppMemory != pBufferSave )
  933. {
  934. RpcpMemoryCopy( *ppMemory,
  935. pBufferSave,
  936. StructSize );
  937. }
  938. RESET_CORRELATION_MEMORY();
  939. return 0;
  940. }
  941. unsigned char * RPC_ENTRY
  942. NdrConformantStructUnmarshall(
  943. PMIDL_STUB_MESSAGE pStubMsg,
  944. uchar ** ppMemory,
  945. PFORMAT_STRING pFormat,
  946. uchar fMustAlloc )
  947. /*++
  948. Routine description :
  949. Unmarshalls a conformant structure.
  950. Used for FC_CSTRUCT and FC_CPSTRUCT.
  951. Arguments :
  952. pStubMsg - Pointer to the stub message.
  953. ppMemory - Double pointer to where the structure should be unmarshalled.
  954. pFormat - Structure's format string description.
  955. fMustAlloc - TRUE if the structure must be allocate, FALSE otherwise.
  956. Return :
  957. None.
  958. --*/
  959. {
  960. uchar * pBufferStart;
  961. PFORMAT_STRING pFormatArray;
  962. uint StructSize;
  963. uchar fIsEmbeddedStruct = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  964. CORRELATION_RESOURCE_SAVE;
  965. // Unmarshall the conformance count into the stub message.
  966. // Only a bogus struct can embed a conf struct; if so, ->BufferMark is set.
  967. if ( fIsEmbeddedStruct )
  968. pStubMsg->MaxCount = *((ulong *)pStubMsg->BufferMark);
  969. else
  970. {
  971. // Align the buffer for unmarshalling the conformance count.
  972. ALIGN(pStubMsg->Buffer,3);
  973. pStubMsg->MaxCount = *((ulong * &)pStubMsg->Buffer)++;
  974. }
  975. // Re-align the buffer
  976. ALIGN(pStubMsg->Buffer, pFormat[1]);
  977. // Increment format string to structure size field.
  978. pFormat += 2;
  979. // Get flat struct size and increment format string.
  980. StructSize = (ulong) *((ushort * &)pFormat)++;
  981. // Get the conformant array's description.
  982. pFormatArray = pFormat + *((signed short *)pFormat);
  983. CHECK_EOB_RAISE_IB( pStubMsg->Buffer + StructSize );
  984. if ( F_CORRELATION_CHECK )
  985. {
  986. SET_CORRELATION_MEMORY( pStubMsg->Buffer + StructSize);
  987. NdrpCheckCorrelation( pStubMsg,
  988. pStubMsg->MaxCount,
  989. pFormatArray,
  990. NDR_CHECK_CONFORMANCE );
  991. RESET_CORRELATION_MEMORY();
  992. }
  993. // Add the size of the conformant array to the structure size.
  994. // check for possible mulitplication overflow attack here.
  995. StructSize += MultiplyWithOverflowCheck( (ulong)pStubMsg->MaxCount, *((ushort *)(pFormatArray + 2) ) );
  996. // Check the size and the buffer limit.
  997. CHECK_BOUND( (ulong)pStubMsg->MaxCount, pFormatArray[4] & 0x0f );
  998. CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, StructSize );
  999. //
  1000. // Remember where we're going to copy from.
  1001. //
  1002. pBufferStart = pStubMsg->Buffer;
  1003. // Set stub message Buffer field to the end of the structure in the buffer.
  1004. pStubMsg->Buffer += StructSize;
  1005. // Increment pFormat past the array description
  1006. pFormat += 2;
  1007. // Initialize the memory pointer if needed.
  1008. if ( fMustAlloc )
  1009. {
  1010. *ppMemory = (uchar *) NdrAllocate( pStubMsg, StructSize );
  1011. }
  1012. else
  1013. if ( REUSE_BUFFER(pStubMsg) && ! *ppMemory )
  1014. *ppMemory = pBufferStart;
  1015. // Insert full pointer to ref id translation if needed.
  1016. if ( pStubMsg->FullPtrRefId )
  1017. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  1018. SET_CORRELATION_MEMORY( pBufferStart );
  1019. // Unmarshall embedded pointers before copying the struct.
  1020. if ( *pFormat == FC_PP )
  1021. {
  1022. //
  1023. // Set BufferMark to the beginning of the structure in the buffer.
  1024. //
  1025. pStubMsg->BufferMark = pBufferStart;
  1026. NdrpEmbeddedPointerUnmarshall( pStubMsg,
  1027. *ppMemory,
  1028. pFormat,
  1029. fMustAlloc );
  1030. }
  1031. // Copy the struct if we're not using the rpc buffer.
  1032. if ( *ppMemory != pBufferStart )
  1033. {
  1034. RpcpMemoryCopy( *ppMemory,
  1035. pBufferStart,
  1036. StructSize );
  1037. }
  1038. RESET_CORRELATION_MEMORY();
  1039. // Set the reverse flag to signal that the array has been unmarshaled.
  1040. if ( fIsEmbeddedStruct )
  1041. SET_CONF_ARRAY_DONE( pStubMsg->uFlags );
  1042. return 0;
  1043. }
  1044. unsigned char * RPC_ENTRY
  1045. NdrConformantVaryingStructUnmarshall(
  1046. PMIDL_STUB_MESSAGE pStubMsg,
  1047. uchar ** ppMemory,
  1048. PFORMAT_STRING pFormat,
  1049. uchar fMustAlloc )
  1050. /*++
  1051. Routine description :
  1052. Unmarshalls a structure which contains a conformant varying array.
  1053. Used for FC_CVSTRUCT.
  1054. Arguments :
  1055. pStubMsg - Pointer to the stub message.
  1056. ppMemory - Double pointer to where the structure should be unmarshalled.
  1057. pFormat - Structure's format string description.
  1058. fMustAlloc - Ignored.
  1059. Return :
  1060. None.
  1061. --*/
  1062. {
  1063. PFORMAT_STRING pFormatArray;
  1064. uchar * pBufferStruct;
  1065. uchar * pBufferArray;
  1066. uint StructSize, ArrayCopySize, ArrayOffset;
  1067. ulong AllocationSize;
  1068. ulong Elements;
  1069. uchar Alignment;
  1070. uchar fIsEmbeddedStruct = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  1071. CORRELATION_RESOURCE_SAVE;
  1072. IGNORED(fMustAlloc);
  1073. // Save structure's alignment.
  1074. Alignment = pFormat[1];
  1075. // Increment format string to struct size field.
  1076. pFormat += 2;
  1077. // Get non-conformant struct size and increment format string.
  1078. StructSize = (ulong) *((ushort * &)pFormat)++;
  1079. // Get conformant varying array's description.
  1080. pFormatArray = pFormat + *((signed short *)pFormat);
  1081. AllocationSize = 0;
  1082. // Conformant array size
  1083. // Only a bogus struct can embed a conf struct; if so, ->BufferMark is set.
  1084. if ( fIsEmbeddedStruct )
  1085. Elements = *((ulong *)pStubMsg->BufferMark);
  1086. else
  1087. {
  1088. // Align the buffer for conformance count unmarshalling.
  1089. ALIGN(pStubMsg->Buffer,3);
  1090. Elements = *((ulong * &)pStubMsg->Buffer)++;
  1091. }
  1092. // Check the size.
  1093. if ( *pFormatArray == FC_CVARRAY )
  1094. CHECK_BOUND( Elements, pFormatArray[4] & 0x0f );
  1095. else
  1096. if ( pFormatArray[1] == FC_STRING_SIZED )
  1097. CHECK_BOUND( Elements, pFormatArray[2] & 0x0f );
  1098. CHECK_EOB_RAISE_IB( pStubMsg->Buffer + StructSize );
  1099. if ( F_CORRELATION_CHECK )
  1100. {
  1101. SET_CORRELATION_MEMORY( pStubMsg->Buffer + StructSize);
  1102. NdrpCheckCorrelation( pStubMsg,
  1103. Elements,
  1104. pFormatArray,
  1105. NDR_CHECK_CONFORMANCE );
  1106. RESET_CORRELATION_MEMORY();
  1107. }
  1108. //
  1109. // For a conformant varying struct we ignore all allocation flags.
  1110. // Memory must always be allocated on both client and server stubs
  1111. // if the current memory pointer is null.
  1112. //
  1113. if ( ! *ppMemory )
  1114. {
  1115. AllocationSize = StructSize;
  1116. ULONG ElementSize;
  1117. if ( *pFormatArray == FC_CVARRAY )
  1118. {
  1119. // check for possible mulitplication overflow attack here.
  1120. AllocationSize += MultiplyWithOverflowCheck( Elements, *((ushort *)(pFormatArray + 2)) );
  1121. }
  1122. else // must be a conformant string
  1123. {
  1124. if ( *pFormatArray != FC_C_WSTRING )
  1125. AllocationSize += Elements;
  1126. else
  1127. {
  1128. AllocationSize += MultiplyWithOverflowCheck( Elements, 2 );
  1129. }
  1130. }
  1131. // do the real allocation after correlation checks.
  1132. }
  1133. // Align for the struct
  1134. ALIGN(pStubMsg->Buffer,Alignment);
  1135. // Remember where the structure starts in the buffer.
  1136. pBufferStruct = pStubMsg->Buffer;
  1137. // Mark the start of the structure in the buffer.
  1138. pStubMsg->BufferMark = pStubMsg->Buffer;
  1139. // Increment past the non-conformant part of the structure.
  1140. //
  1141. pStubMsg->Buffer += StructSize;
  1142. // Align again for variance unmarshalling.
  1143. ALIGN(pStubMsg->Buffer,3);
  1144. //
  1145. // Get offset and actual count. Put the actual count into the MaxCount
  1146. // field of the stub message, where it is used if the array has pointers.
  1147. //
  1148. pStubMsg->Offset = ArrayOffset = *((ulong * &)pStubMsg->Buffer)++;
  1149. ArrayCopySize = *((ulong * &)pStubMsg->Buffer)++;
  1150. pStubMsg->MaxCount = ArrayCopySize;
  1151. // Check the offset and lentgth.
  1152. if ( *pFormatArray == FC_CVARRAY )
  1153. {
  1154. PFORMAT_STRING pFormatVar = pFormatArray + 8;
  1155. CORRELATION_DESC_INCREMENT( pFormatVar );
  1156. CHECK_BOUND( ArrayOffset, FC_LONG );
  1157. CHECK_BOUND( ArrayCopySize, *pFormatVar & 0x0f );
  1158. if ( F_CORRELATION_CHECK )
  1159. {
  1160. SET_CORRELATION_MEMORY( pBufferStruct + StructSize ); // at the end of the fixed part
  1161. NdrpCheckCorrelation( pStubMsg,
  1162. (ulong)pStubMsg->MaxCount, // yes, this is variance from above
  1163. pFormatArray,
  1164. NDR_CHECK_VARIANCE );
  1165. NdrpCheckCorrelation( pStubMsg,
  1166. pStubMsg->Offset,
  1167. pFormatArray,
  1168. NDR_CHECK_OFFSET );
  1169. RESET_CORRELATION_MEMORY();
  1170. }
  1171. }
  1172. else
  1173. // has to be strings here. check for invalid offset
  1174. {
  1175. if ( ArrayOffset != 0 )
  1176. RpcRaiseException( RPC_X_INVALID_BOUND );
  1177. }
  1178. if ( (Elements < (ArrayOffset + ArrayCopySize)) )
  1179. RpcRaiseException( RPC_X_INVALID_BOUND );
  1180. SET_CORRELATION_MEMORY( pBufferStruct );
  1181. // Remember where the array starts in the buffer.
  1182. pBufferArray = pStubMsg->Buffer;
  1183. // we don't need to check overflow for length_is and first_is:
  1184. // if size_is doesn't overflow, and size_is > length_is+first_is, neither of them can overflow.
  1185. if ( *pFormatArray == FC_CVARRAY )
  1186. {
  1187. // Skip to array element size field.
  1188. pFormatArray += 2;
  1189. //
  1190. // Compute the real offset (in bytes) from the beginning of the
  1191. // array for the copy and the real total number of bytes to copy.
  1192. //
  1193. ArrayOffset = MultiplyWithOverflowCheck( ArrayOffset, *((ushort *)pFormatArray) );
  1194. ArrayCopySize = MultiplyWithOverflowCheck( ArrayCopySize, *((ushort *)pFormatArray) );
  1195. }
  1196. else
  1197. {
  1198. ulong CharSize = 1;
  1199. // Conformant string.
  1200. if ( *pFormatArray == FC_C_WSTRING )
  1201. {
  1202. // Double the offset and copy size for wide char string.
  1203. ArrayOffset = MultiplyWithOverflowCheck( ArrayOffset, sizeof(wchar_t) );
  1204. ArrayCopySize = MultiplyWithOverflowCheck( ArrayCopySize, sizeof(wchar_t) );
  1205. CharSize = sizeof(wchar_t);
  1206. }
  1207. if ( ArrayCopySize )
  1208. {
  1209. uchar * p;
  1210. // Check if the terminator is there.
  1211. for ( p = pStubMsg->Buffer + ArrayCopySize - CharSize; CharSize--; )
  1212. {
  1213. if ( *p++ != 0 )
  1214. RpcRaiseException( RPC_X_INVALID_BOUND );
  1215. }
  1216. }
  1217. else // cannot be zero here.
  1218. {
  1219. RpcRaiseException( RPC_X_INVALID_BOUND );
  1220. }
  1221. }
  1222. // Set the stub message Buffer field to the end of the array/string.
  1223. CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, ArrayCopySize );
  1224. pStubMsg->Buffer += ArrayCopySize;
  1225. // Increment format string past offset to array description field.
  1226. pFormat += 2;
  1227. // allocate the memory after correlation checks. Should help avoid allocation in
  1228. // early correlation.
  1229. if ( AllocationSize != 0 )
  1230. {
  1231. *ppMemory = (uchar *) NdrAllocate( pStubMsg, (uint) AllocationSize );
  1232. }
  1233. // Insert full pointer to ref id translation if needed.
  1234. if ( pStubMsg->FullPtrRefId )
  1235. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  1236. //
  1237. // Unmarshall embedded pointers before copying the struct.
  1238. //
  1239. if ( *pFormat == FC_PP )
  1240. {
  1241. pStubMsg->BufferMark = pBufferStruct;
  1242. NdrpEmbeddedPointerUnmarshall( pStubMsg,
  1243. *ppMemory,
  1244. pFormat,
  1245. (uchar) (AllocationSize != 0) );
  1246. }
  1247. RESET_CORRELATION_MEMORY();
  1248. //
  1249. // Copy the array. Make sure the destination memory pointer is at
  1250. // the proper offset from the beginning of the array in memory.
  1251. //
  1252. RpcpMemoryCopy( *ppMemory,
  1253. pBufferStruct,
  1254. StructSize );
  1255. RpcpMemoryCopy( *ppMemory + StructSize + ArrayOffset,
  1256. pBufferArray,
  1257. ArrayCopySize );
  1258. // Set the reverse flag to signal that the array has been unmarshaled.
  1259. if ( fIsEmbeddedStruct )
  1260. SET_CONF_ARRAY_DONE( pStubMsg->uFlags );
  1261. return 0;
  1262. }
  1263. #if 0
  1264. unsigned char * RPC_ENTRY
  1265. NdrHardStructUnmarshall(
  1266. PMIDL_STUB_MESSAGE pStubMsg,
  1267. uchar ** ppMemory,
  1268. PFORMAT_STRING pFormat,
  1269. uchar fMustAlloc )
  1270. /*++
  1271. Routine description :
  1272. Unmarshalls a hard structure.
  1273. Used for FC_HARD_STRUCT.
  1274. Arguments :
  1275. pStubMsg - Pointer to the stub message.
  1276. ppMemory - Double pointer to where the structure should be unmarshalled.
  1277. pFormat - Structure's format string description.
  1278. fMustAlloc - Ignored.
  1279. Return :
  1280. None.
  1281. --*/
  1282. {
  1283. uchar * pUnion;
  1284. uchar * pEnum;
  1285. BOOL fNewMemory;
  1286. ushort CopySize;
  1287. ALIGN(pStubMsg->Buffer,pFormat[1]);
  1288. pFormat += 2;
  1289. if ( fNewMemory = (! *ppMemory || fMustAlloc) )
  1290. {
  1291. //
  1292. // Allocate if forced to, or if we have a union.
  1293. //
  1294. if ( fMustAlloc || *((short *)&pFormat[12]) )
  1295. *ppMemory = (uchar *) NdrAllocate( pStubMsg, *((ushort *)pFormat) );
  1296. else // pStubMsg->ReuseBuffer assumed
  1297. *ppMemory = pStubMsg->Buffer;
  1298. }
  1299. // Insert full pointer to ref id translation if needed.
  1300. if ( pStubMsg->FullPtrRefId )
  1301. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  1302. pFormat += 8;
  1303. CopySize = *((ushort *)pFormat);
  1304. CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + CopySize );
  1305. if ( *ppMemory != pStubMsg->Buffer )
  1306. {
  1307. RpcpMemoryCopy( *ppMemory,
  1308. pStubMsg->Buffer,
  1309. CopySize );
  1310. }
  1311. //
  1312. // Zero out the upper two bytes of enums!
  1313. //
  1314. if ( *((short *)&pFormat[-2]) != (short) -1 )
  1315. {
  1316. pEnum = *ppMemory + *((ushort *)&pFormat[-2]);
  1317. *((int *)(pEnum)) = *((int *)pEnum) & ((int)0x7fff) ;
  1318. }
  1319. pStubMsg->Buffer += *((ushort *)pFormat)++;
  1320. //
  1321. // See if we have a union.
  1322. //
  1323. if ( *((short *)&pFormat[2]) )
  1324. {
  1325. pUnion = *ppMemory + *((ushort *)pFormat);
  1326. if ( fNewMemory )
  1327. MIDL_memset( pUnion,
  1328. 0,
  1329. *((ushort *)&pFormat[-10]) - *((ushort *)pFormat) );
  1330. pFormat += 2;
  1331. pFormat += *((short *)pFormat);
  1332. (*pfnUnmarshallRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  1333. &pUnion,
  1334. pFormat,
  1335. FALSE );
  1336. }
  1337. return 0;
  1338. }
  1339. #endif // 0
  1340. unsigned char * RPC_ENTRY
  1341. NdrComplexStructUnmarshall(
  1342. PMIDL_STUB_MESSAGE pStubMsg,
  1343. uchar ** ppMemory,
  1344. PFORMAT_STRING pFormat,
  1345. uchar fMustAlloc )
  1346. /*++
  1347. Routine description :
  1348. Unmarshalls a complex structure.
  1349. Used for FC_BOGUS_STRUCT.
  1350. Arguments :
  1351. pStubMsg - Pointer to the stub message.
  1352. ppMemory - Double pointer to where the structure should be unmarshalled.
  1353. pFormat - Structure's format string description.
  1354. fMustAlloc - Ignored.
  1355. Return :
  1356. None.
  1357. --*/
  1358. {
  1359. uchar * pBuffer;
  1360. uchar * pBufferMark;
  1361. uchar * pMemory;
  1362. PFORMAT_STRING pFormatPointers;
  1363. PFORMAT_STRING pFormatArray;
  1364. PFORMAT_STRING pFormatComplex;
  1365. PFORMAT_STRING pFormatSave;
  1366. uint StructSize;
  1367. long Alignment;
  1368. long Align8Mod;
  1369. uchar fIsEmbeddedStruct = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  1370. BOOL fOldIgnore;
  1371. BOOL fSetPointerBufferMark;
  1372. BOOL fEmbedConfStructContext;
  1373. CORRELATION_RESOURCE_SAVE;
  1374. IGNORED(fMustAlloc);
  1375. pFormatSave = pFormat;
  1376. StructSize = 0;
  1377. // Get structure's buffer alignment.
  1378. Alignment = pFormat[1];
  1379. // Increment to the conformat array offset field.
  1380. pFormat += 4;
  1381. // Get conformant array description.
  1382. if ( *((ushort *)pFormat) )
  1383. pFormatArray = pFormat + *((signed short *)pFormat);
  1384. else
  1385. pFormatArray = 0;
  1386. pFormat += 2;
  1387. // Get pointer layout description.
  1388. if ( *((ushort *)pFormat) )
  1389. pFormatPointers = pFormat + *((ushort *)pFormat);
  1390. else
  1391. pFormatPointers = 0;
  1392. pFormat += 2;
  1393. //
  1394. // If the stub message PointerBufferMark field is not currently set, then
  1395. // set it to the end of the flat part of structure in the buffer.
  1396. //
  1397. // We do this to handle embedded pointers.
  1398. //
  1399. if ( fSetPointerBufferMark = ! pStubMsg->PointerBufferMark )
  1400. {
  1401. pBuffer = pStubMsg->Buffer;
  1402. // Save field.
  1403. fOldIgnore = pStubMsg->IgnoreEmbeddedPointers;
  1404. pStubMsg->IgnoreEmbeddedPointers = TRUE;
  1405. // Clear MemorySize.
  1406. pStubMsg->MemorySize = 0;
  1407. //
  1408. // Get a buffer pointer to where the struct's pointees will be
  1409. // unmarshalled from and remember the flat struct size in case we
  1410. // have to allocate.
  1411. //
  1412. // Note that this function will recursively do buffer overrun
  1413. // checks, bound checks, and sanity checks on size, actual count,
  1414. // and offset. And further checks in this function or called functions
  1415. // are redundant.
  1416. StructSize = NdrComplexStructMemorySize( pStubMsg,
  1417. pFormatSave );
  1418. CHECK_EOB_RAISE_BSD( pStubMsg->Buffer );
  1419. // This is where any pointees begin in the buffer.
  1420. pStubMsg->PointerBufferMark = pStubMsg->Buffer;
  1421. pStubMsg->IgnoreEmbeddedPointers = fOldIgnore;
  1422. pStubMsg->Buffer = pBuffer;
  1423. }
  1424. if ( fMustAlloc || ! *ppMemory )
  1425. {
  1426. //
  1427. // We can only get here if pStubMsg->PointerBufferMark was 0 upon
  1428. // entry to this proc.
  1429. //
  1430. NDR_ASSERT( StructSize ,"Complex struct size is 0" );
  1431. *ppMemory = (uchar*)NdrAllocate( pStubMsg, StructSize );
  1432. //
  1433. // Zero out all of the allocated memory so that deeply nested pointers
  1434. // getted properly zeroed out.
  1435. //
  1436. MIDL_memset( *ppMemory, 0, StructSize );
  1437. }
  1438. // Insert the full pointer to ref id translation if needed.
  1439. if ( pStubMsg->FullPtrRefId )
  1440. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  1441. //
  1442. // Now check if there is a conformant array and mark where the conformance
  1443. // will be unmarshalled from.
  1444. //
  1445. fEmbedConfStructContext = fIsEmbeddedStruct;
  1446. if ( pFormatArray && !fIsEmbeddedStruct )
  1447. {
  1448. ALIGN(pStubMsg->Buffer,3);
  1449. pStubMsg->BufferMark = pStubMsg->Buffer;
  1450. //
  1451. // Increment the buffer pointer 4 bytes for every dimension in the
  1452. // conformant array.
  1453. //
  1454. pStubMsg->Buffer += NdrpArrayDimensions( pStubMsg, pFormatArray, FALSE ) * 4;
  1455. if ( FixWireRepForDComVerGTE54( pStubMsg ) )
  1456. fEmbedConfStructContext = TRUE;
  1457. }
  1458. // BufferMark may be set up by an outer bogus struct.
  1459. pBufferMark = pStubMsg->BufferMark;
  1460. // conformance count mark
  1461. pStubMsg->BufferMark = pBufferMark;
  1462. // Align the buffer on the struct's alignment.
  1463. ALIGN(pStubMsg->Buffer,Alignment);
  1464. // Get the beginning memory pointer.
  1465. pMemory = *ppMemory;
  1466. // Set it to the beginning of the struct.
  1467. SET_CORRELATION_MEMORY( pMemory );
  1468. //
  1469. // This is used for support of structs with doubles passed on an
  1470. // i386 stack. The alignment of such struct's is no guaranteed to be on
  1471. // an 8 byte boundary. Similarly, od 16 bit platforms for 4 byte align.
  1472. //
  1473. // A cast to long is what we need.
  1474. Align8Mod = 0x7 & PtrToLong( pMemory );
  1475. //
  1476. // Unmarshall the structure member by member.
  1477. //
  1478. for ( ; ; pFormat++ )
  1479. {
  1480. switch ( *pFormat )
  1481. {
  1482. //
  1483. // simple types
  1484. //
  1485. case FC_CHAR :
  1486. case FC_BYTE :
  1487. case FC_SMALL :
  1488. case FC_WCHAR :
  1489. case FC_SHORT :
  1490. case FC_LONG :
  1491. #if defined(__RPC_WIN64__)
  1492. case FC_INT3264 :
  1493. case FC_UINT3264 :
  1494. #endif
  1495. case FC_FLOAT :
  1496. case FC_HYPER :
  1497. case FC_DOUBLE :
  1498. case FC_ENUM16 :
  1499. case FC_ENUM32 :
  1500. NdrSimpleTypeUnmarshall( pStubMsg,
  1501. pMemory,
  1502. *pFormat );
  1503. pMemory += SIMPLE_TYPE_MEMSIZE(*pFormat);
  1504. break;
  1505. case FC_IGNORE :
  1506. ALIGN(pStubMsg->Buffer,3);
  1507. pStubMsg->Buffer += 4;
  1508. pMemory += PTR_MEM_SIZE;
  1509. break;
  1510. case FC_POINTER :
  1511. {
  1512. uchar * pMemorySave = NULL;
  1513. ALIGN( pStubMsg->Buffer, 0x3 );
  1514. long *pPointerId = (long*)pStubMsg->Buffer;
  1515. pStubMsg->Buffer += PTR_WIRE_SIZE;
  1516. // A sized pointer here would have an offset from the beginning of the struct.
  1517. // for [in,out] struct containing "[size_is(num)] IFoo ** pfoo",
  1518. // we need to setup the pStub->memory pointing to the beginning of the struct
  1519. // such that we can get the conformance correctly during freeing pass, before
  1520. // unmarshall the returning result to the same memory spot.
  1521. if (FC_OP == *pFormatPointers )
  1522. {
  1523. pMemorySave = pStubMsg->Memory;
  1524. pStubMsg->Memory = *ppMemory;
  1525. }
  1526. POINTER_BUFFER_SWAP_CONTEXT SwapContext(pStubMsg);
  1527. NdrpPointerUnmarshall( pStubMsg,
  1528. (uchar **)pMemory, // Where the memory pointer will be written
  1529. *((uchar **)pMemory),
  1530. pPointerId, // Where the pointer in the buffer is.
  1531. pFormatPointers );
  1532. if (FC_OP == *pFormatPointers )
  1533. pStubMsg->Memory = pMemorySave;
  1534. // Increment past the memory for the pointer.
  1535. pMemory += PTR_MEM_SIZE;
  1536. pFormatPointers += 4;
  1537. break;
  1538. }
  1539. //
  1540. // Embedded complex things.
  1541. //
  1542. case FC_EMBEDDED_COMPLEX :
  1543. {
  1544. // Note, we opened a new block, so this is a different set of
  1545. // save variables than the one on the top.
  1546. CORRELATION_RESOURCE_SAVE;
  1547. // Add memory padding.
  1548. pMemory += pFormat[1];
  1549. pFormat += 2;
  1550. // Get the type's description.
  1551. pFormatComplex = pFormat + *((signed short UNALIGNED *)pFormat);
  1552. if ( FC_IP == *pFormatComplex )
  1553. {
  1554. // Treat like an embedded pointer except set the
  1555. // mark for iid_is.
  1556. SET_CORRELATION_MEMORY( pMemory );
  1557. ALIGN( pStubMsg->Buffer, 0x3 );
  1558. long *pPointerId = (long*)pStubMsg->Buffer;
  1559. pStubMsg->Buffer += PTR_WIRE_SIZE;
  1560. POINTER_BUFFER_SWAP_CONTEXT SwapContext(pStubMsg);
  1561. NdrpPointerUnmarshall( pStubMsg,
  1562. (uchar **)pMemory, // Where the memory pointer will be written
  1563. *((uchar **)pMemory),
  1564. pPointerId, // Where the pointer in the buffer is.
  1565. pFormatComplex );
  1566. pMemory += PTR_MEM_SIZE;
  1567. pFormat++;
  1568. RESET_CORRELATION_MEMORY();
  1569. break;
  1570. }
  1571. // A sized thingy here is relative to its position.
  1572. SET_CORRELATION_MEMORY( pMemory );
  1573. // Needed for an embedded conf struct.
  1574. //
  1575. pStubMsg->BufferMark = pBufferMark;
  1576. if ( fEmbedConfStructContext )
  1577. SET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  1578. (*pfnUnmarshallRoutines[ROUTINE_INDEX(*pFormatComplex)])
  1579. ( pStubMsg,
  1580. &pMemory,
  1581. pFormatComplex,
  1582. FALSE );
  1583. pMemory = NdrpMemoryIncrement( pStubMsg,
  1584. pMemory,
  1585. pFormatComplex );
  1586. RESET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  1587. RESET_CORRELATION_MEMORY();
  1588. //
  1589. // Increment the main format string one byte. The loop
  1590. // will increment it one more byte past the offset field.
  1591. //
  1592. pFormat++;
  1593. }
  1594. break;
  1595. case FC_ALIGNM2 :
  1596. ALIGN( pMemory, 0x1 );
  1597. break;
  1598. case FC_ALIGNM4 :
  1599. ALIGN( pMemory, 0x3 );
  1600. break;
  1601. case FC_ALIGNM8 :
  1602. //
  1603. // We have to play some tricks for the i386 to handle the case
  1604. // when an 8 byte aligned structure is passed by value. The
  1605. // alignment of the struct on the stack is not guaranteed to be
  1606. // on an 8 byte boundary.
  1607. //
  1608. pMemory -= Align8Mod;
  1609. ALIGN( pMemory, 0x7 );
  1610. pMemory += Align8Mod;
  1611. break;
  1612. case FC_STRUCTPAD1 :
  1613. case FC_STRUCTPAD2 :
  1614. case FC_STRUCTPAD3 :
  1615. case FC_STRUCTPAD4 :
  1616. case FC_STRUCTPAD5 :
  1617. case FC_STRUCTPAD6 :
  1618. case FC_STRUCTPAD7 :
  1619. //
  1620. // Increment memory pointer by amount of padding.
  1621. //
  1622. pMemory += (*pFormat - FC_STRUCTPAD1) + 1;
  1623. break;
  1624. case FC_STRUCTPADN :
  1625. // FC_STRUCTPADN 0 <unsigned short>
  1626. pMemory += *(((unsigned short *)pFormat) + 1);
  1627. pFormat += 3;
  1628. break;
  1629. case FC_PAD :
  1630. break;
  1631. //
  1632. // Done with layout.
  1633. //
  1634. case FC_END :
  1635. goto ComplexUnmarshallEnd;
  1636. default :
  1637. NDR_ASSERT(0,"NdrComplexStructUnmarshall : bad format char");
  1638. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  1639. return 0;
  1640. }
  1641. }
  1642. ComplexUnmarshallEnd:
  1643. RESET_CORRELATION_MEMORY();
  1644. //
  1645. // Unmarshall conformant array if the struct has one.
  1646. //
  1647. if ( pFormatArray && !fIsEmbeddedStruct &&
  1648. ! IS_CONF_ARRAY_DONE( pStubMsg->uFlags ) )
  1649. {
  1650. PPRIVATE_UNMARSHALL_ROUTINE pfnPUnmarshall;
  1651. switch ( *pFormatArray )
  1652. {
  1653. case FC_CARRAY :
  1654. pfnPUnmarshall = NdrpConformantArrayUnmarshall;
  1655. break;
  1656. case FC_CVARRAY :
  1657. pfnPUnmarshall = NdrpConformantVaryingArrayUnmarshall;
  1658. break;
  1659. case FC_BOGUS_ARRAY :
  1660. pfnPUnmarshall = NdrpComplexArrayUnmarshall;
  1661. break;
  1662. case FC_C_WSTRING :
  1663. ALIGN( pMemory, 1 );
  1664. // fall through
  1665. // case FC_C_CSTRING :
  1666. // case FC_C_BSTRING :
  1667. // case FC_C_SSTRING :
  1668. default :
  1669. pfnPUnmarshall = NdrpConformantStringUnmarshall;
  1670. break;
  1671. }
  1672. // Set it to the end of the non-conformant part of the struct.
  1673. SET_CORRELATION_MEMORY( pMemory );
  1674. //
  1675. // Unmarshall the conformance count of the outer array dimension for
  1676. // unidimensional arrays.
  1677. //
  1678. pStubMsg->MaxCount = *((ulong *)pBufferMark);
  1679. //
  1680. // Mark where conformace counts are in the buffer.
  1681. //
  1682. pStubMsg->BufferMark = pBufferMark;
  1683. //
  1684. // Unmarshall the array/string. The final flag is the fMustCopy flag,
  1685. // which must be set.
  1686. //
  1687. (*pfnPUnmarshall)( pStubMsg,
  1688. &pMemory,
  1689. pFormatArray,
  1690. TRUE,
  1691. FALSE );
  1692. RESET_CORRELATION_MEMORY();
  1693. }
  1694. //
  1695. // Now fix up the stub message Buffer field if we set the PointerBufferMark
  1696. // field.
  1697. //
  1698. if ( fSetPointerBufferMark )
  1699. {
  1700. pStubMsg->Buffer = pStubMsg->PointerBufferMark;
  1701. pStubMsg->PointerBufferMark = 0;
  1702. }
  1703. if ( fIsEmbeddedStruct )
  1704. SET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  1705. else
  1706. RESET_CONF_ARRAY_DONE( pStubMsg->uFlags );
  1707. return 0;
  1708. }
  1709. unsigned char * RPC_ENTRY
  1710. NdrNonConformantStringUnmarshall(
  1711. PMIDL_STUB_MESSAGE pStubMsg,
  1712. uchar ** ppMemory,
  1713. PFORMAT_STRING pFormat,
  1714. uchar fMustAlloc )
  1715. /*++
  1716. Routine description :
  1717. Unmarshalls a non conformant string.
  1718. Used for FC_CSTRING, FC_WSTRING, FC_SSTRING, and FC_BSTRING (NT Beta2
  1719. compatability only).
  1720. Arguments :
  1721. pStubMsg - Pointer to the stub message.
  1722. pMemory - Double pointer to the string should be unmarshalled.
  1723. pFormat - String's format string description.
  1724. fMustAlloc - Ignored.
  1725. Return :
  1726. None.
  1727. --*/
  1728. {
  1729. ulong Offset, Count, AllocSize, CharSize;
  1730. IGNORED(fMustAlloc);
  1731. // Align the buffer.
  1732. ALIGN(pStubMsg->Buffer,3);
  1733. // Get the count.
  1734. Offset = *((ulong * &)pStubMsg->Buffer)++;
  1735. Count = *((ulong * &)pStubMsg->Buffer)++;
  1736. // Get total number of elements.
  1737. AllocSize = (ulong) *((ushort *)(pFormat + 2));
  1738. CharSize = 1;
  1739. // Adjust count for wide char strings and stringable structs.
  1740. // Adjust alloc size for wide char strings and stringable structs.
  1741. switch ( *pFormat )
  1742. {
  1743. case FC_WSTRING :
  1744. CharSize = 2;
  1745. Count *= 2;
  1746. AllocSize = MultiplyWithOverflowCheck( AllocSize , 2 );
  1747. break;
  1748. case FC_SSTRING :
  1749. CharSize = pFormat[1];
  1750. Count *= pFormat[1];
  1751. AllocSize = MultiplyWithOverflowCheck( AllocSize, pFormat[1] );
  1752. break;
  1753. default :
  1754. break;
  1755. }
  1756. if ( Offset != 0 || AllocSize < Count )
  1757. RpcRaiseException( RPC_X_INVALID_BOUND );
  1758. if ( Count )
  1759. {
  1760. uchar * p;
  1761. CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, Count );
  1762. // Check if the terminator is there.
  1763. for ( p = pStubMsg->Buffer + Count - CharSize; CharSize--; )
  1764. {
  1765. if ( *p++ != 0 )
  1766. RpcRaiseException( RPC_X_INVALID_BOUND );
  1767. }
  1768. }
  1769. else
  1770. {
  1771. // any MS product will generate non-zero out;
  1772. // what about interop? will they send zero in valid case?
  1773. RpcRaiseException( RPC_X_INVALID_BOUND );
  1774. }
  1775. // Allocate memory if needed.
  1776. if ( ! *ppMemory )
  1777. {
  1778. *ppMemory = (uchar*)NdrAllocate( pStubMsg, (uint) AllocSize );
  1779. }
  1780. // Insert full pointer to ref id translation if needed.
  1781. if ( pStubMsg->FullPtrRefId )
  1782. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  1783. RpcpMemoryCopy( *ppMemory,
  1784. pStubMsg->Buffer,
  1785. (uint) Count );
  1786. // Update buffer pointer.
  1787. pStubMsg->Buffer += Count;
  1788. return 0;
  1789. }
  1790. unsigned char * RPC_ENTRY
  1791. NdrConformantStringUnmarshall(
  1792. PMIDL_STUB_MESSAGE pStubMsg,
  1793. uchar ** ppMemory,
  1794. PFORMAT_STRING pFormat,
  1795. uchar fMustAlloc )
  1796. /*++
  1797. Routine description :
  1798. Unmarshalls a top level conformant string.
  1799. Used for FC_C_CSTRING, FC_C_WSTRING, FC_C_SSTRING, and FC_C_BSTRING
  1800. (NT Beta2 compatability only).
  1801. Arguments :
  1802. pStubMsg - Pointer to the stub message.
  1803. ppMemory - Double pointer to where the string should be unmarshalled.
  1804. pFormat - String's format string description.
  1805. fMustAlloc - TRUE if the string must be allocated, FALSE otherwise.
  1806. Return :
  1807. None.
  1808. --*/
  1809. {
  1810. uchar fMustCopy;
  1811. ulong MaxCount;
  1812. if ( pStubMsg->pArrayInfo == 0 )
  1813. {
  1814. ulong ActualCount, Offset;
  1815. ulong ElementSize;
  1816. ulong ConformanceType = FC_LONG;
  1817. BOOL fIsSized;
  1818. // find string type
  1819. if ( *pFormat != FC_C_SSTRING )
  1820. {
  1821. // Typical case: char and wchar strings
  1822. ElementSize = (*pFormat == FC_C_WSTRING) ? 2
  1823. : 1;
  1824. fIsSized = (pFormat[1] == FC_STRING_SIZED);
  1825. if ( fIsSized )
  1826. ConformanceType = (pFormat[2] & 0x0f);
  1827. }
  1828. else
  1829. {
  1830. ElementSize = pFormat[1];
  1831. fIsSized = (pFormat[2] == FC_STRING_SIZED);
  1832. if ( fIsSized )
  1833. ConformanceType = (pFormat[4] & 0x0f);
  1834. }
  1835. // Align the buffer for conformance unmarshalling.
  1836. ALIGN( pStubMsg->Buffer,3 );
  1837. MaxCount = *((ulong * &)pStubMsg->Buffer)++;
  1838. Offset = ((ulong *)pStubMsg->Buffer)[0];
  1839. ActualCount = ((ulong *)pStubMsg->Buffer)[1];
  1840. CHECK_BOUND( MaxCount, ConformanceType );
  1841. if ( (Offset != 0) ||
  1842. (MaxCount < ActualCount) )
  1843. RpcRaiseException( RPC_X_INVALID_BOUND );
  1844. MultiplyWithOverflowCheck( MaxCount, ElementSize );
  1845. CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, (ActualCount * ElementSize) + 8);
  1846. // Defer the termination check till NdrpConformantStringUnmarshall.
  1847. //
  1848. // Initialize the memory pointer if needed. If the string is sized
  1849. // then we always malloc on the server side.
  1850. //
  1851. fMustAlloc = fMustAlloc || (!pStubMsg->IsClient && fIsSized);
  1852. if ( fMustAlloc )
  1853. {
  1854. fMustCopy = TRUE;
  1855. }
  1856. else
  1857. {
  1858. if ( REUSE_BUFFER(pStubMsg) )
  1859. *ppMemory = pStubMsg->Buffer + 8;
  1860. fMustCopy = FALSE;
  1861. // Insert full pointer to ref id translation if needed.
  1862. if ( pStubMsg->FullPtrRefId )
  1863. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  1864. }
  1865. }
  1866. else
  1867. {
  1868. //
  1869. // If this is part of a multidimensional array then we get the location
  1870. // where the conformance is located from a special place.
  1871. // When coming here, the StubMsg->Buffer is already behind conf sizes.
  1872. //
  1873. MaxCount = (pStubMsg->pArrayInfo->
  1874. BufferConformanceMark[pStubMsg->pArrayInfo->Dimension]);
  1875. //
  1876. // We must copy the string from the buffer to new memory.
  1877. //
  1878. fMustCopy = TRUE;
  1879. // Since this case is called by NdrComplexArrayUnmarshall, the buffer will
  1880. // have already been validated for buffer overruns and bound checks in
  1881. // NdrComplexArrayMemorySize.
  1882. // The offset and actual counts will also have been checked for sanity.
  1883. }
  1884. // Load up conformant size for next stage.
  1885. pStubMsg->MaxCount = MaxCount;
  1886. // Call the private unmarshalling routine to do the work.
  1887. NdrpConformantStringUnmarshall( pStubMsg,
  1888. ppMemory,
  1889. pFormat,
  1890. fMustCopy,
  1891. fMustAlloc );
  1892. return 0;
  1893. }
  1894. void
  1895. NdrpConformantStringUnmarshall(
  1896. PMIDL_STUB_MESSAGE pStubMsg,
  1897. uchar ** ppMemory,
  1898. PFORMAT_STRING pFormat,
  1899. uchar fMustCopy ,
  1900. uchar fMustAlloc )
  1901. /*++
  1902. Routine description :
  1903. Private routine for unmarshalling a conformant string. This is the
  1904. entry point for unmarshalling an embedded conformant strings.
  1905. Used for FC_C_CSTRING, FC_C_WSTRING, FC_C_SSTRING, and FC_C_BSTRING
  1906. (NT Beta2 compatability only).
  1907. Note this functions is only called from NdrConformantStringUnmarshall
  1908. and NdrComplexStructUnmarshall. NdrComplexStructUnmarshall calls
  1909. NdrComplexStructMemSize which validates everything except correlation.
  1910. This allows many validation checks to be skipped. If the call is through
  1911. NdrConformantStringUnmarshall, most of the necessary checks are in
  1912. NdrConformantStringUnmarshall.
  1913. Arguments :
  1914. pStubMsg - Pointer to the stub message.
  1915. pMemory - Pointer to where the string should be unmarshalled.
  1916. pFormat - String's format string description.
  1917. fMustCopy - TRUE if the string must be copied from the buffer to memory,
  1918. FALSE otherwise.
  1919. Return :
  1920. None.
  1921. --*/
  1922. {
  1923. ulong Offset, Count, CharSize;
  1924. BOOL fIsSized;
  1925. fIsSized = (*pFormat != FC_C_SSTRING) ? (pFormat[1] == FC_STRING_SIZED)
  1926. : (pFormat[2] == FC_STRING_SIZED);
  1927. if ( fIsSized && F_CORRELATION_CHECK)
  1928. {
  1929. NdrpCheckCorrelation( pStubMsg,
  1930. (long)pStubMsg->MaxCount,
  1931. pFormat,
  1932. NDR_CHECK_CONFORMANCE );
  1933. }
  1934. // Align for variance unmarshalling.
  1935. ALIGN(pStubMsg->Buffer,3);
  1936. // Unmarshall the string count.
  1937. Offset = *((ulong * &)pStubMsg->Buffer)++;
  1938. Count = *((ulong * &)pStubMsg->Buffer)++;
  1939. // Adjust the count for a wide strings and stringable structs.
  1940. // This is good enough for BSTRs as the mem pointer has already moved.
  1941. switch ( *pFormat )
  1942. {
  1943. case FC_C_WSTRING :
  1944. CharSize = 2;
  1945. Count *= 2;
  1946. break;
  1947. case FC_C_SSTRING :
  1948. CharSize = pFormat[1];
  1949. Count *= pFormat[1];
  1950. break;
  1951. default :
  1952. CharSize = 1;
  1953. break;
  1954. }
  1955. // String must have a terminator since we computed the size
  1956. // in marshaling with wcslen/strlen+charsize and the app has no
  1957. // method to size a string without a terminator.
  1958. if ( 0 == Count )
  1959. {
  1960. RpcRaiseException( RPC_X_INVALID_BOUND );
  1961. }
  1962. if ( Count )
  1963. {
  1964. uchar * p;
  1965. ulong ElemSize = CharSize;
  1966. // Check if the terminator is there.
  1967. for ( p = pStubMsg->Buffer + Count - ElemSize; ElemSize--; )
  1968. {
  1969. if ( *p++ != 0 )
  1970. RpcRaiseException( RPC_X_INVALID_BOUND );
  1971. }
  1972. }
  1973. if ( fMustAlloc )
  1974. {
  1975. *ppMemory = (uchar *) NdrAllocate( pStubMsg, pStubMsg->MaxCount * CharSize );
  1976. // Insert full pointer to ref id translation if needed.
  1977. if ( pStubMsg->FullPtrRefId )
  1978. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  1979. }
  1980. // Copy the string if needed.
  1981. if ( pStubMsg->IsClient || fMustCopy )
  1982. {
  1983. RpcpMemoryCopy( *ppMemory,
  1984. pStubMsg->Buffer,
  1985. (uint) Count );
  1986. }
  1987. // Update buffer pointer.
  1988. pStubMsg->Buffer += Count;
  1989. }
  1990. unsigned char * RPC_ENTRY
  1991. NdrFixedArrayUnmarshall(
  1992. PMIDL_STUB_MESSAGE pStubMsg,
  1993. uchar ** ppMemory,
  1994. PFORMAT_STRING pFormat,
  1995. uchar fMustAlloc )
  1996. /*++
  1997. Routine Description :
  1998. Unmarshalls a fixed array of any number of dimensions.
  1999. Used for FC_SMFARRAY and FC_LGFARRAY.
  2000. Arguments :
  2001. pStubMsg - Pointer to the stub message.
  2002. ppMemory - Pointer to the array to unmarshall.
  2003. pFormat - Array's format string description.
  2004. fMustAlloc - TRUE if the array must be allocated, FALSE otherwise.
  2005. Return :
  2006. None.
  2007. --*/
  2008. {
  2009. uchar * pBufferStart;
  2010. ulong Size;
  2011. ALIGN(pStubMsg->Buffer,pFormat[1]);
  2012. // Get the total array size.
  2013. if ( *pFormat == FC_SMFARRAY )
  2014. {
  2015. pFormat += 2;
  2016. Size = (ulong) *((ushort * &)pFormat)++;
  2017. }
  2018. else // *pFormat++ == FC_LGFARRAY
  2019. {
  2020. pFormat += 2;
  2021. Size = *((ulong UNALIGNED * &)pFormat)++;
  2022. }
  2023. pBufferStart = pStubMsg->Buffer;
  2024. CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + Size );
  2025. // Set stub message buffer pointer past array.
  2026. pStubMsg->Buffer += Size;
  2027. // Initialize the memory pointer if necessary.
  2028. if ( fMustAlloc )
  2029. *ppMemory = (uchar*)NdrAllocate( pStubMsg, (uint) Size );
  2030. else
  2031. if (REUSE_BUFFER(pStubMsg) && ! *ppMemory )
  2032. *ppMemory = pBufferStart;
  2033. // Insert full pointer to ref id translation if needed.
  2034. if ( pStubMsg->FullPtrRefId )
  2035. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  2036. // Unmarshall embedded pointers.
  2037. if ( *pFormat == FC_PP )
  2038. {
  2039. // Mark the beginning of the array in the buffer.
  2040. pStubMsg->BufferMark = pBufferStart;
  2041. NdrpEmbeddedPointerUnmarshall( pStubMsg,
  2042. *ppMemory,
  2043. pFormat,
  2044. fMustAlloc );
  2045. }
  2046. // Copy the array if we're not using the rpc buffer to hold it.
  2047. if ( *ppMemory != pBufferStart )
  2048. {
  2049. RpcpMemoryCopy( *ppMemory,
  2050. pBufferStart,
  2051. (uint) Size );
  2052. }
  2053. return 0;
  2054. }
  2055. unsigned char * RPC_ENTRY
  2056. NdrConformantArrayUnmarshall(
  2057. PMIDL_STUB_MESSAGE pStubMsg,
  2058. uchar ** ppMemory,
  2059. PFORMAT_STRING pFormat,
  2060. uchar fMustAlloc )
  2061. /*++
  2062. Routine Description :
  2063. Unmarshalls a top level one dimensional conformant array.
  2064. Used for FC_CARRAY.
  2065. Arguments :
  2066. pStubMsg - Pointer to the stub message.
  2067. ppMemory - Pointer to array to be unmarshalled.
  2068. pFormat - Array's format string description.
  2069. Return :
  2070. None.
  2071. --*/
  2072. {
  2073. ulong CopySize;
  2074. // Align the buffer for conformance unmarshalling.
  2075. ALIGN(pStubMsg->Buffer,3);
  2076. // Unmarshall the conformance count.
  2077. pStubMsg->MaxCount = *((ulong * &)pStubMsg->Buffer)++;
  2078. CHECK_BOUND( (ulong)pStubMsg->MaxCount, pFormat[4] & 0x0f );
  2079. CopySize = MultiplyWithOverflowCheck( (ulong)pStubMsg->MaxCount , *((ushort *)(pFormat + 2)) );
  2080. // Buffer size checking will be done in NdrpConformantArrayUnmarshall after alignment.
  2081. // Initialize the memory pointer if necessary.
  2082. if (!fMustAlloc && REUSE_BUFFER(pStubMsg) && ! *ppMemory )
  2083. {
  2084. *ppMemory = pStubMsg->Buffer;
  2085. //
  2086. // Align memory pointer on an 8 byte boundary if needed.
  2087. // We can't align the buffer pointer because we haven't made
  2088. // the check for size_is == 0 yet.
  2089. //
  2090. ALIGN(*ppMemory, pFormat[1]);
  2091. // Insert full pointer to ref id translation if needed.
  2092. if ( pStubMsg->FullPtrRefId )
  2093. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  2094. }
  2095. NdrpConformantArrayUnmarshall( pStubMsg,
  2096. ppMemory,
  2097. pFormat,
  2098. fMustAlloc,
  2099. fMustAlloc);
  2100. return 0;
  2101. }
  2102. void
  2103. NdrpConformantArrayUnmarshall(
  2104. PMIDL_STUB_MESSAGE pStubMsg,
  2105. uchar ** ppMemory,
  2106. PFORMAT_STRING pFormat,
  2107. uchar fMustCopy,
  2108. uchar fMustAlloc )
  2109. /*++
  2110. Routine Description :
  2111. Private routine for unmarshalling a one dimensional conformant array.
  2112. This is the entry point for unmarshalling an embedded conformant array.
  2113. Used for FC_CARRAY.
  2114. Note this functions is only called from NdrConformantArrayUnmarshall
  2115. and NdrComplexStructUnmarshall. NdrComplexStructUnmarshall calls
  2116. NdrComplexStructMemSize which validates everything except correlation.
  2117. NdrConformantArrayUnmarshall also does buffer validation.
  2118. This allows many validation checks to be skipped.
  2119. Arguments :
  2120. pStubMsg - Pointer to the stub message.
  2121. pMemory - Array being unmarshalled.
  2122. pFormat - Array's format string description.
  2123. Return :
  2124. None.
  2125. --*/
  2126. {
  2127. uchar * pBufferStart;
  2128. ulong CopySize;
  2129. // do correlation testing even if the array size is zero
  2130. if (F_CORRELATION_CHECK )
  2131. {
  2132. NdrpCheckCorrelation( pStubMsg,
  2133. (long) pStubMsg->MaxCount,
  2134. pFormat,
  2135. NDR_CHECK_CONFORMANCE );
  2136. }
  2137. // Return if array size is 0 so that we don't align the buffer.
  2138. if ( ! pStubMsg->MaxCount )
  2139. {
  2140. // allocate before return; shouldn't happen here.
  2141. if ( fMustAlloc )
  2142. {
  2143. // Compute total array size in bytes.
  2144. *ppMemory = (uchar*)NdrAllocate( pStubMsg, (uint) 0 );
  2145. // Insert full pointer to ref id translation if needed.
  2146. if ( pStubMsg->FullPtrRefId )
  2147. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  2148. }
  2149. return;
  2150. }
  2151. ALIGN(pStubMsg->Buffer,pFormat[1]);
  2152. // Compute total array size in bytes.
  2153. CopySize = MultiplyWithOverflowCheck( (ulong)pStubMsg->MaxCount , *((ushort *)(pFormat + 2)) );
  2154. pBufferStart = pStubMsg->Buffer;
  2155. CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, CopySize);
  2156. pStubMsg->Buffer += CopySize;
  2157. // we need to copy the whole allocated size in conformance array
  2158. if ( fMustAlloc )
  2159. {
  2160. // Compute total array size in bytes.
  2161. *ppMemory = (uchar*)NdrAllocate( pStubMsg, (uint) CopySize );
  2162. // Insert full pointer to ref id translation if needed.
  2163. if ( pStubMsg->FullPtrRefId )
  2164. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  2165. }
  2166. // Increment the format string pointer to possible pointer layout.
  2167. pFormat += 8;
  2168. CORRELATION_DESC_INCREMENT( pFormat );
  2169. // Unmarshall embedded pointers.
  2170. if ( *pFormat == FC_PP )
  2171. {
  2172. // Mark the beginning of the array in the buffer.
  2173. pStubMsg->BufferMark = pBufferStart;
  2174. NdrpEmbeddedPointerUnmarshall( pStubMsg,
  2175. *ppMemory,
  2176. pFormat,
  2177. fMustCopy );
  2178. }
  2179. // Copy the array if we're not using the rpc message buffer for it.
  2180. if ( pStubMsg->IsClient || fMustCopy )
  2181. {
  2182. RpcpMemoryCopy( *ppMemory,
  2183. pBufferStart,
  2184. (uint) CopySize );
  2185. }
  2186. }
  2187. unsigned char * RPC_ENTRY
  2188. NdrConformantVaryingArrayUnmarshall(
  2189. PMIDL_STUB_MESSAGE pStubMsg,
  2190. uchar ** ppMemory,
  2191. PFORMAT_STRING pFormat,
  2192. uchar fMustAlloc )
  2193. /*++
  2194. Routine Description :
  2195. Unmarshalls a top level one dimensional conformant varying array.
  2196. Used for FC_CVARRAY.
  2197. Arguments :
  2198. pStubMsg - Pointer to the stub message.
  2199. ppMemory - Pointer to the array being unmarshalled.
  2200. pFormat - Array's format string description.
  2201. fMustAlloc - Ignored.
  2202. Return :
  2203. None.
  2204. --*/
  2205. {
  2206. ulong ArrayElements = 0;
  2207. // Align the buffer for conformance unmarshalling.
  2208. ALIGN(pStubMsg->Buffer,3);
  2209. // Unmarshall the conformance size.
  2210. ArrayElements = *((ulong * &)pStubMsg->Buffer)++;
  2211. {
  2212. ulong Size;
  2213. ulong Offset, ActualCount;
  2214. PFORMAT_STRING pFormatVar;
  2215. CHECK_BOUND( ArrayElements, pFormat[4] & 0x0f );
  2216. Offset = *((ulong *)pStubMsg->Buffer);
  2217. CHECK_BOUND( Offset, FC_LONG );
  2218. ActualCount = *((ulong *)(pStubMsg->Buffer + 4));
  2219. pFormatVar = pFormat + 8;
  2220. CORRELATION_DESC_INCREMENT( pFormatVar );
  2221. CHECK_BOUND( ActualCount, *pFormatVar & 0x0f );
  2222. // we only need to check overflow for conformant size . we don't need
  2223. // to check varying overflow after we check conformance overflow
  2224. MultiplyWithOverflowCheck( ArrayElements, *((ushort *)(pFormat + 2)) );
  2225. Size = ActualCount * *((ushort *)(pFormat + 2));
  2226. if ( ((long)Offset < 0) ||
  2227. (ArrayElements < (Offset + ActualCount)) )
  2228. RpcRaiseException( RPC_X_INVALID_BOUND );
  2229. if ( (pStubMsg->Buffer + 8 + Size) > pStubMsg->BufferEnd )
  2230. RpcRaiseException( RPC_X_INVALID_BOUND );
  2231. }
  2232. //
  2233. // For a conformant varying array, we can't reuse the buffer
  2234. // because it doesn't hold the total size of the array. So
  2235. // allocate if the current memory pointer is 0.
  2236. //
  2237. if ( ! *ppMemory )
  2238. {
  2239. fMustAlloc = TRUE;
  2240. }
  2241. else
  2242. {
  2243. fMustAlloc = FALSE;
  2244. // Insert full pointer to ref id translation if needed.
  2245. // do this only when not allocating memory. this will be done
  2246. // in p version if new memory is allocated.
  2247. if ( pStubMsg->FullPtrRefId )
  2248. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  2249. }
  2250. pStubMsg->MaxCount = ArrayElements;
  2251. NdrpConformantVaryingArrayUnmarshall( pStubMsg,
  2252. ppMemory,
  2253. pFormat,
  2254. fMustAlloc,
  2255. fMustAlloc);
  2256. return 0;
  2257. }
  2258. void
  2259. NdrpConformantVaryingArrayUnmarshall(
  2260. PMIDL_STUB_MESSAGE pStubMsg,
  2261. uchar ** ppMemory,
  2262. PFORMAT_STRING pFormat,
  2263. uchar fMustCopy,
  2264. uchar fMustAlloc )
  2265. /*++
  2266. Routine Description :
  2267. Private routine for unmarshalling a one dimensional conformant varying
  2268. array. This is the entry point for unmarshalling an embedded conformant
  2269. varying array.
  2270. Used for FC_CVARRAY.
  2271. Note this functions is only called from NdrConformantVaryingArrayUnmarshall
  2272. and NdrComplexStructUnmarshall. NdrComplexStructUnmarshall calls
  2273. NdrComplexStructMemSize which validates everything except correlation.
  2274. NdrConformantVaryingArrayUnmarshall also does buffer validation.
  2275. This allows many validation checks to be skipped.
  2276. Arguments :
  2277. pStubMsg - Pointer to the stub message.
  2278. pMemory - Array being unmarshalled.
  2279. pFormat - Array's format string description.
  2280. fMustCopy - Ignored.
  2281. Return :
  2282. None.
  2283. --*/
  2284. {
  2285. uchar * pBufferStart;
  2286. ulong CopyOffset, CopySize;
  2287. ushort ElemSize;
  2288. IGNORED(fMustCopy);
  2289. // Align the buffer for conformance unmarshalling.
  2290. ALIGN(pStubMsg->Buffer,3);
  2291. // Unmarshall offset and actual count.
  2292. pStubMsg->Offset = *((ulong * &)pStubMsg->Buffer)++;
  2293. pStubMsg->ActualCount = *((ulong * &)pStubMsg->Buffer)++;
  2294. if (F_CORRELATION_CHECK )
  2295. {
  2296. NdrpCheckCorrelation( pStubMsg,
  2297. (long) pStubMsg->MaxCount,
  2298. pFormat,
  2299. NDR_CHECK_CONFORMANCE );
  2300. NdrpCheckCorrelation( pStubMsg,
  2301. (long) pStubMsg->ActualCount,
  2302. pFormat,
  2303. NDR_CHECK_VARIANCE );
  2304. NdrpCheckCorrelation( pStubMsg,
  2305. (long) pStubMsg->Offset,
  2306. pFormat,
  2307. NDR_CHECK_OFFSET );
  2308. }
  2309. ElemSize = *((ushort *)(pFormat + 2));
  2310. //
  2311. // Return if length is 0.
  2312. //
  2313. if ( ! pStubMsg->ActualCount )
  2314. {
  2315. // needs to allocate before return.
  2316. if ( fMustAlloc )
  2317. {
  2318. *ppMemory = (uchar*)NdrAllocate( pStubMsg, (uint) pStubMsg->MaxCount * ElemSize );
  2319. // Insert full pointer to ref id translation if needed.
  2320. if ( pStubMsg->FullPtrRefId )
  2321. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  2322. }
  2323. return;
  2324. }
  2325. CopyOffset = MultiplyWithOverflowCheck(pStubMsg->Offset , ElemSize );
  2326. CopySize = MultiplyWithOverflowCheck( pStubMsg->ActualCount , ElemSize );
  2327. ALIGN(pStubMsg->Buffer, pFormat[1]);
  2328. pBufferStart = pStubMsg->Buffer;
  2329. // Increment buffer pointer past array.
  2330. CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, CopySize );
  2331. pStubMsg->Buffer += CopySize;
  2332. // Increment format string to possible pointer description.
  2333. pFormat += 12;
  2334. CORRELATION_DESC_INCREMENT( pFormat );
  2335. CORRELATION_DESC_INCREMENT( pFormat );
  2336. if ( fMustAlloc )
  2337. {
  2338. *ppMemory = (uchar*)NdrAllocate( pStubMsg, (uint) pStubMsg->MaxCount * ElemSize );
  2339. // Insert full pointer to ref id translation if needed.
  2340. if ( pStubMsg->FullPtrRefId )
  2341. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  2342. }
  2343. // Unmarshall embedded pointers first.
  2344. if ( *pFormat == FC_PP )
  2345. {
  2346. //
  2347. // Set the MaxCount field equal to the variance count.
  2348. // The pointer unmarshalling routine uses the MaxCount field
  2349. // to determine the number of times an FC_VARIABLE_REPEAT
  2350. // pointer is unmarshalled. In the face of variance the
  2351. // correct number of time is the actual count, not MaxCount.
  2352. //
  2353. pStubMsg->MaxCount = pStubMsg->ActualCount;
  2354. //
  2355. // Mark the location of the first transmitted array element in
  2356. // the buffer.
  2357. //
  2358. pStubMsg->BufferMark = pBufferStart;
  2359. NdrpEmbeddedPointerUnmarshall( pStubMsg,
  2360. *ppMemory,
  2361. pFormat,
  2362. fMustCopy );
  2363. }
  2364. // Always copy. Buffer reuse is not possible.
  2365. RpcpMemoryCopy( *ppMemory + CopyOffset,
  2366. pBufferStart,
  2367. (uint) CopySize );
  2368. }
  2369. unsigned char * RPC_ENTRY
  2370. NdrVaryingArrayUnmarshall(
  2371. PMIDL_STUB_MESSAGE pStubMsg,
  2372. uchar ** ppMemory,
  2373. PFORMAT_STRING pFormat,
  2374. uchar fMustAlloc )
  2375. /*++
  2376. Routine Description :
  2377. Unmarshalls top level or embedded a one dimensional varying array.
  2378. Used for FC_SMVARRAY and FC_LGVARRAY.
  2379. Arguments :
  2380. pStubMsg - Pointer to the stub message.
  2381. pMemory - Array being unmarshalled.
  2382. pFormat - Array's format string description.
  2383. fMustAlloc - Ignored.
  2384. --*/
  2385. {
  2386. uchar * pBufferStart;
  2387. ulong TotalSize;
  2388. ulong Offset, Count;
  2389. ulong CopyOffset, CopySize;
  2390. ushort ElemSize;
  2391. uchar fNewMemory;
  2392. long Elements;
  2393. // Align the buffer for variance unmarshalling.
  2394. ALIGN(pStubMsg->Buffer,3);
  2395. Offset = *((ulong * &)pStubMsg->Buffer)++;
  2396. Count = *((ulong * &)pStubMsg->Buffer)++;
  2397. if ( ! Count )
  2398. return 0;
  2399. // We fish out type from the (old part of the) variance descriptor.
  2400. CHECK_BOUND( Offset, FC_LONG);
  2401. CHECK_BOUND( Count,
  2402. pFormat[(*pFormat == FC_SMVARRAY) ? 8 : 12] & 0x0f );
  2403. Elements =
  2404. (*pFormat == FC_SMVARRAY) ?
  2405. *((ushort *)(pFormat + 4)) : *((ulong UNALIGNED *)(pFormat + 6));
  2406. if ( ((long)Offset < 0 ) ||
  2407. (Elements < (long)(Count + Offset)) )
  2408. RpcRaiseException( RPC_X_INVALID_BOUND );
  2409. if (F_CORRELATION_CHECK )
  2410. {
  2411. NdrpCheckCorrelation( pStubMsg,
  2412. (long)Count,
  2413. pFormat,
  2414. NDR_CHECK_VARIANCE );
  2415. NdrpCheckCorrelation( pStubMsg,
  2416. (long)Offset,
  2417. pFormat,
  2418. NDR_CHECK_OFFSET );
  2419. }
  2420. ALIGN(pStubMsg->Buffer, pFormat[1]);
  2421. // Get array's total size and increment to element size field.
  2422. if ( *pFormat == FC_SMVARRAY )
  2423. {
  2424. TotalSize = (ulong) *((ushort *)(pFormat + 2));
  2425. pFormat += 6;
  2426. }
  2427. else
  2428. {
  2429. TotalSize = *((ulong UNALIGNED *)(pFormat + 2));
  2430. pFormat += 10;
  2431. }
  2432. if ( fNewMemory = ! *ppMemory )
  2433. {
  2434. *ppMemory = (uchar*)NdrAllocate( pStubMsg, (uint) TotalSize );
  2435. }
  2436. // Insert full pointer to ref id translation if needed.
  2437. if ( pStubMsg->FullPtrRefId )
  2438. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  2439. ElemSize = *((ushort *)pFormat);
  2440. CopyOffset = MultiplyWithOverflowCheck( Offset, ElemSize );
  2441. CopySize = MultiplyWithOverflowCheck( Count, ElemSize );
  2442. if ( (long) CopyOffset < 0 ||
  2443. ( TotalSize < CopyOffset + CopySize ) )
  2444. RpcRaiseException( RPC_X_INVALID_BOUND );
  2445. pBufferStart = pStubMsg->Buffer;
  2446. CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, CopySize );
  2447. pStubMsg->Buffer += CopySize;
  2448. // Increment format string to possible pointer description.
  2449. pFormat += 6;
  2450. CORRELATION_DESC_INCREMENT( pFormat );
  2451. // Unmarshall embedded pointers.
  2452. if ( *pFormat == FC_PP )
  2453. {
  2454. //
  2455. // Set the MaxCount field equal to the variance count.
  2456. // The pointer unmarshalling routine uses the MaxCount field
  2457. // to determine the number of times an FC_VARIABLE_REPEAT
  2458. // pointer is unmarshalled. In the face of variance the
  2459. // correct number of time is the actual count, not MaxCount.
  2460. //
  2461. pStubMsg->MaxCount = Count;
  2462. //
  2463. // Mark the location of the first transmitted array element in
  2464. // the buffer
  2465. //
  2466. pStubMsg->BufferMark = pBufferStart;
  2467. NdrpEmbeddedPointerUnmarshall( pStubMsg,
  2468. *ppMemory,
  2469. pFormat,
  2470. fNewMemory );
  2471. }
  2472. RpcpMemoryCopy( *ppMemory + CopyOffset,
  2473. pBufferStart,
  2474. (uint) CopySize );
  2475. return 0;
  2476. }
  2477. unsigned char * RPC_ENTRY
  2478. NdrComplexArrayUnmarshall(
  2479. PMIDL_STUB_MESSAGE pStubMsg,
  2480. uchar ** ppMemory,
  2481. PFORMAT_STRING pFormat,
  2482. uchar fMustAlloc )
  2483. /*++
  2484. Routine Description :
  2485. Unmarshalls a top level complex array.
  2486. Used for FC_BOGUS_STRUCT.
  2487. Arguments :
  2488. pStubMsg - Pointer to the stub message.
  2489. ppMemory - Pointer to the array being unmarshalled.
  2490. pFormat - Array's format string description.
  2491. fMustAlloc - Ignored.
  2492. Return :
  2493. None.
  2494. --*/
  2495. {
  2496. uchar * pBuffer;
  2497. long ArraySize;
  2498. BOOL fSetPointerBufferMark;
  2499. ArraySize = 0;
  2500. //
  2501. // Setting this flag means that the array is not embedded inside of
  2502. // another complex struct or array.
  2503. //
  2504. fSetPointerBufferMark = ! pStubMsg->PointerBufferMark;
  2505. if ( fSetPointerBufferMark )
  2506. {
  2507. BOOL fOldIgnore;
  2508. PFORMAT_STRING pFormatPP;
  2509. pBuffer = pStubMsg->Buffer;
  2510. fOldIgnore = pStubMsg->IgnoreEmbeddedPointers;
  2511. pStubMsg->IgnoreEmbeddedPointers = TRUE;
  2512. pStubMsg->MemorySize = 0;
  2513. //
  2514. // Get a buffer pointer to where the arrays's pointees will be
  2515. // unmarshalled from and remember the array size in case we
  2516. // have to allocate.
  2517. //
  2518. // Note this function will recursively check buffer overflows,
  2519. // bounds, and trial sanity checks on array offsets, sizes,
  2520. // and actual counts. This make additional checks in this
  2521. // function redundant.
  2522. ArraySize = NdrComplexArrayMemorySize( pStubMsg,
  2523. pFormat );
  2524. // at least we are not out of bound in flat part. not really necessary
  2525. // but good to have.
  2526. CHECK_EOB_RAISE_BSD( pStubMsg->Buffer );
  2527. //
  2528. // PointerBufferaMark is where the pointees begin in the buffer.
  2529. // If this is an array of ref pointers then we don't want to set
  2530. // this, all we wanted was the array size.
  2531. //
  2532. pFormatPP = pFormat + 12;
  2533. CORRELATION_DESC_INCREMENT( pFormatPP );
  2534. CORRELATION_DESC_INCREMENT( pFormatPP );
  2535. if ( *pFormatPP != FC_RP )
  2536. {
  2537. pStubMsg->PointerBufferMark = pStubMsg->Buffer;
  2538. }
  2539. else
  2540. fSetPointerBufferMark = FALSE;
  2541. pStubMsg->IgnoreEmbeddedPointers = fOldIgnore;
  2542. pStubMsg->Buffer = pBuffer;
  2543. }
  2544. if ( fMustAlloc || ! *ppMemory )
  2545. {
  2546. *ppMemory = (uchar*)NdrAllocate( pStubMsg, (uint) ArraySize );
  2547. //
  2548. // Zero out the memory of the array if we allocated it, to insure
  2549. // that all embedded pointers are zeroed out. Blech.
  2550. //
  2551. MIDL_memset( *ppMemory, 0, (uint) ArraySize );
  2552. }
  2553. // Insert full pointer to ref id translation if needed.
  2554. if ( pStubMsg->FullPtrRefId )
  2555. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  2556. //
  2557. // Check for a conformance description.
  2558. //
  2559. if ( ( *((long UNALIGNED *)(pFormat + 4)) != 0xffffffff ) &&
  2560. ( pStubMsg->pArrayInfo == 0 ) )
  2561. {
  2562. //
  2563. // The outer most array dimension sets the conformance marker.
  2564. //
  2565. ALIGN(pStubMsg->Buffer,0x3);
  2566. // Mark where the conformance count(s) will be unmarshalled from.
  2567. pStubMsg->BufferMark = pStubMsg->Buffer;
  2568. // Increment past conformance count(s).
  2569. pStubMsg->Buffer += NdrpArrayDimensions( pStubMsg, pFormat, FALSE ) * 4;
  2570. }
  2571. NdrpComplexArrayUnmarshall( pStubMsg,
  2572. ppMemory,
  2573. pFormat,
  2574. TRUE,
  2575. FALSE );
  2576. if ( fSetPointerBufferMark )
  2577. {
  2578. //
  2579. // This will set the buffer pointer to end of all of the array's
  2580. // unmarshalled data in the buffer.
  2581. //
  2582. pStubMsg->Buffer = pStubMsg->PointerBufferMark;
  2583. pStubMsg->PointerBufferMark = 0;
  2584. }
  2585. return 0;
  2586. }
  2587. void
  2588. NdrpComplexArrayUnmarshall(
  2589. PMIDL_STUB_MESSAGE pStubMsg,
  2590. uchar ** ppMemory,
  2591. PFORMAT_STRING pFormat,
  2592. uchar fMustCopy,
  2593. uchar fMustAlloc )
  2594. /*++
  2595. Routine Description :
  2596. Private routine for unmarshalling a complex array. This is the entry
  2597. point for unmarshalling an embedded complex array.
  2598. Used for FC_BOGUS_ARRAY.
  2599. Note this functions is only called from NdrComplexArrayUnmarshall
  2600. and NdrComplexStructUnmarshall. NdrComplexStructUnmarshall calls
  2601. NdrComplexStructMemSize which validates everything except correlation.
  2602. MdrComplexArrayUnmarshall has a similar check.
  2603. This allows many validation checks to be skipped.
  2604. Arguments :
  2605. pStubMsg - Pointer to the stub message.
  2606. ppMemory - Pointer to the array being unmarshalled.
  2607. pFormat - Array's format string description.
  2608. fMustCopy - Ignored.
  2609. Return :
  2610. None.
  2611. --*/
  2612. {
  2613. ARRAY_INFO ArrayInfo;
  2614. PARRAY_INFO pArrayInfo;
  2615. PUNMARSHALL_ROUTINE pfnUnmarshall;
  2616. PFORMAT_STRING pFormatSave;
  2617. ulong Elements;
  2618. ulong Offset, Count;
  2619. ulong MemoryElementSize;
  2620. long Dimension;
  2621. uchar Alignment;
  2622. bool UseBrokenInterfacePointer = false;
  2623. // this is called from ComplexStruct & ComplexArray, and in either case, we
  2624. // cann't prevent allocation before correlation check. These are "can't solve"
  2625. // scenarios.
  2626. uchar * pMemory = *ppMemory;
  2627. //
  2628. // Setup if we are the outer dimension. All this is for multidimensional
  2629. // array support. If we didn't have to worry about Beta2 stub
  2630. // compatability we could this much better.
  2631. //
  2632. if ( ! pStubMsg->pArrayInfo )
  2633. {
  2634. pStubMsg->pArrayInfo = &ArrayInfo;
  2635. ArrayInfo.Dimension = 0;
  2636. ArrayInfo.BufferConformanceMark = (unsigned long *)pStubMsg->BufferMark;
  2637. ArrayInfo.BufferVarianceMark = 0;
  2638. }
  2639. pFormatSave = pFormat;
  2640. pArrayInfo = pStubMsg->pArrayInfo;
  2641. Dimension = pArrayInfo->Dimension;
  2642. Alignment = pFormat[1];
  2643. pFormat += 2;
  2644. // This is 0 if the array has conformance.
  2645. Elements = *((ushort * &)pFormat)++;
  2646. //
  2647. // Check for conformance description.
  2648. //
  2649. if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
  2650. {
  2651. Elements = pArrayInfo->BufferConformanceMark[Dimension];
  2652. if ( F_CORRELATION_CHECK )
  2653. {
  2654. NdrpCheckCorrelation( pStubMsg,
  2655. Elements,
  2656. pFormatSave,
  2657. NDR_CHECK_CONFORMANCE );
  2658. }
  2659. }
  2660. pFormat += 4;
  2661. CORRELATION_DESC_INCREMENT( pFormat );
  2662. //
  2663. // Check for variance description.
  2664. //
  2665. if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
  2666. {
  2667. if ( Dimension == 0 )
  2668. {
  2669. ulong VarianceSize;
  2670. ALIGN(pStubMsg->Buffer,0x3);
  2671. // Mark where the variance counts are.
  2672. pArrayInfo->BufferVarianceMark = (unsigned long *)pStubMsg->Buffer;
  2673. // Handle multidimensional arrays.
  2674. VarianceSize = NdrpArrayDimensions( pStubMsg, pFormatSave, TRUE ) * 8;
  2675. pStubMsg->Buffer += VarianceSize;
  2676. }
  2677. Offset = pArrayInfo->BufferVarianceMark[Dimension * 2];
  2678. Count = pArrayInfo->BufferVarianceMark[(Dimension * 2) + 1];
  2679. if ( F_CORRELATION_CHECK )
  2680. {
  2681. NdrpCheckCorrelation( pStubMsg,
  2682. Offset,
  2683. pFormatSave,
  2684. NDR_CHECK_OFFSET );
  2685. NdrpCheckCorrelation( pStubMsg,
  2686. Count,
  2687. pFormatSave,
  2688. NDR_CHECK_VARIANCE );
  2689. }
  2690. }
  2691. else
  2692. {
  2693. Offset = 0;
  2694. Count = Elements;
  2695. }
  2696. pFormat += 4;
  2697. CORRELATION_DESC_INCREMENT( pFormat );
  2698. if ( ! Count )
  2699. goto ComplexArrayUnmarshallEnd;
  2700. ALIGN(pStubMsg->Buffer,Alignment);
  2701. switch ( *pFormat )
  2702. {
  2703. case FC_EMBEDDED_COMPLEX :
  2704. pFormat += 2;
  2705. pFormat += *((signed short *)pFormat);
  2706. if ( *pFormat == FC_IP )
  2707. goto HandleInterfacePointer;
  2708. pfnUnmarshall = pfnUnmarshallRoutines[ROUTINE_INDEX(*pFormat)];
  2709. pArrayInfo->Dimension = Dimension + 1;
  2710. pArrayInfo->MaxCountArray = pArrayInfo->BufferConformanceMark;
  2711. MemoryElementSize = (ulong) ( NdrpMemoryIncrement( pStubMsg,
  2712. pMemory,
  2713. pFormat ) - pMemory );
  2714. pArrayInfo->MaxCountArray = 0;
  2715. break;
  2716. // note : midl doesn't seems to generate FC_OP in here, so we don't want
  2717. // to change it for now. but there is potential bug here that pStubMsg->Memory
  2718. // is not set and NdrPointerFree might fail if FC_OP points to a conformance
  2719. // struct/array.
  2720. case FC_RP :
  2721. case FC_UP :
  2722. case FC_FP :
  2723. case FC_OP :
  2724. pfnUnmarshall = (PUNMARSHALL_ROUTINE) NdrpPointerUnmarshall;
  2725. // Need this in case we have a variant offset.
  2726. MemoryElementSize = PTR_MEM_SIZE;
  2727. break;
  2728. case FC_IP :
  2729. HandleInterfacePointer:
  2730. UseBrokenInterfacePointer = !FixWireRepForDComVerGTE54( pStubMsg );
  2731. // Probably this code is not used, as for arrays of IPs the compiler
  2732. // (as of ver. 5.1.+) generates array of embedded complex.
  2733. //
  2734. pfnUnmarshall = (PUNMARSHALL_ROUTINE)NdrpPointerUnmarshall;
  2735. // Need this in case we have a variant offset.
  2736. MemoryElementSize = PTR_MEM_SIZE;
  2737. break;
  2738. case FC_ENUM16 :
  2739. pfnUnmarshall = 0;
  2740. MemoryElementSize = sizeof(int);
  2741. break;
  2742. #if defined(__RPC_WIN64__)
  2743. case FC_INT3264:
  2744. case FC_UINT3264:
  2745. pfnUnmarshall = 0;
  2746. MemoryElementSize = sizeof(__int64);
  2747. break;
  2748. #endif
  2749. case FC_RANGE:
  2750. pfnUnmarshall = NdrRangeUnmarshall;
  2751. MemoryElementSize = SIMPLE_TYPE_MEMSIZE( pFormat[1] );
  2752. break;
  2753. default :
  2754. NDR_ASSERT( IS_SIMPLE_TYPE(*pFormat),
  2755. "NdrpComplexArrayUnmarshall : bad format char" );
  2756. Count = MultiplyWithOverflowCheck( Count, SIMPLE_TYPE_BUFSIZE(*pFormat) );
  2757. pMemory += MultiplyWithOverflowCheck( Offset , SIMPLE_TYPE_MEMSIZE(*pFormat) );
  2758. RpcpMemoryCopy( pMemory,
  2759. pStubMsg->Buffer,
  2760. (uint) Count );
  2761. pStubMsg->Buffer += Count;
  2762. goto ComplexArrayUnmarshallEnd;
  2763. }
  2764. //
  2765. // If there is variance then increment the memory pointer to the first
  2766. // element actually being marshalled.
  2767. //
  2768. if ( Offset )
  2769. pMemory += MultiplyWithOverflowCheck( Offset , MemoryElementSize );
  2770. //
  2771. // Check for an array of enum16 or int3264.
  2772. //
  2773. if ( ! pfnUnmarshall )
  2774. {
  2775. #if defined(__RPC_WIN64__)
  2776. if ( *pFormat != FC_ENUM16 )
  2777. {
  2778. // int3264
  2779. if ( *pFormat == FC_INT3264 )
  2780. {
  2781. for ( ; Count--; )
  2782. *((INT64 * &)pMemory)++ = *((long * &)pStubMsg->Buffer)++;
  2783. }
  2784. else
  2785. {
  2786. for ( ; Count--; )
  2787. *((UINT64 * &)pMemory)++ = *((ulong * &)pStubMsg->Buffer)++;
  2788. }
  2789. }
  2790. else
  2791. #endif
  2792. {
  2793. for ( ; Count--; )
  2794. {
  2795. // Cast to ushort since we don't want to sign extend.
  2796. *((int * &)pMemory)++ = (int) *((ushort * &)pStubMsg->Buffer)++;
  2797. }
  2798. }
  2799. goto ComplexArrayUnmarshallEnd;
  2800. } // !pfnUnmarshall
  2801. //
  2802. // Array of pointers.
  2803. //
  2804. if ( (pfnUnmarshall == (PUNMARSHALL_ROUTINE) NdrpPointerUnmarshall) )
  2805. {
  2806. // If the broken interface pointer is used,
  2807. // the pointer will not show up in the flat part
  2808. // but in the pointee.
  2809. if ( UseBrokenInterfacePointer )
  2810. {
  2811. pStubMsg->pArrayInfo = 0;
  2812. SET_BROKEN_INTERFACE_POINTER( pStubMsg->uFlags );
  2813. POINTER_BUFFER_SWAP_CONTEXT SwapContext( pStubMsg );
  2814. for ( ; Count--; )
  2815. {
  2816. NdrpPointerUnmarshall(
  2817. pStubMsg,
  2818. (uchar **)pMemory,
  2819. *((uchar **)pMemory),
  2820. NULL,
  2821. pFormat );
  2822. pMemory += PTR_MEM_SIZE;
  2823. }
  2824. RESET_BROKEN_INTERFACE_POINTER( pStubMsg->uFlags );
  2825. }
  2826. else
  2827. {
  2828. long *pBufferPtr;
  2829. ulong DoPtrWireInc;
  2830. if ( *pFormat != FC_RP )
  2831. {
  2832. pBufferPtr = (long*)pStubMsg->Buffer;
  2833. pStubMsg->Buffer += MultiplyWithOverflowCheck( PTR_WIRE_SIZE , Count );
  2834. DoPtrWireInc = 1;
  2835. }
  2836. else
  2837. {
  2838. pBufferPtr = 0;
  2839. DoPtrWireInc = 0;
  2840. }
  2841. pStubMsg->pArrayInfo = 0;
  2842. POINTER_BUFFER_SWAP_CONTEXT SwapContext( pStubMsg );
  2843. for ( ; Count--; )
  2844. {
  2845. NdrpPointerUnmarshall(
  2846. pStubMsg,
  2847. (uchar **)pMemory,
  2848. *((uchar **)pMemory),
  2849. pBufferPtr,
  2850. pFormat );
  2851. pBufferPtr += DoPtrWireInc;
  2852. pMemory += PTR_MEM_SIZE;
  2853. }
  2854. }
  2855. goto ComplexArrayUnmarshallEnd;
  2856. }
  2857. //
  2858. // Unmarshall the complex array elements.
  2859. //
  2860. if ( ! IS_ARRAY_OR_STRING(*pFormat) )
  2861. pStubMsg->pArrayInfo = 0;
  2862. for ( ; Count--; )
  2863. {
  2864. // Keep track of multidimensional array dimension.
  2865. if ( IS_ARRAY_OR_STRING(*pFormat) )
  2866. pArrayInfo->Dimension = Dimension + 1;
  2867. (*pfnUnmarshall)( pStubMsg,
  2868. &pMemory,
  2869. pFormat,
  2870. FALSE );
  2871. // Increment the memory pointer by the element size.
  2872. pMemory += MemoryElementSize;
  2873. }
  2874. ComplexArrayUnmarshallEnd:
  2875. // pArrayInfo must be zero when not valid.
  2876. pStubMsg->pArrayInfo = (Dimension == 0) ? 0 : pArrayInfo;
  2877. }
  2878. unsigned char * RPC_ENTRY
  2879. NdrEncapsulatedUnionUnmarshall (
  2880. PMIDL_STUB_MESSAGE pStubMsg,
  2881. uchar ** ppMemory,
  2882. PFORMAT_STRING pFormat,
  2883. uchar fMustAlloc )
  2884. /*++
  2885. Routine Description :
  2886. Unmarshalls an encapsulated array.
  2887. Used for FC_ENCAPSULATED_UNION.
  2888. Arguments :
  2889. pStubMsg - Pointer to the stub message.
  2890. ppMemory - Double pointer to where the union should be unmarshalled.
  2891. pFormat - Union's format string description.
  2892. fMustAlloc - Ignored.
  2893. Return :
  2894. None.
  2895. --*/
  2896. {
  2897. uchar * pBuffer;
  2898. uchar * pUnion;
  2899. uchar SwitchType;
  2900. IGNORED(fMustAlloc);
  2901. NO_CORRELATION;
  2902. //
  2903. // Since we can never use the buffer to hold a union we simply have
  2904. // to check the current memory pointer to see if memory must be allocated.
  2905. //
  2906. // The memory size of an encapsulated union is the union size plus
  2907. // the memory needed for the switch_is member (including any padding
  2908. // for alignment).
  2909. //
  2910. if ( ! *ppMemory )
  2911. {
  2912. uint Size;
  2913. Size = *((ushort *)(pFormat + 2)) + HIGH_NIBBLE(pFormat[1]);
  2914. *ppMemory = (uchar*)NdrAllocate( pStubMsg, Size );
  2915. //
  2916. // We must zero out all of the new memory in case there are pointers
  2917. // in any of the arms.
  2918. //
  2919. MIDL_memset( *ppMemory, 0, Size );
  2920. }
  2921. // Insert full pointer to ref id translation if needed.
  2922. if ( pStubMsg->FullPtrRefId )
  2923. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  2924. SwitchType = LOW_NIBBLE(pFormat[1]);
  2925. pBuffer = pStubMsg->Buffer;
  2926. //
  2927. // Unmarshall the switch_is field into memory.
  2928. //
  2929. NdrSimpleTypeUnmarshall( pStubMsg,
  2930. *ppMemory,
  2931. SwitchType );
  2932. //
  2933. // The above call incremented the buffer pointer. Set it back to before
  2934. // the switch is value in the buffer.
  2935. //
  2936. pStubMsg->Buffer = pBuffer;
  2937. // Get a memory pointer to the union.
  2938. pUnion = *ppMemory + HIGH_NIBBLE(pFormat[1]);
  2939. NdrpUnionUnmarshall( pStubMsg,
  2940. &pUnion,
  2941. pFormat + 2,
  2942. SwitchType,
  2943. 0 ); // Encapsulated union
  2944. return 0;
  2945. }
  2946. unsigned char * RPC_ENTRY
  2947. NdrNonEncapsulatedUnionUnmarshall (
  2948. PMIDL_STUB_MESSAGE pStubMsg,
  2949. uchar ** ppMemory,
  2950. PFORMAT_STRING pFormat,
  2951. uchar fMustAlloc )
  2952. /*++
  2953. Routine Description :
  2954. Unmarshalls a non encapsulated array.
  2955. Used for FC_NON_ENCAPSULATED_UNION.
  2956. Arguments :
  2957. pStubMsg - Pointer to the stub message.
  2958. ppMemory - Double pointer to where the union should be unmarshalled.
  2959. pFormat - Union's format string description.
  2960. fMustAlloc - Ignored.
  2961. Return :
  2962. None.
  2963. --*/
  2964. {
  2965. uchar SwitchType;
  2966. PFORMAT_STRING pFormatSave = pFormat;
  2967. IGNORED(fMustAlloc);
  2968. SwitchType = pFormat[1];
  2969. //
  2970. // Get the memory size and arm description part of the format string
  2971. // description.
  2972. //
  2973. pFormat += 6;
  2974. CORRELATION_DESC_INCREMENT( pFormat );
  2975. pFormat += *((signed short *)pFormat);
  2976. //
  2977. // Since we can never use the buffer to hold a union we simply have
  2978. // to check the current memory pointer to see if memory must be allocated.
  2979. //
  2980. if ( fMustAlloc || ! *ppMemory )
  2981. {
  2982. uint Size;
  2983. Size = *((ushort *)pFormat);
  2984. *ppMemory = (uchar*)NdrAllocate( pStubMsg, Size );
  2985. //
  2986. // We must zero out all of the new memory in case there are pointers
  2987. // in any of the arms.
  2988. //
  2989. MIDL_memset( *ppMemory, 0, Size );
  2990. }
  2991. // Insert full pointer to ref id translation if needed.
  2992. if ( pStubMsg->FullPtrRefId )
  2993. FULL_POINTER_INSERT( pStubMsg, *ppMemory );
  2994. NdrpUnionUnmarshall( pStubMsg,
  2995. ppMemory,
  2996. pFormat,
  2997. SwitchType,
  2998. pFormatSave );
  2999. return 0;
  3000. }
  3001. void
  3002. NdrpUnionUnmarshall (
  3003. PMIDL_STUB_MESSAGE pStubMsg,
  3004. uchar ** ppMemory,
  3005. PFORMAT_STRING pFormat,
  3006. uchar SwitchType,
  3007. PFORMAT_STRING pFormatNonEncUnion
  3008. )
  3009. /*++
  3010. Routine description :
  3011. Private routine for unmarshalling a union. This routine is shared for
  3012. both encapsulated and non-encapsulated unions and handles the actual
  3013. unmarshalling of the proper union arm.
  3014. Arguments :
  3015. pStubMsg - Pointer to the stub message.
  3016. ppMemory - Double pointer to where the union should be unmarshalled.
  3017. pFormat - Union's format string description.
  3018. SwitchType - Union's switch type.
  3019. Return :
  3020. None.
  3021. --*/
  3022. {
  3023. long SwitchIs;
  3024. long Arms;
  3025. uchar Alignment;
  3026. //
  3027. // Unmarshall the switch is. We have to do it inline here so that a
  3028. // switch_is which is negative will be properly sign extended.
  3029. //
  3030. switch ( SwitchType )
  3031. {
  3032. case FC_SMALL :
  3033. case FC_CHAR :
  3034. SwitchIs = (long) *((char * &)pStubMsg->Buffer)++;
  3035. break;
  3036. case FC_USMALL :
  3037. SwitchIs = (long) *((uchar * &)pStubMsg->Buffer)++;
  3038. break;
  3039. case FC_SHORT :
  3040. case FC_ENUM16 :
  3041. ALIGN(pStubMsg->Buffer,1);
  3042. SwitchIs = (long) *((short * &)pStubMsg->Buffer)++;
  3043. break;
  3044. case FC_USHORT :
  3045. case FC_WCHAR :
  3046. ALIGN(pStubMsg->Buffer,1);
  3047. SwitchIs = (long) *((ushort * &)pStubMsg->Buffer)++;
  3048. break;
  3049. case FC_LONG :
  3050. case FC_ULONG :
  3051. case FC_ENUM32 :
  3052. // FC_INT3264 gets mapped to FC_LONG.
  3053. ALIGN(pStubMsg->Buffer,3);
  3054. SwitchIs = *((long * &)pStubMsg->Buffer)++;
  3055. break;
  3056. default :
  3057. NDR_ASSERT(0,"NdrpUnionUnmarshall : Illegal union switch_type");
  3058. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  3059. return;
  3060. }
  3061. if ( pFormatNonEncUnion )
  3062. {
  3063. if ( F_CORRELATION_CHECK )
  3064. {
  3065. // Unions offset in the switch_is correlation descriptor is relative
  3066. // to the union position itself, not to the beginning of the struct.
  3067. // This is set properly at the complex struct level.
  3068. NdrpCheckCorrelation( pStubMsg,
  3069. SwitchIs,
  3070. pFormatNonEncUnion,
  3071. NDR_CHECK_CONFORMANCE );
  3072. }
  3073. }
  3074. // Skip the memory size field.
  3075. pFormat += 2;
  3076. //
  3077. // We're at the union_arms<2> field now, which contains both the
  3078. // Microsoft union aligment value and the number of union arms.
  3079. //
  3080. //
  3081. // Get the union alignment (0 if this is a DCE union). Get your gun.
  3082. //
  3083. Alignment = (uchar) ( *((ushort *)pFormat) >> 12 );
  3084. ALIGN(pStubMsg->Buffer,Alignment);
  3085. //
  3086. // Number of arms is the lower 12 bits. Ok shoot me.
  3087. //
  3088. Arms = (long) ( *((ushort * &)pFormat)++ & 0x0fff);
  3089. //
  3090. // Search for union arm.
  3091. //
  3092. for ( ; Arms; Arms-- )
  3093. {
  3094. if ( *((long UNALIGNED * &)pFormat)++ == SwitchIs )
  3095. {
  3096. //
  3097. // Found the right arm, break out.
  3098. //
  3099. break;
  3100. }
  3101. // Else increment format string.
  3102. pFormat += 2;
  3103. }
  3104. //
  3105. // Check if we took the default arm and no default arm is specified.
  3106. //
  3107. if ( ! Arms && (*((ushort *)pFormat) == (ushort) 0xffff) )
  3108. {
  3109. RpcRaiseException( RPC_S_INVALID_TAG );
  3110. }
  3111. //
  3112. // Return if the arm is empty.
  3113. //
  3114. if ( ! *((ushort *)pFormat) )
  3115. return;
  3116. // check we aren't EOB after unmarshalling arm selector
  3117. // not really necessary ( we shouldn't overwrite buffer in union) but we shouldn't
  3118. // go further if it failes here.
  3119. CHECK_EOB_RAISE_BSD( pStubMsg->Buffer );
  3120. //
  3121. // Get the arm's description.
  3122. //
  3123. // We need a real solution after beta for simple type arms. This could
  3124. // break if we have a format string larger than about 32K.
  3125. //
  3126. if ( IS_MAGIC_UNION_BYTE(pFormat) )
  3127. {
  3128. // we could read pass the end of buffer, but won't corrupt memory
  3129. // here. We always allocate memory for union in the server side.
  3130. NdrSimpleTypeUnmarshall( pStubMsg,
  3131. *ppMemory,
  3132. pFormat[0] );
  3133. return;
  3134. }
  3135. pFormat += *((signed short *)pFormat);
  3136. //
  3137. // Determine the double memory pointer that we pass to the arm's
  3138. // unmarshalling routine.
  3139. // If the union arm we take is a pointer, we have to dereference the
  3140. // current memory pointer since we're passed the pointer to a pointer
  3141. // to the union (regardless of whether the actual parameter was a by-value
  3142. // union or a pointer to a union).
  3143. //
  3144. // We also have to do a bunch of other special stuff to handle unions
  3145. // embedded inside of strutures.
  3146. //
  3147. if ( IS_POINTER_TYPE(*pFormat) )
  3148. {
  3149. ppMemory = (uchar **) *ppMemory;
  3150. //
  3151. // If we're embedded in a struct or array we have do some extra stuff.
  3152. //
  3153. if ( pStubMsg->PointerBufferMark )
  3154. {
  3155. ALIGN(pStubMsg->Buffer,3);
  3156. long *pPointerId = (long*)pStubMsg->Buffer;
  3157. pStubMsg->Buffer += PTR_WIRE_SIZE;
  3158. POINTER_BUFFER_SWAP_CONTEXT SwapContext( pStubMsg );
  3159. NdrpPointerUnmarshall( pStubMsg,
  3160. ppMemory,
  3161. *((uchar **)ppMemory),
  3162. pPointerId,
  3163. pFormat );
  3164. return;
  3165. }
  3166. }
  3167. //
  3168. // Union arm of a non-simple type.
  3169. //
  3170. (*pfnUnmarshallRoutines[ROUTINE_INDEX(*pFormat)])
  3171. ( pStubMsg,
  3172. ppMemory,
  3173. pFormat,
  3174. FALSE );
  3175. }
  3176. unsigned char * RPC_ENTRY
  3177. NdrByteCountPointerUnmarshall (
  3178. PMIDL_STUB_MESSAGE pStubMsg,
  3179. uchar ** ppMemory,
  3180. PFORMAT_STRING pFormat,
  3181. uchar fMustAlloc )
  3182. /*++
  3183. Routine Description :
  3184. Unmarshalls a pointer with the byte count attribute applied to it.
  3185. Used for FC_BYTE_COUNT_POINTER.
  3186. Arguments :
  3187. pStubMsg - Pointer to the stub message.
  3188. ppMemory - Double pointer to where the byte count pointer should be
  3189. unmarshalled.
  3190. pFormat - Byte count pointer's format string description.
  3191. fMustAlloc - Ignored.
  3192. Return :
  3193. None.
  3194. --*/
  3195. {
  3196. PFORMAT_STRING pFormatComplex;
  3197. long ByteCount;
  3198. long DataSize;
  3199. ByteCount = (ulong) NdrpComputeConformance( pStubMsg,
  3200. NULL,
  3201. pFormat );
  3202. pFormatComplex = pFormat + 6;
  3203. CORRELATION_DESC_INCREMENT( pFormatComplex );
  3204. pFormatComplex += *((signed short *)pFormatComplex);
  3205. //
  3206. // Determine incoming data size.
  3207. //
  3208. if ( pFormat[1] != FC_PAD )
  3209. {
  3210. DataSize = SIMPLE_TYPE_MEMSIZE(pFormat[1]);
  3211. }
  3212. else
  3213. {
  3214. uchar * pBuffer;
  3215. pBuffer = pStubMsg->Buffer;
  3216. pStubMsg->MemorySize = 0;
  3217. //
  3218. // This will give us the allocate(all_nodes) size of the data.
  3219. //
  3220. DataSize = (*pfnMemSizeRoutines[ROUTINE_INDEX(*pFormatComplex)])
  3221. ( pStubMsg,
  3222. pFormatComplex );
  3223. CHECK_EOB_RAISE_BSD( pStubMsg->Buffer );
  3224. pStubMsg->Buffer = pBuffer;
  3225. }
  3226. if ( DataSize > ByteCount )
  3227. RpcRaiseException( RPC_X_BYTE_COUNT_TOO_SMALL );
  3228. //
  3229. // Now make things look like we're handling an allocate all nodes.
  3230. //
  3231. NDR_ALLOC_ALL_NODES_CONTEXT AllocContext;
  3232. AllocContext.AllocAllNodesMemory = *ppMemory;
  3233. AllocContext.AllocAllNodesMemoryBegin = *ppMemory;
  3234. AllocContext.AllocAllNodesMemoryEnd = *ppMemory + ByteCount;
  3235. pStubMsg->pAllocAllNodesContext = &AllocContext;
  3236. //
  3237. // Now unmarshall.
  3238. //
  3239. if ( pFormat[1] != FC_PAD )
  3240. {
  3241. ALIGN(pStubMsg->Buffer,SIMPLE_TYPE_ALIGNMENT(pFormat[1]));
  3242. CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + SIMPLE_TYPE_BUFSIZE(pFormat[1]) );
  3243. NdrSimpleTypeUnmarshall( pStubMsg,
  3244. *ppMemory,
  3245. pFormat[1] );
  3246. }
  3247. else
  3248. {
  3249. (*pfnUnmarshallRoutines[ROUTINE_INDEX(*pFormatComplex)])
  3250. ( pStubMsg,
  3251. ppMemory,
  3252. pFormatComplex,
  3253. TRUE );
  3254. }
  3255. pStubMsg->pAllocAllNodesContext = 0;
  3256. return 0;
  3257. }
  3258. unsigned char * RPC_ENTRY
  3259. NdrpXmitOrRepAsPtrUnmarshall (
  3260. PMIDL_STUB_MESSAGE pStubMsg,
  3261. uchar ** ppMemory,
  3262. PFORMAT_STRING pFormat,
  3263. uchar fMustAlloc )
  3264. /*++
  3265. Routine Description :
  3266. Unmarshalls a transmit as (or represent as) object given by pointers.
  3267. (FC_TRANSMIT_AS_PTR or FC_REPRESENT_AS_PTR)
  3268. See NdrXmitOrRepAsUnmarshall for more detals.
  3269. Arguments :
  3270. pStubMsg - a pointer to the stub message
  3271. ppMemory - pointer to the presented type where to put data
  3272. pFormat - format string description
  3273. fMustAlloc - allocate flag
  3274. Note.
  3275. fMustAlloc is ignored as we always allocate outside of the buffer.
  3276. --*/
  3277. {
  3278. unsigned char * pTransmittedType;
  3279. unsigned char * pPresentedType = *ppMemory;
  3280. BOOL fMustFreeXmit = FALSE;
  3281. const XMIT_ROUTINE_QUINTUPLE * pQuintuple = pStubMsg->StubDesc->aXmitQuintuple;
  3282. unsigned short QIndex;
  3283. unsigned long PresentedTypeSize;
  3284. uchar * PointerBufferMarkSave;
  3285. void * XmitTypePtr = 0;
  3286. void * pMemoryListSave;
  3287. (void) fMustAlloc;
  3288. // Fetch the QuintupleIndex.
  3289. QIndex = *(unsigned short *)(pFormat + 2);
  3290. PresentedTypeSize = *(unsigned short *)(pFormat + 4);
  3291. if ( ! pPresentedType )
  3292. {
  3293. //Allocate a presented type object first.
  3294. pPresentedType = (uchar*)NdrAllocate( pStubMsg, (uint) PresentedTypeSize );
  3295. MIDL_memset( pPresentedType, 0, (uint) PresentedTypeSize );
  3296. }
  3297. // Allocate the transmitted object outside of the buffer
  3298. // and unmarshall into it
  3299. pFormat += 8;
  3300. pFormat = pFormat + *(short *)pFormat;
  3301. // Save the current state of the memory list so that the temporary
  3302. // memory allocated for the transmitted type can be easily removed
  3303. // from the list. This assumes that the memory allocated here
  3304. // will not have any pointers to other blocks of memory. This is true
  3305. // as long as full pointers are not used. The current compiler does
  3306. // not support full pointers, so this in not a problem.
  3307. pMemoryListSave = pStubMsg->pMemoryList;
  3308. pTransmittedType = NULL; // asking the engine to allocate
  3309. // only when ptr is ref: make it look like UP.
  3310. if ( *pFormat == FC_RP )
  3311. pTransmittedType = (uchar *)& XmitTypePtr;
  3312. {
  3313. uchar *PointerBufferMarkSave = pStubMsg->PointerBufferMark;
  3314. pStubMsg->PointerBufferMark = 0;
  3315. NDR_POINTER_QUEUE *pOldQueue = NULL;
  3316. // Set the current queue to NULL so that all pointees will be
  3317. // queued and unmarshalled together
  3318. if ( pStubMsg->pPointerQueueState )
  3319. {
  3320. pOldQueue = pStubMsg->pPointerQueueState->GetActiveQueue();
  3321. pStubMsg->pPointerQueueState->SetActiveQueue(NULL);
  3322. }
  3323. RpcTryFinally
  3324. {
  3325. (*pfnUnmarshallRoutines[ ROUTINE_INDEX( *pFormat )])
  3326. ( pStubMsg,
  3327. & pTransmittedType,
  3328. pFormat,
  3329. TRUE );
  3330. }
  3331. RpcFinally
  3332. {
  3333. pStubMsg->PointerBufferMark = PointerBufferMarkSave;
  3334. if ( pStubMsg->pPointerQueueState )
  3335. {
  3336. pStubMsg->pPointerQueueState->SetActiveQueue( pOldQueue );
  3337. }
  3338. }
  3339. RpcEndFinally
  3340. }
  3341. // Translate from the transmitted type into the presented type.
  3342. pStubMsg->pTransmitType = (uchar *)& pTransmittedType;
  3343. pStubMsg->pPresentedType = pPresentedType;
  3344. pQuintuple[ QIndex ].pfnTranslateFromXmit( pStubMsg );
  3345. *ppMemory = pStubMsg->pPresentedType;
  3346. // Free the transmitted object (it was allocated by the engine)
  3347. // and its pointees. The call through the table frees the pointees
  3348. // plus it frees the object itself as it is a pointer.
  3349. // Remove the memory that will be freed from the allocated memory
  3350. // list by restoring the memory list pointer.
  3351. // If an exception occures during one of these free routines, we
  3352. // are in trouble anyway.
  3353. pStubMsg->pMemoryList = pMemoryListSave;
  3354. {
  3355. uchar *PointerBufferMarkSave = pStubMsg->PointerBufferMark;
  3356. pStubMsg->PointerBufferMark = 0;
  3357. NDR_POINTER_QUEUE *pOldQueue = NULL;
  3358. // Set the current queue to NULL so that all pointees will be
  3359. // queued and freed together
  3360. if ( pStubMsg->pPointerQueueState )
  3361. {
  3362. pOldQueue = pStubMsg->pPointerQueueState->GetActiveQueue();
  3363. pStubMsg->pPointerQueueState->SetActiveQueue(NULL);
  3364. }
  3365. RpcTryFinally
  3366. {
  3367. (*pfnFreeRoutines[ ROUTINE_INDEX( *pFormat )])( pStubMsg,
  3368. pTransmittedType,
  3369. pFormat );
  3370. }
  3371. RpcFinally
  3372. {
  3373. pStubMsg->PointerBufferMark = PointerBufferMarkSave;
  3374. if ( pStubMsg->pPointerQueueState )
  3375. {
  3376. pStubMsg->pPointerQueueState->SetActiveQueue( pOldQueue );
  3377. }
  3378. }
  3379. RpcEndFinally
  3380. }
  3381. return 0;
  3382. }
  3383. unsigned char * RPC_ENTRY
  3384. NdrXmitOrRepAsUnmarshall (
  3385. PMIDL_STUB_MESSAGE pStubMsg,
  3386. uchar ** ppMemory,
  3387. PFORMAT_STRING pFormat,
  3388. uchar fMustAlloc )
  3389. /*++
  3390. Routine Description :
  3391. Unmarshalls a transmit as (or represent as)object.
  3392. Means: allocate the transmitted object,
  3393. unmarshall transmitted object,
  3394. translate the transmitted into presented
  3395. free the transmitted.
  3396. See mrshl.c for the description of the FC layout.
  3397. Arguments :
  3398. pStubMsg - a pointer to the stub message
  3399. ppMemory - pointer to the presented type where to put data
  3400. pFormat - format string description
  3401. fMustAlloc - allocate flag
  3402. Note.
  3403. fMustAlloc is ignored as we always allocate outside of the buffer.
  3404. --*/
  3405. {
  3406. unsigned char * pTransmittedType;
  3407. unsigned char * pPresentedType = *ppMemory;
  3408. __int64 SimpleTypeValueBuffer[2];
  3409. const XMIT_ROUTINE_QUINTUPLE * pQuintuple = pStubMsg->StubDesc->aXmitQuintuple;
  3410. unsigned short QIndex;
  3411. unsigned long PresentedTypeSize;
  3412. uchar * PointerBufferMarkSave;
  3413. BOOL fXmitByPtr = *pFormat == FC_TRANSMIT_AS_PTR ||
  3414. *pFormat == FC_REPRESENT_AS_PTR;
  3415. (void) fMustAlloc;
  3416. if ( fXmitByPtr )
  3417. {
  3418. NdrpXmitOrRepAsPtrUnmarshall( pStubMsg,
  3419. ppMemory,
  3420. pFormat,
  3421. fMustAlloc );
  3422. return 0;
  3423. }
  3424. // Fetch the QuintupleIndex.
  3425. QIndex = *(unsigned short *)(pFormat + 2);
  3426. PresentedTypeSize = *(unsigned short *)(pFormat + 4);
  3427. if ( ! pPresentedType )
  3428. {
  3429. //Allocate a presented type object first.
  3430. pPresentedType = (uchar*)NdrAllocate( pStubMsg, (uint) PresentedTypeSize );
  3431. MIDL_memset( pPresentedType, 0, (uint) PresentedTypeSize );
  3432. }
  3433. // Allocate the transmitted object outside of the buffer
  3434. // and unmarshall into it
  3435. pFormat += 8;
  3436. pFormat = pFormat + *(short *)pFormat;
  3437. if ( IS_SIMPLE_TYPE( *pFormat ))
  3438. {
  3439. pTransmittedType = (unsigned char *)SimpleTypeValueBuffer;
  3440. NdrSimpleTypeUnmarshall( pStubMsg,
  3441. pTransmittedType,
  3442. *pFormat );
  3443. // Translate from the transmitted type into the presented type.
  3444. pStubMsg->pTransmitType = pTransmittedType;
  3445. pStubMsg->pPresentedType = pPresentedType;
  3446. pQuintuple[ QIndex ].pfnTranslateFromXmit( pStubMsg );
  3447. *ppMemory = pStubMsg->pPresentedType;
  3448. }
  3449. else
  3450. {
  3451. // Save the current state of the memory list so that the temporary
  3452. // memory allocated for the transmitted type can be easily removed
  3453. // from the list. This assumes that the memory allocated here
  3454. // will not have any linkes to other blocks of memory. This is true
  3455. // as long as full pointers are not used. Fortunatly, full pointers
  3456. // do not work correctly in the current code.
  3457. void *pMemoryListSave = pStubMsg->pMemoryList;
  3458. {
  3459. uchar *PointerBufferMarkSave = pStubMsg->PointerBufferMark;
  3460. pStubMsg->PointerBufferMark = 0;
  3461. NDR_POINTER_QUEUE *pOldQueue = NULL;
  3462. // Set the current queue to NULL so that all pointees will be
  3463. // queued and unmarshalled together
  3464. if ( pStubMsg->pPointerQueueState )
  3465. {
  3466. pOldQueue = pStubMsg->pPointerQueueState->GetActiveQueue();
  3467. pStubMsg->pPointerQueueState->SetActiveQueue(NULL);
  3468. }
  3469. pTransmittedType = NULL; //asking the engine to allocate
  3470. RpcTryFinally
  3471. {
  3472. (*pfnUnmarshallRoutines[ ROUTINE_INDEX( *pFormat )])
  3473. ( pStubMsg,
  3474. & pTransmittedType,
  3475. pFormat,
  3476. TRUE );
  3477. }
  3478. RpcFinally
  3479. {
  3480. pStubMsg->PointerBufferMark = PointerBufferMarkSave;
  3481. if ( pStubMsg->pPointerQueueState )
  3482. {
  3483. pStubMsg->pPointerQueueState->SetActiveQueue( pOldQueue );
  3484. }
  3485. }
  3486. RpcEndFinally
  3487. }
  3488. // Translate from the transmitted type into the presented type.
  3489. pStubMsg->pTransmitType = pTransmittedType;
  3490. pStubMsg->pPresentedType = pPresentedType;
  3491. pQuintuple[ QIndex ].pfnTranslateFromXmit( pStubMsg );
  3492. *ppMemory = pStubMsg->pPresentedType;
  3493. // Free the transmitted object (it was allocated by the engine)
  3494. // and its pointees. The call through the table frees the pointees
  3495. // only (plus it'd free the object itself if it were a pointer).
  3496. // As the transmitted type is not a pointer here, we need to free it
  3497. // explicitely later.
  3498. // Remove the memory that will be freed from the allocated memory
  3499. // list by restoring the memory list pointer.
  3500. // If an exception occures during one of these free routines, we
  3501. // are in trouble anyway.
  3502. pStubMsg->pMemoryList = pMemoryListSave;
  3503. {
  3504. uchar *PointerBufferMarkSave = pStubMsg->PointerBufferMark;
  3505. pStubMsg->PointerBufferMark = 0;
  3506. NDR_POINTER_QUEUE *pOldQueue = NULL;
  3507. // Set the current queue to NULL so that all pointees will be
  3508. // queued and freed together
  3509. if ( pStubMsg->pPointerQueueState )
  3510. {
  3511. pOldQueue = pStubMsg->pPointerQueueState->GetActiveQueue();
  3512. pStubMsg->pPointerQueueState->SetActiveQueue(NULL);
  3513. }
  3514. RpcTryFinally
  3515. {
  3516. (*pfnFreeRoutines[ ROUTINE_INDEX( *pFormat )])( pStubMsg,
  3517. pTransmittedType,
  3518. pFormat );
  3519. }
  3520. RpcFinally
  3521. {
  3522. pStubMsg->PointerBufferMark = PointerBufferMarkSave;
  3523. if ( pStubMsg->pPointerQueueState )
  3524. {
  3525. pStubMsg->pPointerQueueState->SetActiveQueue( pOldQueue );
  3526. }
  3527. }
  3528. RpcEndFinally
  3529. }
  3530. // The buffer reusage check.
  3531. if ( pTransmittedType < pStubMsg->BufferStart ||
  3532. pTransmittedType > pStubMsg->BufferEnd )
  3533. (*pStubMsg->pfnFree)( pTransmittedType );
  3534. }
  3535. return 0;
  3536. }
  3537. void
  3538. NdrpUserMarshalUnmarshall (
  3539. PMIDL_STUB_MESSAGE pStubMsg,
  3540. uchar * pMemory,
  3541. PFORMAT_STRING pFormat )
  3542. /*++
  3543. Routine Description :
  3544. Unmarshals a user_marshal object.
  3545. The layout is described in marshalling.
  3546. Arguments :
  3547. pStubMsg - Pointer to the stub message.
  3548. pMemory - Pointer to the memory where the object should be unmarshalled to.
  3549. pFormat - Object's format string description.
  3550. Return :
  3551. None.
  3552. --*/
  3553. {
  3554. unsigned char *pUserBuffer = pStubMsg->Buffer;
  3555. unsigned char *pUserBufferSaved = pUserBuffer;
  3556. USER_MARSHAL_CB UserMarshalCB;
  3557. NdrpInitUserMarshalCB( pStubMsg,
  3558. pFormat,
  3559. USER_MARSHAL_CB_UNMARSHALL,
  3560. & UserMarshalCB );
  3561. unsigned short QIndex = *(unsigned short *)(pFormat + 2);
  3562. const USER_MARSHAL_ROUTINE_QUADRUPLE *pQuadruple =
  3563. pStubMsg->StubDesc->aUserMarshalQuadruple;
  3564. if ((pUserBufferSaved < (uchar *) pStubMsg->RpcMsg->Buffer) ||
  3565. ((unsigned long) (pUserBufferSaved - (uchar *) pStubMsg->RpcMsg->Buffer)
  3566. > pStubMsg->RpcMsg->BufferLength))
  3567. {
  3568. RpcRaiseException( RPC_X_INVALID_BUFFER );
  3569. }
  3570. pUserBuffer = pQuadruple[ QIndex ].pfnUnmarshall( (ulong*) &UserMarshalCB,
  3571. pUserBuffer,
  3572. pMemory );
  3573. if ((pUserBufferSaved > pUserBuffer) ||
  3574. ((unsigned long) (pUserBuffer - (uchar *) pStubMsg->RpcMsg->Buffer)
  3575. > pStubMsg->RpcMsg->BufferLength ))
  3576. {
  3577. RpcRaiseException( RPC_X_INVALID_BUFFER );
  3578. }
  3579. pStubMsg->Buffer = pUserBuffer;
  3580. return;
  3581. }
  3582. void
  3583. NDR_USR_MRSHL_UNMRSHL_POINTER_QUEUE_ELEMENT::Dispatch(MIDL_STUB_MESSAGE *pStubMsg)
  3584. {
  3585. NdrpUserMarshalUnmarshall( pStubMsg,
  3586. pMemory,
  3587. pFormat );
  3588. }
  3589. #if defined(DBG)
  3590. void
  3591. NDR_USR_MRSHL_UNMRSHL_POINTER_QUEUE_ELEMENT::Print()
  3592. {
  3593. DbgPrint("NDR_USR_MRSHL_BUFSIZE_POINTER_QUEUE_ELEMENT\n");
  3594. DbgPrint("pMemory: %p\n", pMemory );
  3595. DbgPrint("pFormat: %p\n", pFormat );
  3596. }
  3597. #endif
  3598. unsigned char *
  3599. NdrUserMarshalUnmarshall(
  3600. PMIDL_STUB_MESSAGE pStubMsg,
  3601. uchar ** ppMemory,
  3602. PFORMAT_STRING pFormat,
  3603. uchar fMustAlloc )
  3604. {
  3605. // Align for the object or a pointer to it.
  3606. unsigned long PointerMarker = 0;
  3607. ALIGN( pStubMsg->Buffer, LOW_NIBBLE(pFormat[1]) );
  3608. // Take care of the pointer, if any.
  3609. if ( (pFormat[1] & USER_MARSHAL_UNIQUE) ||
  3610. ((pFormat[1] & USER_MARSHAL_REF) && pStubMsg->PointerBufferMark) )
  3611. {
  3612. PointerMarker = *((unsigned long * &)pStubMsg->Buffer)++;
  3613. }
  3614. // We always call user's routine to unmarshall the user object.
  3615. // However, the top level object is allocated by the engine.
  3616. // Thus, the behavior is exactly the same as for represent_as(),
  3617. // with regard to the top level presented type.
  3618. if ( *ppMemory == NULL )
  3619. {
  3620. // Allocate a presented type object first.
  3621. uint MemSize = *(ushort *)(pFormat + 4);
  3622. *ppMemory = (uchar *) NdrAllocate( pStubMsg, MemSize );
  3623. MIDL_memset( *ppMemory, 0, MemSize );
  3624. }
  3625. if ( pFormat[1] & USER_MARSHAL_POINTER )
  3626. {
  3627. if ((pFormat[1] & USER_MARSHAL_UNIQUE) && !PointerMarker )
  3628. return 0;
  3629. if ( !pStubMsg->pPointerQueueState ||
  3630. !pStubMsg->pPointerQueueState->GetActiveQueue())
  3631. {
  3632. POINTER_BUFFER_SWAP_CONTEXT NewContext(pStubMsg);
  3633. NdrpUserMarshalUnmarshall(
  3634. pStubMsg,
  3635. *ppMemory,
  3636. pFormat );
  3637. }
  3638. else
  3639. {
  3640. NDR_USR_MRSHL_UNMRSHL_POINTER_QUEUE_ELEMENT*pElement =
  3641. new(pStubMsg->pPointerQueueState)
  3642. NDR_USR_MRSHL_UNMRSHL_POINTER_QUEUE_ELEMENT(*ppMemory,
  3643. pFormat );
  3644. pStubMsg->pPointerQueueState->GetActiveQueue()->Enque( pElement );
  3645. }
  3646. return 0;
  3647. }
  3648. NdrpUserMarshalUnmarshall(
  3649. pStubMsg,
  3650. *ppMemory,
  3651. pFormat );
  3652. return 0;
  3653. }
  3654. void
  3655. NdrpInterfacePointerUnmarshall (
  3656. PMIDL_STUB_MESSAGE pStubMsg,
  3657. uchar ** ppMemory,
  3658. PFORMAT_STRING pFormat )
  3659. /*++
  3660. Routine Description :
  3661. Unmarshalls an interface pointer.
  3662. Arguments :
  3663. pStubMsg - Pointer to the stub message.
  3664. ppMemory - Pointer to the interface pointer being unmarshalled.
  3665. pFormat - Interface pointer's format string description.
  3666. Return :
  3667. None.
  3668. Notes : There are two data representation formats for a marshalled
  3669. interface pointer. The NDR engine examines the format string
  3670. to determine the appropriate data format. The format string
  3671. contains FC_IP followed by either FC_CONSTANT_IID or FC_PAD.
  3672. Here is the data representation for the FC_CONSTANT_IID case.
  3673. typedef struct
  3674. {
  3675. unsigned long size;
  3676. [size_is(size)] byte data[];
  3677. }MarshalledInterface;
  3678. Here is the data representation for the FC_PAD case. This format
  3679. is used when [iid_is] is specified in the IDL file.
  3680. typedef struct
  3681. {
  3682. uuid_t iid;
  3683. unsigned long size;
  3684. [size_is(size)] byte data[];
  3685. }MarshalledInterfaceWithIid;
  3686. --*/
  3687. {
  3688. HRESULT hr;
  3689. unsigned long MaxCount, Size;
  3690. IStream * pStream;
  3691. ALIGN(pStubMsg->Buffer,0x3);
  3692. // Unmarshal the conformant size and the count field.
  3693. MaxCount = *((unsigned long * &) pStubMsg->Buffer)++;
  3694. Size = *((unsigned long * &) pStubMsg->Buffer)++;
  3695. //Check the array bounds
  3696. if ( Size != MaxCount )
  3697. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  3698. if( MaxCount > 0)
  3699. {
  3700. CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, MaxCount );
  3701. if ( F_CORRELATION_CHECK )
  3702. {
  3703. IID *piid, *piidValue;
  3704. BOOL fDoCheck = FALSE;
  3705. // Get a pointer to the IID hidden in the interface pointer
  3706. // representation in the buffer with Rick's IRpcHelper.
  3707. //
  3708. NdrpGetIIDFromBuffer( pStubMsg, & piidValue );
  3709. //
  3710. // Get an IID pointer to compare.
  3711. //
  3712. if ( pFormat[1] == FC_CONSTANT_IID )
  3713. {
  3714. //
  3715. // The IID may not be aligned properly in the format string,
  3716. // so we copy it to a local variable.
  3717. //
  3718. piid = (IID*) (pFormat + 2);
  3719. fDoCheck = TRUE;
  3720. }
  3721. else
  3722. {
  3723. ULONG_PTR MaxCountSave = pStubMsg->MaxCount;
  3724. uchar * pMemorySave = pStubMsg->Memory;
  3725. pStubMsg->MaxCount = 0;
  3726. pStubMsg->Memory = pStubMsg->pCorrMemory;
  3727. piid = (IID *)
  3728. NdrpComputeIIDPointer( pStubMsg,
  3729. *ppMemory, // should not be used
  3730. pFormat );
  3731. if (piid != 0)
  3732. {
  3733. PNDR_FCDEF_CORRELATION pFormatCorr = (PNDR_FCDEF_CORRELATION)(pFormat+2);
  3734. if ( pFormatCorr->CorrFlags.Early )
  3735. fDoCheck = TRUE;
  3736. else
  3737. {
  3738. // save ptr as a value to check
  3739. NdrpAddCorrelationData( pStubMsg,
  3740. pStubMsg->pCorrMemory,
  3741. pFormat + 2,
  3742. (LONG_PTR) piid, // "value"
  3743. NDR_CHECK_CONFORMANCE );
  3744. }
  3745. }
  3746. // else could not check for -Os etc.
  3747. pStubMsg->MaxCount = MaxCountSave;
  3748. pStubMsg->Memory = pMemorySave;
  3749. }
  3750. if ( fDoCheck &&
  3751. 0 != memcmp( piidValue, piid, sizeof(IID) ) )
  3752. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  3753. }
  3754. pStream = (*NdrpCreateStreamOnMemory)(pStubMsg->Buffer, MaxCount);
  3755. if(pStream == 0)
  3756. RpcRaiseException(RPC_S_OUT_OF_MEMORY);
  3757. hr = (*pfnCoUnmarshalInterface)(pStream, IID_NULL, (void**)ppMemory);
  3758. pStream->Release();
  3759. pStream = 0;
  3760. if(FAILED(hr))
  3761. RpcRaiseException(hr);
  3762. }
  3763. //Advance the stub message pointer.
  3764. pStubMsg->Buffer += MaxCount;
  3765. }
  3766. unsigned char * RPC_ENTRY
  3767. NdrInterfacePointerUnmarshall (
  3768. PMIDL_STUB_MESSAGE pStubMsg,
  3769. uchar ** ppMemory,
  3770. PFORMAT_STRING pFormat,
  3771. uchar /*fMustAlloc*/ )
  3772. {
  3773. // This is only called for toplevel interface pointers
  3774. // in Os mode stubs.
  3775. IUnknown ** ppunk = (IUnknown **)ppMemory;
  3776. // On the client side, release the [in,out] interface pointer.
  3777. if ((pStubMsg->IsClient == TRUE) && (*ppunk != 0))
  3778. (*ppunk)->Release();
  3779. *ppunk = 0;
  3780. //
  3781. // We always have to pickup the pointer itself from the wire
  3782. // as it behaves like a unique pointer.
  3783. ALIGN(pStubMsg->Buffer,0x3);
  3784. long PtrValue = *((long * &)pStubMsg->Buffer)++;
  3785. // If the pointer is null, we are done.
  3786. if ( 0 == PtrValue )
  3787. return 0;
  3788. NdrpInterfacePointerUnmarshall(
  3789. pStubMsg,
  3790. ppMemory,
  3791. pFormat );
  3792. return 0;
  3793. }
  3794. void RPC_ENTRY
  3795. NdrClientContextUnmarshall(
  3796. PMIDL_STUB_MESSAGE pStubMsg,
  3797. NDR_CCONTEXT * pContextHandle,
  3798. RPC_BINDING_HANDLE BindHandle )
  3799. /*++
  3800. Routine Description :
  3801. Unmarshalls a context handle on the client side.
  3802. Arguments :
  3803. pStubMsg - Pointer to stub message.
  3804. pContextHandle - Pointer to context handle to unmarshall.
  3805. BindHandle - The handle value used by the client for binding.
  3806. Return :
  3807. None.
  3808. --*/
  3809. {
  3810. // Note, this is a routine called directly from -Os stubs.
  3811. // The routine called by interpreter is called NdrUnmarshallHandle
  3812. // and can be found in hndl.c
  3813. ALIGN(pStubMsg->Buffer,3);
  3814. CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + CONTEXT_HANDLE_WIRE_SIZE );
  3815. // All 20 bytes of the buffer are touched so a check is not needed here.
  3816. NDRCContextUnmarshall( pContextHandle,
  3817. BindHandle,
  3818. pStubMsg->Buffer,
  3819. pStubMsg->RpcMsg->DataRepresentation );
  3820. pStubMsg->Buffer += CONTEXT_HANDLE_WIRE_SIZE;
  3821. }
  3822. NDR_SCONTEXT RPC_ENTRY
  3823. NdrServerContextUnmarshall(
  3824. PMIDL_STUB_MESSAGE pStubMsg )
  3825. /*++
  3826. Routine Description :
  3827. Unmarshalls a context handle on the server side.
  3828. Arguments :
  3829. pStubMsg - Pointer to stub message.
  3830. Return :
  3831. The unmarshalled context handle.
  3832. --*/
  3833. {
  3834. // Note, this is a routine called directly from -Os stubs.
  3835. // The routine called by interpreter is called NdrUnmarshallHandle
  3836. // and can be found in hndl.c
  3837. NDR_SCONTEXT Context;
  3838. ALIGN(pStubMsg->Buffer,3);
  3839. // we might corrupt the memory during the byte swap
  3840. CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + CONTEXT_HANDLE_WIRE_SIZE );
  3841. // All 20 bytes of the buffer are touched so a check is not needed here.
  3842. Context = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
  3843. pStubMsg->Buffer,
  3844. pStubMsg->RpcMsg->DataRepresentation,
  3845. RPC_CONTEXT_HANDLE_DEFAULT_GUARD,
  3846. RPC_CONTEXT_HANDLE_DEFAULT_FLAGS );
  3847. if ( ! Context )
  3848. RpcRaiseException( RPC_X_SS_CONTEXT_MISMATCH );
  3849. pStubMsg->Buffer += CONTEXT_HANDLE_WIRE_SIZE;
  3850. return Context;
  3851. }
  3852. NDR_SCONTEXT RPC_ENTRY
  3853. NdrContextHandleInitialize (
  3854. PMIDL_STUB_MESSAGE pStubMsg,
  3855. PFORMAT_STRING pFormat )
  3856. /*
  3857. This routine is to initialize a context handle with a new NT5 flavor.
  3858. It is used in conjunction with NdrContextHandleUnmarshal.
  3859. */
  3860. {
  3861. NDR_SCONTEXT SContext;
  3862. void * pGuard = RPC_CONTEXT_HANDLE_DEFAULT_GUARD;
  3863. DWORD Flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
  3864. // NT5 beta2 features: strict context handle, serialize and noserialize.
  3865. if ( pFormat[1] & NDR_STRICT_CONTEXT_HANDLE )
  3866. {
  3867. // The guard is defined as the interface ID.
  3868. // If you change it, modify hndlsvr.cxx in the same way.
  3869. pGuard = pStubMsg->StubDesc->RpcInterfaceInformation;
  3870. pGuard = & ((PRPC_SERVER_INTERFACE)pGuard)->InterfaceId;
  3871. }
  3872. if ( pFormat[1] & NDR_CONTEXT_HANDLE_NOSERIALIZE )
  3873. {
  3874. Flags = RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
  3875. }
  3876. else if ( pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE )
  3877. {
  3878. Flags = RPC_CONTEXT_HANDLE_SERIALIZE;
  3879. }
  3880. SContext = NDRSContextUnmarshall2(
  3881. pStubMsg->RpcMsg->Handle,
  3882. (void *)0, // buffer
  3883. pStubMsg->RpcMsg->DataRepresentation,
  3884. pGuard,
  3885. Flags );
  3886. return SContext;
  3887. }
  3888. NDR_SCONTEXT RPC_ENTRY
  3889. NdrServerContextNewUnmarshall(
  3890. PMIDL_STUB_MESSAGE pStubMsg,
  3891. PFORMAT_STRING pFormat )
  3892. /*
  3893. This routine to unmarshal a context handle with a new NT5 flavor.
  3894. For the old style handles, we call an optimized routine
  3895. NdrServerContextUnmarshall below.
  3896. Interpreter calls NdrUnmarshallHandle from hndl.c
  3897. ppMemory - note, this is not a pointer to user's context handle but
  3898. a pointer to NDR_SCONTEXT pointer to the runtime internal object.
  3899. User's handle is a field of that object.
  3900. */
  3901. {
  3902. NDR_SCONTEXT SContext;
  3903. void * pGuard = RPC_CONTEXT_HANDLE_DEFAULT_GUARD;
  3904. DWORD Flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
  3905. // Anti-attack defense for servers, NT5 beta3 feature.
  3906. if ( pFormat[1] & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL )
  3907. {
  3908. // Check the incoming context handle on the server.
  3909. // Context handle wire layout: ulong with version (always 0), then a uuid.
  3910. //
  3911. if ( !pStubMsg->IsClient && 0 == memcmp( pStubMsg->Buffer + 4,
  3912. &GUID_NULL,
  3913. sizeof(GUID) ) )
  3914. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  3915. }
  3916. // NT5 beta2 features: strict context handle, serialize and noserialize.
  3917. if ( pFormat[1] & NDR_STRICT_CONTEXT_HANDLE )
  3918. {
  3919. pGuard = pStubMsg->StubDesc->RpcInterfaceInformation;
  3920. pGuard = & ((PRPC_SERVER_INTERFACE)pGuard)->InterfaceId;
  3921. }
  3922. if ( pFormat[1] & NDR_CONTEXT_HANDLE_NOSERIALIZE )
  3923. {
  3924. Flags = RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
  3925. }
  3926. else if ( pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE )
  3927. {
  3928. Flags = RPC_CONTEXT_HANDLE_SERIALIZE;
  3929. }
  3930. ALIGN( pStubMsg->Buffer, 0x3 );
  3931. // All 20 bytes of the buffer are touched so a check is not needed here.
  3932. SContext = NDRSContextUnmarshall2(
  3933. pStubMsg->RpcMsg->Handle,
  3934. pStubMsg->Buffer,
  3935. pStubMsg->RpcMsg->DataRepresentation,
  3936. pGuard,
  3937. Flags );
  3938. if ( ! SContext )
  3939. RpcRaiseException( RPC_X_SS_CONTEXT_MISMATCH );
  3940. pStubMsg->Buffer += CONTEXT_HANDLE_WIRE_SIZE;
  3941. return SContext;
  3942. }
  3943. #ifdef _CS_CHAR_
  3944. unsigned char * RPC_ENTRY
  3945. NdrCsTagUnmarshall(
  3946. PMIDL_STUB_MESSAGE pStubMsg,
  3947. uchar ** ppMemory,
  3948. PFORMAT_STRING pFormat,
  3949. uchar fMustAlloc )
  3950. /*++
  3951. Routine Description :
  3952. Unmarshalls a cs tag.
  3953. Arguments :
  3954. pStubMsg - Pointer to stub message.
  3955. ppMemory - Double pointer to where to unmarshall to
  3956. pFormat - The format string entry
  3957. fMustAlloc - TRUE if we can't reuse the buffer (not relevant in this case)
  3958. --*/
  3959. {
  3960. NDR_CS_TAG_FORMAT *pTagFormat = (NDR_CS_TAG_FORMAT *) pFormat;
  3961. ulong Codeset = NdrpGetSetCSTagUnmarshall(
  3962. pStubMsg,
  3963. (NDR_CS_TAG_FORMAT *) pFormat);
  3964. // If there is a tag routine, then this parameter is not on the stack
  3965. if ( NDR_INVALID_TAG_ROUTINE_INDEX == pTagFormat->TagRoutineIndex )
  3966. ** (ulong **) ppMemory = Codeset;
  3967. pStubMsg->Buffer += sizeof(ulong);
  3968. return 0;
  3969. }
  3970. unsigned char * RPC_ENTRY
  3971. NdrCsArrayUnmarshall(
  3972. PMIDL_STUB_MESSAGE pStubMsg,
  3973. uchar ** ppMemory,
  3974. PFORMAT_STRING pFormat,
  3975. uchar fMustAlloc )
  3976. /*++
  3977. Routine Description :
  3978. Unmarshalls a international character (cs) array tag.
  3979. Arguments :
  3980. pStubMsg - Pointer to stub message.
  3981. ppMemory - Double pointer to where to unmarshall to
  3982. pFormat - The format string entry
  3983. fMustAlloc - TRUE if we can't reuse the buffer
  3984. --*/
  3985. {
  3986. ulong LocalCodeset;
  3987. error_status_t status;
  3988. uchar *ConvertedData;
  3989. uchar *UnconvertedData;
  3990. ulong ArraySize;
  3991. ulong WireLength;
  3992. uchar *OldBuffer;
  3993. uchar fMustAllocOriginal;
  3994. BOOL IsClient;
  3995. NDR_CS_ARRAY_FORMAT *pCSFormat;
  3996. NDR_CS_SIZE_CONVERT_ROUTINES *CSRoutines;
  3997. CS_TYPE_LOCAL_SIZE_ROUTINE LocalSizeRoutine;
  3998. CS_TYPE_FROM_NETCS_ROUTINE FromNetCSRoutine;
  3999. IDL_CS_CONVERT ConversionType;
  4000. pCSFormat = (NDR_CS_ARRAY_FORMAT *) pFormat;
  4001. NDR_ASSERT( NULL != pStubMsg->pCSInfo, "cs stub info not set up");
  4002. // Get all the info out of the FC_CS_ARRAY structure and bump pFormat
  4003. // to point to the underlying data descriptor
  4004. CSRoutines = pStubMsg->StubDesc->CsRoutineTables->pSizeConvertRoutines;
  4005. LocalSizeRoutine = CSRoutines[ pCSFormat->CSRoutineIndex].pfnLocalSize;
  4006. FromNetCSRoutine = CSRoutines[ pCSFormat->CSRoutineIndex].pfnFromNetCs;
  4007. pFormat += pCSFormat->DescriptionOffset;
  4008. // REVIEW: A lot of this code can be eleminted by calling memsize on the
  4009. // cs_char array instead of the underlying one.
  4010. // Get the size of the data on the wire
  4011. OldBuffer = pStubMsg->Buffer;
  4012. WireLength = PtrToUlong( NdrpMemoryIncrement( pStubMsg, 0, pFormat ) );
  4013. // Figure out whether we need to convert and how much we need to allocate
  4014. // if we do
  4015. LocalSizeRoutine(
  4016. pStubMsg->RpcMsg->Handle,
  4017. pStubMsg->pCSInfo->WireCodeset,
  4018. WireLength,
  4019. &ConversionType,
  4020. &ArraySize,
  4021. &status);
  4022. if ( RPC_S_OK != status )
  4023. RpcRaiseException( status );
  4024. // If we need to convert we just want the unmarshalling routine to give us
  4025. // back a pointer and not do any allocations. We'll do the allocation
  4026. // later if need be.
  4027. IsClient = pStubMsg->IsClient;
  4028. if ( IDL_CS_NO_CONVERT != ConversionType )
  4029. {
  4030. fMustAllocOriginal = fMustAlloc;
  4031. OldBuffer = *ppMemory;
  4032. *ppMemory = NULL;
  4033. fMustAlloc = FALSE;
  4034. // Slimy hack to enable buffer reuse on the client side
  4035. pStubMsg->IsClient = FALSE;
  4036. }
  4037. // Unmarshall the base array
  4038. pfnUnmarshallRoutines[ ROUTINE_INDEX( *pFormat ) ] (
  4039. pStubMsg,
  4040. ppMemory,
  4041. pFormat,
  4042. fMustAlloc );
  4043. pStubMsg->IsClient = IsClient;
  4044. // If we don't need to convert, we're done
  4045. if ( IDL_CS_NO_CONVERT == ConversionType )
  4046. return 0;
  4047. // Make sure we've got a buffer to convert into
  4048. NDR_ASSERT( NULL != *ppMemory, "Invalid memory pointer" );
  4049. UnconvertedData = *ppMemory;
  4050. *ppMemory = OldBuffer;
  4051. if ( fMustAllocOriginal || NULL == *ppMemory )
  4052. {
  4053. *ppMemory = (uchar *) NdrAllocate(
  4054. pStubMsg,
  4055. ArraySize * pCSFormat->UserTypeSize );
  4056. }
  4057. else if ( pStubMsg->IsClient )
  4058. {
  4059. // Make sure we don't overflow the client's buffer
  4060. long ClientArraySize;
  4061. long ClientArrayLength;
  4062. long ClientWireSize;
  4063. NdrpGetArraySizeLength(
  4064. pStubMsg,
  4065. *ppMemory,
  4066. pFormat,
  4067. pCSFormat->UserTypeSize,
  4068. &ClientArraySize,
  4069. &ClientArrayLength,
  4070. &ClientWireSize );
  4071. ArraySize = min( ArraySize, (ulong)ClientArraySize );
  4072. }
  4073. // Reset the conformance variable to the new array size
  4074. if ( NdrpArrayMarshallFlags[ *pFormat - FC_CARRAY ] & MARSHALL_CONFORMANCE )
  4075. {
  4076. uchar *pOldCorrMemory = pStubMsg->pCorrMemory;
  4077. if ( !pStubMsg->pCorrMemory )
  4078. pStubMsg->pCorrMemory = pStubMsg->StackTop;
  4079. NdrpCheckCorrelation(
  4080. pStubMsg,
  4081. ArraySize,
  4082. pFormat,
  4083. NDR_CHECK_CONFORMANCE | NDR_RESET_VALUE );
  4084. pStubMsg->pCorrMemory = pOldCorrMemory;
  4085. }
  4086. // Do the conversion
  4087. FromNetCSRoutine(
  4088. pStubMsg->RpcMsg->Handle,
  4089. pStubMsg->pCSInfo->WireCodeset,
  4090. UnconvertedData,
  4091. WireLength,
  4092. ArraySize,
  4093. *ppMemory,
  4094. &ArraySize, // Actually it returns the length not the size
  4095. &status);
  4096. if ( RPC_S_OK != status )
  4097. RpcRaiseException( status );
  4098. // Reset the variance variable to the new array length
  4099. if ( NdrpArrayMarshallFlags[ *pFormat - FC_CARRAY ] & MARSHALL_VARIANCE )
  4100. {
  4101. NdrpCheckCorrelation(
  4102. pStubMsg,
  4103. ArraySize,
  4104. pFormat,
  4105. NDR_CHECK_VARIANCE | NDR_RESET_VALUE );
  4106. }
  4107. return 0;
  4108. }
  4109. #endif // _CS_CHAR_
  4110. void
  4111. NdrPartialIgnoreServerUnmarshall(
  4112. PMIDL_STUB_MESSAGE pStubMsg,
  4113. void ** ppMemory
  4114. )
  4115. {
  4116. ALIGN( pStubMsg->Buffer, 0x3 );
  4117. *ppMemory = UlongToPtr( *(ulong*)pStubMsg->Buffer );
  4118. pStubMsg->Buffer += PTR_WIRE_SIZE;
  4119. }