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

996 lines
25 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. marshall.cxx
  6. Abstract:
  7. Code for custom marshalling spooler structures sent via RPC/LPC.
  8. It handles 32-64 bit machine compatibility depending on the route the call is comming.
  9. It can come either from Kernel mode (NATIVE_CALL), an in-proc winspool.drv call (NATIVE_CALL),
  10. a 32 bit process (RPC_CALL) or a 64 bit process (RPC_CALL).
  11. For native calls we perform basic marshalling. For RPC_CALLS we perform custom marshalling.
  12. Because there is no way to distinguish if a call came from a 64b or 32b proc, we always do
  13. custom marshalling across processes/wire.
  14. Author:
  15. Ramanathan Venkatapathy (RamanV) 4/30/98
  16. Revision History:
  17. Adina Trufinescu (AdinaTru) 12/09/99
  18. --*/
  19. #include "spllibp.hxx"
  20. #pragma hdrstop
  21. #include "cstmarsh.h"
  22. /*++
  23. Routine Name:
  24. GetShrinkedSize
  25. Routine Description:
  26. Calculates the size of a 64bit structure as it is on 32bit.
  27. Arguments:
  28. pFieldInfo -- structure containing information about fields inside the structure.
  29. pShrinkedSize -- how much difference it between the structure'ssize on 32bit and 64bit
  30. Return Value:
  31. Size of the 32bit structure.
  32. Last Error:
  33. Not set.
  34. --*/
  35. EXTERN_C
  36. BOOL
  37. GetShrinkedSize(
  38. IN FieldInfo *pFieldInfo,
  39. OUT SIZE_T *pShrinkedSize
  40. )
  41. {
  42. DWORD Index = 0;
  43. ULONG_PTR Size = 0;
  44. ULONG_PTR Alignment = 0;
  45. BOOL ReturnValue = FALSE;
  46. *pShrinkedSize = 0;
  47. //
  48. // For each field in the structure adds the length and enforce field's alignment.
  49. // For data fileds, the alignment is the same on both 32b and 64b.
  50. //
  51. for (Index = 0; pFieldInfo[Index].Offset != 0xffffffff; ++Index)
  52. {
  53. switch (pFieldInfo[Index].Type)
  54. {
  55. case PTR_TYPE:
  56. {
  57. //
  58. // Treat pointers as they are on 32bit.
  59. //
  60. Size = sizeof(DWORD32);
  61. Alignment = sizeof(DWORD32);
  62. break;
  63. }
  64. case DATA_TYPE:
  65. {
  66. Size = pFieldInfo[Index].Size;
  67. Alignment = pFieldInfo[Index].Alignment;
  68. break;
  69. }
  70. default:
  71. {
  72. SetLastError(ERROR_INVALID_PARAMETER);
  73. goto End;
  74. }
  75. }
  76. //
  77. // Enforce alignment before adding the size of the next field.
  78. //
  79. *pShrinkedSize = (SIZE_T)(AlignIt((PBYTE)*pShrinkedSize, Alignment));
  80. //
  81. // Add field's size.
  82. //
  83. *pShrinkedSize += Size;
  84. }
  85. //
  86. // Almoust done. We need to align the 32b structure's size to 32bit since
  87. // structures come as an array.
  88. //
  89. Alignment = sizeof(DWORD32);
  90. *pShrinkedSize = (SIZE_T)(AlignIt((PBYTE)*pShrinkedSize, Alignment));
  91. ReturnValue = TRUE;
  92. End:
  93. return ReturnValue;
  94. }
  95. /*++
  96. Routine Name:
  97. MarshallDownStructure
  98. Routine Description:
  99. Marshalls down structures to be sent via RPC/LPC.
  100. Arguments:
  101. pStructure -- pointer to the structure to be marshalled down
  102. pFieldInfo -- structure containing information about fileds inside the structure
  103. StructureSize -- size of the unmarshalled structure
  104. RpcRoute -- indicates what type of marshalling we should do
  105. Return Value:
  106. TRUE if successful;
  107. Last Error:
  108. Set to ERROR_INVALID_PARAMETER if unknown Field type or architecture other than 32bit or 64bit.
  109. --*/
  110. EXTERN_C
  111. BOOL
  112. MarshallDownStructure(
  113. IN OUT PBYTE pStructure,
  114. IN FieldInfo *pFieldInfo,
  115. IN SIZE_T StructureSize,
  116. IN CALL_ROUTE Route
  117. )
  118. {
  119. BOOL ReturnValue = FALSE;
  120. if (!pStructure || !pFieldInfo)
  121. {
  122. SetLastError(ERROR_INVALID_PARAMETER);
  123. goto End;
  124. }
  125. switch (kPointerSize)
  126. {
  127. case kSpl32Ptr:
  128. {
  129. //
  130. // 32 bit server does not require special marshalling;
  131. //
  132. ReturnValue = BasicMarshallDownStructure(pStructure, pFieldInfo);
  133. break;
  134. }
  135. case kSpl64Ptr :
  136. {
  137. switch (Route)
  138. {
  139. case NATIVE_CALL:
  140. {
  141. //
  142. // The call came from Kernel Mode. In KM the structure is basic marshalled.
  143. // We need to do the same thing
  144. //
  145. ReturnValue = BasicMarshallDownStructure(pStructure, pFieldInfo);
  146. break;
  147. }
  148. case RPC_CALL:
  149. {
  150. //
  151. // The call came through RPC.
  152. // Do the custom marshalling regardless of caller's bitness.
  153. //
  154. ReturnValue = CustomMarshallDownStructure(pStructure, pFieldInfo, StructureSize);
  155. break;
  156. }
  157. default:
  158. {
  159. //
  160. // Unknown route; should never happen
  161. //
  162. SetLastError(ERROR_INVALID_PARAMETER);
  163. break;
  164. }
  165. }
  166. break;
  167. }
  168. default:
  169. {
  170. //
  171. // Unknown pointer size; should never happen
  172. //
  173. SetLastError(ERROR_INVALID_PARAMETER);
  174. break;
  175. }
  176. }
  177. End:
  178. return ReturnValue;
  179. }
  180. /*++
  181. Routine Name:
  182. MarshallDownEntry
  183. Routine Description:
  184. Custom marshalls down structures to be sent via RPC/LPC.
  185. Arguments:
  186. pStructure -- pointer to the structure to be marshalled down
  187. pNewStructure -- pointer to the new place where the structure will lay down
  188. in the array of marshalled down structures ( pStructure == pNewStructure on 32b)
  189. pFieldInfo -- structure containing information about fileds inside the structure
  190. StructureSize -- size of the unmarshalled structure
  191. RpcRoute -- indicates what type of marshalling we should do
  192. Return Value:
  193. TRUE if successful;
  194. Last Error:
  195. Set to ERROR_INVALID_PARAMETER if unknown Field type or architecture other than 32bit or 64bit.
  196. --*/
  197. BOOL
  198. MarshallDownEntry(
  199. IN OUT PBYTE pStructure,
  200. IN PBYTE pNewStructure,
  201. IN FieldInfo *pFieldInfo,
  202. IN SIZE_T StructureSize,
  203. IN CALL_ROUTE Route
  204. )
  205. {
  206. BOOL ReturnValue = FALSE;
  207. if (!pStructure || !pFieldInfo)
  208. {
  209. SetLastError(ERROR_INVALID_PARAMETER);
  210. goto End;
  211. }
  212. switch (kPointerSize)
  213. {
  214. case kSpl32Ptr:
  215. {
  216. //
  217. // 32 bit server does not require special marshalling
  218. //
  219. ReturnValue = BasicMarshallDownEntry(pStructure, pFieldInfo);
  220. break;
  221. }
  222. case kSpl64Ptr :
  223. {
  224. switch (Route)
  225. {
  226. case NATIVE_CALL:
  227. {
  228. //
  229. // The call came from Kernel Mode. In KM the structure is basic marshalled.
  230. // We need to do the same thing here.
  231. //
  232. ReturnValue = BasicMarshallDownEntry(pStructure, pFieldInfo);
  233. break;
  234. }
  235. case RPC_CALL:
  236. {
  237. //
  238. // The call came through RPC.
  239. // Do the custom marshalling regardless of caller's bitness.
  240. //
  241. ReturnValue = CustomMarshallDownEntry(pStructure, pNewStructure, pFieldInfo, StructureSize);
  242. break;
  243. }
  244. default:
  245. {
  246. //
  247. // Unknown route; should never happen
  248. //
  249. SetLastError(ERROR_INVALID_PARAMETER);
  250. break;
  251. }
  252. }
  253. break;
  254. }
  255. default:
  256. {
  257. //
  258. // Unknown pointer size; should never happen
  259. //
  260. SetLastError(ERROR_INVALID_PARAMETER);
  261. break;
  262. }
  263. }
  264. End:
  265. return ReturnValue;
  266. }
  267. /*++
  268. Routine Name:
  269. MarshallUpStructure
  270. Routine Description:
  271. Custom marshalls up structures to be sent via RPC/LPC.
  272. Arguments:
  273. pStructure -- pointer to the structure to be marshalled up
  274. pFieldInfo -- structure containing information about fileds inside the structure
  275. StructureSize -- size of the structure as it is to be when marsahlled up
  276. Route -- indicates what type of marshalling we should do
  277. Return Value:
  278. TRUE if successful.
  279. Last Error:
  280. Set to ERROR_INVALID_PARAMETER if unknown Field type or architecture other than 32bit or 64bit.
  281. --*/
  282. EXTERN_C
  283. BOOL
  284. MarshallUpStructure(
  285. IN OUT PBYTE pStructure,
  286. IN FieldInfo *pFieldInfo,
  287. IN SIZE_T StructureSize,
  288. IN CALL_ROUTE Route
  289. )
  290. {
  291. BOOL ReturnValue = FALSE;
  292. if (!pStructure || !pFieldInfo)
  293. {
  294. SetLastError(ERROR_INVALID_PARAMETER);
  295. goto End;
  296. }
  297. switch (kPointerSize)
  298. {
  299. case kSpl32Ptr:
  300. {
  301. ReturnValue = BasicMarshallUpStructure(pStructure, pFieldInfo);
  302. break;
  303. }
  304. case kSpl64Ptr:
  305. {
  306. switch (Route)
  307. {
  308. case NATIVE_CALL:
  309. {
  310. //
  311. // The call came from Kernel Mode. In KM the structure is basic marshalled.
  312. // We need to do the same thing here.
  313. //
  314. ReturnValue = BasicMarshallUpStructure(pStructure, pFieldInfo);
  315. break;
  316. }
  317. case RPC_CALL:
  318. {
  319. //
  320. // The call came through RPC.
  321. // Do the custom marshalling regardless of caller's bitness.
  322. //
  323. ReturnValue = CustomMarshallUpStructure(pStructure, pFieldInfo, StructureSize);
  324. break;
  325. }
  326. default:
  327. {
  328. //
  329. // Unknown route; should never happen
  330. //
  331. SetLastError(ERROR_INVALID_PARAMETER);
  332. break;
  333. }
  334. }
  335. break;
  336. }
  337. default:
  338. {
  339. //
  340. // Unknown pointer size; should never happen
  341. //
  342. SetLastError(ERROR_INVALID_PARAMETER);
  343. break;
  344. }
  345. }
  346. End:
  347. return ReturnValue;
  348. }
  349. /*++
  350. Routine Name:
  351. MarshallUpEntry
  352. Routine Description:
  353. Custom marshalls up structures to be sent via RPC/LPC.
  354. Arguments:
  355. pStructure -- pointer to the structure to be marshalled up
  356. pNewStructure -- pointer to the new place where the structure will lay down
  357. in the array of marshalled up structures ( pStructure == pNewStructure on 32b)
  358. pFieldInfo -- structure containing information about fileds inside the structure
  359. StructureSize -- size of the structure as it is to be when marshalled up
  360. Route -- determine what type of marshalling will be performed
  361. Return Value:
  362. TRUE if successful.
  363. Last Error:
  364. Set to ERROR_INVALID_PARAMETER if unknown Field type or architecture other than 32bit or 64bit.
  365. --*/
  366. BOOL
  367. MarshallUpEntry(
  368. IN OUT PBYTE pStructure,
  369. IN PBYTE pNewStructure,
  370. IN FieldInfo *pFieldInfo,
  371. IN SIZE_T StructureSize,
  372. IN SIZE_T ShrinkedSize,
  373. IN CALL_ROUTE Route
  374. )
  375. {
  376. BOOL ReturnValue = FALSE;
  377. if (!pStructure || !pFieldInfo)
  378. {
  379. SetLastError(ERROR_INVALID_PARAMETER);
  380. goto End;
  381. }
  382. switch (kPointerSize)
  383. {
  384. case kSpl32Ptr:
  385. {
  386. ReturnValue = BasicMarshallUpEntry(pStructure, pFieldInfo);
  387. break;
  388. }
  389. case kSpl64Ptr :
  390. {
  391. switch (Route)
  392. {
  393. case NATIVE_CALL:
  394. {
  395. //
  396. // The call came from Kernel Mode. In KM the structure is basic marshalled.
  397. // We need to do the same thing here.
  398. //
  399. ReturnValue = BasicMarshallUpEntry(pStructure, pFieldInfo);
  400. break;
  401. }
  402. case RPC_CALL:
  403. {
  404. //
  405. // The call came through RPC.
  406. // Do the custom marshalling regardless of caller's bitness.
  407. //
  408. ReturnValue = CustomMarshallUpEntry(pStructure, pNewStructure, pFieldInfo,
  409. StructureSize, ShrinkedSize);
  410. break;
  411. }
  412. default:
  413. {
  414. //
  415. // Unknown route; should never happen
  416. //
  417. SetLastError(ERROR_INVALID_PARAMETER);
  418. break;
  419. }
  420. }
  421. break;
  422. }
  423. default:
  424. {
  425. //
  426. // Unknown pointer size; should never happen
  427. //
  428. SetLastError(ERROR_INVALID_PARAMETER);
  429. break;
  430. }
  431. }
  432. End:
  433. return ReturnValue;
  434. }
  435. /*++
  436. Routine Name:
  437. MarshallDownStructuresArray
  438. Routine Description:
  439. Custom marshalls down array of structures to be sent via RPC/LPC.
  440. Arguments:
  441. pBufferArray -- pointer to the buffer containing the array of structures and packed data
  442. cReturned -- number of structures returned
  443. pFieldInfo -- structure containing information about fields inside the structure
  444. StructureSize -- size of the 64bit structure
  445. RpcRoute -- indicates what type of marshalling we should do
  446. Return Value:
  447. TRUE if successful.
  448. Last Error:
  449. Set to ERROR_INVALID_PARAMETER if unknown Field type or architecture other than 32bit or 64bit.
  450. --*/
  451. EXTERN_C
  452. BOOL
  453. MarshallDownStructuresArray(
  454. IN OUT PBYTE pBufferArray,
  455. IN DWORD cReturned,
  456. IN FieldInfo *pFieldInfo,
  457. IN SIZE_T StructureSize,
  458. IN CALL_ROUTE Route
  459. )
  460. {
  461. DWORD Index = 0;
  462. PBYTE pStructure, pNewStructure;
  463. SIZE_T ShrinkedSize = 0;
  464. BOOL ReturnValue = FALSE;
  465. //
  466. // Check if there are any structures in the array.
  467. // This check must come before the one against pBufferArray and pFieldInfo.
  468. // If the Enum function didn't enumerate anything, we need to return success.
  469. //
  470. if (cReturned == 0) {
  471. ReturnValue = TRUE;
  472. goto End;
  473. }
  474. if (!pBufferArray || !pFieldInfo)
  475. {
  476. SetLastError(ERROR_INVALID_PARAMETER);
  477. goto End;
  478. }
  479. switch (kPointerSize)
  480. {
  481. case kSpl32Ptr:
  482. {
  483. //
  484. // The size of the structure remains the same on 32b.
  485. //
  486. ShrinkedSize = StructureSize;
  487. break;
  488. }
  489. case kSpl64Ptr:
  490. {
  491. switch (Route)
  492. {
  493. case NATIVE_CALL:
  494. {
  495. //
  496. // There is no need of special marshalling since the structures
  497. // need to stay padding unaltered.
  498. //
  499. ShrinkedSize = StructureSize;
  500. break;
  501. }
  502. case RPC_CALL:
  503. {
  504. //
  505. // Get the size of the 32b structure ; it takes care of both pointers and pointers/data alignments
  506. //
  507. if (!GetShrinkedSize(pFieldInfo, &ShrinkedSize))
  508. {
  509. goto End;
  510. }
  511. break;
  512. }
  513. default:
  514. {
  515. //
  516. // Unknown route size; should never happen
  517. //
  518. SetLastError(ERROR_INVALID_PARAMETER);
  519. break;
  520. }
  521. }
  522. break;
  523. }
  524. default:
  525. {
  526. SetLastError(ERROR_INVALID_PARAMETER);
  527. goto End;
  528. }
  529. }
  530. //
  531. // pStructure is the pointer to the place where the 64b structure lays down in the array
  532. // pNewStructure is the pointer to the new place where the 32b structure will lay down in the array
  533. // MarshallDownEntry returns a pointer to the end of the just marshalled 32b structure which is
  534. // the new place where the next 32b marshalled structure will lay down in the array
  535. //
  536. for( Index = 0, pNewStructure = pStructure = pBufferArray;
  537. Index < cReturned ;
  538. Index++ , pStructure += StructureSize , pNewStructure += ShrinkedSize )
  539. {
  540. if (!MarshallDownEntry(pStructure, pNewStructure, pFieldInfo, StructureSize, Route))
  541. {
  542. goto End;
  543. }
  544. }
  545. ReturnValue = TRUE;
  546. End:
  547. return ReturnValue;
  548. }
  549. /*++
  550. Routine Name:
  551. MarshallUpStructuresArray
  552. Routine Description:
  553. Custom marshalls up array of structures to be sent via RPC/LPC.
  554. Arguments:
  555. pBufferArray -- pointer to the buffer containing the array of structures and packed data
  556. cReturned -- number of structures returned
  557. pFieldInfo -- structure containing information about fileds inside the structure
  558. StructureSize -- size of the 64bit structure ( including the padding )
  559. Route -- determine what type of marshalling will be performed
  560. Return Value:
  561. TRUE if successful.
  562. Last Error:
  563. Set to ERROR_INVALID_PARAMETER if unknown Field type or architecture other than 32bit or 64bit.
  564. --*/
  565. EXTERN_C
  566. BOOL
  567. MarshallUpStructuresArray(
  568. IN OUT PBYTE pBufferArray,
  569. IN DWORD cReturned,
  570. IN FieldInfo *pFieldInfo,
  571. IN SIZE_T StructureSize,
  572. IN CALL_ROUTE Route
  573. )
  574. {
  575. INT32 Index = 0;
  576. PBYTE pStructure, pNextStructure;
  577. SIZE_T ShrinkedSize = 0;
  578. BOOL ReturnValue = FALSE;
  579. //
  580. // Check if there are any structures in the array.
  581. // This check must come before the one against pBufferArray and pFieldInfo.
  582. // If the Enum function didn't enumerate anything, we need to return success.
  583. //
  584. if (cReturned == 0) {
  585. ReturnValue = TRUE;
  586. goto End;
  587. }
  588. if (!pBufferArray || !pFieldInfo)
  589. {
  590. SetLastError(ERROR_INVALID_PARAMETER);
  591. goto End;
  592. }
  593. switch (kPointerSize)
  594. {
  595. case kSpl32Ptr:
  596. {
  597. //
  598. // The size of the structure remains the same on 32b.
  599. //
  600. ShrinkedSize = StructureSize;
  601. break;
  602. }
  603. case kSpl64Ptr:
  604. {
  605. //
  606. // Get the size of the 32b structure ; it takes care of both pointers and pointers/data alignments
  607. //
  608. if (!GetShrinkedSize(pFieldInfo, &ShrinkedSize))
  609. {
  610. goto End;
  611. }
  612. break;
  613. }
  614. default:
  615. {
  616. SetLastError(ERROR_INVALID_PARAMETER);
  617. goto End;
  618. }
  619. }
  620. //
  621. // pBufferArray is an array of 32b stuctures;
  622. // pStructure is the pointer to the place where the 32b structure lays down in the array
  623. // pNewStructure is the pointer to the new place where the 64b structure will lay down in the array
  624. //
  625. for (Index = cReturned - 1; Index >= 0 ; Index--)
  626. {
  627. pStructure = pBufferArray + Index * ShrinkedSize;
  628. pNextStructure = pBufferArray + Index * StructureSize;
  629. if (!MarshallUpEntry(pStructure, pNextStructure, pFieldInfo, StructureSize, ShrinkedSize, Route))
  630. {
  631. goto End;
  632. }
  633. }
  634. ReturnValue = TRUE;
  635. End:
  636. return ReturnValue;
  637. }
  638. /*++
  639. Routine Name:
  640. UpdateBufferSize
  641. Routine Description:
  642. UpdateBufferSize adjusts the number of bytes required for
  643. returning the structures based on 32 and 64 bit clients and servers.
  644. Arguments:
  645. pOffsets - pointer to Offset struct
  646. cbStruct - sizeof struct
  647. cbStructAlign - sizeof struct aligned on 32b
  648. pcNeeded - pointer to number of bytes needed
  649. cbBuf - sizeof input buffer
  650. dwError - last error from RPC call
  651. pcReturned - pointer to number of returned structures
  652. (valid only if dwError == ERROR_SUCCESS)
  653. Return Value:
  654. Last Error; This function is called right after a RPC call.
  655. dwError is the return value of RPC call.
  656. The return value of this function is the result of applying of this code on the dwError.
  657. Last Error:
  658. Not set.
  659. --*/
  660. EXTERN_C
  661. DWORD
  662. UpdateBufferSize(
  663. IN FieldInfo *pFieldInfo,
  664. IN SIZE_T cbStruct,
  665. IN OUT LPDWORD pcbNeeded,
  666. IN DWORD cbBuf,
  667. IN DWORD dwError,
  668. IN LPDWORD pcReturned
  669. )
  670. {
  671. DWORD cStructures = 0;
  672. SIZE_T cbShrinkedStruct = 0;
  673. if (dwError != ERROR_SUCCESS &&
  674. dwError != ERROR_MORE_DATA &&
  675. dwError != ERROR_INSUFFICIENT_BUFFER)
  676. {
  677. //
  678. // RpcCall failed, no need to update required size
  679. //
  680. goto End;
  681. }
  682. if (!cbStruct)
  683. {
  684. dwError = ERROR_INVALID_PARAMETER;
  685. goto End;
  686. }
  687. switch (kPointerSize)
  688. {
  689. case kSpl32Ptr:
  690. {
  691. //
  692. // The pointers are not bigger on the server. Hence no adjustment is
  693. // required.
  694. //
  695. break;
  696. }
  697. case kSpl64Ptr:
  698. {
  699. if (!GetShrinkedSize(pFieldInfo, &cbShrinkedStruct))
  700. {
  701. dwError = ERROR_INVALID_PARAMETER;
  702. goto End;
  703. }
  704. //
  705. // Increase the required size of buffer. This may be superfluous in the 64-64
  706. // connection but this solution is simpler than adjusting pcbNeeded on the server.
  707. //
  708. // Count the number of structures to be returned
  709. // *pcbNeeded must be divided with the size of the structure on 32 bit.
  710. //
  711. cStructures = *pcbNeeded / (DWORD32)cbShrinkedStruct;
  712. //
  713. // For each structure, pcbNeeded is increased with the number of bites the pointers shrink
  714. // and the number of bites needed fpr padding
  715. // cbStruct - cbStructAlign is the number of bytes the compiler padds
  716. //
  717. *pcbNeeded += (DWORD) (cStructures * (cbStruct - cbShrinkedStruct));
  718. if (cbBuf < *pcbNeeded && dwError == ERROR_SUCCESS)
  719. {
  720. dwError = ERROR_INSUFFICIENT_BUFFER;
  721. }
  722. break;
  723. }
  724. default:
  725. {
  726. //
  727. // Invalid pointer size; should not occur.
  728. //
  729. dwError = ERROR_INVALID_PARAMETER;
  730. break;
  731. }
  732. }
  733. End:
  734. return dwError;
  735. }
  736. /*++
  737. Routine Name:
  738. AdjustPointers
  739. Routine Description:
  740. AdjustPointers adjusts pointer fields inside the structure.
  741. Arguments:
  742. pStructure -- pointer to a structructure
  743. pFieldInfo -- contains information about fields inside the structure
  744. cbAdjustment -- quantity to add to all pointer fields inside the structure
  745. Return Value:
  746. None.
  747. Last Error:
  748. Not set.
  749. --*/
  750. EXTERN_C
  751. VOID
  752. AdjustPointers
  753. ( IN PBYTE pStructure,
  754. IN FieldInfo *pFieldInfo,
  755. IN ULONG_PTR cbAdjustment
  756. )
  757. { PBYTE *pOffset = NULL;
  758. DWORD Index = 0;
  759. DWORD32 Offset = 0;
  760. for (Index = 0; Offset = pFieldInfo[Index].Offset, Offset != 0xffffffff; ++Index)
  761. {
  762. if (pFieldInfo[Index].Type == PTR_TYPE)
  763. {
  764. pOffset = (PBYTE *)(pStructure + Offset);
  765. if ( *pOffset )
  766. {
  767. *pOffset += (ULONG_PTR)cbAdjustment;
  768. }
  769. }
  770. }
  771. }
  772. /*++
  773. Routine Name:
  774. AdjustPointersInStructuresArray
  775. Routine Description:
  776. AdjustPointersInStructuresArray adjusts pointer fields
  777. inside the each structure of an array.
  778. Arguments:
  779. pBufferArray -- pointer to the buffer containing the array of structures
  780. cReturned -- number of structures in array
  781. pFieldInfo -- contains information about fields inside the structure
  782. StructureSize -- size of structure
  783. cbAdjustment -- quantity to add to all pointer fields inside the structure
  784. Return Value:
  785. None.
  786. Last Error:
  787. Not set.
  788. --*/
  789. EXTERN_C
  790. VOID
  791. AdjustPointersInStructuresArray(
  792. IN PBYTE pBufferArray,
  793. IN DWORD cReturned,
  794. IN FieldInfo *pFieldInfo,
  795. IN SIZE_T StructureSize,
  796. IN ULONG_PTR cbAdjustment
  797. )
  798. {
  799. INT32 Index = 0;
  800. PBYTE pStructure;
  801. if (cReturned && cbAdjustment && pBufferArray && pFieldInfo)
  802. {
  803. for (Index = cReturned - 1; Index >= 0 ; Index--)
  804. {
  805. pStructure = pBufferArray + Index * StructureSize;
  806. //
  807. // Call AdjustPointers for each entry in the array
  808. //
  809. AdjustPointers(pStructure, pFieldInfo, cbAdjustment);
  810. }
  811. }
  812. }