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.

1614 lines
35 KiB

4 years ago
  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name :
  4. free.c
  5. Abstract :
  6. This file contains the routines called by MIDL 2.0 stubs and the
  7. interpreter for freeing unmarshalled data on the server.
  8. Author :
  9. David Kays dkays September 1993.
  10. Revision History :
  11. ---------------------------------------------------------------------*/
  12. #include "ndrp.h"
  13. #include "ndrole.h"
  14. //
  15. // Free routine table.
  16. //
  17. const
  18. PFREE_ROUTINE FreeRoutinesTable[] =
  19. {
  20. NdrPointerFree,
  21. NdrPointerFree,
  22. NdrPointerFree,
  23. NdrPointerFree,
  24. 0, // Simple struct
  25. NdrSimpleStructFree,
  26. 0, // Conformant struct
  27. NdrConformantStructFree,
  28. NdrConformantVaryingStructFree,
  29. NdrComplexStructFree,
  30. NdrConformantArrayFree,
  31. NdrConformantVaryingArrayFree,
  32. NdrFixedArrayFree,
  33. NdrFixedArrayFree,
  34. NdrVaryingArrayFree, // Small varying array
  35. NdrVaryingArrayFree, // Large varying array
  36. NdrComplexArrayFree,
  37. 0, // Conformant string
  38. 0, // Conformant string
  39. 0, // Conformant string
  40. 0, // Conformant string
  41. 0, // NonConformant string
  42. 0, // NonConformant string
  43. 0, // NonConformant string
  44. 0, // NonConformant string
  45. NdrEncapsulatedUnionFree,
  46. NdrNonEncapsulatedUnionFree,
  47. NdrByteCountPointerFree,
  48. NdrXmitOrRepAsFree, // transmit as
  49. NdrXmitOrRepAsFree, // represent as
  50. NdrInterfacePointerFree,
  51. 0, // Context handle
  52. // New Post NT 3.5 token serviced from here on.
  53. NdrHardStructFree,
  54. NdrXmitOrRepAsFree, // transmit as ptr
  55. NdrXmitOrRepAsFree, // represent as ptr
  56. NdrUserMarshalFree
  57. };
  58. const
  59. PFREE_ROUTINE * pfnFreeRoutines = &FreeRoutinesTable[-FC_RP];
  60. #if defined( DOS ) && !defined( WIN )
  61. #pragma code_seg( "NDR20_1" )
  62. #endif
  63. void RPC_ENTRY
  64. NdrPointerFree(
  65. PMIDL_STUB_MESSAGE pStubMsg,
  66. uchar * pMemory,
  67. PFORMAT_STRING pFormat )
  68. /*++
  69. Routine Description :
  70. Frees a top level or embedded pointer to anything.
  71. Used for FC_RP, FC_UP, FC_FP, FC_OP.
  72. Arguments :
  73. pStubMsg - Pointer to the stub message.
  74. pMemory - Pointer to be freed.
  75. pFormat - Pointer's format string description.
  76. Return :
  77. None.
  78. --*/
  79. {
  80. PFORMAT_STRING pFormatPointee;
  81. uchar * pMemoryPointee;
  82. pMemoryPointee = pMemory;
  83. if ( ! pMemory )
  84. return;
  85. if ( *pFormat == FC_FP )
  86. {
  87. //
  88. // Check if we've already freed this full pointer.
  89. //
  90. if ( ! NdrFullPointerFree( pStubMsg->FullPtrXlatTables,
  91. pMemory ) )
  92. return;
  93. }
  94. if ( pFormat[1] == 0 )
  95. goto FreeEmbeddedPointers;
  96. //
  97. // Check if this pointer and any possible embedded pointers should not
  98. // be freed.
  99. //
  100. if ( DONT_FREE(pFormat[1]) )
  101. return;
  102. //
  103. // Just go free a pointer to a simple type.
  104. //
  105. if ( SIMPLE_POINTER(pFormat[1]) )
  106. goto FreeTopPointer;
  107. //
  108. // Check if this is an allocate all nodes pointer.
  109. // IDL symantics say that we only free the top most allocate all nodes
  110. // pointer on the server even in the [out] only case. So jump to the
  111. // check for the pointer free at the end of the routine.
  112. //
  113. if ( ALLOCATE_ALL_NODES(pFormat[1]) )
  114. goto FreeTopPointer;
  115. if ( POINTER_DEREF(pFormat[1]) )
  116. pMemoryPointee = *((uchar **)pMemory);
  117. FreeEmbeddedPointers:
  118. pFormatPointee = pFormat + 2;
  119. pFormatPointee += *((signed short *)pFormatPointee);
  120. //
  121. // Call the correct free routine if one exists for this type.
  122. //
  123. if ( pfnFreeRoutines[ROUTINE_INDEX(*pFormatPointee)] )
  124. {
  125. (*pfnFreeRoutines[ROUTINE_INDEX(*pFormatPointee)])
  126. ( pStubMsg,
  127. pMemoryPointee,
  128. pFormatPointee );
  129. }
  130. FreeTopPointer:
  131. //
  132. // Now free the pointer. Pointer guaranteed to be non-null here.
  133. //
  134. // We only free the pointer if it lies outside of the message buffer
  135. // that the server stub received from the RPC runtime. Otherwise we
  136. // used the RPC buffer to hold the pointer's data and should not free it.
  137. //
  138. if ( (pMemory < pStubMsg->BufferStart) || (pMemory > pStubMsg->BufferEnd) )
  139. {
  140. //
  141. // Also check to make sure that the pointer was not allocated on the
  142. // server stub's stack (this may happen for ref pointers).
  143. //
  144. if ( ! ALLOCED_ON_STACK(pFormat[1]) )
  145. {
  146. (*pStubMsg->pfnFree)(pMemory);
  147. }
  148. }
  149. }
  150. void RPC_ENTRY
  151. NdrSimpleStructFree(
  152. PMIDL_STUB_MESSAGE pStubMsg,
  153. uchar * pMemory,
  154. PFORMAT_STRING pFormat )
  155. /*++
  156. Routine Description :
  157. Frees a simple structure's embedded pointers which were allocated during
  158. a remote call.
  159. Used for FC_STRUCT and FC_PSTRUCT.
  160. Arguments :
  161. pStubMsg - Pointer to the stub message.
  162. pMemory - Pointer to be freed.
  163. pFormat - Pointer's format string description.
  164. Return :
  165. None.
  166. --*/
  167. {
  168. if ( *pFormat == FC_PSTRUCT )
  169. {
  170. NdrpEmbeddedPointerFree( pStubMsg,
  171. pMemory,
  172. pFormat + 4 );
  173. }
  174. }
  175. void RPC_ENTRY
  176. NdrConformantStructFree(
  177. PMIDL_STUB_MESSAGE pStubMsg,
  178. uchar * pMemory,
  179. PFORMAT_STRING pFormat )
  180. /*++
  181. Routine Description :
  182. Frees a conformant structure's embedded pointers which were allocated
  183. during a remote call.
  184. Used for FC_CSTRUCT and FC_CPSTRUCT.
  185. Arguments :
  186. pStubMsg - Pointer to the stub message.
  187. pMemory - Pointer to be freed.
  188. pFormat - Pointer's format string description.
  189. Return :
  190. None.
  191. --*/
  192. {
  193. PFORMAT_STRING pFormatArray;
  194. if ( *pFormat == FC_CSTRUCT )
  195. return;
  196. // Get a pointer to the conformant array's description.
  197. pFormatArray = pFormat + 4;
  198. pFormatArray += *((signed short *)pFormatArray);
  199. //
  200. // Get the conformance count. Pass a memory pointer to the beginning
  201. // of the array.
  202. //
  203. NdrpComputeConformance( pStubMsg,
  204. pMemory + *((ushort *)(pFormat + 2)),
  205. pFormatArray );
  206. // Must pass a format string pointing to the pointer layout.
  207. NdrpEmbeddedPointerFree( pStubMsg,
  208. pMemory,
  209. pFormat + 6 );
  210. }
  211. void RPC_ENTRY
  212. NdrConformantVaryingStructFree(
  213. PMIDL_STUB_MESSAGE pStubMsg,
  214. uchar * pMemory,
  215. PFORMAT_STRING pFormat )
  216. /*++
  217. Routine Description :
  218. Frees a conformant varying structure's embedded pointers which were
  219. allocated during a remote call.
  220. Used for FC_CVSTRUCT.
  221. Arguments :
  222. pStubMsg - Pointer to the stub message.
  223. pMemory - Pointer to be freed.
  224. pFormat - Pointer's format string description.
  225. Return :
  226. None.
  227. --*/
  228. {
  229. PFORMAT_STRING pFormatArray;
  230. if ( *(pFormat + 6) != FC_PP )
  231. return;
  232. //
  233. // Set the memory pointer to the start of the conformant array/string.
  234. //
  235. pMemory += *((ushort *)(pFormat + 2));
  236. // Get the conformant array/string description.
  237. pFormatArray = pFormat + 4;
  238. pFormatArray += *((ushort *)pFormatArray);
  239. NdrpComputeConformance( pStubMsg,
  240. pMemory,
  241. pFormatArray );
  242. NdrpComputeVariance( pStubMsg,
  243. pMemory,
  244. pFormatArray );
  245. // Must pass a format string pointing to the pointer layout.
  246. NdrpEmbeddedPointerFree( pStubMsg,
  247. pMemory,
  248. pFormat + 6 );
  249. }
  250. void RPC_ENTRY
  251. NdrHardStructFree(
  252. PMIDL_STUB_MESSAGE pStubMsg,
  253. uchar * pMemory,
  254. PFORMAT_STRING pFormat )
  255. /*++
  256. Routine Description :
  257. Frees a hard structure's embedded pointers which were allocated during
  258. a remote call.
  259. Used for FC_HARD_STRUCT.
  260. Arguments :
  261. pStubMsg - Pointer to the stub message.
  262. pMemory - Pointer to be freed.
  263. pFormat - Pointer's format string description.
  264. Return :
  265. None.
  266. --*/
  267. {
  268. if ( *((short *)&pFormat[14]) )
  269. {
  270. pFormat += 12;
  271. pMemory += *((ushort *)pFormat)++;
  272. pFormat += *((short *)pFormat);
  273. (*pfnFreeRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
  274. pMemory,
  275. pFormat );
  276. }
  277. }
  278. void RPC_ENTRY
  279. NdrComplexStructFree(
  280. PMIDL_STUB_MESSAGE pStubMsg,
  281. uchar * pMemory,
  282. PFORMAT_STRING pFormat )
  283. /*++
  284. Routine Description :
  285. Frees a complex structure's embedded pointers which were allocated during
  286. a remote call.
  287. Used for FC_BOGUS_STRUCT.
  288. Arguments :
  289. pStubMsg - Pointer to the stub message.
  290. pMemory - Pointer to be freed.
  291. pFormat - Pointer's format string description.
  292. Return :
  293. None.
  294. --*/
  295. {
  296. uchar * pMemorySave;
  297. PFORMAT_STRING pFormatPointers;
  298. PFORMAT_STRING pFormatArray;
  299. PFORMAT_STRING pFormatComplex;
  300. long Align8Mod;
  301. #if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
  302. long Align4Mod;
  303. #endif
  304. //
  305. // This is used for support of structs with doubles passed on an
  306. // i386 stack.
  307. //
  308. Align8Mod = (long) pMemory % 8;
  309. #if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
  310. Align4Mod = (long) pMemory % 4;
  311. #endif
  312. pMemorySave = pStubMsg->Memory;
  313. pStubMsg->Memory = pMemory;
  314. pFormat += 4;
  315. // Get conformant array description.
  316. if ( *((ushort *)pFormat) )
  317. pFormatArray = pFormat + *((signed short *)pFormat);
  318. else
  319. pFormatArray = 0;
  320. pFormat += 2;
  321. // Get pointer layout description.
  322. if ( *((ushort *)pFormat) )
  323. pFormatPointers = pFormat + *((ushort *)pFormat);
  324. else
  325. pFormatPointers = 0;
  326. pFormat += 2;
  327. //
  328. // Free the structure member by member.
  329. //
  330. for ( ; ; pFormat++ )
  331. {
  332. switch ( *pFormat )
  333. {
  334. //
  335. // simple types
  336. //
  337. case FC_CHAR :
  338. case FC_BYTE :
  339. case FC_SMALL :
  340. case FC_WCHAR :
  341. case FC_SHORT :
  342. case FC_LONG :
  343. case FC_FLOAT :
  344. case FC_HYPER :
  345. case FC_DOUBLE :
  346. case FC_ENUM16 :
  347. case FC_ENUM32 :
  348. case FC_IGNORE :
  349. pMemory += SIMPLE_TYPE_MEMSIZE(*pFormat);
  350. break;
  351. case FC_POINTER :
  352. NdrPointerFree( pStubMsg,
  353. *((uchar **)pMemory),
  354. pFormatPointers );
  355. pMemory += PTR_MEM_SIZE;
  356. pFormatPointers += 4;
  357. break;
  358. //
  359. // Embedded complex types.
  360. //
  361. case FC_EMBEDDED_COMPLEX :
  362. // Add padding.
  363. pMemory += pFormat[1];
  364. pFormat += 2;
  365. // Get the type's description.
  366. pFormatComplex = pFormat + *((signed short UNALIGNED *)pFormat);
  367. if ( pfnFreeRoutines[ROUTINE_INDEX(*pFormatComplex)] )
  368. {
  369. (*pfnFreeRoutines[ROUTINE_INDEX(*pFormatComplex)])
  370. ( pStubMsg,
  371. (*pFormatComplex == FC_IP) ? *(uchar **)pMemory : pMemory,
  372. pFormatComplex );
  373. }
  374. pMemory = NdrpMemoryIncrement( pStubMsg,
  375. pMemory,
  376. pFormatComplex );
  377. //
  378. // Increment the main format string one byte. The loop
  379. // will increment it one more byte past the offset field.
  380. //
  381. pFormat++;
  382. break;
  383. case FC_ALIGNM2 :
  384. ALIGN( pMemory, 0x1 );
  385. break;
  386. case FC_ALIGNM4 :
  387. #if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
  388. //
  389. // We have to play some tricks for the dos and win16
  390. // to handle the case when an 4 byte aligned structure
  391. // is passed by value. The alignment of the struct on
  392. // the stack is not guaranteed to be on an 4 byte boundary.
  393. //
  394. pMemory -= Align4Mod;
  395. ALIGN( pMemory, 0x3 );
  396. pMemory += Align4Mod;
  397. #else
  398. ALIGN( pMemory, 0x3 );
  399. #endif
  400. break;
  401. case FC_ALIGNM8 :
  402. //
  403. // We have to play some tricks for the i386 to handle the case
  404. // when an 8 byte aligned structure is passed by value. The
  405. // alignment of the struct on the stack is not guaranteed to be
  406. // on an 8 byte boundary.
  407. //
  408. pMemory -= Align8Mod;
  409. ALIGN( pMemory, 0x7 );
  410. pMemory += Align8Mod;
  411. break;
  412. case FC_STRUCTPAD1 :
  413. case FC_STRUCTPAD2 :
  414. case FC_STRUCTPAD3 :
  415. case FC_STRUCTPAD4 :
  416. case FC_STRUCTPAD5 :
  417. case FC_STRUCTPAD6 :
  418. case FC_STRUCTPAD7 :
  419. //
  420. // Increment memory pointer by amount of padding.
  421. //
  422. pMemory += (*pFormat - FC_STRUCTPAD1) + 1;
  423. break;
  424. case FC_PAD :
  425. break;
  426. //
  427. // Done with layout.
  428. //
  429. case FC_END :
  430. goto ComplexFreeEnd;
  431. default :
  432. NDR_ASSERT(0,"NdrComplexStructFree : bad format char");
  433. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  434. return;
  435. } // switch
  436. } // for
  437. ComplexFreeEnd :
  438. if ( pFormatArray )
  439. {
  440. PFREE_ROUTINE pfnFree;
  441. switch ( *pFormatArray )
  442. {
  443. case FC_CARRAY :
  444. pfnFree = NdrConformantArrayFree;
  445. break;
  446. case FC_CVARRAY :
  447. pfnFree = NdrConformantVaryingArrayFree;
  448. break;
  449. case FC_BOGUS_ARRAY :
  450. pfnFree = NdrComplexArrayFree;
  451. break;
  452. // case FC_C_CSTRING :
  453. // case FC_C_BSTRING :
  454. // case FC_C_WSTRING :
  455. // case FC_C_SSTRING :
  456. default :
  457. pfnFree = 0;
  458. break;
  459. }
  460. if ( pfnFree )
  461. {
  462. (*pfnFree)( pStubMsg,
  463. pMemory,
  464. pFormatArray );
  465. }
  466. }
  467. pStubMsg->Memory = pMemorySave;
  468. }
  469. void RPC_ENTRY
  470. NdrFixedArrayFree(
  471. PMIDL_STUB_MESSAGE pStubMsg,
  472. uchar * pMemory,
  473. PFORMAT_STRING pFormat )
  474. /*++
  475. Routine Description :
  476. Frees a fixed array's embedded pointers which were allocated during
  477. a remote call.
  478. Used for FC_SMFARRAY and FC_LGFARRAY.
  479. Arguments :
  480. pStubMsg - Pointer to the stub message.
  481. pMemory - Pointer to be freed.
  482. pFormat - Pointer's format string description.
  483. Return :
  484. None.
  485. --*/
  486. {
  487. //
  488. // We have to check this in case we get an exception before actually
  489. // unmarshalling the array.
  490. //
  491. if ( ! pMemory )
  492. return;
  493. if ( *pFormat == FC_SMFARRAY )
  494. pFormat += 4;
  495. else // *pFormat == FC_LGFARRAY
  496. pFormat += 6;
  497. if ( *pFormat == FC_PP )
  498. NdrpEmbeddedPointerFree( pStubMsg,
  499. pMemory,
  500. pFormat );
  501. }
  502. void RPC_ENTRY
  503. NdrConformantArrayFree(
  504. PMIDL_STUB_MESSAGE pStubMsg,
  505. uchar * pMemory,
  506. PFORMAT_STRING pFormat )
  507. /*++
  508. Routine Description :
  509. Frees a one dimensional conformant array's embedded pointers which were
  510. allocated during a remote call. Called for both top level and embedded
  511. conformant arrays.
  512. Used for FC_CARRAY.
  513. Arguments :
  514. pStubMsg - Pointer to the stub message.
  515. pMemory - Pointer to be freed.
  516. pFormat - Pointer's format string description.
  517. Return :
  518. None.
  519. --*/
  520. {
  521. //
  522. // We have to check this in case we get an exception before actually
  523. // unmarshalling the array.
  524. //
  525. if ( ! pMemory )
  526. return;
  527. if ( *(pFormat + 8) == FC_PP )
  528. {
  529. NdrpComputeConformance( pStubMsg,
  530. pMemory,
  531. pFormat );
  532. NdrpEmbeddedPointerFree( pStubMsg,
  533. pMemory,
  534. pFormat + 8 );
  535. }
  536. }
  537. void RPC_ENTRY
  538. NdrConformantVaryingArrayFree(
  539. PMIDL_STUB_MESSAGE pStubMsg,
  540. uchar * pMemory,
  541. PFORMAT_STRING pFormat )
  542. /*++
  543. Routine Description :
  544. Frees a one dimensional conformant varying array's embedded pointers which
  545. were allocated during a remote call. Called for both top level and
  546. embedded conformant varying arrays.
  547. Used for FC_CVARRAY.
  548. Arguments :
  549. pStubMsg - Pointer to the stub message.
  550. pMemory - Pointer to be freed.
  551. pFormat - Pointer's format string description.
  552. Return :
  553. None.
  554. --*/
  555. {
  556. //
  557. // We have to check this in case we get an exception before actually
  558. // unmarshalling the array.
  559. //
  560. if ( ! pMemory )
  561. return;
  562. if ( *(pFormat + 12) == FC_PP )
  563. {
  564. NdrpComputeConformance( pStubMsg,
  565. pMemory,
  566. pFormat );
  567. NdrpComputeVariance( pStubMsg,
  568. pMemory,
  569. pFormat );
  570. //
  571. // Set MaxCount equal to the number of shipped elements.
  572. //
  573. pStubMsg->MaxCount = pStubMsg->ActualCount;
  574. NdrpEmbeddedPointerFree( pStubMsg,
  575. pMemory,
  576. pFormat + 12 );
  577. }
  578. }
  579. void RPC_ENTRY
  580. NdrVaryingArrayFree(
  581. PMIDL_STUB_MESSAGE pStubMsg,
  582. uchar * pMemory,
  583. PFORMAT_STRING pFormat )
  584. /*++
  585. Routine Description :
  586. Frees a varying array's embedded pointers which were allocated
  587. during a remote call. Called for both top level and embedded varying
  588. arrays.
  589. Used for FC_SMVARRAY and FC_LGVARRAY.
  590. Arguments :
  591. pStubMsg - Pointer to the stub message.
  592. pMemory - Pointer to be freed.
  593. pFormat - Pointer's format string description.
  594. Return :
  595. None.
  596. --*/
  597. {
  598. PFORMAT_STRING pFormatPointers;
  599. //
  600. // We have to check this in case we get an exception before actually
  601. // unmarshalling the array.
  602. //
  603. if ( ! pMemory )
  604. return;
  605. if ( *pFormat == FC_SMVARRAY )
  606. pFormatPointers = pFormat + 10;
  607. else // *pFormat == FC_LGVARRAY
  608. pFormatPointers = pFormat + 16;
  609. if ( *pFormatPointers == FC_PP )
  610. {
  611. NdrpComputeVariance( pStubMsg,
  612. pMemory,
  613. pFormat );
  614. //
  615. // Set MaxCount equal to the number of shipped elements.
  616. //
  617. pStubMsg->MaxCount = pStubMsg->ActualCount;
  618. NdrpEmbeddedPointerFree( pStubMsg,
  619. pMemory,
  620. pFormatPointers );
  621. }
  622. }
  623. void RPC_ENTRY
  624. NdrComplexArrayFree(
  625. PMIDL_STUB_MESSAGE pStubMsg,
  626. uchar * pMemory,
  627. PFORMAT_STRING pFormat )
  628. /*++
  629. Routine Description :
  630. Frees a complex array's embedded pointers which were allocated
  631. during a remote call. Called for both top level and embedded complex
  632. arrays.
  633. Used for FC_BOGUS_STRUCT.
  634. Arguments :
  635. pStubMsg - Pointer to the stub message.
  636. pMemory - Pointer to be freed.
  637. pFormat - Pointer's format string description.
  638. Return :
  639. None.
  640. --*/
  641. {
  642. ARRAY_INFO ArrayInfo;
  643. PARRAY_INFO pArrayInfo;
  644. PFREE_ROUTINE pfnFree;
  645. PFORMAT_STRING pFormatStart;
  646. uchar * pMemorySave;
  647. ulong Elements;
  648. ulong Offset, Count;
  649. ulong MemoryElementSize;
  650. long Dimension;
  651. //
  652. // We have to check this in case we get an exception before actually
  653. // unmarshalling the array.
  654. //
  655. if ( ! pMemory )
  656. return;
  657. //
  658. // Lots of setup if we are the outer dimension.
  659. //
  660. if ( ! pStubMsg->pArrayInfo )
  661. {
  662. pStubMsg->pArrayInfo = &ArrayInfo;
  663. ArrayInfo.Dimension = 0;
  664. ArrayInfo.BufferConformanceMark = (unsigned long *)pStubMsg->BufferMark;
  665. ArrayInfo.BufferVarianceMark = 0;
  666. ArrayInfo.MaxCountArray = (unsigned long *) pStubMsg->MaxCount;
  667. ArrayInfo.OffsetArray = (unsigned long *) pStubMsg->Offset;
  668. ArrayInfo.ActualCountArray = (unsigned long *) pStubMsg->ActualCount;
  669. }
  670. pArrayInfo = pStubMsg->pArrayInfo;
  671. Dimension = pArrayInfo->Dimension;
  672. pFormatStart = pFormat;
  673. pFormat += 2;
  674. // Get number of elements (0 if conformance present).
  675. Elements = *((ushort *)pFormat)++;
  676. //
  677. // Check for conformance description.
  678. //
  679. if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
  680. {
  681. Elements = NdrpComputeConformance( pStubMsg,
  682. pMemory,
  683. pFormatStart );
  684. }
  685. pFormat += 4;
  686. //
  687. // Check for variance description.
  688. //
  689. if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
  690. {
  691. NdrpComputeVariance( pStubMsg,
  692. pMemory,
  693. pFormatStart );
  694. Offset = pStubMsg->Offset;
  695. Count = pStubMsg->ActualCount;
  696. }
  697. else
  698. {
  699. Offset = 0;
  700. Count = Elements;
  701. }
  702. pFormat += 4;
  703. switch ( *pFormat )
  704. {
  705. case FC_EMBEDDED_COMPLEX :
  706. pFormat += 2;
  707. pFormat += *((signed short *)pFormat);
  708. if ( ! (pfnFree = pfnFreeRoutines[ROUTINE_INDEX(*pFormat)]) )
  709. goto ComplexArrayFreeEnd;
  710. pArrayInfo->Dimension = Dimension + 1;
  711. MemoryElementSize = NdrpMemoryIncrement( pStubMsg,
  712. pMemory,
  713. pFormat ) - pMemory;
  714. break;
  715. case FC_RP :
  716. case FC_UP :
  717. case FC_FP :
  718. case FC_OP :
  719. pfnFree = NdrPointerFree;
  720. // Need this in case we have a variant offset.
  721. MemoryElementSize = PTR_MEM_SIZE;
  722. break;
  723. case FC_IP :
  724. pfnFree = NdrInterfacePointerFree;
  725. // Need this in case we have a variant offset.
  726. MemoryElementSize = PTR_MEM_SIZE;
  727. break;
  728. default :
  729. // Must be a basetype.
  730. goto ComplexArrayFreeEnd;
  731. }
  732. pMemorySave = pMemory;
  733. //
  734. // If there is variance then increment the memory pointer to the first
  735. // element actually being marshalled.
  736. //
  737. if ( Offset )
  738. pMemory += Offset * MemoryElementSize;
  739. if ( (pfnFree == NdrPointerFree) ||
  740. (pfnFree == NdrInterfacePointerFree) )
  741. {
  742. pStubMsg->pArrayInfo = 0;
  743. for ( ; Count--; )
  744. {
  745. (*pfnFree)( pStubMsg,
  746. *((uchar **)pMemory),
  747. pFormat );
  748. // Increment the memory pointer by the element size.
  749. pMemory += PTR_MEM_SIZE;
  750. }
  751. goto ComplexArrayFreeEnd;
  752. }
  753. if ( ! IS_ARRAY_OR_STRING(*pFormat) )
  754. pStubMsg->pArrayInfo = 0;
  755. for ( ; Count--; )
  756. {
  757. // Keep track of multidimensional array dimension.
  758. if ( IS_ARRAY_OR_STRING(*pFormat) )
  759. pArrayInfo->Dimension = Dimension + 1;
  760. (*pfnFree)( pStubMsg,
  761. pMemory,
  762. pFormat );
  763. // Increment the memory pointer by the element size.
  764. pMemory += MemoryElementSize;
  765. }
  766. ComplexArrayFreeEnd:
  767. // pArrayInfo must be zero when not valid.
  768. pStubMsg->pArrayInfo = (Dimension == 0) ? 0 : pArrayInfo;
  769. }
  770. void RPC_ENTRY
  771. NdrEncapsulatedUnionFree(
  772. PMIDL_STUB_MESSAGE pStubMsg,
  773. uchar * pMemory,
  774. PFORMAT_STRING pFormat )
  775. /*++
  776. Routine Description :
  777. Frees an encapsulated union's embedded pointers which were allocated
  778. during a remote call.
  779. Used for FC_ENCAPSULATED_UNION.
  780. Arguments :
  781. pStubMsg - Pointer to the stub message.
  782. pMemory - Pointer to be freed.
  783. pFormat - Pointer's format string description.
  784. Return :
  785. None.
  786. --*/
  787. {
  788. long SwitchIs;
  789. switch ( LOW_NIBBLE(pFormat[1]) )
  790. {
  791. case FC_SMALL :
  792. case FC_CHAR :
  793. SwitchIs = (long) *((char *)pMemory);
  794. break;
  795. case FC_USMALL :
  796. SwitchIs = (long) *((uchar *)pMemory);
  797. break;
  798. case FC_ENUM16 :
  799. #if defined(__RPC_MAC__)
  800. SwitchIs = (long) *((short *)(pMemory+2));
  801. break;
  802. #endif
  803. // non-Mac: fall to short
  804. case FC_SHORT :
  805. SwitchIs = (long) *((short *)pMemory);
  806. break;
  807. case FC_USHORT :
  808. case FC_WCHAR :
  809. SwitchIs = (long) *((ushort *)pMemory);
  810. break;
  811. case FC_LONG :
  812. case FC_ULONG :
  813. case FC_ENUM32 :
  814. SwitchIs = *((long *)pMemory);
  815. break;
  816. default :
  817. NDR_ASSERT(0,"NdrEncapsulatedUnionFree : bad switch type");
  818. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  819. return;
  820. }
  821. // Increment memory pointer to the union.
  822. pMemory += HIGH_NIBBLE(pFormat[1]);
  823. NdrpUnionFree( pStubMsg,
  824. pMemory,
  825. pFormat + 2,
  826. SwitchIs );
  827. }
  828. void RPC_ENTRY
  829. NdrNonEncapsulatedUnionFree(
  830. PMIDL_STUB_MESSAGE pStubMsg,
  831. uchar * pMemory,
  832. PFORMAT_STRING pFormat )
  833. /*++
  834. Routine Description :
  835. Frees a non-encapsulated union's embedded pointers which were allocated
  836. during a remote call.
  837. Used for FC_NON_ENCAPSULATED_UNION.
  838. Arguments :
  839. pStubMsg - Pointer to the stub message.
  840. pMemory - Pointer to be freed.
  841. pFormat - Pointer's format string description.
  842. Return :
  843. None.
  844. --*/
  845. {
  846. long SwitchIs;
  847. SwitchIs = NdrpComputeSwitchIs( pStubMsg,
  848. pMemory,
  849. pFormat );
  850. //
  851. // Set the format string to the memory size and arm description.
  852. //
  853. pFormat += 6;
  854. pFormat += *((signed short *)pFormat);
  855. NdrpUnionFree( pStubMsg,
  856. pMemory,
  857. pFormat,
  858. SwitchIs );
  859. }
  860. void
  861. NdrpUnionFree(
  862. PMIDL_STUB_MESSAGE pStubMsg,
  863. uchar * pMemory,
  864. PFORMAT_STRING pFormat,
  865. long SwitchIs )
  866. /*++
  867. Routine Description :
  868. Private routine shared by encapsulated and non-encapsulated unions for
  869. freeing a union's embedded pointers which were allocated during a remote
  870. call.
  871. Arguments :
  872. pStubMsg - Pointer to the stub message.
  873. pMemory - Pointer to be freed.
  874. pFormat - Pointer's format string description.
  875. SwitchIs - The union's switch is.
  876. Return :
  877. None.
  878. --*/
  879. {
  880. long Arms;
  881. PFREE_ROUTINE pfnFree;
  882. // Skip the memory size field.
  883. pFormat += 2;
  884. Arms = (long) ( *((ushort *)pFormat)++ & 0x0fff );
  885. //
  886. // Search for the arm.
  887. //
  888. for ( ; Arms; Arms-- )
  889. {
  890. if ( *((long UNALIGNED *)pFormat)++ == SwitchIs )
  891. {
  892. //
  893. // Found the right arm, break out.
  894. //
  895. break;
  896. }
  897. // Else increment format string.
  898. pFormat += 2;
  899. }
  900. //
  901. // Check if we took the default arm and no default arm is specified.
  902. //
  903. if ( ! Arms && (*((ushort *)pFormat) == (ushort) 0xffff) )
  904. {
  905. return;
  906. }
  907. //
  908. // Return if the arm is empty.
  909. //
  910. if ( ! *((ushort *)pFormat) )
  911. return;
  912. //
  913. // Get the arm's description.
  914. //
  915. // We need a real solution after beta for simple type arms. This could
  916. // break if we have a format string larger than about 32K.
  917. //
  918. if ( IS_MAGIC_UNION_BYTE(pFormat) )
  919. return;
  920. pFormat += *((signed short *)pFormat);
  921. //
  922. // If the union arm we take is a pointer, we have to dereference the
  923. // current memory pointer since we're passed a pointer to the union
  924. // (regardless of whether the actual parameter was a by-value union
  925. // or a pointer to a union).
  926. //
  927. if ( IS_POINTER_TYPE(*pFormat) )
  928. pMemory = *((uchar **)pMemory);
  929. if ( pfnFree = pfnFreeRoutines[ROUTINE_INDEX(*pFormat)] )
  930. {
  931. (*pfnFree)( pStubMsg,
  932. pMemory,
  933. pFormat );
  934. }
  935. }
  936. void RPC_ENTRY
  937. NdrByteCountPointerFree(
  938. PMIDL_STUB_MESSAGE pStubMsg,
  939. uchar * pMemory,
  940. PFORMAT_STRING pFormat )
  941. /*++
  942. Routine Description :
  943. Frees a byte count pointer.
  944. Used for FC_BYTE_COUNT_POINTER.
  945. Arguments :
  946. pStubMsg - Pointer to the stub message.
  947. pMemory - Pointer to be freed.
  948. pFormat - Pointer's format string description.
  949. Return :
  950. None.
  951. --*/
  952. {
  953. if ( ! pMemory )
  954. return;
  955. //
  956. // Free it if we didn't use the rpc buffer for it.
  957. //
  958. if ( (pMemory < pStubMsg->BufferStart) || (pMemory > pStubMsg->BufferEnd) )
  959. (*pStubMsg->pfnFree)(pMemory);
  960. }
  961. #if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
  962. #pragma optimize( "", off )
  963. #endif
  964. void RPC_ENTRY
  965. NdrXmitOrRepAsFree(
  966. PMIDL_STUB_MESSAGE pStubMsg,
  967. uchar * pMemory,
  968. PFORMAT_STRING pFormat )
  969. /*++
  970. Routine Description :
  971. Frees the transmit-as object (actually the presented type instance)
  972. and steps over the object.
  973. There is an exceptional situation where the spec forbids stub to free
  974. the instance. This happens when there is an [in] only parameter with
  975. a [transmit_as()] on a component of the parameter, and the presented
  976. typedef is composed of one or more pointers.
  977. We have a flag in the stub msg that is set when this happens.
  978. See mrshl.c for the description of the FC layout.
  979. Arguments :
  980. pStubMsg - Pointer to the stub message.
  981. pMemory - Pointer to be freed.
  982. pFormat - Pointer's format string description.
  983. Return :
  984. None.
  985. --*/
  986. {
  987. const XMIT_ROUTINE_QUINTUPLE * pQuintuple;
  988. unsigned short QIndex;
  989. // Skip the token itself and Oi flag. Fetch the QuintupleIndex.
  990. QIndex = *(unsigned short *)(pFormat + 2);
  991. pQuintuple = pStubMsg->StubDesc->aXmitQuintuple;
  992. // Free the presented type instance unless forbidden explicitely.
  993. if ( ! pStubMsg->fDontCallFreeInst )
  994. {
  995. pStubMsg->pPresentedType = pMemory;
  996. pQuintuple[ QIndex ].pfnFreeInst( pStubMsg );
  997. }
  998. }
  999. #if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
  1000. #pragma optimize( "", on )
  1001. #endif
  1002. void RPC_ENTRY
  1003. NdrUserMarshalFree(
  1004. PMIDL_STUB_MESSAGE pStubMsg,
  1005. uchar * pMemory,
  1006. PFORMAT_STRING pFormat )
  1007. /*++
  1008. Routine Description :
  1009. Frees the usr_marshal object and steps over the object.
  1010. See mrshl.c for the description of the layouts.
  1011. Arguments :
  1012. pStubMsg - Pointer to the stub message.
  1013. pMemory - Pointer to be freed.
  1014. pFormat - Pointer's format string description.
  1015. Return :
  1016. None.
  1017. --*/
  1018. {
  1019. const USER_MARSHAL_ROUTINE_QUADRUPLE * pQuadruple;
  1020. unsigned short QIndex;
  1021. USER_MARSHAL_CB UserMarshalCB;
  1022. QIndex = *(unsigned short *)(pFormat + 2);
  1023. pQuadruple = pStubMsg->StubDesc->aUserMarshalQuadruple;
  1024. // Call the user to free his stuff.
  1025. UserMarshalCB.Flags = USER_CALL_CTXT_MASK( pStubMsg->dwDestContext );
  1026. UserMarshalCB.pStubMsg = pStubMsg;
  1027. if ( pFormat[1] & USER_MARSHAL_IID )
  1028. {
  1029. UserMarshalCB.pReserve = pFormat + 10;
  1030. }
  1031. else
  1032. {
  1033. UserMarshalCB.pReserve = 0;
  1034. }
  1035. // The user shouldn't ever free the top level object as we free it.
  1036. // He should free only pointees of his top level object.
  1037. pQuadruple[ QIndex ].pfnFree( (ulong*) &UserMarshalCB, pMemory );
  1038. // NdrpMemoryIncrement steps over the memory object.
  1039. }
  1040. void RPC_ENTRY
  1041. NdrInterfacePointerFree(
  1042. PMIDL_STUB_MESSAGE pStubMsg,
  1043. uchar * pMemory,
  1044. PFORMAT_STRING pFormat )
  1045. /*++
  1046. Routine Description :
  1047. Frees any memory associated with an interface pointer.
  1048. Arguments :
  1049. pStubMsg - Pointer to the stub message.
  1050. pMemory - Interface pointer.
  1051. pFormat - Interface pointer's format string description.
  1052. Return :
  1053. None.
  1054. --*/
  1055. {
  1056. #if defined( NDR_OLE_SUPPORT )
  1057. if(pMemory != 0)
  1058. {
  1059. ((IUnknown *)pMemory)->lpVtbl->Release((IUnknown *)pMemory);
  1060. pMemory = 0;
  1061. }
  1062. #endif
  1063. }
  1064. void
  1065. NdrpEmbeddedPointerFree(
  1066. PMIDL_STUB_MESSAGE pStubMsg,
  1067. uchar * pMemory,
  1068. PFORMAT_STRING pFormat )
  1069. /*++
  1070. Routine Description :
  1071. Frees an array's or a structure's embedded pointers which were allocated
  1072. during a remote call.
  1073. Arguments :
  1074. pStubMsg - Pointer to the stub message.
  1075. pMemory - Pointer to be freed.
  1076. pFormat - Pointer's format string description.
  1077. Return :
  1078. None.
  1079. --*/
  1080. {
  1081. uchar ** ppMemPtr;
  1082. uchar * pMemorySave;
  1083. long MaxCountSave, OffsetSave;
  1084. MaxCountSave = pStubMsg->MaxCount;
  1085. OffsetSave = pStubMsg->Offset;
  1086. pMemorySave = pStubMsg->Memory;
  1087. pStubMsg->Memory = pMemory;
  1088. // Increment past the FC_PP and pad.
  1089. pFormat += 2;
  1090. for (;;)
  1091. {
  1092. if ( *pFormat == FC_END )
  1093. {
  1094. pStubMsg->Memory = pMemorySave;
  1095. return;
  1096. }
  1097. // Check for FC_FIXED_REPEAT or FC_VARIABLE_REPEAT.
  1098. if ( *pFormat != FC_NO_REPEAT )
  1099. {
  1100. pStubMsg->MaxCount = MaxCountSave;
  1101. pStubMsg->Offset = OffsetSave;
  1102. pFormat = NdrpEmbeddedRepeatPointerFree( pStubMsg,
  1103. pMemory,
  1104. pFormat );
  1105. // Continue loop to next pointer.
  1106. continue;
  1107. }
  1108. // Get the pointer to the pointer to free.
  1109. ppMemPtr = (uchar **)( pMemory + *((signed short *)(pFormat + 2)) );
  1110. // Increment to pointer description.
  1111. pFormat += 6;
  1112. NdrPointerFree( pStubMsg,
  1113. *ppMemPtr,
  1114. pFormat );
  1115. // Increment to the next pointer description.
  1116. pFormat += 4;
  1117. }
  1118. }
  1119. PFORMAT_STRING
  1120. NdrpEmbeddedRepeatPointerFree(
  1121. PMIDL_STUB_MESSAGE pStubMsg,
  1122. uchar * pMemory,
  1123. PFORMAT_STRING pFormat )
  1124. /*++
  1125. Routine Description :
  1126. Frees an array's embedded pointers which were allocated during a remote
  1127. call.
  1128. Arguments :
  1129. pStubMsg - Pointer to the stub message.
  1130. pMemory - Pointer to be freed.
  1131. pFormat - Pointer's format string description.
  1132. Return :
  1133. Format string pointer after the array's pointer description.
  1134. --*/
  1135. {
  1136. uchar ** ppMemPtr;
  1137. uchar * pMemorySave;
  1138. PFORMAT_STRING pFormatSave;
  1139. ulong RepeatCount, RepeatIncrement, Pointers, PointersSave;
  1140. pMemorySave = pStubMsg->Memory;
  1141. switch ( *pFormat )
  1142. {
  1143. case FC_FIXED_REPEAT :
  1144. // Increment past the FC_FIXED_REPEAT and FC_PAD.
  1145. pFormat += 2;
  1146. // Get the total number of times to repeat the pointer marshall.
  1147. RepeatCount = *((ushort *)pFormat)++;
  1148. break;
  1149. case FC_VARIABLE_REPEAT :
  1150. // Get the total number of times to repeat the pointer marshall.
  1151. RepeatCount = pStubMsg->MaxCount;
  1152. //
  1153. // Check if this variable repeat instance also has a variable
  1154. // offset (this would be the case for a conformant varying array
  1155. // of pointers). If so then increment the memory pointer to point
  1156. // to the actual first array element which is being marshalled.
  1157. //
  1158. if ( pFormat[1] == FC_VARIABLE_OFFSET )
  1159. pMemory += *((ushort *)(pFormat + 2)) * pStubMsg->Offset;
  1160. // else pFormat[1] == FC_FIXED_OFFSET - do nothing
  1161. // Increment past the FC_VARIABLE_REPEAT and FC_PAD.
  1162. pFormat += 2;
  1163. break;
  1164. default :
  1165. NDR_ASSERT(0,"NdrEmbeddedRepeatPointerFree : bad format char");
  1166. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  1167. return 0;
  1168. }
  1169. // Get the increment amount between successive pointers.
  1170. RepeatIncrement = *((ushort *)pFormat)++;
  1171. //
  1172. // Add the offset to the beginning of this array to the Memory
  1173. // pointer. This is the offset from the current embedding structure
  1174. // to the array whose pointers we're marshalling.
  1175. //
  1176. pStubMsg->Memory += *((ushort *)pFormat)++;
  1177. // Get the number of pointers in this repeat instance.
  1178. PointersSave = Pointers = *((ushort *)pFormat)++;
  1179. pFormatSave = pFormat;
  1180. //
  1181. // Loop over the number of array elements.
  1182. //
  1183. for ( ; RepeatCount--;
  1184. pMemory += RepeatIncrement,
  1185. pStubMsg->Memory += RepeatIncrement )
  1186. {
  1187. pFormat = pFormatSave;
  1188. Pointers = PointersSave;
  1189. //
  1190. // Loop over the number of pointers per array element (this can be
  1191. // zero for an array of structures).
  1192. //
  1193. for ( ; Pointers--; )
  1194. {
  1195. ppMemPtr = (uchar **)(pMemory + *((signed short *)pFormat));
  1196. // Increment to pointer's description.
  1197. pFormat += 4;
  1198. NdrPointerFree( pStubMsg,
  1199. *ppMemPtr,
  1200. pFormat );
  1201. // Increment to next pointer description.
  1202. pFormat += 4;
  1203. }
  1204. }
  1205. pStubMsg->Memory = pMemory;
  1206. // Return format string pointer past the array's pointer layout.
  1207. return pFormatSave + PointersSave * 8;
  1208. }