Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2959 lines
74 KiB

4 years ago
  1. /************************************************************************
  2. Copyright (c) 1993 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. //
  16. // Function table of marshalling routines.
  17. //
  18. const PMARSHALL_ROUTINE MarshallRoutinesTable[] =
  19. {
  20. NdrPointerMarshall,
  21. NdrPointerMarshall,
  22. NdrPointerMarshall,
  23. NdrPointerMarshall,
  24. NdrSimpleStructMarshall,
  25. NdrSimpleStructMarshall,
  26. NdrConformantStructMarshall,
  27. NdrConformantStructMarshall,
  28. NdrConformantVaryingStructMarshall,
  29. NdrComplexStructMarshall,
  30. NdrConformantArrayMarshall,
  31. NdrConformantVaryingArrayMarshall,
  32. NdrFixedArrayMarshall,
  33. NdrFixedArrayMarshall,
  34. NdrVaryingArrayMarshall,
  35. NdrVaryingArrayMarshall,
  36. NdrComplexArrayMarshall,
  37. NdrConformantStringMarshall,
  38. NdrConformantStringMarshall,
  39. NdrConformantStringMarshall,
  40. NdrConformantStringMarshall,
  41. NdrNonConformantStringMarshall,
  42. NdrNonConformantStringMarshall,
  43. NdrNonConformantStringMarshall,
  44. NdrNonConformantStringMarshall,
  45. NdrEncapsulatedUnionMarshall,
  46. NdrNonEncapsulatedUnionMarshall,
  47. NdrByteCountPointerMarshall,
  48. NdrXmitOrRepAsMarshall, // transmit as
  49. NdrXmitOrRepAsMarshall, // represent as
  50. NdrInterfacePointerMarshall,
  51. NdrMarshallHandle,
  52. // New Post NT 3.5 token serviced from here on.
  53. NdrHardStructMarshall,
  54. NdrXmitOrRepAsMarshall, // transmit as ptr
  55. NdrXmitOrRepAsMarshall, // represent as ptr
  56. NdrUserMarshalMarshall
  57. };
  58. const PMARSHALL_ROUTINE * pfnMarshallRoutines = &MarshallRoutinesTable[-FC_RP];
  59. #if defined( DOS ) && !defined( WIN )
  60. #pragma code_seg( "NDR20_3" )
  61. #endif
  62. void RPC_ENTRY
  63. NdrSimpleTypeMarshall(
  64. PMIDL_STUB_MESSAGE pStubMsg,
  65. uchar * pMemory,
  66. uchar FormatChar )
  67. /*++
  68. Routine Description :
  69. Marshalls a simple type.
  70. Arguments :
  71. pStubMsg - Pointer to the stub message.
  72. pMemory - Pointer to the data to be marshalled.
  73. FormatChar - Simple type format character.
  74. Return :
  75. None.
  76. --*/
  77. {
  78. switch ( FormatChar )
  79. {
  80. case FC_CHAR :
  81. case FC_BYTE :
  82. case FC_SMALL :
  83. case FC_USMALL :
  84. *(pStubMsg->Buffer)++ = *pMemory;
  85. break;
  86. case FC_ENUM16 :
  87. if ( *((int *)pMemory) & ~((int)0x7fff) )
  88. {
  89. RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
  90. }
  91. #if defined(__RPC_MAC__)
  92. pMemory += 2;
  93. #endif
  94. // fall through...
  95. case FC_WCHAR :
  96. case FC_SHORT :
  97. case FC_USHORT :
  98. ALIGN(pStubMsg->Buffer,1);
  99. *((ushort *)pStubMsg->Buffer)++ = *((ushort *)pMemory);
  100. break;
  101. case FC_LONG :
  102. case FC_ULONG :
  103. case FC_FLOAT :
  104. case FC_ENUM32 :
  105. case FC_ERROR_STATUS_T:
  106. ALIGN(pStubMsg->Buffer,3);
  107. *((ulong *)pStubMsg->Buffer)++ = *((ulong *)pMemory);
  108. break;
  109. case FC_HYPER :
  110. case FC_DOUBLE :
  111. ALIGN(pStubMsg->Buffer,7);
  112. //
  113. // Let's stay away from casts to double.
  114. //
  115. *((ulong *)pStubMsg->Buffer)++ = *((ulong *)pMemory);
  116. *((ulong *)pStubMsg->Buffer)++ = *((ulong *)(pMemory + 4));
  117. break;
  118. case FC_IGNORE:
  119. break;
  120. default :
  121. NDR_ASSERT(0,"NdrSimpleTypeMarshall : bad format char");
  122. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  123. return;
  124. }
  125. }
  126. unsigned char * RPC_ENTRY
  127. NdrPointerMarshall(
  128. PMIDL_STUB_MESSAGE pStubMsg,
  129. uchar * pMemory,
  130. PFORMAT_STRING pFormat )
  131. /*++
  132. Routine Description :
  133. Marshalls a top level pointer to anything. Pointers embedded in
  134. structures, arrays, or unions call NdrpPointerMarshall directly.
  135. Used for FC_RP, FC_UP, FC_FP, FC_OP.
  136. Arguments :
  137. pStubMsg - Pointer to the stub message.
  138. pMemory - Pointer to the data to be marshalled.
  139. pFormat - Pointer's format string description.
  140. Return :
  141. None.
  142. --*/
  143. {
  144. uchar * pBufferMark;
  145. //
  146. // If this is not a ref pointer then set buffer mark and increment the
  147. // stub message buffer pointer.
  148. //
  149. if ( *pFormat != FC_RP )
  150. {
  151. ALIGN( pStubMsg->Buffer, 3 );
  152. // This is where we marshall the node id.
  153. pBufferMark = pStubMsg->Buffer;
  154. pStubMsg->Buffer += 4;
  155. }
  156. else
  157. pBufferMark = 0;
  158. //
  159. // For ref pointers pBufferMark will not be used and can be left
  160. // unitialized.
  161. //
  162. NdrpPointerMarshall( pStubMsg,
  163. pBufferMark,
  164. pMemory,
  165. pFormat );
  166. return 0;
  167. }
  168. #if defined( DOS ) || defined( WIN )
  169. #pragma code_seg()
  170. #endif
  171. #if defined( DOS ) && !defined( WIN )
  172. #pragma code_seg( "NDR20_9" )
  173. #endif
  174. void
  175. NdrpPointerMarshall(
  176. PMIDL_STUB_MESSAGE pStubMsg,
  177. uchar * pBufferMark,
  178. uchar * pMemory,
  179. PFORMAT_STRING pFormat )
  180. /*++
  181. Routine Description :
  182. Private routine for marshalling a pointer to anything. This is the
  183. entry point for pointers embedded in structures, arrays, and unions.
  184. Used for FC_RP, FC_UP, FC_FP, FC_OP.
  185. Arguments :
  186. pStubMsg - Pointer to the stub message.
  187. pBufferMark - The location in the buffer where the pointer's node id is
  188. marshalled. Important for full pointers, unfortunately it's
  189. overkill for unique pointers.
  190. pMemory - Pointer to the data to be marshalled.
  191. pFormat - Pointer format string description.
  192. Return :
  193. None.
  194. --*/
  195. {
  196. //
  197. // Check the pointer type.
  198. //
  199. switch ( *pFormat )
  200. {
  201. case FC_RP :
  202. if ( ! pMemory )
  203. RpcRaiseException( RPC_X_NULL_REF_POINTER );
  204. break;
  205. case FC_UP :
  206. case FC_OP :
  207. // Put the pointer in the buffer.
  208. *((ulong *)pBufferMark)++ = (ulong) pMemory;
  209. if ( ! pMemory )
  210. return;
  211. break;
  212. case FC_FP :
  213. //
  214. // Marshall the pointer's ref id and see if we've already
  215. // marshalled the pointer's data.
  216. //
  217. if ( NdrFullPointerQueryPointer( pStubMsg->FullPtrXlatTables,
  218. pMemory,
  219. FULL_POINTER_MARSHALLED,
  220. (ulong *) pBufferMark ) )
  221. return;
  222. break;
  223. default :
  224. NDR_ASSERT(0,"NdrpPointerMarshall : bad pointer type");
  225. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  226. return;
  227. }
  228. //
  229. // Check for a pointer to a complex type.
  230. //
  231. if ( ! SIMPLE_POINTER(pFormat[1]) )
  232. {
  233. if ( POINTER_DEREF(pFormat[1]) )
  234. pMemory = *((uchar **)pMemory);
  235. // Increment to offset_to_complex_description<2> field.
  236. pFormat += 2;
  237. //
  238. // Set format string to complex type description.
  239. // Cast must be to a signed short since some offsets are negative.
  240. //
  241. pFormat += *((signed short *)pFormat);
  242. //
  243. // Look up the proper marshalling routine in the marshalling function
  244. // table.
  245. //
  246. (*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  247. pMemory,
  248. pFormat );
  249. return;
  250. }
  251. //
  252. // Else it's a pointer to a simple type or a string pointer.
  253. //
  254. switch ( pFormat[2] )
  255. {
  256. case FC_C_CSTRING :
  257. case FC_C_BSTRING :
  258. case FC_C_WSTRING :
  259. case FC_C_SSTRING :
  260. NdrConformantStringMarshall( pStubMsg,
  261. pMemory,
  262. pFormat + 2 );
  263. break;
  264. default :
  265. NdrSimpleTypeMarshall( pStubMsg,
  266. pMemory,
  267. pFormat[2] );
  268. break;
  269. }
  270. }
  271. #if defined( DOS ) && !defined( WIN )
  272. #pragma code_seg()
  273. #endif
  274. unsigned char * RPC_ENTRY
  275. NdrSimpleStructMarshall(
  276. PMIDL_STUB_MESSAGE pStubMsg,
  277. uchar * pMemory,
  278. PFORMAT_STRING pFormat )
  279. /*++
  280. Routine description :
  281. Marshalls a simple structure.
  282. Used for FC_STRUCT and FC_PSTRUCT.
  283. Arguments :
  284. pStubMsg - Pointer to the stub message.
  285. pMemory - Pointer to the structure to be marshalled.
  286. pFormat - Structure's format string description.
  287. Return :
  288. None.
  289. --*/
  290. {
  291. uint StructSize;
  292. ALIGN(pStubMsg->Buffer,pFormat[1]);
  293. StructSize = (uint) *((ushort *)(pFormat + 2));
  294. RpcpMemoryCopy( pStubMsg->Buffer,
  295. pMemory,
  296. StructSize );
  297. // Mark the start of the structure in the buffer.
  298. pStubMsg->BufferMark = pStubMsg->Buffer;
  299. pStubMsg->Buffer += StructSize;
  300. // Marshall embedded pointers.
  301. if ( *pFormat == FC_PSTRUCT )
  302. {
  303. NdrpEmbeddedPointerMarshall( pStubMsg,
  304. pMemory,
  305. pFormat + 4 );
  306. }
  307. return 0;
  308. }
  309. unsigned char * RPC_ENTRY
  310. NdrConformantStructMarshall(
  311. PMIDL_STUB_MESSAGE pStubMsg,
  312. uchar * pMemory,
  313. PFORMAT_STRING pFormat )
  314. /*++
  315. Routine description :
  316. Marshalls a conformant structure.
  317. Used for FC_CSTRUCT and FC_CPSTRUCT.
  318. Arguments :
  319. pStubMsg - Pointer to the stub message.
  320. pMemory - Pointer to the structure to be marshalled.
  321. pFormat - Structure's format string description.
  322. Return :
  323. None.
  324. --*/
  325. {
  326. PFORMAT_STRING pFormatArray;
  327. uint StructSize;
  328. uchar Alignment;
  329. // Align the buffer for conformance count marshalling.
  330. ALIGN(pStubMsg->Buffer,3);
  331. // Save structure's alignment.
  332. Alignment = pFormat[1];
  333. // Increment format string to struct size field.
  334. pFormat += 2;
  335. // Get flat struct size and increment format string.
  336. StructSize = (uint) *((ushort *)pFormat)++;
  337. // Set conformant array format string description.
  338. pFormatArray = pFormat + *((signed short *)pFormat);
  339. //
  340. // Compute conformance information. Pass a memory pointer to the
  341. // end of the non-conformant part of the structure.
  342. //
  343. NdrpComputeConformance( pStubMsg,
  344. pMemory + StructSize,
  345. pFormatArray );
  346. // Marshall conformance count.
  347. *((ulong *)pStubMsg->Buffer)++ = pStubMsg->MaxCount;
  348. // Re-align buffer only if struct is aligned on an 8 byte boundary.
  349. if ( Alignment == 7 )
  350. ALIGN(pStubMsg->Buffer,7);
  351. // Increment array format string to array element size field.
  352. pFormatArray += 2;
  353. // Add the size of the conformant array to the structure size.
  354. StructSize += pStubMsg->MaxCount * *((ushort *)pFormatArray);
  355. RpcpMemoryCopy( pStubMsg->Buffer,
  356. pMemory,
  357. StructSize );
  358. // Update the buffer pointer.
  359. pStubMsg->Buffer += StructSize;
  360. // Increment format string past offset to array description field.
  361. pFormat += 2;
  362. // Marshall embedded pointers.
  363. if ( *pFormat == FC_PP )
  364. {
  365. // Mark the start of the structure in the buffer.
  366. pStubMsg->BufferMark = pStubMsg->Buffer - StructSize;
  367. NdrpEmbeddedPointerMarshall( pStubMsg,
  368. pMemory,
  369. pFormat );
  370. }
  371. return 0;
  372. }
  373. #if defined( DOS ) || defined( WIN )
  374. #pragma code_seg( "NDR20_9" )
  375. #endif
  376. unsigned char * RPC_ENTRY
  377. NdrConformantVaryingStructMarshall(
  378. PMIDL_STUB_MESSAGE pStubMsg,
  379. uchar * pMemory,
  380. PFORMAT_STRING pFormat )
  381. /*++
  382. Routine description :
  383. Marshalls a structure which contains a conformant varying array.
  384. Used for FC_CVSTRUCT.
  385. Arguments :
  386. pStubMsg - Pointer to the stub message.
  387. pMemory - Pointer to the structure to be marshalled.
  388. pFormat - Structure's format string description.
  389. Return :
  390. None.
  391. --*/
  392. {
  393. PFORMAT_STRING pFormatArray;
  394. uint StructSize;
  395. uchar Alignment;
  396. // Align the buffer for marshalling conformance info.
  397. ALIGN(pStubMsg->Buffer,3);
  398. // Mark the location in the buffer where the conformance will be marshalled.
  399. pStubMsg->BufferMark = pStubMsg->Buffer;
  400. // Save the structure's alignment.
  401. Alignment = pFormat[1];
  402. // Increment format string to struct size field.
  403. pFormat += 2;
  404. // Get non-conformance struct size and increment format string.
  405. StructSize = (uint) *((ushort *)pFormat)++;
  406. // Get conformant array's description.
  407. pFormatArray = pFormat + *((signed short *)pFormat);
  408. // Increment buffer pointer past where conformance will be marshalled.
  409. pStubMsg->Buffer += 4;
  410. // Align buffer if needed on 8 byte boundary.
  411. if ( Alignment == 7 )
  412. ALIGN(pStubMsg->Buffer,7);
  413. RpcpMemoryCopy( pStubMsg->Buffer,
  414. pMemory,
  415. StructSize );
  416. // Set stub message buffer pointer past non-conformant part of struct.
  417. pStubMsg->Buffer += StructSize;
  418. //
  419. // Call the correct private array or string marshalling routine.
  420. // We must pass a memory pointer to the beginning of the array/string.
  421. //
  422. if ( *pFormatArray == FC_CVARRAY )
  423. {
  424. NdrpConformantVaryingArrayMarshall( pStubMsg,
  425. pMemory + StructSize,
  426. pFormatArray );
  427. }
  428. else
  429. {
  430. NdrpConformantStringMarshall( pStubMsg,
  431. pMemory + StructSize,
  432. pFormatArray );
  433. }
  434. // Increment format string past the offset_to_array_description<2> field.
  435. pFormat += 2;
  436. //
  437. // Marshall embedded pointers.
  438. //
  439. if ( *pFormat == FC_PP )
  440. {
  441. // Mark the start of the structure in the buffer.
  442. pStubMsg->BufferMark = pStubMsg->Buffer - StructSize;
  443. NdrpEmbeddedPointerMarshall( pStubMsg,
  444. pMemory,
  445. pFormat );
  446. }
  447. return 0;
  448. }
  449. unsigned char * RPC_ENTRY
  450. NdrHardStructMarshall(
  451. PMIDL_STUB_MESSAGE pStubMsg,
  452. uchar * pMemory,
  453. PFORMAT_STRING pFormat )
  454. /*++
  455. Routine description :
  456. Marshalls a hard structure.
  457. Used for FC_HARD_STRUCT.
  458. Arguments :
  459. pStubMsg - Pointer to the stub message.
  460. pMemory - Pointer to the structure being marshalled.
  461. pFormat - Structure's format string description.
  462. Return :
  463. None.
  464. --*/
  465. {
  466. ALIGN(pStubMsg->Buffer,pFormat[1]);
  467. pFormat += 8;
  468. //
  469. // Do any needed enum16 exception check.
  470. //
  471. if ( *((short *)pFormat) != (short) -1 )
  472. {
  473. if ( *((int *)(pMemory + *((ushort *)pFormat))) & ~((int)0x7fff) )
  474. {
  475. RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
  476. }
  477. }
  478. pFormat += 2;
  479. RpcpMemoryCopy( pStubMsg->Buffer,
  480. pMemory,
  481. *((ushort *)pFormat) );
  482. pStubMsg->Buffer += *((ushort *)pFormat)++;
  483. //
  484. // See if we have a union.
  485. //
  486. if ( *((short *)&pFormat[2]) )
  487. {
  488. pMemory += *((ushort *)pFormat)++;
  489. pFormat += *((short *)pFormat);
  490. (*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  491. pMemory,
  492. pFormat );
  493. }
  494. return 0;
  495. }
  496. unsigned char * RPC_ENTRY
  497. NdrComplexStructMarshall(
  498. PMIDL_STUB_MESSAGE pStubMsg,
  499. uchar * pMemory,
  500. PFORMAT_STRING pFormat )
  501. /*++
  502. Routine description :
  503. Marshalls a complex structure.
  504. Used for FC_BOGUS_STRUCT.
  505. Arguments :
  506. pStubMsg - Pointer to the stub message.
  507. pMemory - Pointer to the structure being marshalled.
  508. pFormat - Structure's format string description.
  509. Return :
  510. None.
  511. --*/
  512. {
  513. uchar * pBufferSave;
  514. uchar * pBufferMark;
  515. uchar * pMemorySave;
  516. PFORMAT_STRING pFormatPointers;
  517. PFORMAT_STRING pFormatArray;
  518. PFORMAT_STRING pFormatSave;
  519. PFORMAT_STRING pFormatComplex;
  520. long Alignment;
  521. long Align8Mod;
  522. uchar fSetPointerBufferMark;
  523. #if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
  524. long Align4Mod;
  525. #endif
  526. // Get struct's wire alignment.
  527. Alignment = pFormat[1];
  528. //
  529. // This is used for support of structs with doubles passed on an
  530. // i386 stack.
  531. //
  532. Align8Mod = (long) pMemory % 8;
  533. #if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
  534. Align4Mod = (long) pMemory % 4;
  535. #endif
  536. pFormatSave = pFormat;
  537. pBufferSave = pStubMsg->Buffer;
  538. pMemorySave = pStubMsg->Memory;
  539. pStubMsg->Memory = pMemory;
  540. // Increment to conformant array offset field.
  541. pFormat += 4;
  542. // Get conformant array description.
  543. if ( *((ushort *)pFormat) )
  544. {
  545. pFormatArray = pFormat + *((signed short *)pFormat);
  546. // Align for conformance marshalling.
  547. ALIGN(pStubMsg->Buffer,3);
  548. // Remember where the conformance count(s) will be marshalled.
  549. pBufferMark = pStubMsg->Buffer;
  550. // Increment the buffer pointer 4 bytes for every array dimension.
  551. pStubMsg->Buffer += NdrpArrayDimensions( pFormatArray, FALSE ) * 4;
  552. }
  553. else
  554. {
  555. pFormatArray = 0;
  556. pBufferMark = 0;
  557. }
  558. pFormat += 2;
  559. // Get pointer layout description.
  560. if ( *((ushort *)pFormat) )
  561. pFormatPointers = pFormat + *((ushort *)pFormat);
  562. else
  563. pFormatPointers = 0;
  564. pFormat += 2;
  565. // Align buffer on struct's alignment.
  566. ALIGN(pStubMsg->Buffer,Alignment);
  567. //
  568. // If the the stub message PointerBufferMark field is 0, then determine
  569. // the position in the buffer where pointees will be marshalled.
  570. //
  571. // We have to do this to handle embedded pointers.
  572. //
  573. if ( fSetPointerBufferMark = ! pStubMsg->PointerBufferMark )
  574. {
  575. BOOL fOldIgnore;
  576. fOldIgnore = pStubMsg->IgnoreEmbeddedPointers;
  577. pStubMsg->IgnoreEmbeddedPointers = TRUE;
  578. //
  579. // Set BufferLength equal to the current buffer pointer, and then
  580. // when we return from NdrComplexStructBufferSize it will pointer to
  581. // the location in the buffer where the pointees should be marshalled.
  582. //
  583. pStubMsg->BufferLength = (ulong) pBufferSave;
  584. NdrComplexStructBufferSize( pStubMsg,
  585. pMemory,
  586. pFormatSave );
  587. // Set the location in the buffer where pointees will be marshalled.
  588. pStubMsg->PointerBufferMark = (uchar *) pStubMsg->BufferLength;
  589. pStubMsg->IgnoreEmbeddedPointers = fOldIgnore;
  590. }
  591. //
  592. // Marshall the structure member by member.
  593. //
  594. for ( ; ; pFormat++ )
  595. {
  596. switch ( *pFormat )
  597. {
  598. //
  599. // Simple types.
  600. //
  601. case FC_CHAR :
  602. case FC_BYTE :
  603. case FC_SMALL :
  604. case FC_WCHAR :
  605. case FC_SHORT :
  606. case FC_LONG :
  607. case FC_FLOAT :
  608. case FC_HYPER :
  609. case FC_DOUBLE :
  610. case FC_ENUM16 :
  611. case FC_ENUM32 :
  612. NdrSimpleTypeMarshall( pStubMsg,
  613. pMemory,
  614. *pFormat );
  615. pMemory += SIMPLE_TYPE_MEMSIZE(*pFormat);
  616. break;
  617. case FC_IGNORE :
  618. ALIGN(pStubMsg->Buffer,3);
  619. pStubMsg->Buffer += 4;
  620. break;
  621. case FC_POINTER :
  622. {
  623. uchar * pBuffer;
  624. ALIGN( pStubMsg->Buffer, 0x3 );
  625. // Save current buffer pointer.
  626. pBuffer = pStubMsg->Buffer;
  627. //
  628. // Set the buffer pointer to where the pointees are being
  629. // marshalled in the buffer.
  630. //
  631. pStubMsg->Buffer = pStubMsg->PointerBufferMark;
  632. pStubMsg->PointerBufferMark = 0;
  633. NdrpPointerMarshall( pStubMsg,
  634. pBuffer,
  635. *((uchar **)pMemory),
  636. pFormatPointers );
  637. // Update.
  638. pStubMsg->PointerBufferMark = pStubMsg->Buffer;
  639. //
  640. // Increment buffer and memory pointers past the pointer.
  641. //
  642. pStubMsg->Buffer = pBuffer + 4;
  643. pMemory += PTR_MEM_SIZE;
  644. pFormatPointers += 4;
  645. break;
  646. }
  647. //
  648. // Embedded complex types.
  649. //
  650. case FC_EMBEDDED_COMPLEX :
  651. // Increment memory pointer by padding.
  652. pMemory += pFormat[1];
  653. pFormat += 2;
  654. // Get the type's description.
  655. pFormatComplex = pFormat + *((signed short UNALIGNED *)pFormat);
  656. // Marshall complex type.
  657. (*pfnMarshallRoutines[ROUTINE_INDEX(*pFormatComplex)])
  658. ( pStubMsg,
  659. (*pFormatComplex == FC_IP) ? *(uchar **)pMemory : pMemory,
  660. pFormatComplex );
  661. //
  662. // Increment the memory pointer.
  663. //
  664. pMemory = NdrpMemoryIncrement( pStubMsg,
  665. pMemory,
  666. pFormatComplex );
  667. //
  668. // Increment the main format string one byte. The loop
  669. // will increment it one more byte past the offset field.
  670. //
  671. pFormat++;
  672. break;
  673. case FC_ALIGNM2 :
  674. ALIGN( pMemory, 0x1 );
  675. break;
  676. case FC_ALIGNM4 :
  677. #if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
  678. //
  679. // We have to play some tricks for the dos and win16
  680. // to handle the case when an 4 byte aligned structure
  681. // is passed by value. The alignment of the struct on
  682. // the stack is not guaranteed to be on an 4 byte boundary.
  683. //
  684. pMemory -= Align4Mod;
  685. ALIGN( pMemory, 0x3 );
  686. pMemory += Align4Mod;
  687. #else
  688. ALIGN( pMemory, 0x3 );
  689. #endif
  690. break;
  691. case FC_ALIGNM8 :
  692. //
  693. // We have to play some tricks for the i386 to handle the case
  694. // when an 8 byte aligned structure is passed by value. The
  695. // alignment of the struct on the stack is not guaranteed to be
  696. // on an 8 byte boundary.
  697. //
  698. pMemory -= Align8Mod;
  699. ALIGN( pMemory, 0x7 );
  700. pMemory += Align8Mod;
  701. break;
  702. case FC_STRUCTPAD1 :
  703. case FC_STRUCTPAD2 :
  704. case FC_STRUCTPAD3 :
  705. case FC_STRUCTPAD4 :
  706. case FC_STRUCTPAD5 :
  707. case FC_STRUCTPAD6 :
  708. case FC_STRUCTPAD7 :
  709. //
  710. // Increment memory pointer by amount of padding.
  711. //
  712. pMemory += (*pFormat - FC_STRUCTPAD1) + 1;
  713. break;
  714. case FC_PAD :
  715. break;
  716. //
  717. // Done with layout.
  718. //
  719. case FC_END :
  720. goto ComplexMarshallEnd;
  721. default :
  722. NDR_ASSERT(0,"NdrComplexStructMarshall : bad format char");
  723. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  724. return 0;
  725. } // switch
  726. } // for
  727. ComplexMarshallEnd:
  728. //
  729. // Marshall conformant array if we have one.
  730. //
  731. if ( pFormatArray )
  732. {
  733. PPRIVATE_MARSHALL_ROUTINE pfnPMarshall;
  734. switch ( *pFormatArray )
  735. {
  736. case FC_CARRAY :
  737. pfnPMarshall = NdrpConformantArrayMarshall;
  738. break;
  739. case FC_CVARRAY :
  740. pfnPMarshall = NdrpConformantVaryingArrayMarshall;
  741. break;
  742. case FC_BOGUS_ARRAY :
  743. pfnPMarshall = NdrpComplexArrayMarshall;
  744. break;
  745. case FC_C_WSTRING :
  746. ALIGN(pMemory,1);
  747. // fall through
  748. // case FC_C_CSTRING :
  749. // case FC_C_BSTRING :
  750. // case FC_C_SSTRING :
  751. default :
  752. pfnPMarshall = NdrpConformantStringMarshall;
  753. goto MarshallConfArray;
  754. }
  755. MarshallConfArray:
  756. //
  757. // Mark where the conformance count(s) will be marshalled.
  758. //
  759. pStubMsg->BufferMark = pBufferMark;
  760. // Marshall the array.
  761. (*pfnPMarshall)( pStubMsg,
  762. pMemory,
  763. pFormatArray );
  764. }
  765. //
  766. // Now fix up the stub message Buffer field if we set the PointerBufferMark
  767. // field.
  768. //
  769. if ( fSetPointerBufferMark )
  770. {
  771. pStubMsg->Buffer = pStubMsg->PointerBufferMark;
  772. pStubMsg->PointerBufferMark = 0;
  773. }
  774. pStubMsg->Memory = pMemorySave;
  775. return 0;
  776. }
  777. unsigned char * RPC_ENTRY
  778. NdrNonConformantStringMarshall(
  779. PMIDL_STUB_MESSAGE pStubMsg,
  780. uchar * pMemory,
  781. PFORMAT_STRING pFormat )
  782. /*++
  783. Routine description :
  784. Marshalls a non conformant string.
  785. Used for FC_CSTRING, FC_WSTRING, FC_SSTRING, and FC_BSTRING (NT Beta2
  786. compatability only).
  787. Arguments :
  788. pStubMsg - Pointer to the stub message.
  789. pMemory - Pointer to the string to be marshalled.
  790. pFormat - String's format string description.
  791. Return :
  792. None.
  793. --*/
  794. {
  795. uint Count;
  796. uint CopySize;
  797. // Align the buffer for offset and count marshalling.
  798. ALIGN(pStubMsg->Buffer,3);
  799. switch ( *pFormat )
  800. {
  801. case FC_CSTRING :
  802. case FC_BSTRING :
  803. CopySize = Count = MIDL_ascii_strlen((char *)pMemory) + 1;
  804. break;
  805. case FC_WSTRING :
  806. Count = MIDL_wchar_strlen((wchar_t *)pMemory) + 1;
  807. CopySize = Count * 2;
  808. break;
  809. case FC_SSTRING :
  810. Count = NdrpStringStructLen( pMemory, pFormat[1] ) + 1;
  811. CopySize = Count * pFormat[1];
  812. break;
  813. default :
  814. NDR_ASSERT(0,"NdrNonConformantStringMarshall : bad format char");
  815. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  816. return 0;
  817. }
  818. // Marshall variance.
  819. *((ulong *)pStubMsg->Buffer)++ = 0;
  820. *((ulong *)pStubMsg->Buffer)++ = Count;
  821. // Copy the string.
  822. RpcpMemoryCopy( pStubMsg->Buffer,
  823. pMemory,
  824. CopySize );
  825. // Update buffer pointer.
  826. pStubMsg->Buffer += CopySize;
  827. return 0;
  828. }
  829. unsigned char * RPC_ENTRY
  830. NdrConformantStringMarshall(
  831. PMIDL_STUB_MESSAGE pStubMsg,
  832. uchar * pMemory,
  833. PFORMAT_STRING pFormat )
  834. /*++
  835. Routine description :
  836. Marshalls a top level conformant string.
  837. Used for FC_C_CSTRING, FC_C_WSTRING, FC_C_SSTRING, and FC_C_BSTRING
  838. (NT Beta2 compatability only).
  839. Arguments :
  840. pStubMsg - Pointer to the stub message.
  841. pMemory - Pointer to the string to be marshalled.
  842. pFormat - String's format string description.
  843. Return :
  844. None.
  845. --*/
  846. {
  847. if ( pStubMsg->pArrayInfo != 0 )
  848. {
  849. //
  850. // If this is part of a multidimensional array then we get the location
  851. // where the conformance is marshalled from a special place.
  852. //
  853. pStubMsg->BufferMark = ( uchar * )
  854. &(pStubMsg->pArrayInfo->
  855. BufferConformanceMark[pStubMsg->pArrayInfo->Dimension]);
  856. }
  857. else
  858. {
  859. // Align the buffer for max count marshalling.
  860. ALIGN(pStubMsg->Buffer,3);
  861. // Mark where the max count will be marshalled.
  862. pStubMsg->BufferMark = pStubMsg->Buffer;
  863. // Increment the buffer past where the max count will be marshalled.
  864. pStubMsg->Buffer += 4;
  865. }
  866. // Call the private marshalling routine.
  867. NdrpConformantStringMarshall( pStubMsg,
  868. pMemory,
  869. pFormat );
  870. return 0;
  871. }
  872. #if defined( DOS ) || defined( WIN )
  873. #pragma code_seg()
  874. #endif
  875. #if defined( DOS ) && !defined( WIN )
  876. #pragma code_seg( "NDR20_9" )
  877. #endif
  878. void
  879. NdrpConformantStringMarshall(
  880. PMIDL_STUB_MESSAGE pStubMsg,
  881. uchar * pMemory,
  882. PFORMAT_STRING pFormat )
  883. /*++
  884. Routine description :
  885. Private routine for marshalling a conformant string. This is the
  886. entry point for marshalling an embedded conformant strings.
  887. Used for FC_C_CSTRING, FC_C_WSTRING, FC_C_SSTRING, and FC_C_BSTRING
  888. (NT Beta2 compatability only).
  889. Arguments :
  890. pStubMsg - Pointer to the stub message.
  891. pMemory - Pointer to the string to be marshalled.
  892. pFormat - String's format string description.
  893. Return :
  894. None.
  895. --*/
  896. {
  897. ulong MaxCount;
  898. uint ActualCount, CopySize;
  899. BOOL IsSized;
  900. IsSized = (pFormat[1] == FC_STRING_SIZED);
  901. // Compute the element count of the string and the total copy size.
  902. switch ( *pFormat )
  903. {
  904. case FC_C_CSTRING :
  905. case FC_C_BSTRING :
  906. CopySize = ActualCount = MIDL_ascii_strlen((char *)pMemory) + 1;
  907. break;
  908. case FC_C_WSTRING :
  909. ActualCount = MIDL_wchar_strlen((wchar_t *)pMemory) + 1;
  910. CopySize = ActualCount * 2;
  911. break;
  912. case FC_C_SSTRING :
  913. ActualCount = NdrpStringStructLen( pMemory, pFormat[1] ) + 1;
  914. CopySize = ActualCount * pFormat[1];
  915. // Redo this check correctly.
  916. IsSized = (pFormat[2] == FC_STRING_SIZED);
  917. break;
  918. default :
  919. NDR_ASSERT(0,"NdrpConformantStringMarshall : bad format char");
  920. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  921. return;
  922. }
  923. //
  924. // If the string is sized then compute the max count, otherwise the
  925. // max count is equal to the actual count.
  926. //
  927. if ( IsSized )
  928. {
  929. MaxCount = NdrpComputeConformance( pStubMsg,
  930. pMemory,
  931. pFormat );
  932. }
  933. else
  934. {
  935. MaxCount = ActualCount;
  936. }
  937. // Marshall the max count.
  938. *((ulong *)pStubMsg->BufferMark) = MaxCount;
  939. // Align the buffer for variance marshalling.
  940. ALIGN(pStubMsg->Buffer,3);
  941. // Marshall variance.
  942. *((ulong *)pStubMsg->Buffer)++ = 0;
  943. *((ulong *)pStubMsg->Buffer)++ = ActualCount;
  944. RpcpMemoryCopy( pStubMsg->Buffer,
  945. pMemory,
  946. CopySize );
  947. // Update the Buffer pointer.
  948. pStubMsg->Buffer += CopySize;
  949. }
  950. #if defined( DOS ) && !defined( WIN )
  951. #pragma code_seg()
  952. #endif
  953. unsigned char * RPC_ENTRY
  954. NdrFixedArrayMarshall(
  955. PMIDL_STUB_MESSAGE pStubMsg,
  956. uchar * pMemory,
  957. PFORMAT_STRING pFormat )
  958. /*++
  959. Routine Description :
  960. Marshalls a fixed array of any number of dimensions.
  961. Used for FC_SMFARRAY and FC_LGFARRAY.
  962. Arguments :
  963. pStubMsg - Pointer to the stub message.
  964. pMemory - Pointer to the array to be marshalled.
  965. pFormat - Array's format string description.
  966. Return :
  967. None.
  968. --*/
  969. {
  970. uint Size;
  971. // Align the buffer.
  972. ALIGN(pStubMsg->Buffer,pFormat[1]);
  973. // Get total array size.
  974. if ( *pFormat == FC_SMFARRAY )
  975. {
  976. pFormat += 2;
  977. Size = (ulong) *((ushort *)pFormat)++;
  978. }
  979. else // *pFormat == FC_LGFARRAY
  980. {
  981. pFormat += 2;
  982. Size = *((ulong UNALIGNED *)pFormat)++;
  983. }
  984. // Copy the array.
  985. RpcpMemoryCopy( pStubMsg->Buffer,
  986. pMemory,
  987. Size );
  988. // Increment stub message buffer pointer.
  989. pStubMsg->Buffer += Size;
  990. // Marshall embedded pointers.
  991. if ( *pFormat == FC_PP )
  992. {
  993. // Mark the start of the array in the buffer.
  994. pStubMsg->BufferMark = pStubMsg->Buffer - Size;
  995. NdrpEmbeddedPointerMarshall( pStubMsg,
  996. pMemory,
  997. pFormat );
  998. }
  999. return 0;
  1000. }
  1001. unsigned char * RPC_ENTRY
  1002. NdrConformantArrayMarshall(
  1003. PMIDL_STUB_MESSAGE pStubMsg,
  1004. uchar * pMemory,
  1005. PFORMAT_STRING pFormat )
  1006. /*++
  1007. Routine Description :
  1008. Marshalls a top level one dimensional conformant array.
  1009. Used for FC_CARRAY.
  1010. Arguments :
  1011. pStubMsg - Pointer to the stub message.
  1012. pMemory - Pointer to the array being marshalled.
  1013. pFormat - Array's format string description.
  1014. Return :
  1015. None.
  1016. --*/
  1017. {
  1018. // Align the buffer for conformance marshalling.
  1019. ALIGN(pStubMsg->Buffer,3);
  1020. // Mark where the conformance will be marshalled.
  1021. pStubMsg->BufferMark = pStubMsg->Buffer;
  1022. // Increment past where the conformance will go.
  1023. pStubMsg->Buffer += 4;
  1024. // Call the private marshalling routine to do the work.
  1025. NdrpConformantArrayMarshall( pStubMsg,
  1026. pMemory,
  1027. pFormat );
  1028. return 0;
  1029. }
  1030. void
  1031. NdrpConformantArrayMarshall(
  1032. PMIDL_STUB_MESSAGE pStubMsg,
  1033. uchar * pMemory,
  1034. PFORMAT_STRING pFormat )
  1035. /*++
  1036. Routine Description :
  1037. Private routine for marshalling a one dimensional conformant array.
  1038. This is the entry point for marshalling an embedded conformant array.
  1039. Used for FC_CARRAY.
  1040. Arguments :
  1041. pStubMsg - Pointer to the stub message.
  1042. pMemory - Pointer to the array being marshalled.
  1043. pFormat - Array's format string description.
  1044. Return :
  1045. None.
  1046. --*/
  1047. {
  1048. ulong Count;
  1049. uint CopySize;
  1050. // Compute conformance information.
  1051. Count = NdrpComputeConformance( pStubMsg,
  1052. pMemory,
  1053. pFormat );
  1054. // Marshall the conformance.
  1055. *((ulong *)pStubMsg->BufferMark) = Count;
  1056. //
  1057. // Return if size is 0.
  1058. //
  1059. if ( ! Count )
  1060. return;
  1061. ALIGN(pStubMsg->Buffer,pFormat[1]);
  1062. // Compute the total array size in bytes.
  1063. CopySize = Count * *((ushort *)(pFormat + 2));
  1064. RpcpMemoryCopy( pStubMsg->Buffer,
  1065. pMemory,
  1066. CopySize );
  1067. // Update buffer pointer.
  1068. pStubMsg->Buffer += CopySize;
  1069. // Increment to possible pointer layout.
  1070. pFormat += 8;
  1071. // Marshall embedded pointers.
  1072. if ( *pFormat == FC_PP )
  1073. {
  1074. //
  1075. // Mark the start of the array in the buffer.
  1076. //
  1077. pStubMsg->BufferMark = pStubMsg->Buffer - CopySize;
  1078. NdrpEmbeddedPointerMarshall( pStubMsg,
  1079. pMemory,
  1080. pFormat );
  1081. }
  1082. }
  1083. unsigned char * RPC_ENTRY
  1084. NdrConformantVaryingArrayMarshall(
  1085. PMIDL_STUB_MESSAGE pStubMsg,
  1086. uchar * pMemory,
  1087. PFORMAT_STRING pFormat )
  1088. /*++
  1089. Routine Description :
  1090. Marshalls a top level one dimensional conformant varying array.
  1091. Used for FC_CVARRAY.
  1092. Arguments :
  1093. pStubMsg - Pointer to the stub message.
  1094. pMemory - Pointer to the array being marshalled.
  1095. pFormat - Array's format string description.
  1096. Return :
  1097. None.
  1098. --*/
  1099. {
  1100. // Align the buffer for conformance marshalling.
  1101. ALIGN(pStubMsg->Buffer,3);
  1102. // Mark where the conformance will be marshalled.
  1103. pStubMsg->BufferMark = pStubMsg->Buffer;
  1104. // Increment past where the conformance will go.
  1105. pStubMsg->Buffer += 4;
  1106. // Call the private marshalling routine to do the work.
  1107. NdrpConformantVaryingArrayMarshall( pStubMsg,
  1108. pMemory,
  1109. pFormat );
  1110. return 0;
  1111. }
  1112. #if defined( DOS ) || defined( WIN )
  1113. #pragma code_seg()
  1114. #endif
  1115. #if defined( DOS ) && !defined( WIN )
  1116. #pragma code_seg( "NDR20_9" )
  1117. #endif
  1118. void
  1119. NdrpConformantVaryingArrayMarshall(
  1120. PMIDL_STUB_MESSAGE pStubMsg,
  1121. uchar * pMemory,
  1122. PFORMAT_STRING pFormat )
  1123. /*++
  1124. Routine Description :
  1125. Private routine for marshalling a one dimensional conformant varying array.
  1126. This is the entry point for marshalling an embedded conformant varying
  1127. array.
  1128. Used for FC_CVARRAY.
  1129. Arguments :
  1130. pStubMsg - Pointer to the stub message.
  1131. pMemory - Pointer to the array to be marshalled.
  1132. pFormat - Array's format string description.
  1133. Return :
  1134. None.
  1135. --*/
  1136. {
  1137. uint CopyOffset, CopySize;
  1138. ushort ElemSize;
  1139. // Compute and marshall the conformant size.
  1140. *((ulong *)pStubMsg->BufferMark) = NdrpComputeConformance( pStubMsg,
  1141. pMemory,
  1142. pFormat );
  1143. // Compute variance offset and count.
  1144. NdrpComputeVariance( pStubMsg,
  1145. pMemory,
  1146. pFormat );
  1147. // Align the buffer for variance marshalling.
  1148. ALIGN(pStubMsg->Buffer,3);
  1149. // Marshall variance.
  1150. *((ulong *)pStubMsg->Buffer)++ = pStubMsg->Offset;
  1151. *((ulong *)pStubMsg->Buffer)++ = pStubMsg->ActualCount;
  1152. //
  1153. // Return if length is 0.
  1154. //
  1155. if ( ! pStubMsg->ActualCount )
  1156. return;
  1157. // Align the buffer if needed on an 8 byte boundary.
  1158. if ( pFormat[1] == 7 )
  1159. ALIGN(pStubMsg->Buffer,7);
  1160. ElemSize = *((ushort *)(pFormat + 2));
  1161. // Compute byte offset and size for the array copy.
  1162. CopyOffset = pStubMsg->Offset * ElemSize;
  1163. CopySize = pStubMsg->ActualCount * ElemSize;
  1164. RpcpMemoryCopy( pStubMsg->Buffer,
  1165. pMemory + CopyOffset,
  1166. CopySize );
  1167. pStubMsg->Buffer += CopySize;
  1168. // Increment to a possible pointer layout.
  1169. pFormat += 12;
  1170. // Marshall embedded pointers.
  1171. if ( *pFormat == FC_PP )
  1172. {
  1173. //
  1174. // Set the MaxCount field equal to the ActualCount field. The pointer
  1175. // marshalling routine uses the MaxCount field to determine the number
  1176. // of times an FC_VARIABLE_REPEAT pointer is marshalled. In the face
  1177. // of variance the correct number of time is the ActualCount, not the
  1178. // the MaxCount.
  1179. //
  1180. pStubMsg->MaxCount = pStubMsg->ActualCount;
  1181. //
  1182. // Mark the start of the array in the buffer.
  1183. //
  1184. pStubMsg->BufferMark = pStubMsg->Buffer - CopySize;
  1185. NdrpEmbeddedPointerMarshall( pStubMsg,
  1186. pMemory,
  1187. pFormat );
  1188. }
  1189. }
  1190. #if defined( DOS ) && !defined( WIN )
  1191. #pragma code_seg()
  1192. #endif
  1193. unsigned char * RPC_ENTRY
  1194. NdrVaryingArrayMarshall(
  1195. PMIDL_STUB_MESSAGE pStubMsg,
  1196. uchar * pMemory,
  1197. PFORMAT_STRING pFormat )
  1198. /*++
  1199. Routine Description :
  1200. Marshalls a top level or embedded one dimensional varying array.
  1201. Used for FC_SMVARRAY and FC_LGVARRAY.
  1202. Arguments :
  1203. pStubMsg - Pointer to the stub message.
  1204. pMemory - Pointer to the array being marshalled.
  1205. pFormat - Array's format string description.
  1206. Return :
  1207. None.
  1208. --*/
  1209. {
  1210. uint CopyOffset, CopySize;
  1211. ushort ElemSize;
  1212. // Compute the variance offset and count.
  1213. NdrpComputeVariance( pStubMsg,
  1214. pMemory,
  1215. pFormat );
  1216. // Align the buffer for variance marshalling.
  1217. ALIGN(pStubMsg->Buffer,3);
  1218. // Marshall variance.
  1219. *((ulong *)pStubMsg->Buffer)++ = pStubMsg->Offset;
  1220. *((ulong *)pStubMsg->Buffer)++ = pStubMsg->ActualCount;
  1221. //
  1222. // Return if length is 0.
  1223. //
  1224. if ( ! pStubMsg->ActualCount )
  1225. return 0;
  1226. // Align the buffer if needed on an 8 byte boundary.
  1227. if ( pFormat[1] == 7 )
  1228. ALIGN(pStubMsg->Buffer,7);
  1229. // Increment the format string to the element_size field.
  1230. if ( *pFormat == FC_SMVARRAY )
  1231. pFormat += 6;
  1232. else // *pFormat == FC_LGVARRAY
  1233. pFormat += 10;
  1234. // Get element size.
  1235. ElemSize = *((ushort *)pFormat);
  1236. //
  1237. // Compute the byte offset from the beginning of the array for the copy
  1238. // and the number of bytes to copy.
  1239. //
  1240. CopyOffset = pStubMsg->Offset * ElemSize;
  1241. CopySize = pStubMsg->ActualCount * ElemSize;
  1242. // Copy the array.
  1243. RpcpMemoryCopy( pStubMsg->Buffer,
  1244. pMemory + CopyOffset,
  1245. CopySize );
  1246. // Update buffer pointer.
  1247. pStubMsg->Buffer += CopySize;
  1248. // Increment format string to possible pointer layout.
  1249. pFormat += 6;
  1250. // Marshall embedded pointers.
  1251. if ( *pFormat == FC_PP )
  1252. {
  1253. // Mark the start of the array in the buffer.
  1254. pStubMsg->BufferMark = pStubMsg->Buffer - CopySize;
  1255. //
  1256. // Set the MaxCount field equal to the ActualCount field. The pointer
  1257. // marshalling routine uses the MaxCount field to determine the number
  1258. // of times an FC_VARIABLE_REPEAT pointer is marshalled. In the face
  1259. // of variance the correct number of time is the ActualCount, not the
  1260. // the MaxCount.
  1261. //
  1262. pStubMsg->MaxCount = pStubMsg->ActualCount;
  1263. //
  1264. // Marshall the embedded pointers.
  1265. // Make sure to pass a memory pointer to the first array element
  1266. // which is actually being marshalled.
  1267. //
  1268. NdrpEmbeddedPointerMarshall( pStubMsg,
  1269. pMemory + CopyOffset,
  1270. pFormat );
  1271. }
  1272. return 0;
  1273. }
  1274. unsigned char * RPC_ENTRY
  1275. NdrComplexArrayMarshall(
  1276. PMIDL_STUB_MESSAGE pStubMsg,
  1277. uchar * pMemory,
  1278. PFORMAT_STRING pFormat )
  1279. /*++
  1280. Routine Description :
  1281. Marshalls a top level complex array.
  1282. Used for FC_BOGUS_STRUCT.
  1283. Arguments :
  1284. pStubMsg - Pointer to the stub message.
  1285. pMemory - Pointer to the array being marshalled.
  1286. pFormat - Array's format string description.
  1287. Return :
  1288. None.
  1289. --*/
  1290. {
  1291. BOOL fSetPointerBufferMark;
  1292. //
  1293. // Setting this flag means that the array is not embedded inside of
  1294. // another complex struct or array.
  1295. //
  1296. fSetPointerBufferMark = (! pStubMsg->PointerBufferMark) &&
  1297. (pFormat[12] != FC_RP);
  1298. if ( fSetPointerBufferMark )
  1299. {
  1300. BOOL fOldIgnore;
  1301. ulong MaxCount, Offset, ActualCount;
  1302. //
  1303. // Save the current conformance and variance fields. The sizing
  1304. // routine can overwrite them.
  1305. //
  1306. MaxCount = pStubMsg->MaxCount;
  1307. Offset = pStubMsg->Offset;
  1308. ActualCount = pStubMsg->ActualCount;
  1309. fOldIgnore = pStubMsg->IgnoreEmbeddedPointers;
  1310. pStubMsg->IgnoreEmbeddedPointers = TRUE;
  1311. //
  1312. // Set BufferLength equal to the current buffer pointer, and then
  1313. // when we return from NdrComplexArrayBufferSize it will point to
  1314. // the location in the buffer where the pointers should be marshalled
  1315. // into.
  1316. //
  1317. pStubMsg->BufferLength = (ulong) pStubMsg->Buffer;
  1318. NdrComplexArrayBufferSize( pStubMsg,
  1319. pMemory,
  1320. pFormat );
  1321. //
  1322. // This is the buffer pointer to the position where embedded pointers
  1323. // will be marshalled.
  1324. //
  1325. pStubMsg->PointerBufferMark = (uchar *) pStubMsg->BufferLength;
  1326. pStubMsg->IgnoreEmbeddedPointers = fOldIgnore;
  1327. // Restore conformance and variance fields.
  1328. pStubMsg->MaxCount = MaxCount;
  1329. pStubMsg->Offset = Offset;
  1330. pStubMsg->ActualCount = ActualCount;
  1331. }
  1332. if ( ( *((long UNALIGNED *)(pFormat + 4)) != 0xffffffff ) &&
  1333. ( pStubMsg->pArrayInfo == 0 ) )
  1334. {
  1335. //
  1336. // Outer most dimension sets the conformance marker.
  1337. //
  1338. // Align the buffer for conformance marshalling.
  1339. ALIGN(pStubMsg->Buffer,3);
  1340. // Mark where the conformance count(s) will be marshalled.
  1341. pStubMsg->BufferMark = pStubMsg->Buffer;
  1342. // Increment past where the conformance will go.
  1343. pStubMsg->Buffer += NdrpArrayDimensions( pFormat, FALSE ) * 4;
  1344. }
  1345. // Call the private marshalling routine to do all the work.
  1346. NdrpComplexArrayMarshall( pStubMsg,
  1347. pMemory,
  1348. pFormat );
  1349. if ( fSetPointerBufferMark )
  1350. {
  1351. //
  1352. // This will set the buffer pointer to end of all of the array's
  1353. // unmarshalled data in the buffer.
  1354. //
  1355. pStubMsg->Buffer = pStubMsg->PointerBufferMark;
  1356. pStubMsg->PointerBufferMark = 0;
  1357. }
  1358. return 0;
  1359. }
  1360. #if defined( DOS ) && !defined( WIN )
  1361. #pragma code_seg( "NDR20_9" )
  1362. #endif
  1363. void
  1364. NdrpComplexArrayMarshall(
  1365. PMIDL_STUB_MESSAGE pStubMsg,
  1366. uchar * pMemory,
  1367. PFORMAT_STRING pFormat )
  1368. /*++
  1369. Routine Description :
  1370. Private routine for marshalling a complex array. This is the entry
  1371. point for marshalling an embedded complex array.
  1372. Used for FC_BOGUS_ARRAY.
  1373. Arguments :
  1374. pStubMsg - Pointer to the stub message.
  1375. pMemory - Pointer to the array being marshalled.
  1376. pFormat - Array's format string description.
  1377. Return :
  1378. None.
  1379. --*/
  1380. {
  1381. ARRAY_INFO ArrayInfo;
  1382. PARRAY_INFO pArrayInfo;
  1383. PMARSHALL_ROUTINE pfnMarshall;
  1384. PFORMAT_STRING pFormatStart;
  1385. uint Elements;
  1386. uint Offset, Count;
  1387. uint MemoryElementSize;
  1388. long Dimension;
  1389. uchar Alignment;
  1390. //
  1391. // Lots of setup if we are the outer dimension. All this is for
  1392. // multidimensional array support. If we didn't have to worry about
  1393. // Beta2 stub compatability we could this much better.
  1394. //
  1395. //
  1396. if ( ! pStubMsg->pArrayInfo )
  1397. {
  1398. pStubMsg->pArrayInfo = &ArrayInfo;
  1399. ArrayInfo.Dimension = 0;
  1400. ArrayInfo.BufferConformanceMark = (unsigned long *) pStubMsg->BufferMark;
  1401. ArrayInfo.BufferVarianceMark = 0;
  1402. ArrayInfo.MaxCountArray = (unsigned long *) pStubMsg->MaxCount;
  1403. ArrayInfo.OffsetArray = (unsigned long *) pStubMsg->Offset;
  1404. ArrayInfo.ActualCountArray = (unsigned long *) pStubMsg->ActualCount;
  1405. }
  1406. pFormatStart = pFormat;
  1407. pArrayInfo = pStubMsg->pArrayInfo;
  1408. Dimension = pArrayInfo->Dimension;
  1409. // Get the array's alignment.
  1410. Alignment = pFormat[1];
  1411. pFormat += 2;
  1412. // Get number of elements (0 if the array has conformance).
  1413. Elements = *((ushort *)pFormat)++;
  1414. //
  1415. // Check for conformance description.
  1416. //
  1417. if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
  1418. {
  1419. Elements = NdrpComputeConformance( pStubMsg,
  1420. pMemory,
  1421. pFormatStart );
  1422. // Marshall this dimension's conformance count.
  1423. pArrayInfo->BufferConformanceMark[Dimension] = Elements;
  1424. }
  1425. pFormat += 4;
  1426. //
  1427. // Check for variance description.
  1428. //
  1429. if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
  1430. {
  1431. if ( Dimension == 0 )
  1432. {
  1433. //
  1434. // Set the variance marker.
  1435. //
  1436. ALIGN(pStubMsg->Buffer,0x3);
  1437. // Mark where the variance count(s) will be marshalled.
  1438. pArrayInfo->BufferVarianceMark = (unsigned long *) pStubMsg->Buffer;
  1439. // Increment past where the variance will go.
  1440. pStubMsg->Buffer +=
  1441. NdrpArrayDimensions( pFormatStart, TRUE ) * 8;
  1442. }
  1443. NdrpComputeVariance( pStubMsg,
  1444. pMemory,
  1445. pFormatStart );
  1446. Offset = pStubMsg->Offset;
  1447. Count = pStubMsg->ActualCount;
  1448. //
  1449. // Marshall the outer dimension's variance.
  1450. //
  1451. pArrayInfo->BufferVarianceMark[Dimension * 2] = Offset;
  1452. pArrayInfo->BufferVarianceMark[(Dimension * 2) + 1] = Count;
  1453. }
  1454. else
  1455. {
  1456. Offset = 0;
  1457. Count = Elements;
  1458. }
  1459. pFormat += 4;
  1460. //
  1461. // Return if count is 0.
  1462. //
  1463. if ( ! Count )
  1464. goto ComplexArrayMarshallEnd;
  1465. // Align on array's alignment.
  1466. ALIGN(pStubMsg->Buffer,Alignment);
  1467. switch ( *pFormat )
  1468. {
  1469. case FC_EMBEDDED_COMPLEX :
  1470. pFormat += 2;
  1471. pFormat += *((signed short *)pFormat);
  1472. // Get the proper marshalling routine.
  1473. pfnMarshall = pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)];
  1474. pArrayInfo->Dimension = Dimension + 1;
  1475. // Compute the size of an array element.
  1476. MemoryElementSize = NdrpMemoryIncrement( pStubMsg,
  1477. pMemory,
  1478. pFormat ) - pMemory;
  1479. break;
  1480. case FC_RP :
  1481. case FC_UP :
  1482. case FC_FP :
  1483. case FC_OP :
  1484. pfnMarshall = (PMARSHALL_ROUTINE) NdrpPointerMarshall;
  1485. // Need this in case we have a variant offset.
  1486. MemoryElementSize = PTR_MEM_SIZE;
  1487. break;
  1488. case FC_IP :
  1489. pfnMarshall = NdrInterfacePointerMarshall;
  1490. // Need this in case we have a variant offset.
  1491. MemoryElementSize = PTR_MEM_SIZE;
  1492. break;
  1493. case FC_ENUM16 :
  1494. pfnMarshall = 0;
  1495. // Need this in case we have a variant offset.
  1496. MemoryElementSize = sizeof(int);
  1497. break;
  1498. default :
  1499. NDR_ASSERT( IS_SIMPLE_TYPE(*pFormat),
  1500. "NdrpComplexArrayMarshall : bad format char" );
  1501. Count *= SIMPLE_TYPE_BUFSIZE(*pFormat);
  1502. pMemory += Offset * SIMPLE_TYPE_MEMSIZE(*pFormat);
  1503. RpcpMemoryCopy( pStubMsg->Buffer,
  1504. pMemory,
  1505. Count );
  1506. pStubMsg->Buffer += Count;
  1507. goto ComplexArrayMarshallEnd;
  1508. }
  1509. //
  1510. // If there is variance then increment the memory pointer to the first
  1511. // element actually being marshalled.
  1512. //
  1513. if ( Offset )
  1514. pMemory += Offset * MemoryElementSize;
  1515. //
  1516. // Array of enum16.
  1517. //
  1518. if ( ! pfnMarshall )
  1519. {
  1520. for ( ; Count--; )
  1521. {
  1522. if ( *((int *)pMemory) & ~((int)0x7fff) )
  1523. RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
  1524. *((ushort *)pStubMsg->Buffer)++ = (ushort) *((int *)pMemory)++;
  1525. }
  1526. goto ComplexArrayMarshallEnd;
  1527. }
  1528. //
  1529. // Array of ref or interface pointers.
  1530. //
  1531. if ( (pfnMarshall == (PMARSHALL_ROUTINE) NdrpPointerMarshall) ||
  1532. (pfnMarshall == NdrInterfacePointerMarshall) )
  1533. {
  1534. uchar * pBuffer;
  1535. pStubMsg->pArrayInfo = 0;
  1536. //
  1537. // If PointerBufferMark is set then we must set the buffer pointer
  1538. // here before marshalling.
  1539. //
  1540. if ( pStubMsg->PointerBufferMark )
  1541. {
  1542. pBuffer = pStubMsg->Buffer;
  1543. pStubMsg->Buffer = pStubMsg->PointerBufferMark;
  1544. pStubMsg->PointerBufferMark = 0;
  1545. }
  1546. else
  1547. pBuffer = 0;
  1548. if ( pfnMarshall == (PMARSHALL_ROUTINE) NdrpPointerMarshall )
  1549. {
  1550. for ( ; Count--; )
  1551. {
  1552. NdrpPointerMarshall( pStubMsg,
  1553. 0,
  1554. *((uchar **)pMemory)++,
  1555. pFormat );
  1556. }
  1557. }
  1558. else
  1559. {
  1560. for ( ; Count--; )
  1561. {
  1562. NdrInterfacePointerMarshall( pStubMsg,
  1563. *((uchar **)pMemory)++,
  1564. pFormat );
  1565. }
  1566. }
  1567. //
  1568. // Fix up the stub message buffer fields if needed.
  1569. //
  1570. if ( pBuffer )
  1571. {
  1572. pStubMsg->PointerBufferMark = pStubMsg->Buffer;
  1573. pStubMsg->Buffer = pBuffer;
  1574. }
  1575. goto ComplexArrayMarshallEnd;
  1576. }
  1577. //
  1578. // It's an array of complex types.
  1579. //
  1580. if ( ! IS_ARRAY_OR_STRING(*pFormat) )
  1581. pStubMsg->pArrayInfo = 0;
  1582. // Marshall the array elements.
  1583. for ( ; Count--; )
  1584. {
  1585. // Keep track of multidimensional array dimension.
  1586. if ( IS_ARRAY_OR_STRING(*pFormat) )
  1587. pArrayInfo->Dimension = Dimension + 1;
  1588. (*pfnMarshall)( pStubMsg,
  1589. pMemory,
  1590. pFormat );
  1591. // Increment the memory pointer by the element size.
  1592. pMemory += MemoryElementSize;
  1593. }
  1594. ComplexArrayMarshallEnd:
  1595. // pArrayInfo must be zero when not valid.
  1596. pStubMsg->pArrayInfo = (Dimension == 0) ? 0 : pArrayInfo;
  1597. }
  1598. #if defined( DOS ) && !defined( WIN )
  1599. #pragma code_seg()
  1600. #endif
  1601. unsigned char * RPC_ENTRY
  1602. NdrEncapsulatedUnionMarshall (
  1603. PMIDL_STUB_MESSAGE pStubMsg,
  1604. uchar * pMemory,
  1605. PFORMAT_STRING pFormat )
  1606. /*++
  1607. Routine Description :
  1608. Marshalls an encapsulated union.
  1609. Used for FC_ENCAPSULATED_UNION.
  1610. Arguments :
  1611. pStubMsg - Pointer to the stub message.
  1612. pMemory - Pointer to the union being marshalled.
  1613. pFormat - Union's format string description.
  1614. Return :
  1615. None.
  1616. --*/
  1617. {
  1618. long SwitchIs;
  1619. uchar SwitchType;
  1620. SwitchType = LOW_NIBBLE(pFormat[1]);
  1621. switch ( SwitchType )
  1622. {
  1623. case FC_SMALL :
  1624. case FC_CHAR :
  1625. SwitchIs = (long) *((char *)pMemory);
  1626. break;
  1627. case FC_USMALL :
  1628. SwitchIs = (long) *((uchar *)pMemory);
  1629. break;
  1630. case FC_ENUM16 :
  1631. #if defined(__RPC_MAC__)
  1632. SwitchIs = (long) *((short *)(pMemory+2));
  1633. break;
  1634. #endif
  1635. // non-Mac: fall to short
  1636. case FC_SHORT :
  1637. SwitchIs = (long) *((short *)pMemory);
  1638. break;
  1639. case FC_USHORT :
  1640. case FC_WCHAR :
  1641. SwitchIs = (long) *((ushort *)pMemory);
  1642. break;
  1643. case FC_LONG :
  1644. case FC_ULONG :
  1645. case FC_ENUM32 :
  1646. SwitchIs = *((long *)pMemory);
  1647. break;
  1648. default :
  1649. NDR_ASSERT(0,"NdrEncapsulatedUnionMarshall : bad swith type");
  1650. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  1651. return 0;
  1652. }
  1653. // Increment the memory pointer to the union.
  1654. pMemory += HIGH_NIBBLE(pFormat[1]);
  1655. NdrpUnionMarshall( pStubMsg,
  1656. pMemory,
  1657. pFormat + 2,
  1658. SwitchIs,
  1659. SwitchType );
  1660. return 0;
  1661. }
  1662. unsigned char * RPC_ENTRY
  1663. NdrNonEncapsulatedUnionMarshall (
  1664. PMIDL_STUB_MESSAGE pStubMsg,
  1665. uchar * pMemory,
  1666. PFORMAT_STRING pFormat )
  1667. /*++
  1668. Routine Description :
  1669. Marshalls a non encapsulated union.
  1670. Used for FC_NON_ENCAPSULATED_UNION.
  1671. Arguments :
  1672. pStubMsg - Pointer to the stub message.
  1673. pMemory - Pointer to the union being marshalled.
  1674. pFormat - Union's format string description.
  1675. Return :
  1676. None.
  1677. --*/
  1678. {
  1679. long SwitchIs;
  1680. uchar SwitchType;
  1681. SwitchType = pFormat[1];
  1682. SwitchIs = NdrpComputeSwitchIs( pStubMsg,
  1683. pMemory,
  1684. pFormat );
  1685. //
  1686. // Set the format string to the memory size and arm description.
  1687. //
  1688. pFormat += 6;
  1689. pFormat += *((signed short *)pFormat);
  1690. NdrpUnionMarshall( pStubMsg,
  1691. pMemory,
  1692. pFormat,
  1693. SwitchIs,
  1694. SwitchType );
  1695. return 0;
  1696. }
  1697. #if defined( DOS ) && !defined( WIN )
  1698. #pragma code_seg( "NDR20_9" )
  1699. #endif
  1700. void
  1701. NdrpUnionMarshall (
  1702. PMIDL_STUB_MESSAGE pStubMsg,
  1703. uchar * pMemory,
  1704. PFORMAT_STRING pFormat,
  1705. long SwitchIs,
  1706. uchar SwitchType )
  1707. /*++
  1708. Routine Description :
  1709. Private routine for marshalling a union. This routine is shared for
  1710. both encapsulated and non-encapsulated unions and handles the actual
  1711. marshalling of the proper union arm.
  1712. Arguments :
  1713. pStubMsg - Pointer to the stub message.
  1714. pMemory - Pointer to the union being marshalled.
  1715. pFormat - The memory size and arm description portion of the format
  1716. string for the union.
  1717. SwitchIs - Union's switch is.
  1718. SwitchType - Union's switch is type.
  1719. Return :
  1720. None.
  1721. --*/
  1722. {
  1723. long Arms;
  1724. uchar Alignment;
  1725. #if defined(__RPC_MAC__)
  1726. long SavedSwitchIs;
  1727. SavedSwitchIs = SwitchIs;
  1728. if ( (FC_BYTE <= SwitchType) && (SwitchType <= FC_USMALL) )
  1729. SwitchIs <<= 24;
  1730. else if ( (FC_WCHAR <= SwitchType) && (SwitchType <= FC_USHORT) )
  1731. SwitchIs <<= 16;
  1732. #endif
  1733. // Marshall the switch is value.
  1734. NdrSimpleTypeMarshall( pStubMsg,
  1735. (uchar *)&SwitchIs,
  1736. SwitchType );
  1737. #if defined(__RPC_MAC__)
  1738. SwitchIs = SavedSwitchIs;
  1739. #endif
  1740. // Skip the memory size field.
  1741. pFormat += 2;
  1742. //
  1743. // We're at the union_arms<2> field now, which contains both the
  1744. // Microsoft union aligment value and the number of union arms.
  1745. //
  1746. //
  1747. // Get the union alignment (0 if this is a DCE union).
  1748. //
  1749. Alignment = (uchar) ( *((ushort *)pFormat) >> 12 );
  1750. ALIGN(pStubMsg->Buffer,Alignment);
  1751. //
  1752. // Number of arms is the lower 12 bits.
  1753. //
  1754. Arms = (long) ( *((ushort *)pFormat)++ & 0x0fff);
  1755. //
  1756. // Search for the correct arm.
  1757. //
  1758. for ( ; Arms; Arms-- )
  1759. {
  1760. if ( *((long UNALIGNED *)pFormat)++ == SwitchIs )
  1761. {
  1762. //
  1763. // Found the right arm, break out.
  1764. //
  1765. break;
  1766. }
  1767. // Else increment format string.
  1768. pFormat += 2;
  1769. }
  1770. //
  1771. // Check if we took the default arm and no default arm is specified.
  1772. //
  1773. if ( ! Arms && (*((ushort *)pFormat) == (ushort) 0xffff) )
  1774. {
  1775. RpcRaiseException( RPC_S_INVALID_TAG );
  1776. }
  1777. //
  1778. // Return if the arm is empty.
  1779. //
  1780. if ( ! *((ushort *)pFormat) )
  1781. return;
  1782. //
  1783. // Get the arm's description.
  1784. //
  1785. // We need a real solution after beta for simple type arms. This could
  1786. // break if we have a format string larger than about 32K.
  1787. //
  1788. if ( IS_MAGIC_UNION_BYTE(pFormat) )
  1789. {
  1790. NdrSimpleTypeMarshall( pStubMsg,
  1791. pMemory,
  1792. #if defined(__RPC_MAC__)
  1793. pFormat[1] );
  1794. #else
  1795. pFormat[0] );
  1796. #endif
  1797. return;
  1798. }
  1799. pFormat += *((signed short *)pFormat);
  1800. //
  1801. // If the union arm we take is a pointer, we have to dereference the
  1802. // current memory pointer since we're passed a pointer to the union
  1803. // (regardless of whether the actual parameter was a by-value union
  1804. // or a pointer to a union).
  1805. //
  1806. // We also have to do a bunch of other special stuff to handle unions
  1807. // embedded inside of strutures.
  1808. //
  1809. if ( IS_POINTER_TYPE(*pFormat) )
  1810. {
  1811. pMemory = *((uchar **)pMemory);
  1812. }
  1813. //
  1814. // Non-interface pointers only.
  1815. //
  1816. if ( IS_BASIC_POINTER(*pFormat) )
  1817. {
  1818. //
  1819. // If we're embedded in a struct or array we have do some extra stuff.
  1820. //
  1821. if ( pStubMsg->PointerBufferMark )
  1822. {
  1823. uchar * pBufferSave;
  1824. pBufferSave = pStubMsg->Buffer;
  1825. // We have to align pBufferSave as well.
  1826. ALIGN(pBufferSave,3);
  1827. pStubMsg->Buffer = pStubMsg->PointerBufferMark;
  1828. pStubMsg->PointerBufferMark = 0;
  1829. //
  1830. // We must call the private pointer marshalling routine.
  1831. //
  1832. NdrpPointerMarshall( pStubMsg,
  1833. pBufferSave,
  1834. pMemory,
  1835. pFormat );
  1836. pStubMsg->PointerBufferMark = pStubMsg->Buffer;
  1837. // Increment past the pointer in the buffer.
  1838. pStubMsg->Buffer = pBufferSave + 4;
  1839. return;
  1840. }
  1841. }
  1842. //
  1843. // Union arm of a non-simple type.
  1844. //
  1845. (*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])
  1846. ( pStubMsg,
  1847. pMemory,
  1848. pFormat );
  1849. }
  1850. #if defined( DOS ) && !defined( WIN )
  1851. #pragma code_seg()
  1852. #endif
  1853. unsigned char * RPC_ENTRY
  1854. NdrByteCountPointerMarshall (
  1855. PMIDL_STUB_MESSAGE pStubMsg,
  1856. uchar * pMemory,
  1857. PFORMAT_STRING pFormat )
  1858. /*++
  1859. Routine Description :
  1860. Marshalls a pointer with the byte count attribute applied to it.
  1861. Used for FC_BYTE_COUNT_POINTER.
  1862. Arguments :
  1863. pStubMsg - Pointer to the stub message.
  1864. pMemory - Pointer to the byte count pointer being marshalled.
  1865. pFormat - Byte count pointer's format string description.
  1866. Return :
  1867. None.
  1868. --*/
  1869. {
  1870. //
  1871. // We don't do anything special here. Just pass things on to the
  1872. // right marshalling routine.
  1873. //
  1874. if ( pFormat[1] != FC_PAD )
  1875. {
  1876. NdrSimpleTypeMarshall( pStubMsg,
  1877. pMemory,
  1878. pFormat[1] );
  1879. }
  1880. else
  1881. {
  1882. pFormat += 6;
  1883. pFormat += *((signed short *)pFormat);
  1884. (*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  1885. pMemory,
  1886. pFormat );
  1887. }
  1888. return 0;
  1889. }
  1890. #if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
  1891. #pragma optimize( "", off )
  1892. #endif
  1893. unsigned char * RPC_ENTRY
  1894. NdrXmitOrRepAsMarshall (
  1895. PMIDL_STUB_MESSAGE pStubMsg,
  1896. uchar * pMemory,
  1897. PFORMAT_STRING pFormat )
  1898. /*++
  1899. Routine Description :
  1900. Marshalls a transmit as or represent as argument:
  1901. - translate the presented object into a transmitted object
  1902. - marshall the transmitted object
  1903. - free the transmitted object
  1904. Format string layout:
  1905. 0 FC_TRANSMIT_AS or FC_REPRESENT_AS
  1906. Oi array flag/alignment<1>
  1907. +2 quintuple index<2>
  1908. +4 pres type mem size<2>
  1909. +6 tran type buf size<2>
  1910. +8 offset<2>
  1911. Arguments :
  1912. pStubMsg - a pointer to the stub message
  1913. pMemory - presented type translated into transmitted type
  1914. and than to be marshalled
  1915. pFormat - format string description
  1916. --*/
  1917. {
  1918. unsigned char * pTransmittedType;
  1919. const XMIT_ROUTINE_QUINTUPLE * pQuintuple = pStubMsg->StubDesc->aXmitQuintuple;
  1920. unsigned short QIndex;
  1921. BOOL fXmitByPtr = *pFormat == FC_TRANSMIT_AS_PTR ||
  1922. *pFormat == FC_REPRESENT_AS_PTR;
  1923. // Skip the token itself and Oi flag. Fetch the QuintupleIndex.
  1924. QIndex = *(unsigned short *)(pFormat + 2);
  1925. // First translate the presented type into the transmitted type.
  1926. // This includes an allocation of a transmitted type object.
  1927. pStubMsg->pPresentedType = pMemory;
  1928. pStubMsg->pTransmitType = NULL;
  1929. pQuintuple[ QIndex ].pfnTranslateToXmit( pStubMsg );
  1930. // Marshall the transmitted type.
  1931. pFormat += 8;
  1932. pFormat = pFormat + *(short *) pFormat;
  1933. pTransmittedType = pStubMsg->pTransmitType;
  1934. if ( IS_SIMPLE_TYPE( *pFormat ))
  1935. {
  1936. NdrSimpleTypeMarshall( pStubMsg,
  1937. pTransmittedType,
  1938. *pFormat );
  1939. }
  1940. else
  1941. {
  1942. (*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])
  1943. ( pStubMsg,
  1944. fXmitByPtr ? *(uchar **)pTransmittedType
  1945. : pTransmittedType,
  1946. pFormat );
  1947. }
  1948. pStubMsg->pTransmitType = pTransmittedType;
  1949. // Free the temporary transmitted object (it was allocated by the user).
  1950. pQuintuple[ QIndex ].pfnFreeXmit( pStubMsg );
  1951. return 0;
  1952. }
  1953. #if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
  1954. #pragma optimize( "", on )
  1955. #endif
  1956. unsigned char * RPC_ENTRY
  1957. NdrUserMarshalMarshall(
  1958. PMIDL_STUB_MESSAGE pStubMsg,
  1959. uchar * pMemory,
  1960. PFORMAT_STRING pFormat )
  1961. /*++
  1962. Routine Description :
  1963. Marshals a usr_marshall object.
  1964. The format string layout is as follows:
  1965. FC_USER_MARSHAL
  1966. flags & alignment<1>
  1967. quadruple index<2>
  1968. memory size<2>
  1969. wire size<2>
  1970. type offset<2>
  1971. The wire layout description is at the type offset.
  1972. Arguments :
  1973. pStubMsg - Pointer to the stub message.
  1974. pMemory - Pointer to the usr_marshall object to marshall.
  1975. pFormat - Object's format string description.
  1976. Return :
  1977. None.
  1978. --*/
  1979. {
  1980. const USER_MARSHAL_ROUTINE_QUADRUPLE * pQuadruple;
  1981. unsigned short QIndex;
  1982. unsigned char * pUserBuffer;
  1983. USER_MARSHAL_CB UserMarshalCB;
  1984. unsigned long * pWireMarkerPtr = 0;
  1985. unsigned char * pUserBufferSaved;
  1986. // Align for the object or a pointer to it.
  1987. ALIGN( pStubMsg->Buffer, LOW_NIBBLE(pFormat[1]) );
  1988. if ( (pFormat[1] & USER_MARSHAL_UNIQUE) ||
  1989. ((pFormat[1] & USER_MARSHAL_REF) && pStubMsg->PointerBufferMark) )
  1990. {
  1991. pWireMarkerPtr = (unsigned long *) pStubMsg->Buffer;
  1992. *((unsigned long *)pStubMsg->Buffer)++ = USER_MARSHAL_MARKER;
  1993. }
  1994. // Check if the object is embedded.
  1995. // Pointer buffer mark is set only when in a complex struct or array.
  1996. // For unions, when the union is embedded in a complex struct or array.
  1997. // If the union is top level, it's the same like a top level object.
  1998. if ( (pFormat[1] & USER_MARSHAL_POINTER) && pStubMsg->PointerBufferMark )
  1999. {
  2000. // Embedded: User object among pointees.
  2001. pUserBuffer = pStubMsg->PointerBufferMark;
  2002. }
  2003. else
  2004. pUserBuffer = pStubMsg->Buffer;
  2005. pUserBufferSaved = pUserBuffer;
  2006. // We always call user's routine to marshall.
  2007. UserMarshalCB.Flags = USER_CALL_CTXT_MASK( pStubMsg->dwDestContext );
  2008. UserMarshalCB.pStubMsg = pStubMsg;
  2009. if ( pFormat[1] & USER_MARSHAL_IID )
  2010. {
  2011. UserMarshalCB.pReserve = pFormat + 10;
  2012. }
  2013. else
  2014. {
  2015. UserMarshalCB.pReserve = 0;
  2016. }
  2017. QIndex = *(unsigned short *)(pFormat + 2);
  2018. pQuadruple = pStubMsg->StubDesc->aUserMarshalQuadruple;
  2019. pUserBuffer = pQuadruple[ QIndex ].pfnMarshall( (ulong*) &UserMarshalCB,
  2020. pUserBuffer,
  2021. pMemory );
  2022. if ( (unsigned long) (pUserBuffer - (uchar *) pStubMsg->RpcMsg->Buffer)
  2023. > pStubMsg->RpcMsg->BufferLength )
  2024. RpcRaiseException( RPC_X_INVALID_BUFFER );
  2025. if ( pUserBuffer == pUserBufferSaved )
  2026. {
  2027. // This is valid only if the wire type was a unique type.
  2028. if ( (pFormat[1] & USER_MARSHAL_UNIQUE) )
  2029. {
  2030. *pWireMarkerPtr = 0;
  2031. return 0;
  2032. }
  2033. else
  2034. RpcRaiseException( RPC_X_NULL_REF_POINTER );
  2035. }
  2036. // Advance the appropriate buffer pointer.
  2037. if ( (pFormat[1] & USER_MARSHAL_POINTER) && pStubMsg->PointerBufferMark )
  2038. pStubMsg->PointerBufferMark = pUserBuffer;
  2039. else
  2040. pStubMsg->Buffer = pUserBuffer;
  2041. return(0);
  2042. }
  2043. unsigned char * RPC_ENTRY
  2044. NdrInterfacePointerMarshall (
  2045. PMIDL_STUB_MESSAGE pStubMsg,
  2046. uchar * pMemory,
  2047. PFORMAT_STRING pFormat )
  2048. /*++
  2049. Routine Description :
  2050. Marshalls an interface pointer.
  2051. Arguments :
  2052. pStubMsg - Pointer to the stub message.
  2053. pMemory - Pointer to the interface pointer being marshalled.
  2054. pFormat - Interface pointer's format string description.
  2055. Return :
  2056. None.
  2057. Notes : There is now one representation of a marshalled interface pointer.
  2058. The format string contains FC_IP followed by either
  2059. FC_CONSTANT_IID or FC_PAD.
  2060. typedef struct
  2061. {
  2062. unsigned long size;
  2063. [size_is(size)] byte data[];
  2064. }MarshalledInterface;
  2065. --*/
  2066. {
  2067. #if !defined( NDR_OLE_SUPPORT )
  2068. NDR_ASSERT(0, "Unimplemented");
  2069. #else //NT or Chicago
  2070. HRESULT hr;
  2071. IID iid;
  2072. IID * piid;
  2073. unsigned long * pSize;
  2074. unsigned long * pMaxCount;
  2075. unsigned long cbData = 0;
  2076. unsigned long cbMax;
  2077. unsigned long position;
  2078. IStream * pStream;
  2079. LARGE_INTEGER libMove;
  2080. ULARGE_INTEGER libPosition;
  2081. uchar * pBufferSave;
  2082. // Always put the pointer itself on wire, it behaves like a unique.
  2083. //
  2084. ALIGN(pStubMsg->Buffer,0x3);
  2085. *((long *)pStubMsg->Buffer)++ = (long) pMemory;
  2086. // If the pointer is null, it's done.
  2087. if ( pMemory == 0 )
  2088. return 0;
  2089. // Check if the pointer is embedded, to put the pointee
  2090. // in the right place.
  2091. //
  2092. if ( pStubMsg->PointerBufferMark )
  2093. {
  2094. pBufferSave = pStubMsg->Buffer;
  2095. pStubMsg->Buffer = pStubMsg->PointerBufferMark;
  2096. //Align the buffer on a 4 byte boundary
  2097. ALIGN(pStubMsg->Buffer,0x3);
  2098. }
  2099. else
  2100. pBufferSave = 0;
  2101. //
  2102. // Get an IID pointer.
  2103. //
  2104. if ( pFormat[1] != FC_CONSTANT_IID )
  2105. {
  2106. //
  2107. // This is like computing a variance with a long.
  2108. //
  2109. piid = (IID *) NdrpComputeIIDPointer( pStubMsg,
  2110. pMemory,
  2111. pFormat );
  2112. if(piid == 0)
  2113. RpcRaiseException( RPC_S_INVALID_ARG );
  2114. }
  2115. else
  2116. {
  2117. //
  2118. // The IID may not be aligned properly in the format string,
  2119. // so we copy it to a local variable.
  2120. //
  2121. piid = &iid;
  2122. RpcpMemoryCopy( &iid, &pFormat[2], sizeof(iid) );
  2123. }
  2124. // Leave space in the buffer for the conformant size an the size field.
  2125. pMaxCount = (unsigned long *) pStubMsg->Buffer;
  2126. pStubMsg->Buffer += sizeof(unsigned long);
  2127. pSize = (unsigned long *) pStubMsg->Buffer;
  2128. pStubMsg->Buffer += sizeof(unsigned long);
  2129. if(pMemory)
  2130. {
  2131. //Calculate the maximum size of the stream.
  2132. position = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
  2133. cbMax = pStubMsg->BufferLength - position;
  2134. #if DBG == 1
  2135. //In the debug build, we call CoGetMarshalSizeMax to get
  2136. //upper bound for the size of the marshalled interface pointer.
  2137. hr = (*pfnCoGetMarshalSizeMax)(&cbMax, piid, (IUnknown *)pMemory, pStubMsg->dwDestContext, pStubMsg->pvDestContext, 0);
  2138. #endif
  2139. //Create a stream on memory.
  2140. pStream = NdrpCreateStreamOnMemory(pStubMsg->Buffer, cbMax);
  2141. if(pStream == 0)
  2142. RpcRaiseException(RPC_S_OUT_OF_MEMORY);
  2143. hr = (*pfnCoMarshalInterface)(pStream, piid, (IUnknown *)pMemory, pStubMsg->dwDestContext, pStubMsg->pvDestContext, 0);
  2144. if(FAILED(hr))
  2145. {
  2146. pStream->lpVtbl->Release(pStream);
  2147. pStream = 0;
  2148. RpcRaiseException(hr);
  2149. }
  2150. //Calculate the size of the data written
  2151. libMove.LowPart = 0;
  2152. libMove.HighPart = 0;
  2153. pStream->lpVtbl->Seek(pStream, libMove, STREAM_SEEK_CUR, &libPosition);
  2154. pStream->lpVtbl->Release(pStream);
  2155. pStream = 0;
  2156. cbData = libPosition.LowPart;
  2157. }
  2158. //Update the array bounds.
  2159. *pMaxCount = cbData;
  2160. *pSize = cbData;
  2161. //Advance the stub message buffer pointer.
  2162. pStubMsg->Buffer += cbData;
  2163. //
  2164. // End of MAGIC.
  2165. //
  2166. if ( pBufferSave )
  2167. {
  2168. pStubMsg->PointerBufferMark = pStubMsg->Buffer;
  2169. pStubMsg->Buffer = pBufferSave;
  2170. }
  2171. #endif// NT or Chicago
  2172. return 0;
  2173. }
  2174. //
  2175. // Context handle marshalling routines.
  2176. //
  2177. void RPC_ENTRY
  2178. NdrClientContextMarshall(
  2179. PMIDL_STUB_MESSAGE pStubMsg,
  2180. NDR_CCONTEXT ContextHandle,
  2181. int fCheck )
  2182. /*++
  2183. Routine Description :
  2184. Marshalls a context handle on the client side.
  2185. Arguments :
  2186. pStubMsg - Pointer to stub message.
  2187. ContextHandle - Context handle to marshall.
  2188. fCheck - TRUE if an exception check should be made on the handle,
  2189. FALSE otherwise.
  2190. Return :
  2191. None.
  2192. --*/
  2193. {
  2194. if ( fCheck && ! ContextHandle )
  2195. RpcRaiseException( RPC_X_SS_IN_NULL_CONTEXT );
  2196. ALIGN(pStubMsg->Buffer,3);
  2197. // This call will check for bogus handles now and will raise
  2198. // an exception when necessary.
  2199. NDRCContextMarshall( ContextHandle, pStubMsg->Buffer );
  2200. pStubMsg->Buffer += 20;
  2201. }
  2202. void RPC_ENTRY
  2203. NdrServerContextMarshall(
  2204. PMIDL_STUB_MESSAGE pStubMsg,
  2205. NDR_SCONTEXT ContextHandle,
  2206. NDR_RUNDOWN RundownRoutine )
  2207. /*++
  2208. Routine Description :
  2209. Marshalls a context handle on the server side.
  2210. Arguments :
  2211. pStubMsg - Pointer to stub message.
  2212. ContextHandle - Context handle to marshall.
  2213. RundownRoutine - The context rundown routine.
  2214. Return :
  2215. None.
  2216. --*/
  2217. {
  2218. #if defined( NDR_SERVER_SUPPORT )
  2219. ALIGN(pStubMsg->Buffer,3);
  2220. NDRSContextMarshall( ContextHandle,
  2221. pStubMsg->Buffer,
  2222. RundownRoutine );
  2223. pStubMsg->Buffer += 20;
  2224. #endif
  2225. }