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.

3677 lines
98 KiB

  1. /************************************************************************
  2. Copyright (c) 1993-2000 Microsoft Corporation
  3. Module Name :
  4. mrshl.c
  5. Abstract :
  6. This file contains the marshalling 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. NdrUDTSimpleTypeMarshall1(
  19. PMIDL_STUB_MESSAGE pStubMsg,
  20. unsigned char * pMemory,
  21. PFORMAT_STRING pFormat
  22. );
  23. //
  24. // Function table of marshalling routines.
  25. //
  26. extern const PMARSHALL_ROUTINE MarshallRoutinesTable[] =
  27. {
  28. NdrUDTSimpleTypeMarshall1,
  29. NdrUDTSimpleTypeMarshall1,
  30. NdrUDTSimpleTypeMarshall1,
  31. NdrUDTSimpleTypeMarshall1,
  32. NdrUDTSimpleTypeMarshall1,
  33. NdrUDTSimpleTypeMarshall1,
  34. NdrUDTSimpleTypeMarshall1,
  35. NdrUDTSimpleTypeMarshall1,
  36. NdrUDTSimpleTypeMarshall1,
  37. NdrUDTSimpleTypeMarshall1,
  38. NdrUDTSimpleTypeMarshall1,
  39. NdrUDTSimpleTypeMarshall1,
  40. NdrUDTSimpleTypeMarshall1,
  41. NdrUDTSimpleTypeMarshall1,
  42. NdrUDTSimpleTypeMarshall1,
  43. NdrUDTSimpleTypeMarshall1,
  44. NdrUDTSimpleTypeMarshall1,
  45. NdrPointerMarshall,
  46. NdrPointerMarshall,
  47. NdrPointerMarshall,
  48. NdrPointerMarshall,
  49. NdrSimpleStructMarshall,
  50. NdrSimpleStructMarshall,
  51. NdrConformantStructMarshall,
  52. NdrConformantStructMarshall,
  53. NdrConformantVaryingStructMarshall,
  54. NdrComplexStructMarshall,
  55. NdrConformantArrayMarshall,
  56. NdrConformantVaryingArrayMarshall,
  57. NdrFixedArrayMarshall,
  58. NdrFixedArrayMarshall,
  59. NdrVaryingArrayMarshall,
  60. NdrVaryingArrayMarshall,
  61. NdrComplexArrayMarshall,
  62. NdrConformantStringMarshall,
  63. NdrConformantStringMarshall,
  64. NdrConformantStringMarshall,
  65. NdrConformantStringMarshall,
  66. NdrNonConformantStringMarshall,
  67. NdrNonConformantStringMarshall,
  68. NdrNonConformantStringMarshall,
  69. NdrNonConformantStringMarshall,
  70. NdrEncapsulatedUnionMarshall,
  71. NdrNonEncapsulatedUnionMarshall,
  72. NdrByteCountPointerMarshall,
  73. NdrXmitOrRepAsMarshall, // transmit as
  74. NdrXmitOrRepAsMarshall, // represent as
  75. NdrPointerMarshall,
  76. NdrMarshallHandle,
  77. // New Post NT 3.5 token serviced from here on.
  78. 0, // NdrHardStructMarshall,
  79. NdrXmitOrRepAsMarshall, // transmit as ptr
  80. NdrXmitOrRepAsMarshall, // represent as ptr
  81. NdrUserMarshalMarshall,
  82. 0, // FC_PIPE
  83. 0, // FC_BLK_HOLE
  84. NdrpRangeMarshall,
  85. 0, // FC_INT3264
  86. 0, // FC_UINT3264
  87. 0, // NdrCsArrayMarshall,
  88. 0, // NdrCsTagMarshall
  89. };
  90. extern const PMARSHALL_ROUTINE * pfnMarshallRoutines = MarshallRoutinesTable;
  91. unsigned char *
  92. NdrpInterfacePointerMarshall (
  93. PMIDL_STUB_MESSAGE pStubMsg,
  94. uchar * pMemory,
  95. PFORMAT_STRING pFormat );
  96. RPCRTAPI
  97. unsigned char *RPC_ENTRY
  98. NdrTypeMarshall(
  99. PMIDL_STUB_MESSAGE pStubMsg,
  100. uchar * pMemory,
  101. PFORMAT_STRING pFormat )
  102. {
  103. return
  104. (*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  105. pMemory,
  106. pFormat );
  107. }
  108. __inline unsigned char *RPC_ENTRY
  109. NdrUDTSimpleTypeMarshall1(
  110. PMIDL_STUB_MESSAGE pStubMsg,
  111. uchar * pMemory,
  112. PFORMAT_STRING FormatString )
  113. {
  114. NdrSimpleTypeMarshall(pStubMsg,pMemory,*FormatString);
  115. return 0;
  116. }
  117. void RPC_ENTRY
  118. NdrSimpleTypeMarshall(
  119. PMIDL_STUB_MESSAGE pStubMsg,
  120. uchar * pMemory,
  121. uchar FormatChar )
  122. /*++
  123. Routine Description :
  124. Marshalls a simple type.
  125. Arguments :
  126. pStubMsg - Pointer to the stub message.
  127. pMemory - Pointer to the data to be marshalled.
  128. FormatChar - Simple type format character.
  129. Return :
  130. None.
  131. --*/
  132. {
  133. switch ( FormatChar )
  134. {
  135. case FC_CHAR :
  136. case FC_BYTE :
  137. case FC_SMALL :
  138. case FC_USMALL :
  139. *(pStubMsg->Buffer)++ = *pMemory;
  140. break;
  141. case FC_ENUM16 :
  142. if ( *((int *)pMemory) & ~((int)0x7fff) )
  143. {
  144. RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
  145. }
  146. // fall through...
  147. case FC_WCHAR :
  148. case FC_SHORT :
  149. case FC_USHORT :
  150. ALIGN(pStubMsg->Buffer,1);
  151. *((ushort *&)pStubMsg->Buffer)++ = *((ushort *)pMemory);
  152. break;
  153. case FC_LONG :
  154. case FC_ULONG :
  155. #if defined(__RPC_WIN64__)
  156. case FC_INT3264:
  157. case FC_UINT3264:
  158. #endif
  159. case FC_FLOAT :
  160. case FC_ENUM32 :
  161. case FC_ERROR_STATUS_T:
  162. ALIGN(pStubMsg->Buffer,3);
  163. *((ulong *&)pStubMsg->Buffer)++ = *((ulong *)pMemory);
  164. break;
  165. case FC_HYPER :
  166. case FC_DOUBLE :
  167. ALIGN(pStubMsg->Buffer,7);
  168. //
  169. // Let's stay away from casts to double.
  170. //
  171. *((ulong *&)pStubMsg->Buffer)++ = *((ulong *)pMemory);
  172. *((ulong *&)pStubMsg->Buffer)++ = *((ulong *)(pMemory + 4));
  173. break;
  174. case FC_IGNORE:
  175. break;
  176. default :
  177. NDR_ASSERT(0,"NdrSimpleTypeMarshall : bad format char");
  178. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  179. return;
  180. }
  181. }
  182. unsigned char * RPC_ENTRY
  183. NdrpRangeMarshall(
  184. PMIDL_STUB_MESSAGE pStubMsg,
  185. uchar * pMemory,
  186. PFORMAT_STRING pFormat )
  187. /*++
  188. --*/
  189. {
  190. uchar FcType = pFormat[1] & 0x0f;
  191. NdrSimpleTypeMarshall( pStubMsg, pMemory, FcType );
  192. return 0;
  193. }
  194. unsigned char * RPC_ENTRY
  195. NdrPointerMarshall(
  196. PMIDL_STUB_MESSAGE pStubMsg,
  197. uchar * pMemory,
  198. PFORMAT_STRING pFormat )
  199. /*++
  200. Routine Description :
  201. Marshalls a top level pointer to anything. Pointers embedded in
  202. structures, arrays, or unions call NdrpPointerMarshall directly.
  203. Used for FC_RP, FC_UP, FC_FP, FC_OP.
  204. Arguments :
  205. pStubMsg - Pointer to the stub message.
  206. pMemory - Pointer to the data to be marshalled.
  207. pFormat - Pointer's format string description.
  208. Return :
  209. None.
  210. --*/
  211. {
  212. uchar * pBufferMark;
  213. //
  214. // If this is not a ref pointer then set buffer mark and increment the
  215. // stub message buffer pointer.
  216. //
  217. if ( *pFormat != FC_RP )
  218. {
  219. ALIGN( pStubMsg->Buffer, 3 );
  220. // This is where we marshall the node id.
  221. pBufferMark = pStubMsg->Buffer;
  222. pStubMsg->Buffer += PTR_WIRE_SIZE;
  223. }
  224. else
  225. pBufferMark = 0;
  226. //
  227. // For ref pointers pBufferMark will not be used and can be left
  228. // unitialized.
  229. //
  230. NdrpPointerMarshall( pStubMsg,
  231. pBufferMark,
  232. pMemory,
  233. pFormat );
  234. return 0;
  235. }
  236. __forceinline void
  237. NdrpPointerMarshallInternal(
  238. PMIDL_STUB_MESSAGE pStubMsg,
  239. uchar * pBufferMark,
  240. uchar * pMemory,
  241. PFORMAT_STRING pFormat )
  242. /*++
  243. Routine Description :
  244. Private routine for marshalling a pointer and its pointee. This is the
  245. entry point for pointers embedded in structures, arrays, and unions.
  246. Used for FC_RP, FC_UP, FC_FP, FC_OP.
  247. Arguments :
  248. pStubMsg - Pointer to the stub message.
  249. pBufferMark - The location in the buffer where the pointer itself is
  250. marshalled. Important for full pointers, unfortunately it's
  251. overkill for unique pointers.
  252. pMemory - Pointer to the data to be marshalled.
  253. pFormat - Pointer format string description.
  254. pStubMsg->Buffer - the place for the pointee.
  255. Return :
  256. None.
  257. --*/
  258. {
  259. //
  260. // Check the pointer type.
  261. //
  262. switch ( *pFormat )
  263. {
  264. case FC_RP :
  265. if ( ! pMemory )
  266. RpcRaiseException( RPC_X_NULL_REF_POINTER );
  267. break;
  268. case FC_UP :
  269. case FC_OP :
  270. // Put the pointer in the buffer.
  271. *((ulong*&)pBufferMark)++ = PTR_WIRE_REP(pMemory);
  272. if ( ! pMemory )
  273. return;
  274. break;
  275. case FC_IP :
  276. if ( IS_BROKEN_INTERFACE_POINTER(pStubMsg->uFlags) )
  277. {
  278. // The pointee is effectivly both the pointer
  279. // and the pointee.
  280. NdrInterfacePointerMarshall( pStubMsg,
  281. pMemory,
  282. pFormat );
  283. return;
  284. }
  285. // Interface pointers behave like unique pointers
  286. *((ulong*&)pBufferMark)++ = PTR_WIRE_REP(pMemory);
  287. if ( ! pMemory )
  288. return;
  289. NdrpInterfacePointerMarshall( pStubMsg,
  290. pMemory,
  291. pFormat );
  292. return;
  293. case FC_FP :
  294. //
  295. // Marshall the pointer's ref id and see if we've already
  296. // marshalled the pointer's data.
  297. //
  298. if ( NdrFullPointerQueryPointer( pStubMsg->FullPtrXlatTables,
  299. pMemory,
  300. FULL_POINTER_MARSHALLED,
  301. (ulong *) pBufferMark ) )
  302. return;
  303. break;
  304. default :
  305. NDR_ASSERT(0,"NdrpPointerMarshall : bad pointer type");
  306. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  307. return;
  308. }
  309. //
  310. // Check for a pointer to a complex type.
  311. //
  312. if ( ! SIMPLE_POINTER(pFormat[1]) )
  313. {
  314. uchar uFlagsSave;
  315. if ( POINTER_DEREF(pFormat[1]) )
  316. pMemory = *((uchar **)pMemory);
  317. // Increment to offset_to_complex_description<2> field.
  318. pFormat += 2;
  319. //
  320. // Set format string to complex type description.
  321. // Cast must be to a signed short since some offsets are negative.
  322. //
  323. pFormat += *((signed short *)pFormat);
  324. //
  325. // Look up the proper marshalling routine in the marshalling function
  326. // table.
  327. //
  328. uFlagsSave = pStubMsg->uFlags;
  329. RESET_CONF_FLAGS_TO_STANDALONE(pStubMsg->uFlags);
  330. (*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  331. pMemory,
  332. pFormat );
  333. pStubMsg->uFlags = uFlagsSave;
  334. return;
  335. }
  336. //
  337. // Else it's a pointer to a simple type or a string pointer.
  338. //
  339. switch ( pFormat[2] )
  340. {
  341. case FC_C_CSTRING :
  342. case FC_C_BSTRING :
  343. case FC_C_WSTRING :
  344. case FC_C_SSTRING :
  345. NdrConformantStringMarshall( pStubMsg,
  346. pMemory,
  347. pFormat + 2 );
  348. break;
  349. default :
  350. NdrSimpleTypeMarshall( pStubMsg,
  351. pMemory,
  352. pFormat[2] );
  353. break;
  354. }
  355. }
  356. NDR_MRSHL_POINTER_QUEUE_ELEMENT::NDR_MRSHL_POINTER_QUEUE_ELEMENT(
  357. MIDL_STUB_MESSAGE *pStubMsg,
  358. uchar * const pBufferMarkNew,
  359. uchar * const pMemoryNew,
  360. const PFORMAT_STRING pFormatNew) :
  361. pBufferMark(pBufferMarkNew),
  362. pMemory(pMemoryNew),
  363. pFormat(pFormatNew),
  364. Memory(pStubMsg->Memory),
  365. uFlags(pStubMsg->uFlags)
  366. {
  367. }
  368. void
  369. NDR_MRSHL_POINTER_QUEUE_ELEMENT::Dispatch(
  370. MIDL_STUB_MESSAGE *pStubMsg)
  371. {
  372. SAVE_CONTEXT<uchar*> MemorySave( pStubMsg->Memory, Memory );
  373. SAVE_CONTEXT<uchar> uFlagsSave( pStubMsg->uFlags, uFlags );
  374. NDR_ASSERT( !pStubMsg->PointerBufferMark, "PointerBufferMark is not 0\n");
  375. NdrpPointerMarshallInternal( pStubMsg,
  376. pBufferMark,
  377. pMemory,
  378. pFormat );
  379. }
  380. #if defined(DBG)
  381. void
  382. NDR_MRSHL_POINTER_QUEUE_ELEMENT::Print()
  383. {
  384. DbgPrint("NDR_MRSHL_POINTER_QUEUE_ELEMENT\n");
  385. DbgPrint("pNext: %p\n", pNext );
  386. DbgPrint("pBufferMark: %p\n", pBufferMark );
  387. DbgPrint("pMemory: %p\n", pMemory );
  388. DbgPrint("pFormat: %p\n", pFormat );
  389. DbgPrint("Memory: %p\n", Memory );
  390. DbgPrint("uFlags: %x\n", uFlags );
  391. }
  392. #endif
  393. void
  394. NdrpEnquePointerMarshall(
  395. PMIDL_STUB_MESSAGE pStubMsg,
  396. uchar * pBufferMark,
  397. uchar * pMemory,
  398. PFORMAT_STRING pFormat )
  399. {
  400. NDR32_POINTER_CONTEXT PointerContext( pStubMsg );
  401. RpcTryFinally
  402. {
  403. NDR_MRSHL_POINTER_QUEUE_ELEMENT*pElement =
  404. new(PointerContext.GetActiveState())
  405. NDR_MRSHL_POINTER_QUEUE_ELEMENT(pStubMsg,
  406. pBufferMark,
  407. pMemory,
  408. pFormat);
  409. PointerContext.Enque( pElement );
  410. PointerContext.DispatchIfRequired();
  411. }
  412. RpcFinally
  413. {
  414. PointerContext.EndContext();
  415. }
  416. RpcEndFinally
  417. }
  418. void
  419. NdrpPointerMarshall(
  420. PMIDL_STUB_MESSAGE pStubMsg,
  421. uchar * pBufferMark,
  422. uchar * pMemory,
  423. PFORMAT_STRING pFormat )
  424. {
  425. if ( !NdrIsLowStack(pStubMsg) )
  426. {
  427. NdrpPointerMarshallInternal( pStubMsg,
  428. pBufferMark,
  429. pMemory,
  430. pFormat );
  431. return;
  432. }
  433. NdrpEnquePointerMarshall( pStubMsg,
  434. pBufferMark,
  435. pMemory,
  436. pFormat );
  437. }
  438. unsigned char * RPC_ENTRY
  439. NdrSimpleStructMarshall(
  440. PMIDL_STUB_MESSAGE pStubMsg,
  441. uchar * pMemory,
  442. PFORMAT_STRING pFormat )
  443. /*++
  444. Routine description :
  445. Marshalls a simple structure.
  446. Used for FC_STRUCT and FC_PSTRUCT.
  447. Arguments :
  448. pStubMsg - Pointer to the stub message.
  449. pMemory - Pointer to the structure to be marshalled.
  450. pFormat - Structure's format string description.
  451. Return :
  452. None.
  453. --*/
  454. {
  455. uint StructSize;
  456. ALIGN(pStubMsg->Buffer,pFormat[1]);
  457. StructSize = (uint) *((ushort *)(pFormat + 2));
  458. RpcpMemoryCopy( pStubMsg->Buffer,
  459. pMemory,
  460. StructSize );
  461. // Mark the start of the structure in the buffer.
  462. pStubMsg->BufferMark = pStubMsg->Buffer;
  463. pStubMsg->Buffer += StructSize;
  464. // Marshall embedded pointers.
  465. if ( *pFormat == FC_PSTRUCT )
  466. {
  467. NdrpEmbeddedPointerMarshall( pStubMsg,
  468. pMemory,
  469. pFormat + 4 );
  470. }
  471. return 0;
  472. }
  473. unsigned char * RPC_ENTRY
  474. NdrConformantStructMarshall(
  475. PMIDL_STUB_MESSAGE pStubMsg,
  476. uchar * pMemory,
  477. PFORMAT_STRING pFormat )
  478. /*++
  479. Routine description :
  480. Marshalls a conformant structure.
  481. Used for FC_CSTRUCT and FC_CPSTRUCT.
  482. Arguments :
  483. pStubMsg - Pointer to the stub message.
  484. pMemory - Pointer to the structure to be marshalled.
  485. pFormat - Structure's format string description.
  486. Return :
  487. None. - may set the CONF_ARRAY_DONE flag.
  488. Note
  489. Due to problems with MIDL generated code, the ConformantStruct routine always
  490. marshals the conformant array. Only a bogus struct can embed a conf struct,
  491. and there is a flag that bogus struct watches in order not to marshal the array
  492. second time.
  493. --*/
  494. {
  495. PFORMAT_STRING pFormatArray;
  496. uint StructSize;
  497. uchar Alignment;
  498. uchar fIsEmbeddedStruct = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  499. // Save structure's alignment.
  500. Alignment = pFormat[1];
  501. // Increment format string to struct size field.
  502. pFormat += 2;
  503. // Get flat struct size and increment format string.
  504. StructSize = (uint) *((ushort *&)pFormat)++;
  505. // Set conformant array format string description.
  506. pFormatArray = pFormat + *((signed short *)pFormat);
  507. //
  508. // Compute conformance information. Pass a memory pointer to the
  509. // end of the non-conformant part of the structure.
  510. //
  511. NdrpComputeConformance( pStubMsg,
  512. pMemory + StructSize,
  513. pFormatArray );
  514. // Only a bogus struct can embed a conf struct.
  515. if ( fIsEmbeddedStruct )
  516. *(ulong *)pStubMsg->BufferMark = (ulong)pStubMsg->MaxCount;
  517. else
  518. {
  519. // Align the buffer for conformance count marshalling.
  520. ALIGN(pStubMsg->Buffer,3);
  521. // Marshall conformance count.
  522. *((ulong *&)pStubMsg->Buffer)++ = (ulong)pStubMsg->MaxCount;
  523. }
  524. // Re-align buffer
  525. ALIGN(pStubMsg->Buffer,Alignment);
  526. // Increment array format string to array element size field.
  527. pFormatArray += 2;
  528. // Add the size of the conformant array to the structure size.
  529. StructSize += (ulong)pStubMsg->MaxCount * *((ushort *)pFormatArray);
  530. RpcpMemoryCopy( pStubMsg->Buffer,
  531. pMemory,
  532. StructSize );
  533. // Update the buffer pointer.
  534. pStubMsg->Buffer += StructSize;
  535. // Increment format string past offset to array description field.
  536. pFormat += 2;
  537. // Marshall embedded pointers. This covers the struct and the conf array.
  538. if ( *pFormat == FC_PP )
  539. {
  540. // Mark the start of the structure in the buffer.
  541. pStubMsg->BufferMark = pStubMsg->Buffer - StructSize;
  542. NdrpEmbeddedPointerMarshall( pStubMsg,
  543. pMemory,
  544. pFormat );
  545. }
  546. // Only a complex struct may set up this flag for embedding.
  547. // Set the reverse flag to signal that array has been marshaled.
  548. if ( fIsEmbeddedStruct )
  549. SET_CONF_ARRAY_DONE( pStubMsg->uFlags );
  550. return 0;
  551. }
  552. unsigned char * RPC_ENTRY
  553. NdrConformantVaryingStructMarshall(
  554. PMIDL_STUB_MESSAGE pStubMsg,
  555. uchar * pMemory,
  556. PFORMAT_STRING pFormat )
  557. /*++
  558. Routine description :
  559. Marshalls a structure which contains a conformant varying array.
  560. Used for FC_CVSTRUCT.
  561. Arguments :
  562. pStubMsg - Pointer to the stub message.
  563. pMemory - Pointer to the structure to be marshalled.
  564. pFormat - Structure's format string description.
  565. Return :
  566. None.
  567. --*/
  568. {
  569. PFORMAT_STRING pFormatArray;
  570. uint StructSize;
  571. uchar Alignment;
  572. uchar fIsEmbeddedStruct = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  573. uchar* pBuffer;
  574. if ( !fIsEmbeddedStruct )
  575. {
  576. // Align the buffer for marshalling conformance info.
  577. ALIGN(pStubMsg->Buffer,3);
  578. // Mark the location in the buffer where the conformance will be marshalled.
  579. pStubMsg->BufferMark = pStubMsg->Buffer;
  580. // Increment buffer pointer past where conformance will be marshalled.
  581. pStubMsg->Buffer += 4;
  582. }
  583. // else BufferMark is set by the ComplexStruct code.
  584. // Save the structure's alignment.
  585. Alignment = pFormat[1];
  586. // Increment format string to struct size field.
  587. pFormat += 2;
  588. // Get non-conformance struct size and increment format string.
  589. StructSize = (uint) *((ushort *&)pFormat)++;
  590. // Get conformant array's description.
  591. pFormatArray = pFormat + *((signed short *)pFormat);
  592. // Align buffer for struct
  593. ALIGN(pStubMsg->Buffer, Alignment);
  594. pBuffer = pStubMsg->Buffer;
  595. RpcpMemoryCopy( pStubMsg->Buffer,
  596. pMemory,
  597. StructSize );
  598. // Set stub message buffer pointer past non-conformant part of struct.
  599. pStubMsg->Buffer += StructSize;
  600. //
  601. // Call the correct private array or string marshalling routine.
  602. // We must pass a memory pointer to the beginning of the array/string.
  603. //
  604. if ( *pFormatArray == FC_CVARRAY )
  605. {
  606. NdrpConformantVaryingArrayMarshall( pStubMsg,
  607. pMemory + StructSize,
  608. pFormatArray );
  609. }
  610. else
  611. {
  612. NdrpConformantStringMarshall( pStubMsg,
  613. pMemory + StructSize,
  614. pFormatArray );
  615. }
  616. // Increment format string past the offset_to_array_description<2> field.
  617. pFormat += 2;
  618. //
  619. // Marshall embedded pointers.
  620. //
  621. if ( *pFormat == FC_PP )
  622. {
  623. // Mark the start of the structure in the buffer.
  624. pStubMsg->BufferMark = pBuffer;
  625. pStubMsg->MaxCount = pStubMsg->ActualCount;
  626. NdrpEmbeddedPointerMarshall( pStubMsg,
  627. pMemory,
  628. pFormat );
  629. }
  630. // Only a complex struct may set up this flag for embedding.
  631. // Set the reverse flag to signal that array has been marshaled.
  632. if ( fIsEmbeddedStruct )
  633. SET_CONF_ARRAY_DONE( pStubMsg->uFlags );
  634. return 0;
  635. }
  636. #if 0
  637. unsigned char * RPC_ENTRY
  638. NdrHardStructMarshall(
  639. PMIDL_STUB_MESSAGE pStubMsg,
  640. uchar * pMemory,
  641. PFORMAT_STRING pFormat )
  642. /*++
  643. Routine description :
  644. Marshalls a hard structure.
  645. Used for FC_HARD_STRUCT.
  646. Arguments :
  647. pStubMsg - Pointer to the stub message.
  648. pMemory - Pointer to the structure being marshalled.
  649. pFormat - Structure's format string description.
  650. Return :
  651. None.
  652. --*/
  653. {
  654. ALIGN(pStubMsg->Buffer,pFormat[1]);
  655. pFormat += 8;
  656. //
  657. // Do any needed enum16 exception check.
  658. //
  659. if ( *((short *)pFormat) != (short) -1 )
  660. {
  661. if ( *((int *)(pMemory + *((ushort *)pFormat))) & ~((int)0x7fff) )
  662. {
  663. RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
  664. }
  665. }
  666. pFormat += 2;
  667. RpcpMemoryCopy( pStubMsg->Buffer,
  668. pMemory,
  669. *((ushort *)pFormat) );
  670. pStubMsg->Buffer += *((ushort *)pFormat)++;
  671. //
  672. // See if we have a union.
  673. //
  674. if ( *((short *)&pFormat[2]) )
  675. {
  676. pMemory += *((ushort *)pFormat)++;
  677. pFormat += *((short *)pFormat);
  678. (*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  679. pMemory,
  680. pFormat );
  681. }
  682. return 0;
  683. }
  684. #endif // 0
  685. unsigned char * RPC_ENTRY
  686. NdrComplexStructMarshall(
  687. PMIDL_STUB_MESSAGE pStubMsg,
  688. uchar * pMemory,
  689. PFORMAT_STRING pFormat )
  690. /*++
  691. Routine description :
  692. Marshalls a complex structure.
  693. Used for FC_BOGUS_STRUCT.
  694. Arguments :
  695. pStubMsg - Pointer to the stub message.
  696. pMemory - Pointer to the structure being marshalled.
  697. pFormat - Structure's format string description.
  698. Return :
  699. None.
  700. Notes :
  701. pStubMsg->BufferMark is set to a place where conformance would be marhaled.
  702. pStubMsg->pPointerBufferMark is a pointee buffer mark a usual.
  703. --*/
  704. {
  705. uchar * pBufferSave;
  706. uchar * pBufferMark;
  707. uchar * pMemorySave;
  708. PFORMAT_STRING pFormatPointers;
  709. PFORMAT_STRING pFormatArray;
  710. PFORMAT_STRING pFormatSave;
  711. PFORMAT_STRING pFormatComplex;
  712. long Alignment;
  713. long Align8Mod;
  714. uchar fSetPointerBufferMark;
  715. uchar fIsEmbeddedStruct = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  716. BOOL fEmbedConfStructContext;
  717. // Get struct's wire alignment.
  718. Alignment = pFormat[1];
  719. //
  720. // This is used for support of structs with doubles passed on an
  721. // i386 stack.
  722. //
  723. // A cast to long is what we need.
  724. Align8Mod = 0x7 & PtrToLong( pMemory );
  725. pFormatSave = pFormat;
  726. pBufferSave = pStubMsg->Buffer;
  727. pMemorySave = pStubMsg->Memory;
  728. pStubMsg->Memory = pMemory;
  729. // Increment to conformant array offset field.
  730. pFormat += 4;
  731. // Get conformant array description.
  732. if ( *((ushort *)pFormat) )
  733. {
  734. pFormatArray = pFormat + *((signed short *)pFormat);
  735. if ( !fIsEmbeddedStruct )
  736. {
  737. // Align for conformance marshalling.
  738. ALIGN(pStubMsg->Buffer,3);
  739. // Remember where the conformance count(s) will be marshalled.
  740. pStubMsg->BufferMark = pStubMsg->Buffer;
  741. // Increment the buffer pointer 4 bytes for every array dimension.
  742. pStubMsg->Buffer += NdrpArrayDimensions( pStubMsg, pFormatArray, FALSE ) * 4;
  743. }
  744. }
  745. else
  746. pFormatArray = 0;
  747. // Mark the place to marshal conformant size(s), this may come from upper levels.
  748. pBufferMark = pStubMsg->BufferMark;
  749. pFormat += 2;
  750. // Get pointer layout description.
  751. if ( *((ushort *)pFormat) )
  752. pFormatPointers = pFormat + *((ushort *)pFormat);
  753. else
  754. pFormatPointers = 0;
  755. pFormat += 2;
  756. // Align buffer on struct's alignment.
  757. ALIGN(pStubMsg->Buffer,Alignment);
  758. //
  759. // If the the stub message PointerBufferMark field is 0, then determine
  760. // the position in the buffer where pointees will be marshalled.
  761. //
  762. // We have to do this to handle embedded pointers.
  763. //
  764. if ( fSetPointerBufferMark = ! pStubMsg->PointerBufferMark )
  765. {
  766. BOOL fOldIgnore;
  767. ulong BufferLenOffset;
  768. fOldIgnore = pStubMsg->IgnoreEmbeddedPointers;
  769. pStubMsg->IgnoreEmbeddedPointers = TRUE;
  770. //
  771. // Set BufferLength equal to the current buffer pointer, and then
  772. // when we return from NdrComplexStructBufferSize it will pointer to
  773. // the location in the buffer where the pointees should be marshalled.
  774. // pStubMsg->BufferLength = pBufferSave;
  775. // Instead of pointer, we now calculate pointer increment explicitly.
  776. // Set the pointer alignment as a base.
  777. // We use pBufferSave as the sizing routine accounts for the conf sizes.
  778. //
  779. BufferLenOffset = 0xf & PtrToUlong( pBufferSave );
  780. ulong BufferLengthSave = pStubMsg->BufferLength;
  781. pStubMsg->BufferLength = BufferLenOffset;
  782. NdrComplexStructBufferSize( pStubMsg,
  783. pMemory,
  784. pFormatSave );
  785. // Pointer increment including alignments.
  786. BufferLenOffset = pStubMsg->BufferLength - BufferLenOffset;
  787. // Set the location in the buffer where pointees will be marshalled.
  788. pStubMsg->PointerBufferMark = pBufferSave + BufferLenOffset;
  789. pStubMsg->BufferLength = BufferLengthSave;
  790. pStubMsg->IgnoreEmbeddedPointers = fOldIgnore;
  791. }
  792. fEmbedConfStructContext = fIsEmbeddedStruct ||
  793. pFormatArray && FixWireRepForDComVerGTE54( pStubMsg );
  794. RESET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  795. //
  796. // Marshall the structure member by member.
  797. //
  798. for ( ; ; pFormat++ )
  799. {
  800. switch ( *pFormat )
  801. {
  802. //
  803. // Simple types.
  804. //
  805. case FC_CHAR :
  806. case FC_BYTE :
  807. case FC_SMALL :
  808. case FC_WCHAR :
  809. case FC_SHORT :
  810. case FC_LONG :
  811. #if defined(__RPC_WIN64__)
  812. case FC_INT3264 :
  813. case FC_UINT3264 :
  814. #endif
  815. case FC_FLOAT :
  816. case FC_HYPER :
  817. case FC_DOUBLE :
  818. case FC_ENUM16 :
  819. case FC_ENUM32 :
  820. NdrSimpleTypeMarshall( pStubMsg,
  821. pMemory,
  822. *pFormat );
  823. pMemory += SIMPLE_TYPE_MEMSIZE(*pFormat);
  824. break;
  825. case FC_IGNORE :
  826. ALIGN(pStubMsg->Buffer,3);
  827. pStubMsg->Buffer += PTR_WIRE_SIZE;
  828. pMemory += PTR_MEM_SIZE;
  829. break;
  830. case FC_POINTER :
  831. {
  832. ALIGN( pStubMsg->Buffer, 0x3 );
  833. uchar *pPointerId = pStubMsg->Buffer;
  834. pStubMsg->Buffer += PTR_WIRE_SIZE;
  835. NDR_ASSERT(pFormatPointers, "NdrComplexStructMarshall: pointer field but no pointer layout");
  836. {
  837. POINTER_BUFFER_SWAP_CONTEXT NewContext(pStubMsg);
  838. NdrpPointerMarshall( pStubMsg,
  839. pPointerId,
  840. *((uchar **)pMemory),
  841. pFormatPointers );
  842. }
  843. //
  844. // Increment memory pointers past the pointer.
  845. //
  846. pMemory += PTR_MEM_SIZE;
  847. pFormatPointers += 4;
  848. break;
  849. }
  850. //
  851. // Embedded complex types.
  852. //
  853. case FC_EMBEDDED_COMPLEX :
  854. // Increment memory pointer by padding.
  855. pMemory += pFormat[1];
  856. pFormat += 2;
  857. // Get the type's description.
  858. pFormatComplex = pFormat + *((signed short UNALIGNED *)pFormat);
  859. if ( FC_IP == *pFormatComplex )
  860. {
  861. // Treat the same as an embedded pointer
  862. ALIGN( pStubMsg->Buffer, 0x3 );
  863. uchar *pPointerId = pStubMsg->Buffer;
  864. pStubMsg->Buffer += PTR_WIRE_SIZE;
  865. {
  866. POINTER_BUFFER_SWAP_CONTEXT NewContext(pStubMsg);
  867. NdrpPointerMarshall( pStubMsg,
  868. pPointerId,
  869. *((uchar **)pMemory),
  870. pFormatComplex );
  871. }
  872. pMemory += PTR_MEM_SIZE;
  873. pFormat++;
  874. break;
  875. }
  876. // Context needed for the embedded conf struct.
  877. //
  878. pStubMsg->BufferMark = pBufferMark;
  879. if ( fEmbedConfStructContext )
  880. SET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  881. // Marshall complex type.
  882. (*pfnMarshallRoutines[ROUTINE_INDEX(*pFormatComplex)])
  883. ( pStubMsg,
  884. pMemory,
  885. pFormatComplex );
  886. //
  887. // Increment the memory pointer.
  888. //
  889. pMemory = NdrpMemoryIncrement( pStubMsg,
  890. pMemory,
  891. pFormatComplex );
  892. RESET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  893. //
  894. // Increment the main format string one byte. The loop
  895. // will increment it one more byte past the offset field.
  896. //
  897. pFormat++;
  898. break;
  899. case FC_ALIGNM2 :
  900. ALIGN( pMemory, 0x1 );
  901. break;
  902. case FC_ALIGNM4 :
  903. ALIGN( pMemory, 0x3 );
  904. break;
  905. case FC_ALIGNM8 :
  906. //
  907. // We have to play some tricks for the i386 to handle the case
  908. // when an 8 byte aligned structure is passed by value. The
  909. // alignment of the struct on the stack is not guaranteed to be
  910. // on an 8 byte boundary.
  911. //
  912. pMemory -= Align8Mod;
  913. ALIGN( pMemory, 0x7 );
  914. pMemory += Align8Mod;
  915. break;
  916. case FC_STRUCTPAD1 :
  917. case FC_STRUCTPAD2 :
  918. case FC_STRUCTPAD3 :
  919. case FC_STRUCTPAD4 :
  920. case FC_STRUCTPAD5 :
  921. case FC_STRUCTPAD6 :
  922. case FC_STRUCTPAD7 :
  923. //
  924. // Increment memory pointer by amount of padding.
  925. //
  926. pMemory += (*pFormat - FC_STRUCTPAD1) + 1;
  927. break;
  928. case FC_STRUCTPADN :
  929. // FC_STRUCTPADN 0 <unsigned short>
  930. pMemory += *(((unsigned short *)pFormat) + 1);
  931. pFormat += 3;
  932. break;
  933. case FC_PAD :
  934. break;
  935. //
  936. // Done with layout.
  937. //
  938. case FC_END :
  939. goto ComplexMarshallEnd;
  940. default :
  941. NDR_ASSERT(0,"NdrComplexStructMarshall : bad format char");
  942. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  943. return 0;
  944. } // switch
  945. } // for
  946. ComplexMarshallEnd:
  947. //
  948. // Marshall conformant array if we have one.
  949. // .. but not when embedded and not when it had been marshaled by conf struct.
  950. //
  951. if ( pFormatArray && !fIsEmbeddedStruct &&
  952. ! IS_CONF_ARRAY_DONE( pStubMsg->uFlags ) )
  953. {
  954. // Normal case: top level marshaling.
  955. PPRIVATE_MARSHALL_ROUTINE pfnPMarshall;
  956. switch ( *pFormatArray )
  957. {
  958. case FC_CARRAY :
  959. pfnPMarshall = NdrpConformantArrayMarshall;
  960. break;
  961. case FC_CVARRAY :
  962. pfnPMarshall = NdrpConformantVaryingArrayMarshall;
  963. break;
  964. case FC_BOGUS_ARRAY :
  965. pfnPMarshall = NdrpComplexArrayMarshall;
  966. break;
  967. case FC_C_WSTRING :
  968. ALIGN(pMemory,1);
  969. // fall through
  970. // case FC_C_CSTRING :
  971. // case FC_C_BSTRING :
  972. // case FC_C_SSTRING :
  973. default :
  974. pfnPMarshall = NdrpConformantStringMarshall;
  975. break;
  976. }
  977. //
  978. // Mark where the conformance count(s) will be marshalled.
  979. //
  980. pStubMsg->BufferMark = pBufferMark;
  981. // Marshall the array.
  982. (*pfnPMarshall)( pStubMsg,
  983. pMemory,
  984. pFormatArray );
  985. }
  986. //
  987. // Now fix up the stub message Buffer field if we set the PointerBufferMark
  988. // field.
  989. //
  990. if ( fSetPointerBufferMark )
  991. {
  992. pStubMsg->Buffer = pStubMsg->PointerBufferMark;
  993. pStubMsg->PointerBufferMark = 0;
  994. }
  995. pStubMsg->Memory = pMemorySave;
  996. if ( fIsEmbeddedStruct )
  997. SET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
  998. else
  999. RESET_CONF_ARRAY_DONE( pStubMsg->uFlags );
  1000. return 0;
  1001. }
  1002. unsigned char * RPC_ENTRY
  1003. NdrNonConformantStringMarshall(
  1004. PMIDL_STUB_MESSAGE pStubMsg,
  1005. uchar * pMemory,
  1006. PFORMAT_STRING pFormat )
  1007. /*++
  1008. Routine description :
  1009. Marshalls a non conformant string.
  1010. Used for FC_CSTRING, FC_WSTRING, FC_SSTRING, and FC_BSTRING (NT Beta2
  1011. compatability only).
  1012. Arguments :
  1013. pStubMsg - Pointer to the stub message.
  1014. pMemory - Pointer to the string to be marshalled.
  1015. pFormat - String's format string description.
  1016. Return :
  1017. None.
  1018. --*/
  1019. {
  1020. uint Count;
  1021. uint CopySize;
  1022. // Align the buffer for offset and count marshalling.
  1023. ALIGN(pStubMsg->Buffer,3);
  1024. switch ( *pFormat )
  1025. {
  1026. case FC_CSTRING :
  1027. case FC_BSTRING :
  1028. CopySize = Count = MIDL_ascii_strlen((char *)pMemory) + 1;
  1029. break;
  1030. case FC_WSTRING :
  1031. Count = wcslen((wchar_t *)pMemory) + 1;
  1032. CopySize = Count * sizeof(wchar_t);
  1033. break;
  1034. case FC_SSTRING :
  1035. Count = NdrpStringStructLen( pMemory, pFormat[1] ) + 1;
  1036. CopySize = Count * pFormat[1];
  1037. break;
  1038. default :
  1039. NDR_ASSERT(0,"NdrNonConformantStringMarshall : bad format char");
  1040. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  1041. return 0;
  1042. }
  1043. // Marshall variance.
  1044. *((ulong *&)pStubMsg->Buffer)++ = 0;
  1045. *((ulong *&)pStubMsg->Buffer)++ = Count;
  1046. // Copy the string.
  1047. RpcpMemoryCopy( pStubMsg->Buffer,
  1048. pMemory,
  1049. CopySize );
  1050. // Update buffer pointer.
  1051. pStubMsg->Buffer += CopySize;
  1052. return 0;
  1053. }
  1054. unsigned char * RPC_ENTRY
  1055. NdrConformantStringMarshall(
  1056. PMIDL_STUB_MESSAGE pStubMsg,
  1057. uchar * pMemory,
  1058. PFORMAT_STRING pFormat )
  1059. /*++
  1060. Routine description :
  1061. Marshalls a top level conformant string.
  1062. Used for FC_C_CSTRING, FC_C_WSTRING, FC_C_SSTRING, and FC_C_BSTRING
  1063. (NT Beta2 compatability only).
  1064. Arguments :
  1065. pStubMsg - Pointer to the stub message.
  1066. pMemory - Pointer to the string to be marshalled.
  1067. pFormat - String's format string description.
  1068. Return :
  1069. None.
  1070. --*/
  1071. {
  1072. if ( pStubMsg->pArrayInfo != 0 )
  1073. {
  1074. //
  1075. // If this is part of a multidimensional array then we get the location
  1076. // where the conformance is marshalled from a special place.
  1077. //
  1078. pStubMsg->BufferMark = ( uchar * )
  1079. &(pStubMsg->pArrayInfo->
  1080. BufferConformanceMark[pStubMsg->pArrayInfo->Dimension]);
  1081. }
  1082. else
  1083. {
  1084. // Align the buffer for max count marshalling.
  1085. ALIGN(pStubMsg->Buffer,3);
  1086. // Mark where the max count will be marshalled.
  1087. pStubMsg->BufferMark = pStubMsg->Buffer;
  1088. // Increment the buffer past where the max count will be marshalled.
  1089. pStubMsg->Buffer += 4;
  1090. }
  1091. // Call the private marshalling routine.
  1092. NdrpConformantStringMarshall( pStubMsg,
  1093. pMemory,
  1094. pFormat );
  1095. return 0;
  1096. }
  1097. void
  1098. NdrpConformantStringMarshall(
  1099. PMIDL_STUB_MESSAGE pStubMsg,
  1100. uchar * pMemory,
  1101. PFORMAT_STRING pFormat )
  1102. /*++
  1103. Routine description :
  1104. Private routine for marshalling a conformant string. This is the
  1105. entry point for marshalling an embedded conformant strings.
  1106. Used for FC_C_CSTRING, FC_C_WSTRING, FC_C_SSTRING, and FC_C_BSTRING
  1107. (NT Beta2 compatability only).
  1108. Arguments :
  1109. pStubMsg - Pointer to the stub message.
  1110. pMemory - Pointer to the string to be marshalled.
  1111. pFormat - String's format string description.
  1112. Return :
  1113. None.
  1114. --*/
  1115. {
  1116. ulong MaxCount;
  1117. uint ActualCount, CopySize;
  1118. BOOL IsSized;
  1119. IsSized = (pFormat[1] == FC_STRING_SIZED);
  1120. // Compute the element count of the string and the total copy size.
  1121. switch ( *pFormat )
  1122. {
  1123. case FC_C_CSTRING :
  1124. case FC_C_BSTRING :
  1125. CopySize = ActualCount = MIDL_ascii_strlen((char *)pMemory) + 1;
  1126. break;
  1127. case FC_C_WSTRING :
  1128. ActualCount = wcslen((wchar_t *)pMemory) + 1;
  1129. CopySize = ActualCount * sizeof(wchar_t);
  1130. break;
  1131. case FC_C_SSTRING :
  1132. ActualCount = NdrpStringStructLen( pMemory, pFormat[1] ) + 1;
  1133. CopySize = ActualCount * pFormat[1];
  1134. // Redo this check correctly.
  1135. IsSized = (pFormat[2] == FC_STRING_SIZED);
  1136. break;
  1137. default :
  1138. NDR_ASSERT(0,"NdrpConformantStringMarshall : bad format char");
  1139. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  1140. return;
  1141. }
  1142. //
  1143. // If the string is sized then compute the max count, otherwise the
  1144. // max count is equal to the actual count.
  1145. //
  1146. if ( IsSized )
  1147. {
  1148. MaxCount = (ulong) NdrpComputeConformance( pStubMsg,
  1149. pMemory,
  1150. pFormat );
  1151. }
  1152. else
  1153. {
  1154. MaxCount = ActualCount;
  1155. }
  1156. // Marshall the max count.
  1157. *((ulong *)pStubMsg->BufferMark) = MaxCount;
  1158. // Align the buffer for variance marshalling.
  1159. ALIGN(pStubMsg->Buffer,3);
  1160. // Marshall variance.
  1161. *((ulong *&)pStubMsg->Buffer)++ = 0;
  1162. *((ulong *&)pStubMsg->Buffer)++ = ActualCount;
  1163. RpcpMemoryCopy( pStubMsg->Buffer,
  1164. pMemory,
  1165. CopySize );
  1166. // Update the Buffer pointer.
  1167. pStubMsg->Buffer += CopySize;
  1168. }
  1169. unsigned char * RPC_ENTRY
  1170. NdrFixedArrayMarshall(
  1171. PMIDL_STUB_MESSAGE pStubMsg,
  1172. uchar * pMemory,
  1173. PFORMAT_STRING pFormat )
  1174. /*++
  1175. Routine Description :
  1176. Marshalls a fixed array of any number of dimensions.
  1177. Used for FC_SMFARRAY and FC_LGFARRAY.
  1178. Arguments :
  1179. pStubMsg - Pointer to the stub message.
  1180. pMemory - Pointer to the array to be marshalled.
  1181. pFormat - Array's format string description.
  1182. Return :
  1183. None.
  1184. --*/
  1185. {
  1186. uint Size;
  1187. // Align the buffer.
  1188. ALIGN(pStubMsg->Buffer,pFormat[1]);
  1189. // Get total array size.
  1190. if ( *pFormat == FC_SMFARRAY )
  1191. {
  1192. pFormat += 2;
  1193. Size = (ulong) *((ushort *&)pFormat)++;
  1194. }
  1195. else // *pFormat == FC_LGFARRAY
  1196. {
  1197. pFormat += 2;
  1198. Size = *((ulong UNALIGNED *&)pFormat)++;
  1199. }
  1200. // Copy the array.
  1201. RpcpMemoryCopy( pStubMsg->Buffer,
  1202. pMemory,
  1203. Size );
  1204. // Increment stub message buffer pointer.
  1205. pStubMsg->Buffer += Size;
  1206. // Marshall embedded pointers.
  1207. if ( *pFormat == FC_PP )
  1208. {
  1209. // Mark the start of the array in the buffer.
  1210. pStubMsg->BufferMark = pStubMsg->Buffer - Size;
  1211. NdrpEmbeddedPointerMarshall( pStubMsg,
  1212. pMemory,
  1213. pFormat );
  1214. }
  1215. return 0;
  1216. }
  1217. unsigned char * RPC_ENTRY
  1218. NdrConformantArrayMarshall(
  1219. PMIDL_STUB_MESSAGE pStubMsg,
  1220. uchar * pMemory,
  1221. PFORMAT_STRING pFormat )
  1222. /*++
  1223. Routine Description :
  1224. Marshalls a top level one dimensional conformant array.
  1225. Used for FC_CARRAY.
  1226. Arguments :
  1227. pStubMsg - Pointer to the stub message.
  1228. pMemory - Pointer to the array being marshalled.
  1229. pFormat - Array's format string description.
  1230. Return :
  1231. None.
  1232. --*/
  1233. {
  1234. // Align the buffer for conformance marshalling.
  1235. ALIGN(pStubMsg->Buffer,3);
  1236. // Mark where the conformance will be marshalled.
  1237. pStubMsg->BufferMark = pStubMsg->Buffer;
  1238. // Increment past where the conformance will go.
  1239. pStubMsg->Buffer += 4;
  1240. // Call the private marshalling routine to do the work.
  1241. NdrpConformantArrayMarshall( pStubMsg,
  1242. pMemory,
  1243. pFormat );
  1244. return 0;
  1245. }
  1246. void
  1247. NdrpConformantArrayMarshall(
  1248. PMIDL_STUB_MESSAGE pStubMsg,
  1249. uchar * pMemory,
  1250. PFORMAT_STRING pFormat )
  1251. /*++
  1252. Routine Description :
  1253. Private routine for marshalling a one dimensional conformant array.
  1254. This is the entry point for marshalling an embedded conformant array.
  1255. Used for FC_CARRAY.
  1256. Arguments :
  1257. pStubMsg - Pointer to the stub message.
  1258. pMemory - Pointer to the array being marshalled.
  1259. pFormat - Array's format string description.
  1260. Return :
  1261. None.
  1262. --*/
  1263. {
  1264. ulong Count;
  1265. uint CopySize;
  1266. // Compute conformance information.
  1267. Count = (ulong) NdrpComputeConformance( pStubMsg,
  1268. pMemory,
  1269. pFormat );
  1270. // Marshall the conformance.
  1271. *((ulong *)pStubMsg->BufferMark) = Count;
  1272. //
  1273. // Return if size is 0.
  1274. //
  1275. if ( ! Count )
  1276. return;
  1277. ALIGN(pStubMsg->Buffer,pFormat[1]);
  1278. // Compute the total array size in bytes.
  1279. CopySize = Count * *((ushort *)(pFormat + 2));
  1280. RpcpMemoryCopy( pStubMsg->Buffer,
  1281. pMemory,
  1282. CopySize );
  1283. // Update buffer pointer.
  1284. pStubMsg->Buffer += CopySize;
  1285. // Increment to possible pointer layout.
  1286. pFormat += 8;
  1287. CORRELATION_DESC_INCREMENT( pFormat );
  1288. // Marshall embedded pointers.
  1289. if ( *pFormat == FC_PP )
  1290. {
  1291. //
  1292. // Mark the start of the array in the buffer.
  1293. //
  1294. pStubMsg->BufferMark = pStubMsg->Buffer - CopySize;
  1295. NdrpEmbeddedPointerMarshall( pStubMsg,
  1296. pMemory,
  1297. pFormat );
  1298. }
  1299. }
  1300. unsigned char * RPC_ENTRY
  1301. NdrConformantVaryingArrayMarshall(
  1302. PMIDL_STUB_MESSAGE pStubMsg,
  1303. uchar * pMemory,
  1304. PFORMAT_STRING pFormat )
  1305. /*++
  1306. Routine Description :
  1307. Marshalls a top level one dimensional conformant varying array.
  1308. Used for FC_CVARRAY.
  1309. Arguments :
  1310. pStubMsg - Pointer to the stub message.
  1311. pMemory - Pointer to the array being marshalled.
  1312. pFormat - Array's format string description.
  1313. Return :
  1314. None.
  1315. --*/
  1316. {
  1317. // Align the buffer for conformance marshalling.
  1318. ALIGN(pStubMsg->Buffer,3);
  1319. // Mark where the conformance will be marshalled.
  1320. pStubMsg->BufferMark = pStubMsg->Buffer;
  1321. // Increment past where the conformance will go.
  1322. pStubMsg->Buffer += 4;
  1323. // Call the private marshalling routine to do the work.
  1324. NdrpConformantVaryingArrayMarshall( pStubMsg,
  1325. pMemory,
  1326. pFormat );
  1327. return 0;
  1328. }
  1329. void
  1330. NdrpConformantVaryingArrayMarshall(
  1331. PMIDL_STUB_MESSAGE pStubMsg,
  1332. uchar * pMemory,
  1333. PFORMAT_STRING pFormat )
  1334. /*++
  1335. Routine Description :
  1336. Private routine for marshalling a one dimensional conformant varying array.
  1337. This is the entry point for marshalling an embedded conformant varying
  1338. array.
  1339. Used for FC_CVARRAY.
  1340. Arguments :
  1341. pStubMsg - Pointer to the stub message.
  1342. pMemory - Pointer to the array to be marshalled.
  1343. pFormat - Array's format string description.
  1344. Return :
  1345. None.
  1346. --*/
  1347. {
  1348. uint CopyOffset, CopySize;
  1349. ushort ElemSize;
  1350. // Compute and marshall the conformant size.
  1351. *((ulong *)pStubMsg->BufferMark) = (ulong) NdrpComputeConformance( pStubMsg,
  1352. pMemory,
  1353. pFormat );
  1354. // Compute variance offset and count.
  1355. NdrpComputeVariance( pStubMsg,
  1356. pMemory,
  1357. pFormat );
  1358. // Align the buffer for variance marshalling.
  1359. ALIGN(pStubMsg->Buffer,3);
  1360. // Marshall variance.
  1361. *((ulong *&)pStubMsg->Buffer)++ = pStubMsg->Offset;
  1362. *((ulong *&)pStubMsg->Buffer)++ = pStubMsg->ActualCount;
  1363. //
  1364. // Return if length is 0.
  1365. //
  1366. if ( ! pStubMsg->ActualCount )
  1367. return;
  1368. ALIGN(pStubMsg->Buffer, pFormat[1]);
  1369. ElemSize = *((ushort *)(pFormat + 2));
  1370. // Compute byte offset and size for the array copy.
  1371. CopyOffset = pStubMsg->Offset * ElemSize;
  1372. CopySize = pStubMsg->ActualCount * ElemSize;
  1373. RpcpMemoryCopy( pStubMsg->Buffer,
  1374. pMemory + CopyOffset,
  1375. CopySize );
  1376. pStubMsg->Buffer += CopySize;
  1377. // Increment to a possible pointer layout.
  1378. pFormat += 12;
  1379. CORRELATION_DESC_INCREMENT( pFormat );
  1380. CORRELATION_DESC_INCREMENT( pFormat );
  1381. // Marshall embedded pointers.
  1382. if ( *pFormat == FC_PP )
  1383. {
  1384. //
  1385. // Set the MaxCount field equal to the ActualCount field. The pointer
  1386. // marshalling routine uses the MaxCount field to determine the number
  1387. // of times an FC_VARIABLE_REPEAT pointer is marshalled. In the face
  1388. // of variance the correct number of time is the ActualCount, not the
  1389. // the MaxCount.
  1390. //
  1391. pStubMsg->MaxCount = pStubMsg->ActualCount;
  1392. //
  1393. // Mark the start of the array in the buffer.
  1394. //
  1395. pStubMsg->BufferMark = pStubMsg->Buffer - CopySize;
  1396. NdrpEmbeddedPointerMarshall( pStubMsg,
  1397. pMemory,
  1398. pFormat );
  1399. }
  1400. }
  1401. unsigned char * RPC_ENTRY
  1402. NdrVaryingArrayMarshall(
  1403. PMIDL_STUB_MESSAGE pStubMsg,
  1404. uchar * pMemory,
  1405. PFORMAT_STRING pFormat )
  1406. /*++
  1407. Routine Description :
  1408. Marshalls a top level or embedded one dimensional varying array.
  1409. Used for FC_SMVARRAY and FC_LGVARRAY.
  1410. Arguments :
  1411. pStubMsg - Pointer to the stub message.
  1412. pMemory - Pointer to the array being marshalled.
  1413. pFormat - Array's format string description.
  1414. Return :
  1415. None.
  1416. --*/
  1417. {
  1418. uint CopyOffset, CopySize;
  1419. ushort ElemSize;
  1420. // Compute the variance offset and count.
  1421. NdrpComputeVariance( pStubMsg,
  1422. pMemory,
  1423. pFormat );
  1424. // Align the buffer for variance marshalling.
  1425. ALIGN(pStubMsg->Buffer,3);
  1426. // Marshall variance.
  1427. *((ulong *&)pStubMsg->Buffer)++ = pStubMsg->Offset;
  1428. *((ulong *&)pStubMsg->Buffer)++ = pStubMsg->ActualCount;
  1429. //
  1430. // Return if length is 0.
  1431. //
  1432. if ( ! pStubMsg->ActualCount )
  1433. return 0;
  1434. ALIGN(pStubMsg->Buffer, pFormat[1]);
  1435. // Increment the format string to the element_size field.
  1436. if ( *pFormat == FC_SMVARRAY )
  1437. pFormat += 6;
  1438. else // *pFormat == FC_LGVARRAY
  1439. pFormat += 10;
  1440. // Get element size.
  1441. ElemSize = *((ushort *)pFormat);
  1442. //
  1443. // Compute the byte offset from the beginning of the array for the copy
  1444. // and the number of bytes to copy.
  1445. //
  1446. CopyOffset = pStubMsg->Offset * ElemSize;
  1447. CopySize = pStubMsg->ActualCount * ElemSize;
  1448. // Copy the array.
  1449. RpcpMemoryCopy( pStubMsg->Buffer,
  1450. pMemory + CopyOffset,
  1451. CopySize );
  1452. // Update buffer pointer.
  1453. pStubMsg->Buffer += CopySize;
  1454. // Increment format string to possible pointer layout.
  1455. pFormat += 6;
  1456. CORRELATION_DESC_INCREMENT( pFormat );
  1457. // Marshall embedded pointers.
  1458. if ( *pFormat == FC_PP )
  1459. {
  1460. // Mark the start of the array in the buffer.
  1461. pStubMsg->BufferMark = pStubMsg->Buffer - CopySize;
  1462. //
  1463. // Set the MaxCount field equal to the ActualCount field. The pointer
  1464. // marshalling routine uses the MaxCount field to determine the number
  1465. // of times an FC_VARIABLE_REPEAT pointer is marshalled. In the face
  1466. // of variance the correct number of time is the ActualCount, not the
  1467. // the MaxCount.
  1468. //
  1469. pStubMsg->MaxCount = pStubMsg->ActualCount;
  1470. //
  1471. // Marshall the embedded pointers.
  1472. // Make sure to pass a memory pointer to the first array element
  1473. // which is actually being marshalled.
  1474. //
  1475. NdrpEmbeddedPointerMarshall( pStubMsg,
  1476. pMemory + CopyOffset,
  1477. pFormat );
  1478. }
  1479. return 0;
  1480. }
  1481. unsigned char * RPC_ENTRY
  1482. NdrComplexArrayMarshall(
  1483. PMIDL_STUB_MESSAGE pStubMsg,
  1484. uchar * pMemory,
  1485. PFORMAT_STRING pFormat )
  1486. /*++
  1487. Routine Description :
  1488. Marshalls a top level complex array.
  1489. Used for FC_BOGUS_STRUCT.
  1490. Arguments :
  1491. pStubMsg - Pointer to the stub message.
  1492. pMemory - Pointer to the array being marshalled.
  1493. pFormat - Array's format string description.
  1494. Return :
  1495. None.
  1496. --*/
  1497. {
  1498. BOOL fSetPointerBufferMark;
  1499. PFORMAT_STRING pFormatPP;
  1500. //
  1501. // Setting this flag means that the array is not embedded inside of
  1502. // another complex struct or array.
  1503. //
  1504. pFormatPP = pFormat + 12;
  1505. CORRELATION_DESC_INCREMENT( pFormatPP );
  1506. CORRELATION_DESC_INCREMENT( pFormatPP );
  1507. fSetPointerBufferMark = (! pStubMsg->PointerBufferMark) &&
  1508. (*pFormatPP != FC_RP);
  1509. if ( fSetPointerBufferMark )
  1510. {
  1511. BOOL fOldIgnore;
  1512. ULONG_PTR MaxCountSave;
  1513. ulong Offset, ActualCount;
  1514. ulong BufferLenOffset;
  1515. //
  1516. // Save the current conformance and variance fields. The sizing
  1517. // routine can overwrite them.
  1518. //
  1519. MaxCountSave = pStubMsg->MaxCount;
  1520. Offset = pStubMsg->Offset;
  1521. ActualCount = pStubMsg->ActualCount;
  1522. fOldIgnore = pStubMsg->IgnoreEmbeddedPointers;
  1523. pStubMsg->IgnoreEmbeddedPointers = TRUE;
  1524. //
  1525. // Set BufferLength equal to the current buffer pointer, and then
  1526. // when we return from NdrComplexArrayBufferSize it will point to
  1527. // the location in the buffer where the pointers should be marshalled
  1528. // into.
  1529. // Instead of pointer, we now calculate pointer increment explicitly.
  1530. //
  1531. // Set the pointer alignment as a base.
  1532. BufferLenOffset = 0xf & PtrToUlong( pStubMsg->Buffer );
  1533. ulong BufferLengthSave = pStubMsg->BufferLength;
  1534. pStubMsg->BufferLength = BufferLenOffset;
  1535. NdrComplexArrayBufferSize( pStubMsg,
  1536. pMemory,
  1537. pFormat );
  1538. // Pointer increment including alignments.
  1539. BufferLenOffset = pStubMsg->BufferLength - BufferLenOffset;
  1540. //
  1541. // This is the buffer pointer to the position where embedded pointers
  1542. // will be marshalled.
  1543. //
  1544. pStubMsg->PointerBufferMark = pStubMsg->Buffer + BufferLenOffset;
  1545. pStubMsg->BufferLength = BufferLengthSave;
  1546. pStubMsg->IgnoreEmbeddedPointers = fOldIgnore;
  1547. // Restore conformance and variance fields.
  1548. pStubMsg->MaxCount = MaxCountSave;
  1549. pStubMsg->Offset = Offset;
  1550. pStubMsg->ActualCount = ActualCount;
  1551. }
  1552. if ( ( *((long UNALIGNED *)(pFormat + 4)) != 0xffffffff ) &&
  1553. ( pStubMsg->pArrayInfo == 0 ) )
  1554. {
  1555. //
  1556. // Outer most dimension sets the conformance marker.
  1557. //
  1558. // Align the buffer for conformance marshalling.
  1559. ALIGN(pStubMsg->Buffer,3);
  1560. // Mark where the conformance count(s) will be marshalled.
  1561. pStubMsg->BufferMark = pStubMsg->Buffer;
  1562. // Increment past where the conformance will go.
  1563. pStubMsg->Buffer += NdrpArrayDimensions( pStubMsg, pFormat, FALSE ) * 4;
  1564. }
  1565. // Call the private marshalling routine to do all the work.
  1566. NdrpComplexArrayMarshall( pStubMsg,
  1567. pMemory,
  1568. pFormat );
  1569. if ( fSetPointerBufferMark )
  1570. {
  1571. //
  1572. // This will set the buffer pointer to end of all of the array's
  1573. // unmarshalled data in the buffer.
  1574. //
  1575. pStubMsg->Buffer = pStubMsg->PointerBufferMark;
  1576. pStubMsg->PointerBufferMark = 0;
  1577. }
  1578. return 0;
  1579. }
  1580. void
  1581. NdrpComplexArrayMarshall(
  1582. PMIDL_STUB_MESSAGE pStubMsg,
  1583. uchar * pMemory,
  1584. PFORMAT_STRING pFormat )
  1585. /*++
  1586. Routine Description :
  1587. Private routine for marshalling a complex array. This is the entry
  1588. point for marshalling an embedded complex array.
  1589. Used for FC_BOGUS_ARRAY.
  1590. Arguments :
  1591. pStubMsg - Pointer to the stub message.
  1592. pMemory - Pointer to the array being marshalled.
  1593. pFormat - Array's format string description.
  1594. pStubMsg->Buffer - array pointer
  1595. pStubMsg->BufferMark - a place to marshal the conformant size
  1596. pStubMsg->BufferPointerMark - a place to marshal the pointees
  1597. Return :
  1598. None.
  1599. --*/
  1600. {
  1601. ARRAY_INFO ArrayInfo;
  1602. PARRAY_INFO pArrayInfo;
  1603. PMARSHALL_ROUTINE pfnMarshall;
  1604. PFORMAT_STRING pFormatStart;
  1605. uint Elements;
  1606. uint Offset, Count;
  1607. uint MemoryElementSize;
  1608. long Dimension;
  1609. uchar Alignment;
  1610. bool UseBrokenInterfacePointerRep = false;
  1611. //
  1612. // Lots of setup if we are the outer dimension. All this is for
  1613. // multidimensional array support. If we didn't have to worry about
  1614. // Beta2 stub compatability we could this much better.
  1615. //
  1616. //
  1617. if ( ! pStubMsg->pArrayInfo )
  1618. {
  1619. pStubMsg->pArrayInfo = &ArrayInfo;
  1620. ArrayInfo.Dimension = 0;
  1621. ArrayInfo.BufferConformanceMark = (unsigned long *) pStubMsg->BufferMark;
  1622. ArrayInfo.BufferVarianceMark = 0;
  1623. ArrayInfo.MaxCountArray = (ulong *) pStubMsg->MaxCount;
  1624. ArrayInfo.OffsetArray = (ulong *) UlongToPtr( pStubMsg->Offset );
  1625. ArrayInfo.ActualCountArray = (ulong *) UlongToPtr( pStubMsg->ActualCount );
  1626. }
  1627. pFormatStart = pFormat;
  1628. pArrayInfo = pStubMsg->pArrayInfo;
  1629. Dimension = pArrayInfo->Dimension;
  1630. // Get the array's alignment.
  1631. Alignment = pFormat[1];
  1632. pFormat += 2;
  1633. // Get number of elements (0 if the array has conformance).
  1634. Elements = *((ushort *&)pFormat)++;
  1635. //
  1636. // Check for conformance description.
  1637. //
  1638. if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
  1639. {
  1640. Elements = (ulong) NdrpComputeConformance( pStubMsg,
  1641. pMemory,
  1642. pFormatStart );
  1643. // Marshall this dimension's conformance count.
  1644. pArrayInfo->BufferConformanceMark[Dimension] = Elements;
  1645. }
  1646. pFormat += 4;
  1647. CORRELATION_DESC_INCREMENT( pFormat );
  1648. //
  1649. // Check for variance description.
  1650. //
  1651. if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
  1652. {
  1653. if ( Dimension == 0 )
  1654. {
  1655. //
  1656. // Set the variance marker.
  1657. //
  1658. ALIGN(pStubMsg->Buffer,0x3);
  1659. // Mark where the variance count(s) will be marshalled.
  1660. pArrayInfo->BufferVarianceMark = (unsigned long *) pStubMsg->Buffer;
  1661. // Increment past where the variance will go.
  1662. pStubMsg->Buffer +=
  1663. NdrpArrayDimensions( pStubMsg, pFormatStart, TRUE ) * 8;
  1664. }
  1665. NdrpComputeVariance( pStubMsg,
  1666. pMemory,
  1667. pFormatStart );
  1668. Offset = pStubMsg->Offset;
  1669. Count = pStubMsg->ActualCount;
  1670. //
  1671. // Marshall the outer dimension's variance.
  1672. //
  1673. pArrayInfo->BufferVarianceMark[Dimension * 2] = Offset;
  1674. pArrayInfo->BufferVarianceMark[(Dimension * 2) + 1] = Count;
  1675. }
  1676. else
  1677. {
  1678. Offset = 0;
  1679. Count = Elements;
  1680. }
  1681. pFormat += 4;
  1682. CORRELATION_DESC_INCREMENT( pFormat );
  1683. //
  1684. // Return if count is 0.
  1685. //
  1686. if ( ! Count )
  1687. goto ComplexArrayMarshallEnd;
  1688. // Align on array's alignment.
  1689. ALIGN(pStubMsg->Buffer,Alignment);
  1690. switch ( *pFormat )
  1691. {
  1692. case FC_EMBEDDED_COMPLEX :
  1693. pFormat += 2;
  1694. pFormat += *((signed short *)pFormat);
  1695. if ( FC_IP == *pFormat )
  1696. goto HandleInterfacePointer;
  1697. // Get the proper marshalling routine.
  1698. pfnMarshall = pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)];
  1699. pArrayInfo->Dimension = Dimension + 1;
  1700. // Compute the size of an array element.
  1701. MemoryElementSize = (uint) (NdrpMemoryIncrement( pStubMsg,
  1702. pMemory,
  1703. pFormat ) - pMemory);
  1704. break;
  1705. case FC_RP :
  1706. case FC_UP :
  1707. case FC_FP :
  1708. case FC_OP :
  1709. pfnMarshall = (PMARSHALL_ROUTINE) NdrpPointerMarshall;
  1710. // Need this in case we have a variant offset.
  1711. MemoryElementSize = PTR_MEM_SIZE;
  1712. break;
  1713. case FC_IP :
  1714. HandleInterfacePointer:
  1715. UseBrokenInterfacePointerRep = !FixWireRepForDComVerGTE54( pStubMsg );
  1716. // Probably does not exercise this code path, for IP the compiler
  1717. // generates embedded complex as an array element.
  1718. //
  1719. pfnMarshall = (PMARSHALL_ROUTINE) NdrpPointerMarshall;
  1720. // Need this in case we have a variant offset.
  1721. MemoryElementSize = PTR_MEM_SIZE;
  1722. break;
  1723. case FC_ENUM16 :
  1724. pfnMarshall = 0;
  1725. // Need this in case we have a variant offset.
  1726. MemoryElementSize = sizeof(int);
  1727. break;
  1728. #if defined(__RPC_WIN64__)
  1729. case FC_INT3264:
  1730. case FC_UINT3264:
  1731. pfnMarshall = 0;
  1732. MemoryElementSize = sizeof(__int64);
  1733. break;
  1734. #endif
  1735. case FC_RANGE:
  1736. // let's just memcpy in marshalling phase: don't need to check value here.
  1737. Count *= SIMPLE_TYPE_BUFSIZE( pFormat[1] );
  1738. pMemory += Offset * SIMPLE_TYPE_MEMSIZE( pFormat[1] );
  1739. RpcpMemoryCopy( pStubMsg->Buffer,
  1740. pMemory,
  1741. Count );
  1742. pStubMsg->Buffer += Count;
  1743. break;
  1744. default :
  1745. NDR_ASSERT( IS_SIMPLE_TYPE(*pFormat),
  1746. "NdrpComplexArrayMarshall : bad format char" );
  1747. Count *= SIMPLE_TYPE_BUFSIZE(*pFormat);
  1748. pMemory += Offset * SIMPLE_TYPE_MEMSIZE(*pFormat);
  1749. RpcpMemoryCopy( pStubMsg->Buffer,
  1750. pMemory,
  1751. Count );
  1752. pStubMsg->Buffer += Count;
  1753. goto ComplexArrayMarshallEnd;
  1754. }
  1755. //
  1756. // If there is variance then increment the memory pointer to the first
  1757. // element actually being marshalled.
  1758. //
  1759. if ( Offset )
  1760. pMemory += Offset * MemoryElementSize;
  1761. //
  1762. // Array of enum16 or int3264.
  1763. //
  1764. if ( ! pfnMarshall )
  1765. {
  1766. #if defined(__RPC_WIN64__)
  1767. if ( *pFormat != FC_ENUM16 )
  1768. {
  1769. for ( ; Count--; )
  1770. *((long * &)pStubMsg->Buffer)++ = (long)*((INT64 * &)pMemory)++;
  1771. }
  1772. else
  1773. #endif
  1774. {
  1775. for ( ; Count--; )
  1776. {
  1777. if ( *((int *)pMemory) & ~((int)0x7fff) )
  1778. RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
  1779. *((ushort *&)pStubMsg->Buffer)++ = (ushort) *((int *&)pMemory)++;
  1780. }
  1781. }
  1782. goto ComplexArrayMarshallEnd;
  1783. }
  1784. //
  1785. // For 32b, an array of ref or interface pointers.
  1786. // For 64b, an array of any pointers.
  1787. //
  1788. if ( pfnMarshall == (PMARSHALL_ROUTINE) NdrpPointerMarshall )
  1789. {
  1790. pStubMsg->pArrayInfo = 0;
  1791. uchar * pPointerId = (*pFormat == FC_RP) ? 0 : pStubMsg->Buffer;
  1792. if ( UseBrokenInterfacePointerRep )
  1793. {
  1794. // If were using the broken array format, do no increment the
  1795. // buffer pointer for the flat part, and throw everything
  1796. // where the pointee should go.
  1797. SET_BROKEN_INTERFACE_POINTER( pStubMsg->uFlags );
  1798. POINTER_BUFFER_SWAP_CONTEXT NewContext(pStubMsg);
  1799. for ( ; Count--; )
  1800. {
  1801. // This effectively calls NdrInterfacePointerMarshall. Doinging
  1802. // this so another queue structure/callback isn't needed just for
  1803. // this rare code.
  1804. NdrpPointerMarshall(
  1805. pStubMsg,
  1806. pPointerId,
  1807. *((uchar **&)pMemory)++,
  1808. pFormat );
  1809. pPointerId += PTR_WIRE_SIZE;
  1810. }
  1811. RESET_BROKEN_INTERFACE_POINTER( pStubMsg->uFlags );
  1812. }
  1813. else
  1814. {
  1815. {
  1816. POINTER_BUFFER_SWAP_CONTEXT NewContext(pStubMsg);
  1817. for ( ; Count--; )
  1818. {
  1819. NdrpPointerMarshall(
  1820. pStubMsg,
  1821. pPointerId,
  1822. *((uchar **&)pMemory)++,
  1823. pFormat );
  1824. //
  1825. // Needed only for non ref pointers, but pPointerIds is not used for refs.
  1826. //
  1827. pPointerId += PTR_WIRE_SIZE;
  1828. }
  1829. }
  1830. // Increment buffer pointer past the flat part of the array.
  1831. if ( *pFormat != FC_RP )
  1832. pStubMsg->Buffer = pPointerId;
  1833. }
  1834. goto ComplexArrayMarshallEnd;
  1835. }
  1836. //
  1837. // It's an array of complex types.
  1838. //
  1839. if ( ! IS_ARRAY_OR_STRING(*pFormat) )
  1840. pStubMsg->pArrayInfo = 0;
  1841. // Marshall the array elements.
  1842. for ( ; Count--; )
  1843. {
  1844. // Keep track of multidimensional array dimension.
  1845. if ( IS_ARRAY_OR_STRING(*pFormat) )
  1846. pArrayInfo->Dimension = Dimension + 1;
  1847. (*pfnMarshall)( pStubMsg,
  1848. pMemory,
  1849. pFormat );
  1850. // Increment the memory pointer by the element size.
  1851. pMemory += MemoryElementSize;
  1852. }
  1853. ComplexArrayMarshallEnd:
  1854. // pArrayInfo must be zero when not valid.
  1855. pStubMsg->pArrayInfo = (Dimension == 0) ? 0 : pArrayInfo;
  1856. }
  1857. unsigned char * RPC_ENTRY
  1858. NdrEncapsulatedUnionMarshall (
  1859. PMIDL_STUB_MESSAGE pStubMsg,
  1860. uchar * pMemory,
  1861. PFORMAT_STRING pFormat )
  1862. /*++
  1863. Routine Description :
  1864. Marshalls an encapsulated union.
  1865. Used for FC_ENCAPSULATED_UNION.
  1866. Arguments :
  1867. pStubMsg - Pointer to the stub message.
  1868. pMemory - Pointer to the union being marshalled.
  1869. pFormat - Union's format string description.
  1870. Return :
  1871. None.
  1872. --*/
  1873. {
  1874. long SwitchIs;
  1875. uchar SwitchType;
  1876. NO_CORRELATION;
  1877. SwitchType = LOW_NIBBLE(pFormat[1]);
  1878. switch ( SwitchType )
  1879. {
  1880. case FC_SMALL :
  1881. case FC_CHAR :
  1882. SwitchIs = (long) *((char *)pMemory);
  1883. break;
  1884. case FC_USMALL :
  1885. SwitchIs = (long) *((uchar *)pMemory);
  1886. break;
  1887. case FC_ENUM16 :
  1888. case FC_SHORT :
  1889. SwitchIs = (long) *((short *)pMemory);
  1890. break;
  1891. case FC_USHORT :
  1892. case FC_WCHAR :
  1893. SwitchIs = (long) *((ushort *)pMemory);
  1894. break;
  1895. case FC_LONG :
  1896. case FC_ULONG :
  1897. case FC_ENUM32 :
  1898. // FC_INT3264 gets mapped to FC_LONG
  1899. SwitchIs = *((long *)pMemory);
  1900. break;
  1901. default :
  1902. NDR_ASSERT(0,"NdrEncapsulatedUnionMarshall : bad swith type");
  1903. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  1904. return 0;
  1905. }
  1906. // Increment the memory pointer to the union.
  1907. pMemory += HIGH_NIBBLE(pFormat[1]);
  1908. NdrpUnionMarshall( pStubMsg,
  1909. pMemory,
  1910. pFormat + 2,
  1911. SwitchIs,
  1912. SwitchType );
  1913. return 0;
  1914. }
  1915. unsigned char * RPC_ENTRY
  1916. NdrNonEncapsulatedUnionMarshall (
  1917. PMIDL_STUB_MESSAGE pStubMsg,
  1918. uchar * pMemory,
  1919. PFORMAT_STRING pFormat )
  1920. /*++
  1921. Routine Description :
  1922. Marshalls a non encapsulated union.
  1923. Used for FC_NON_ENCAPSULATED_UNION.
  1924. Arguments :
  1925. pStubMsg - Pointer to the stub message.
  1926. pMemory - Pointer to the union being marshalled.
  1927. pFormat - Union's format string description.
  1928. Return :
  1929. None.
  1930. --*/
  1931. {
  1932. long SwitchIs;
  1933. uchar SwitchType;
  1934. SwitchType = pFormat[1];
  1935. SwitchIs = (ulong) NdrpComputeSwitchIs( pStubMsg,
  1936. pMemory,
  1937. pFormat );
  1938. //
  1939. // Set the format string to the memory size and arm description.
  1940. //
  1941. pFormat += 6;
  1942. CORRELATION_DESC_INCREMENT( pFormat );
  1943. pFormat += *((signed short *)pFormat);
  1944. NdrpUnionMarshall( pStubMsg,
  1945. pMemory,
  1946. pFormat,
  1947. SwitchIs,
  1948. SwitchType );
  1949. return 0;
  1950. }
  1951. void
  1952. NdrpUnionMarshall (
  1953. PMIDL_STUB_MESSAGE pStubMsg,
  1954. uchar * pMemory,
  1955. PFORMAT_STRING pFormat,
  1956. long SwitchIs,
  1957. uchar SwitchType )
  1958. /*++
  1959. Routine Description :
  1960. Private routine for marshalling a union. This routine is shared for
  1961. both encapsulated and non-encapsulated unions and handles the actual
  1962. marshalling of the proper union arm.
  1963. Arguments :
  1964. pStubMsg - Pointer to the stub message.
  1965. pMemory - Pointer to the union being marshalled.
  1966. pFormat - The memory size and arm description portion of the format
  1967. string for the union.
  1968. SwitchIs - Union's switch is.
  1969. SwitchType - Union's switch is type.
  1970. Return :
  1971. None.
  1972. --*/
  1973. {
  1974. long Arms;
  1975. uchar Alignment;
  1976. // Marshall the switch is value.
  1977. NdrSimpleTypeMarshall( pStubMsg,
  1978. (uchar *)&SwitchIs,
  1979. SwitchType );
  1980. // Skip the memory size field.
  1981. pFormat += 2;
  1982. //
  1983. // We're at the union_arms<2> field now, which contains both the
  1984. // Microsoft union aligment value and the number of union arms.
  1985. //
  1986. //
  1987. // Get the union alignment (0 if this is a DCE union).
  1988. //
  1989. Alignment = (uchar) ( *((ushort *)pFormat) >> 12 );
  1990. ALIGN(pStubMsg->Buffer,Alignment);
  1991. //
  1992. // Number of arms is the lower 12 bits.
  1993. //
  1994. Arms = (long) ( *((ushort *&)pFormat)++ & 0x0fff);
  1995. //
  1996. // Search for the correct arm.
  1997. //
  1998. for ( ; Arms; Arms-- )
  1999. {
  2000. if ( *((long UNALIGNED *&)pFormat)++ == SwitchIs )
  2001. {
  2002. //
  2003. // Found the right arm, break out.
  2004. //
  2005. break;
  2006. }
  2007. // Else increment format string.
  2008. pFormat += 2;
  2009. }
  2010. //
  2011. // Check if we took the default arm and no default arm is specified.
  2012. //
  2013. if ( ! Arms && (*((ushort *)pFormat) == (ushort) 0xffff) )
  2014. {
  2015. RpcRaiseException( RPC_S_INVALID_TAG );
  2016. }
  2017. //
  2018. // Return if the arm is empty.
  2019. //
  2020. if ( ! *((ushort *)pFormat) )
  2021. return;
  2022. //
  2023. // Get the arm's description.
  2024. //
  2025. // We need a real solution after beta for simple type arms. This could
  2026. // break if we have a format string larger than about 32K.
  2027. //
  2028. if ( IS_MAGIC_UNION_BYTE(pFormat) )
  2029. {
  2030. NdrSimpleTypeMarshall( pStubMsg,
  2031. pMemory,
  2032. pFormat[0] );
  2033. return;
  2034. }
  2035. pFormat += *((signed short *)pFormat);
  2036. //
  2037. // If the union arm we take is a pointer, we have to dereference the
  2038. // current memory pointer since we're passed a pointer to the union
  2039. // (regardless of whether the actual parameter was a by-value union
  2040. // or a pointer to a union).
  2041. //
  2042. // We also have to do a bunch of other special stuff to handle unions
  2043. // embedded inside of strutures.
  2044. //
  2045. if ( IS_POINTER_TYPE(*pFormat) )
  2046. {
  2047. pMemory = *((uchar **)pMemory);
  2048. //
  2049. // If we're embedded in a struct or array we have do some extra stuff.
  2050. //
  2051. if ( pStubMsg->PointerBufferMark )
  2052. {
  2053. ALIGN(pStubMsg->Buffer,3);
  2054. uchar *pPointerId = pStubMsg->Buffer;
  2055. pStubMsg->Buffer += PTR_WIRE_SIZE;
  2056. POINTER_BUFFER_SWAP_CONTEXT SwapContext( pStubMsg );
  2057. NdrpPointerMarshall( pStubMsg,
  2058. pPointerId,
  2059. pMemory,
  2060. pFormat );
  2061. return;
  2062. }
  2063. }
  2064. //
  2065. // Union arm of a non-simple type.
  2066. //
  2067. (*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])
  2068. ( pStubMsg,
  2069. pMemory,
  2070. pFormat );
  2071. }
  2072. unsigned char * RPC_ENTRY
  2073. NdrByteCountPointerMarshall (
  2074. PMIDL_STUB_MESSAGE pStubMsg,
  2075. uchar * pMemory,
  2076. PFORMAT_STRING pFormat )
  2077. /*++
  2078. Routine Description :
  2079. Marshalls a pointer with the byte count attribute applied to it.
  2080. Used for FC_BYTE_COUNT_POINTER.
  2081. Arguments :
  2082. pStubMsg - Pointer to the stub message.
  2083. pMemory - Pointer to the byte count pointer being marshalled.
  2084. pFormat - Byte count pointer's format string description.
  2085. Return :
  2086. None.
  2087. --*/
  2088. {
  2089. //
  2090. // We don't do anything special here. Just pass things on to the
  2091. // right marshalling routine.
  2092. //
  2093. if ( pFormat[1] != FC_PAD )
  2094. {
  2095. NdrSimpleTypeMarshall( pStubMsg,
  2096. pMemory,
  2097. pFormat[1] );
  2098. }
  2099. else
  2100. {
  2101. pFormat += 6;
  2102. CORRELATION_DESC_INCREMENT( pFormat );
  2103. pFormat += *((signed short *)pFormat);
  2104. (*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  2105. pMemory,
  2106. pFormat );
  2107. }
  2108. return 0;
  2109. }
  2110. unsigned char * RPC_ENTRY
  2111. NdrXmitOrRepAsMarshall (
  2112. PMIDL_STUB_MESSAGE pStubMsg,
  2113. uchar * pMemory,
  2114. PFORMAT_STRING pFormat )
  2115. /*++
  2116. Routine Description :
  2117. Marshalls a transmit as or represent as argument:
  2118. - translate the presented object into a transmitted object
  2119. - marshall the transmitted object
  2120. - free the transmitted object
  2121. Format string layout:
  2122. 0 FC_TRANSMIT_AS or FC_REPRESENT_AS
  2123. Oi array flag/alignment<1>
  2124. +2 quintuple index<2>
  2125. +4 pres type mem size<2>
  2126. +6 tran type buf size<2>
  2127. +8 offset<2>
  2128. Arguments :
  2129. pStubMsg - a pointer to the stub message
  2130. pMemory - presented type translated into transmitted type
  2131. and than to be marshalled
  2132. pFormat - format string description
  2133. --*/
  2134. {
  2135. unsigned char * pTransmittedType;
  2136. const XMIT_ROUTINE_QUINTUPLE * pQuintuple = pStubMsg->StubDesc->aXmitQuintuple;
  2137. unsigned short QIndex;
  2138. BOOL fXmitByPtr = *pFormat == FC_TRANSMIT_AS_PTR ||
  2139. *pFormat == FC_REPRESENT_AS_PTR;
  2140. // Skip the token itself and Oi flag. Fetch the QuintupleIndex.
  2141. QIndex = *(unsigned short *)(pFormat + 2);
  2142. // First translate the presented type into the transmitted type.
  2143. // This includes an allocation of a transmitted type object.
  2144. pStubMsg->pPresentedType = pMemory;
  2145. pStubMsg->pTransmitType = NULL;
  2146. pQuintuple[ QIndex ].pfnTranslateToXmit( pStubMsg );
  2147. // Marshall the transmitted type.
  2148. pFormat += 8;
  2149. pFormat = pFormat + *(short *) pFormat;
  2150. pTransmittedType = pStubMsg->pTransmitType;
  2151. if ( IS_SIMPLE_TYPE( *pFormat ))
  2152. {
  2153. NdrSimpleTypeMarshall( pStubMsg,
  2154. pTransmittedType,
  2155. *pFormat );
  2156. }
  2157. else
  2158. {
  2159. uchar *PointerBufferMarkSave = pStubMsg->PointerBufferMark;
  2160. pStubMsg->PointerBufferMark = 0;
  2161. NDR_POINTER_QUEUE *pOldQueue = NULL;
  2162. // Reset the current queue to NULL so that all the pointers
  2163. // in the transmitted type will be queued and marshalled togother.
  2164. if ( pStubMsg->pPointerQueueState )
  2165. {
  2166. pOldQueue = pStubMsg->pPointerQueueState->GetActiveQueue();
  2167. pStubMsg->pPointerQueueState->SetActiveQueue(NULL);
  2168. }
  2169. RpcTryFinally
  2170. {
  2171. (*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])
  2172. ( pStubMsg,
  2173. fXmitByPtr ? *(uchar **)pTransmittedType
  2174. : pTransmittedType,
  2175. pFormat );
  2176. }
  2177. RpcFinally
  2178. {
  2179. pStubMsg->PointerBufferMark = PointerBufferMarkSave;
  2180. if ( pStubMsg->pPointerQueueState )
  2181. {
  2182. pStubMsg->pPointerQueueState->SetActiveQueue( pOldQueue );
  2183. }
  2184. }
  2185. RpcEndFinally
  2186. }
  2187. pStubMsg->pTransmitType = pTransmittedType;
  2188. // Free the temporary transmitted object (it was allocated by the user).
  2189. pQuintuple[ QIndex ].pfnFreeXmit( pStubMsg );
  2190. return 0;
  2191. }
  2192. void
  2193. NdrpUserMarshalMarshall(
  2194. PMIDL_STUB_MESSAGE pStubMsg,
  2195. uchar * pMemory,
  2196. PFORMAT_STRING pFormat,
  2197. unsigned long * pWireMarkerPtr )
  2198. /*++
  2199. Routine Description :
  2200. Marshals a usr_marshall object.
  2201. The format string layout is as follows:
  2202. FC_USER_MARSHAL
  2203. flags & alignment<1>
  2204. quadruple index<2>
  2205. memory size<2>
  2206. wire size<2>
  2207. type offset<2>
  2208. The wire layout description is at the type offset.
  2209. Arguments :
  2210. pStubMsg - Pointer to the stub message.
  2211. pMemory - Pointer to the usr_marshall object to marshall.
  2212. pFormat - Object's format string description.
  2213. Return :
  2214. None.
  2215. --*/
  2216. {
  2217. const USER_MARSHAL_ROUTINE_QUADRUPLE * pQuadruple;
  2218. unsigned short QIndex;
  2219. unsigned char * pUserBuffer;
  2220. USER_MARSHAL_CB UserMarshalCB;
  2221. unsigned char * pUserBufferSaved;
  2222. pUserBufferSaved = pUserBuffer = pStubMsg->Buffer;
  2223. // We always call user's routine to marshall.
  2224. NdrpInitUserMarshalCB( pStubMsg,
  2225. pFormat,
  2226. USER_MARSHAL_CB_MARSHALL,
  2227. & UserMarshalCB );
  2228. QIndex = *(unsigned short *)(pFormat + 2);
  2229. pQuadruple = pStubMsg->StubDesc->aUserMarshalQuadruple;
  2230. if ((pUserBufferSaved < (uchar *) pStubMsg->RpcMsg->Buffer) ||
  2231. ((unsigned long) (pUserBufferSaved - (uchar *) pStubMsg->RpcMsg->Buffer)
  2232. > pStubMsg->RpcMsg->BufferLength))
  2233. {
  2234. RpcRaiseException( RPC_X_INVALID_BUFFER );
  2235. }
  2236. pUserBuffer = pQuadruple[ QIndex ].pfnMarshall( (ulong*) &UserMarshalCB,
  2237. pUserBuffer,
  2238. pMemory );
  2239. if ((pUserBufferSaved > pUserBuffer) ||
  2240. ((unsigned long) (pUserBuffer - (uchar *) pStubMsg->RpcMsg->Buffer)
  2241. > pStubMsg->RpcMsg->BufferLength ))
  2242. {
  2243. RpcRaiseException( RPC_X_INVALID_BUFFER );
  2244. }
  2245. if ( pUserBuffer == pUserBufferSaved )
  2246. {
  2247. // This is valid only if the wire type was a unique type.
  2248. if ( (pFormat[1] & USER_MARSHAL_UNIQUE) )
  2249. {
  2250. *pWireMarkerPtr = 0;
  2251. return;
  2252. }
  2253. else
  2254. RpcRaiseException( RPC_X_NULL_REF_POINTER );
  2255. }
  2256. pStubMsg->Buffer = pUserBuffer;
  2257. return;
  2258. }
  2259. void
  2260. NDR_USR_MRSHL_MRSHL_POINTER_QUEUE_ELEMENT::Dispatch(MIDL_STUB_MESSAGE *pStubMsg)
  2261. {
  2262. NdrpUserMarshalMarshall( pStubMsg,
  2263. pMemory,
  2264. pFormat,
  2265. pWireMarkerPtr );
  2266. }
  2267. #if defined(DBG)
  2268. void
  2269. NDR_USR_MRSHL_MRSHL_POINTER_QUEUE_ELEMENT::Print()
  2270. {
  2271. DbgPrint("NDR_USR_MRSHL_MRSHL_POINTER_QUEUE_ELEMENT\n");
  2272. DbgPrint("pMemory: %p\n", pMemory );
  2273. DbgPrint("pFormat: %p\n", pFormat );
  2274. DbgPrint("pWireMarkerPtr: %p\n", pWireMarkerPtr );
  2275. }
  2276. #endif
  2277. unsigned char * RPC_ENTRY
  2278. NdrUserMarshalMarshall(
  2279. PMIDL_STUB_MESSAGE pStubMsg,
  2280. uchar * pMemory,
  2281. PFORMAT_STRING pFormat )
  2282. {
  2283. unsigned long * pWireMarkerPtr = 0;
  2284. // Align for the object or a pointer to it.
  2285. ALIGN( pStubMsg->Buffer, LOW_NIBBLE(pFormat[1]) );
  2286. if ( pFormat[1] & USER_MARSHAL_POINTER )
  2287. {
  2288. if ( (pFormat[1] & USER_MARSHAL_UNIQUE) ||
  2289. ((pFormat[1] & USER_MARSHAL_REF) && pStubMsg->PointerBufferMark) )
  2290. {
  2291. pWireMarkerPtr = (unsigned long *) pStubMsg->Buffer;
  2292. *((unsigned long *&)pStubMsg->Buffer)++ = USER_MARSHAL_MARKER;
  2293. }
  2294. if ( !pStubMsg->pPointerQueueState ||
  2295. !pStubMsg->pPointerQueueState->GetActiveQueue() )
  2296. {
  2297. // If we are embedded, switch to the pointee buffer.
  2298. POINTER_BUFFER_SWAP_CONTEXT SwapContext(pStubMsg);
  2299. NdrpUserMarshalMarshall( pStubMsg,
  2300. pMemory,
  2301. pFormat,
  2302. pWireMarkerPtr );
  2303. }
  2304. else
  2305. {
  2306. NDR_USR_MRSHL_MRSHL_POINTER_QUEUE_ELEMENT*pElement =
  2307. new(pStubMsg->pPointerQueueState)
  2308. NDR_USR_MRSHL_MRSHL_POINTER_QUEUE_ELEMENT(pMemory,
  2309. pFormat,
  2310. pWireMarkerPtr);
  2311. pStubMsg->pPointerQueueState->GetActiveQueue()->Enque( pElement );
  2312. }
  2313. return 0;
  2314. }
  2315. NdrpUserMarshalMarshall( pStubMsg,
  2316. pMemory,
  2317. pFormat,
  2318. pWireMarkerPtr );
  2319. return 0;
  2320. }
  2321. unsigned char *
  2322. NdrpInterfacePointerMarshall (
  2323. PMIDL_STUB_MESSAGE pStubMsg,
  2324. uchar * pMemory,
  2325. PFORMAT_STRING pFormat )
  2326. /*++
  2327. Routine Description :
  2328. Marshalls an interface pointer.
  2329. Arguments :
  2330. pStubMsg - Pointer to the stub message.
  2331. pMemory - Pointer to the interface pointer being marshalled.
  2332. pFormat - Interface pointer's format string description.
  2333. Return :
  2334. None.
  2335. Notes : There is now one representation of a marshalled interface pointer.
  2336. The format string contains FC_IP followed by either
  2337. FC_CONSTANT_IID or FC_PAD.
  2338. typedef struct
  2339. {
  2340. unsigned long size;
  2341. [size_is(size)] byte data[];
  2342. }MarshalledInterface;
  2343. --*/
  2344. {
  2345. HRESULT hr;
  2346. IID iid;
  2347. IID * piid;
  2348. unsigned long * pSize;
  2349. unsigned long * pMaxCount;
  2350. unsigned long cbData = 0;
  2351. unsigned long cbMax;
  2352. unsigned long position;
  2353. IStream * pStream;
  2354. LARGE_INTEGER libMove;
  2355. ULARGE_INTEGER libPosition;
  2356. ALIGN(pStubMsg->Buffer,0x3);
  2357. //
  2358. // Get an IID pointer.
  2359. //
  2360. if ( pFormat[1] != FC_CONSTANT_IID )
  2361. {
  2362. //
  2363. // This is like computing a variance with a long.
  2364. //
  2365. piid = (IID *) NdrpComputeIIDPointer( pStubMsg,
  2366. pMemory,
  2367. pFormat );
  2368. if(piid == 0)
  2369. RpcRaiseException( RPC_S_INVALID_ARG );
  2370. }
  2371. else
  2372. {
  2373. //
  2374. // The IID may not be aligned properly in the format string,
  2375. // so we copy it to a local variable.
  2376. //
  2377. piid = &iid;
  2378. RpcpMemoryCopy( &iid, &pFormat[2], sizeof(iid) );
  2379. }
  2380. // Leave space in the buffer for the conformant size and the size field.
  2381. pMaxCount = (unsigned long *) pStubMsg->Buffer;
  2382. pStubMsg->Buffer += sizeof(unsigned long);
  2383. pSize = (unsigned long *) pStubMsg->Buffer;
  2384. pStubMsg->Buffer += sizeof(unsigned long);
  2385. if(pMemory)
  2386. {
  2387. //Calculate the maximum size of the stream.
  2388. position = (ulong)( pStubMsg->Buffer - (uchar *)pStubMsg->RpcMsg->Buffer);
  2389. cbMax = pStubMsg->RpcMsg->BufferLength - position;
  2390. #if defined(DEBUG_WALKIP)
  2391. {
  2392. CHAR AppName[MAX_PATH];
  2393. memset(AppName, 0, sizeof(AppName ) );
  2394. GetModuleFileNameA( NULL, AppName, sizeof(AppName ) );
  2395. DbgPrint("MRSHL32 %s %p\n", AppName, pStubMsg->Buffer );
  2396. }
  2397. #endif
  2398. //Create a stream on memory.
  2399. pStream = NdrpCreateStreamOnMemory(pStubMsg->Buffer, cbMax);
  2400. if(pStream == 0)
  2401. RpcRaiseException(RPC_S_OUT_OF_MEMORY);
  2402. hr = (*pfnCoMarshalInterface)(pStream, *piid, (IUnknown *)pMemory, pStubMsg->dwDestContext, pStubMsg->pvDestContext, 0);
  2403. if(FAILED(hr))
  2404. {
  2405. pStream->Release();
  2406. pStream = 0;
  2407. RpcRaiseException(hr);
  2408. }
  2409. //Calculate the size of the data written
  2410. libMove.LowPart = 0;
  2411. libMove.HighPart = 0;
  2412. pStream->Seek(libMove, STREAM_SEEK_CUR, &libPosition);
  2413. pStream->Release();
  2414. pStream = 0;
  2415. cbData = libPosition.LowPart;
  2416. }
  2417. //Update the array bounds.
  2418. *pMaxCount = cbData;
  2419. *pSize = cbData;
  2420. //Advance the stub message buffer pointer.
  2421. pStubMsg->Buffer += cbData;
  2422. return 0;
  2423. }
  2424. unsigned char * RPC_ENTRY
  2425. NdrInterfacePointerMarshall (
  2426. PMIDL_STUB_MESSAGE pStubMsg,
  2427. uchar * pMemory,
  2428. PFORMAT_STRING pFormat )
  2429. {
  2430. // Always put the pointer itself on wire, it behaves like a unique.
  2431. //
  2432. // This function is only called for toplevel interface pointers with Os mode,
  2433. // or when being backward compatible with the incorrect wire format.
  2434. // Oicf uses NdrPointerMarshall.
  2435. ALIGN(pStubMsg->Buffer,0x3);
  2436. *((ulong *&)pStubMsg->Buffer)++ = PTR_WIRE_REP(pMemory);
  2437. // If the pointer is null, it's done.
  2438. if ( pMemory == 0 )
  2439. return 0;
  2440. return
  2441. NdrpInterfacePointerMarshall(
  2442. pStubMsg,
  2443. pMemory,
  2444. pFormat );
  2445. }
  2446. //
  2447. // Context handle marshalling routines.
  2448. //
  2449. void RPC_ENTRY
  2450. NdrClientContextMarshall(
  2451. PMIDL_STUB_MESSAGE pStubMsg,
  2452. NDR_CCONTEXT ContextHandle,
  2453. int fCheck )
  2454. /*++
  2455. Routine Description :
  2456. Marshalls a context handle on the client side.
  2457. Arguments :
  2458. pStubMsg - Pointer to stub message.
  2459. ContextHandle - Context handle to marshall.
  2460. fCheck - TRUE if an exception check should be made on the handle,
  2461. FALSE otherwise.
  2462. Return :
  2463. None.
  2464. --*/
  2465. {
  2466. // Note, this is a routine called directly from -Os stubs.
  2467. // The routine called by interpreter is called NdrMarshallHandle
  2468. // and can be found in hndl.c
  2469. if ( fCheck && ! ContextHandle )
  2470. RpcRaiseException( RPC_X_SS_IN_NULL_CONTEXT );
  2471. ALIGN(pStubMsg->Buffer,3);
  2472. // This call will check for bogus handles now and will raise
  2473. // an exception when necessary.
  2474. NDRCContextMarshall( ContextHandle, pStubMsg->Buffer );
  2475. pStubMsg->Buffer += CONTEXT_HANDLE_WIRE_SIZE;
  2476. }
  2477. void RPC_ENTRY
  2478. NdrServerContextMarshall(
  2479. PMIDL_STUB_MESSAGE pStubMsg,
  2480. NDR_SCONTEXT ContextHandle,
  2481. NDR_RUNDOWN RundownRoutine )
  2482. /*++
  2483. Routine Description :
  2484. Marshalls a context handle on the server side.
  2485. Arguments :
  2486. pStubMsg - Pointer to stub message.
  2487. ContextHandle - Context handle to marshall.
  2488. RundownRoutine - The context rundown routine.
  2489. Return :
  2490. None.
  2491. --*/
  2492. {
  2493. // Note, this is a routine called directly from -Os stubs.
  2494. // The routine called by interpreter is called NdrMarshallHandle
  2495. // and can be found in hndl.c
  2496. ALIGN(pStubMsg->Buffer,3);
  2497. NDRSContextMarshall2(pStubMsg->RpcMsg->Handle,
  2498. ContextHandle,
  2499. pStubMsg->Buffer,
  2500. RundownRoutine,
  2501. RPC_CONTEXT_HANDLE_DEFAULT_GUARD,
  2502. RPC_CONTEXT_HANDLE_DEFAULT_FLAGS );
  2503. pStubMsg->Buffer += CONTEXT_HANDLE_WIRE_SIZE;
  2504. }
  2505. void RPC_ENTRY
  2506. NdrServerContextNewMarshall(
  2507. PMIDL_STUB_MESSAGE pStubMsg,
  2508. NDR_SCONTEXT ContextHandle,
  2509. NDR_RUNDOWN RundownRoutine,
  2510. PFORMAT_STRING pFormat )
  2511. /*
  2512. This is a non-optimized NDR engine entry for context handle marshaling.
  2513. In particular it is able to handle all the new NT5 context handle flavors.
  2514. The optimized routine follows below.
  2515. ContextHandle - note, this is not the user's handle but a
  2516. NDR_SCONTEXT pointer from the stub local stack.
  2517. User's handle is a field in that object.
  2518. Note that intepreter calls NdrMarshallHandle. However, we can't use it
  2519. as it assumes a helper array of saved context handles that we don't need.
  2520. */
  2521. {
  2522. void * pGuard = RPC_CONTEXT_HANDLE_DEFAULT_GUARD;
  2523. DWORD Flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
  2524. // NT5 beta2 features: strict context handle, serialize and noserialize.
  2525. if ( pFormat[1] & NDR_STRICT_CONTEXT_HANDLE )
  2526. {
  2527. pGuard = pStubMsg->StubDesc->RpcInterfaceInformation;
  2528. pGuard = & ((PRPC_SERVER_INTERFACE)pGuard)->InterfaceId;
  2529. }
  2530. if ( pFormat[1] & NDR_CONTEXT_HANDLE_NOSERIALIZE )
  2531. {
  2532. Flags = RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
  2533. }
  2534. else if ( pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE )
  2535. {
  2536. Flags = RPC_CONTEXT_HANDLE_SERIALIZE;
  2537. }
  2538. ALIGN( pStubMsg->Buffer, 0x3 );
  2539. NDRSContextMarshall2(
  2540. pStubMsg->RpcMsg->Handle,
  2541. ContextHandle,
  2542. pStubMsg->Buffer,
  2543. RundownRoutine,
  2544. pGuard,
  2545. Flags );
  2546. pStubMsg->Buffer += CONTEXT_HANDLE_WIRE_SIZE;
  2547. }
  2548. void
  2549. NdrpGetArraySizeLength (
  2550. PMIDL_STUB_MESSAGE pStubMsg,
  2551. uchar * pMemory,
  2552. PFORMAT_STRING pFormat,
  2553. long ElementSize,
  2554. long * pSize,
  2555. long * pLength,
  2556. long * pWireSize )
  2557. /*++
  2558. Routine Description :
  2559. Return the size and length of an array.
  2560. We need to have this routine rather than just calling BufferSize since
  2561. we need the actual length of the array, not the length plus whatever
  2562. goop the NDR format puts in from of it.
  2563. Arguments :
  2564. pStubMsg - Pointer to the stub message.
  2565. pMemory - Pointer to the local array.
  2566. pFormat - Pointer to the array to get the size of.
  2567. Return :
  2568. The size and length.
  2569. Notes:
  2570. --*/
  2571. {
  2572. switch ( *pFormat )
  2573. {
  2574. case FC_SMFARRAY:
  2575. *pWireSize = * (short *) ( pFormat + 2 );
  2576. *pSize = *pWireSize;
  2577. *pLength = *pSize;
  2578. return;
  2579. case FC_LGFARRAY:
  2580. *pWireSize = * (int *) ( pFormat + 2 );
  2581. *pSize = *pWireSize;
  2582. *pLength = *pSize;
  2583. return;
  2584. case FC_CARRAY:
  2585. *pSize = (long) NdrpComputeConformance( pStubMsg, pMemory, pFormat );
  2586. *pWireSize = *pLength * ElementSize;
  2587. *pLength = *pSize;
  2588. return;
  2589. case FC_LGVARRAY:
  2590. *pWireSize = * (long *) ( pFormat + 2 );
  2591. *pSize = * (short *) ( pFormat + 6 );
  2592. NdrpComputeVariance( pStubMsg, pMemory, pFormat );
  2593. *pLength = pStubMsg->ActualCount;
  2594. return;
  2595. case FC_SMVARRAY:
  2596. *pWireSize = * (short *) ( pFormat + 2 );
  2597. *pSize = * (short *) ( pFormat + 4 );
  2598. NdrpComputeVariance( pStubMsg, pMemory, pFormat );
  2599. *pLength = pStubMsg->ActualCount;
  2600. return;
  2601. case FC_CVARRAY:
  2602. *pSize = (long) NdrpComputeConformance( pStubMsg, pMemory, pFormat );
  2603. *pWireSize = *pSize * ElementSize;
  2604. NdrpComputeVariance( pStubMsg, pMemory, pFormat );
  2605. *pLength = pStubMsg->ActualCount;
  2606. return;
  2607. case FC_CSTRING:
  2608. *pSize = strlen( (char*)pMemory ) + 1;
  2609. *pWireSize = *pSize;
  2610. *pLength = *pSize;
  2611. return;
  2612. case FC_WSTRING:
  2613. *pSize = wcslen( (wchar_t *) pMemory ) + 1;
  2614. *pWireSize = *pSize * 2;
  2615. *pLength = *pSize;
  2616. return;
  2617. }
  2618. NDR_ASSERT( 0, "NdrpGetArraySizeLength: Unhandled type" );
  2619. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  2620. *pSize = 0;
  2621. *pWireSize = 0;
  2622. *pLength = 0;
  2623. }
  2624. #ifdef _CS_CHAR_
  2625. unsigned char * RPC_ENTRY
  2626. NdrCsTagMarshall (
  2627. PMIDL_STUB_MESSAGE pStubMsg,
  2628. uchar * pMemory,
  2629. PFORMAT_STRING pFormat )
  2630. /*++
  2631. Routine Description :
  2632. Marshalls a cs tag (i.e. a parameter marked with [cs_stag], [cs_drtag],
  2633. or [cs_rtag].
  2634. Arguments :
  2635. pStubMsg - Pointer to the stub message.
  2636. pMemory - Pointer to the value on the stack.
  2637. pFormat - Pointer to the FC_CS_TAG entry in the format string.
  2638. Return :
  2639. None.
  2640. --*/
  2641. {
  2642. ulong Codeset = NdrpGetSetCSTagMarshall(
  2643. pStubMsg,
  2644. pMemory,
  2645. (NDR_CS_TAG_FORMAT *) pFormat);
  2646. * (ulong *) pStubMsg->Buffer = Codeset;
  2647. pStubMsg->Buffer += sizeof( ulong );
  2648. return 0;
  2649. }
  2650. extern const byte NdrpArrayMarshallFlags[] =
  2651. {
  2652. MARSHALL_CONFORMANCE, // Conformant array
  2653. MARSHALL_CONFORMANCE | MARSHALL_VARIANCE, // Conformant varying
  2654. 0, // Small fixed
  2655. 0, // Large fixed
  2656. MARSHALL_VARIANCE, // Small varying
  2657. MARSHALL_VARIANCE, // Large varying
  2658. MARSHALL_BOGUS, // Bogus array
  2659. MARSHALL_CONFORMANCE | MARSHALL_VARIANCE, // Conformant C string
  2660. MARSHALL_CONFORMANCE | MARSHALL_VARIANCE, // Conformant byte string
  2661. MARSHALL_CONFORMANCE | MARSHALL_VARIANCE, // Conformant struct string
  2662. MARSHALL_CONFORMANCE | MARSHALL_VARIANCE, // Conformant Unicode string
  2663. MARSHALL_VARIANCE, // C string
  2664. MARSHALL_VARIANCE, // byte string
  2665. MARSHALL_VARIANCE, // struct string
  2666. MARSHALL_VARIANCE // Unicode string
  2667. };
  2668. void
  2669. NdrpUpdateArrayProlog(
  2670. PFORMAT_STRING pFormat,
  2671. uchar * BufferMark,
  2672. ulong WireSize,
  2673. ulong Offset,
  2674. ulong WireLength )
  2675. {
  2676. int flags;
  2677. NDR_ASSERT( *pFormat >= FC_CARRAY, "Invalid array descriptor" );
  2678. NDR_ASSERT( *pFormat <= FC_WSTRING, "Invalid array descriptor" );
  2679. // We don't support bogus arrays for now
  2680. NDR_ASSERT( *pFormat != FC_BOGUS_ARRAY, "Bogus arrays are not supported" );
  2681. flags = NdrpArrayMarshallFlags[ *pFormat - FC_CARRAY ];
  2682. if ( flags & MARSHALL_CONFORMANCE )
  2683. {
  2684. * (ulong *) BufferMark = WireSize;
  2685. BufferMark += 4;
  2686. }
  2687. if ( flags & MARSHALL_VARIANCE )
  2688. {
  2689. * (ulong *) BufferMark = Offset;
  2690. BufferMark += 4;
  2691. * (ulong *) BufferMark = WireLength;
  2692. }
  2693. }
  2694. unsigned char * RPC_ENTRY
  2695. NdrCsArrayMarshall (
  2696. PMIDL_STUB_MESSAGE pStubMsg,
  2697. uchar * pMemory,
  2698. PFORMAT_STRING pFormat )
  2699. /*++
  2700. Routine Description :
  2701. Marshalls a [cs_char] array.
  2702. Arguments :
  2703. pStubMsg - Pointer to the stub message.
  2704. pMemory - Pointer to the local array.
  2705. pFormat - Pointer to the FC_CSARRAY entry in the format string.
  2706. Return :
  2707. None.
  2708. Notes :
  2709. Arrays of [cs_char] are defined as arrays of bytes on the wire so
  2710. marshalling is pretty simple once you know which bytes to marshall and
  2711. how many of them. Since the existing array marshalling routines are not
  2712. very general (they don't take size/length parameters) and since the
  2713. overhead of a call to memcpy isn't very high we do the marshalling
  2714. ourselves.
  2715. --*/
  2716. {
  2717. ulong SendingCodeset;
  2718. ulong ReceivingCodeset;
  2719. ulong ArraySize;
  2720. ulong ArrayLength;
  2721. ulong WireSize;
  2722. ulong WireLength;
  2723. uchar *BufferMark;
  2724. error_status_t status;
  2725. NDR_CS_ARRAY_FORMAT *pCSFormat;
  2726. NDR_CS_SIZE_CONVERT_ROUTINES *CSRoutines;
  2727. CS_TYPE_NET_SIZE_ROUTINE NetSizeRoutine;
  2728. CS_TYPE_TO_NETCS_ROUTINE ToNetCSRoutine;
  2729. IDL_CS_CONVERT ConversionType;
  2730. pCSFormat = (NDR_CS_ARRAY_FORMAT *) pFormat;
  2731. // Get all the info out of the FC_CS_ARRAY structure and bump pFormat
  2732. // to point to the underlying data descriptor
  2733. NDR_ASSERT( NULL != pStubMsg->pCSInfo, "cs_char info is not set up");
  2734. if ( pStubMsg->IsClient )
  2735. SendingCodeset = pStubMsg->pCSInfo->WireCodeset;
  2736. else
  2737. SendingCodeset = pStubMsg->pCSInfo->DesiredReceivingCodeset;
  2738. CSRoutines = pStubMsg->StubDesc->CsRoutineTables->pSizeConvertRoutines;
  2739. NetSizeRoutine = CSRoutines[pCSFormat->CSRoutineIndex].pfnNetSize;
  2740. ToNetCSRoutine = CSRoutines[pCSFormat->CSRoutineIndex].pfnToNetCs;
  2741. pFormat += pCSFormat->DescriptionOffset;
  2742. // Get the size and length of the unconverted array.
  2743. NdrpGetArraySizeLength( pStubMsg,
  2744. pMemory,
  2745. pFormat,
  2746. pCSFormat->UserTypeSize,
  2747. (long*)&ArraySize,
  2748. (long*)&ArrayLength,
  2749. (long*)&WireSize );
  2750. // Figure out whether we need to convert the data
  2751. WireSize = ArraySize;
  2752. NetSizeRoutine(
  2753. pStubMsg->RpcMsg->Handle,
  2754. SendingCodeset,
  2755. ArraySize,
  2756. &ConversionType,
  2757. NdrpIsConformantArray( pFormat ) ? &WireSize : NULL,
  2758. &status);
  2759. if ( RPC_S_OK != status )
  2760. RpcRaiseException( status );
  2761. // Skip the buffer ahead to where the actual bits will go. We'll patch
  2762. // up the array prolog later.
  2763. ALIGN( pStubMsg->Buffer, 3 );
  2764. BufferMark = pStubMsg->Buffer;
  2765. pStubMsg->Buffer += NdrpArrayPrologLength( pFormat );
  2766. // If we need to convert do so, otherwise just memcpy
  2767. // WireLength = WireSize;
  2768. WireLength = ArrayLength * pCSFormat->UserTypeSize;
  2769. if ( IDL_CS_NO_CONVERT == ConversionType )
  2770. {
  2771. CopyMemory( pStubMsg->Buffer, pMemory, WireLength );
  2772. pStubMsg->Buffer += WireLength;
  2773. }
  2774. else
  2775. {
  2776. ToNetCSRoutine(
  2777. pStubMsg->RpcMsg->Handle,
  2778. SendingCodeset,
  2779. pMemory,
  2780. ArrayLength,
  2781. pStubMsg->Buffer,
  2782. // ! NdrpIsVaryingArray( pFormat ) ? NULL : &WireLength,
  2783. NdrpIsFixedArray( pFormat ) ? NULL : &WireLength,
  2784. &status);
  2785. if ( RPC_S_OK != status )
  2786. RpcRaiseException( status );
  2787. NDR_ASSERT(
  2788. WireLength <= WireSize,
  2789. "Buffer overflow during [cs_char] conversion");
  2790. pStubMsg->Buffer += WireLength;
  2791. /*
  2792. // For conformant or fixed arrays we must have WireSize bytes on the
  2793. // wire so pad it out if necessary
  2794. if ( ! NdrpIsVaryingArray( pFormat ) && WireLength < WireSize )
  2795. {
  2796. // REVIEW: Is zero'ing necessary?
  2797. ZeroMemory( pStubMsg->Buffer, WireSize - WireLength );
  2798. pStubMsg->Buffer += WireSize - WireLength;
  2799. }
  2800. */
  2801. if ( ! NdrpIsVaryingArray( pFormat ) )
  2802. WireSize = WireLength;
  2803. }
  2804. NdrpUpdateArrayProlog(
  2805. pFormat,
  2806. BufferMark,
  2807. WireSize,
  2808. pStubMsg->Offset,
  2809. WireLength );
  2810. return 0;
  2811. }
  2812. #endif // _CS_CHAR
  2813. void
  2814. RPC_ENTRY
  2815. NdrPartialIgnoreClientMarshall(
  2816. PMIDL_STUB_MESSAGE pStubMsg,
  2817. void * pMemory
  2818. )
  2819. {
  2820. ALIGN( pStubMsg->Buffer, 0x3 );
  2821. *(ulong *)pStubMsg->Buffer = pMemory ? 1 : 0;
  2822. pStubMsg->Buffer += PTR_WIRE_SIZE;
  2823. }