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.

328 lines
7.0 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. misc.c
  5. Abstract:
  6. This module implemets helper routines not readily available
  7. in kernel or TDI libraries for ws2ifsl.sys driver.
  8. Author:
  9. Vadim Eydelman (VadimE) Oct-1997 (Inspired by AFD)
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma alloc_text(PAGE, AllocateMdlChain)
  14. #pragma alloc_text(PAGE, CopyBufferToMdlChain)
  15. #pragma alloc_text(PAGE, CopyMdlChainToBuffer)
  16. VOID
  17. AllocateMdlChain(
  18. IN PIRP Irp,
  19. IN LPWSABUF BufferArray,
  20. IN ULONG BufferCount,
  21. OUT PULONG TotalByteCount
  22. )
  23. /*++
  24. Routine Description:
  25. Allocates a MDL chain describing the WSABUF array and attaches
  26. the chain to the specified IRP.
  27. Arguments:
  28. Irp - The IRP that will receive the MDL chain.
  29. BufferArray - Points to an array of WSABUF structures describing
  30. the user's buffers.
  31. BufferCount - Contains the number of WSABUF structures in the
  32. array.
  33. TotalByteCount - Will receive the total number of BYTEs described
  34. by the WSABUF array.
  35. Return Value:
  36. None
  37. Note:
  38. Raises appropriate exception if probing/allocation fails
  39. --*/
  40. {
  41. PMDL currentMdl;
  42. PMDL * chainTarget;
  43. KPROCESSOR_MODE previousMode;
  44. ULONG totalLength;
  45. PVOID bufferPointer;
  46. ULONG bufferLength;
  47. PAGED_CODE ();
  48. //
  49. // Sanity check.
  50. //
  51. ASSERT( Irp != NULL );
  52. ASSERT( Irp->MdlAddress == NULL );
  53. ASSERT( BufferArray != NULL );
  54. ASSERT( BufferCount > 0 );
  55. ASSERT( TotalByteCount != NULL );
  56. //
  57. // Get the previous processor mode.
  58. //
  59. previousMode = Irp->RequestorMode;
  60. if ((BufferArray == NULL)
  61. || (BufferCount == 0)
  62. // Check for integer overflow (disabled by compiler)
  63. || (BufferCount>(MAXULONG/sizeof (WSABUF)))) {
  64. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  65. }
  66. if( previousMode != KernelMode ) {
  67. //
  68. // Probe the WSABUF array.
  69. //
  70. ProbeForRead(
  71. BufferArray, // Address
  72. BufferCount * sizeof(WSABUF), // Length
  73. sizeof(ULONG) // Alignment
  74. );
  75. }
  76. //
  77. // Get into a known state.
  78. //
  79. currentMdl = NULL;
  80. chainTarget = &Irp->MdlAddress;
  81. totalLength = 0;
  82. //
  83. // Scan the array.
  84. //
  85. do {
  86. bufferPointer = BufferArray->buf;
  87. bufferLength = BufferArray->len;
  88. if( bufferPointer != NULL &&
  89. bufferLength > 0 ) {
  90. //
  91. // Update the total byte counter.
  92. //
  93. totalLength += bufferLength;
  94. //
  95. // Create a new MDL.
  96. //
  97. currentMdl = IoAllocateMdl(
  98. bufferPointer, // VirtualAddress
  99. bufferLength, // Length
  100. FALSE, // SecondaryBuffer
  101. TRUE, // ChargeQuota
  102. NULL // Irp
  103. );
  104. if( currentMdl != NULL ) {
  105. //
  106. // Chain the MDL onto the IRP. In theory, we could
  107. // do this by passing the IRP into IoAllocateMdl(),
  108. // but IoAllocateMdl() does a linear scan on the MDL
  109. // chain to find the last one in the chain.
  110. //
  111. // We can do much better.
  112. //
  113. *chainTarget = currentMdl;
  114. chainTarget = &currentMdl->Next;
  115. //
  116. // Advance to the next WSABUF structure.
  117. //
  118. BufferArray++;
  119. } else {
  120. //
  121. // Cannot allocate new MDL, raise exception.
  122. //
  123. ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
  124. }
  125. }
  126. } while( --BufferCount );
  127. //
  128. // Ensure the MDL chain is NULL terminated.
  129. //
  130. ASSERT( *chainTarget == NULL );
  131. //
  132. // Return the total buffer count.
  133. //
  134. *TotalByteCount = totalLength;
  135. } // AllocateMdlChain
  136. ULONG
  137. CopyMdlChainToBuffer(
  138. IN PMDL SourceMdlChain,
  139. IN PVOID Destination,
  140. IN ULONG DestinationLength
  141. )
  142. /*++
  143. Routine Description:
  144. Copies data from a MDL chain to a linear buffer.
  145. Assumes that MDL in the right process context
  146. (virtual address is valid but it may not be mapped into system space)
  147. Arguments:
  148. SourceMdlChain - chain of MDL to copy buffer from.
  149. Destination - Points to the linear destination of the data.
  150. DestinationLength - The length of Destination.
  151. Return Value:
  152. ULONG - The number of bytes copied.
  153. --*/
  154. {
  155. ULONG SrcBytesLeft = 0;
  156. PUCHAR Dst = Destination, Src;
  157. PAGED_CODE ();
  158. //ASSERT (SourceMdlChain->Process==PsGetCurrentProcess ());
  159. while (DestinationLength != 0) {
  160. do {
  161. if (SourceMdlChain == NULL) {
  162. goto Done;
  163. }
  164. Src = MmGetMdlVirtualAddress (SourceMdlChain);
  165. SrcBytesLeft = MmGetMdlByteCount (SourceMdlChain);
  166. SourceMdlChain = SourceMdlChain->Next;
  167. }
  168. while (SrcBytesLeft == 0);
  169. if (SrcBytesLeft >= DestinationLength) {
  170. RtlCopyMemory (Dst, Src, DestinationLength);
  171. Dst += DestinationLength;
  172. break;
  173. } else {
  174. RtlCopyMemory (Dst, Src, SrcBytesLeft);
  175. DestinationLength -= SrcBytesLeft;
  176. Dst += SrcBytesLeft;
  177. }
  178. }
  179. Done:
  180. return (ULONG)(Dst - (PUCHAR)Destination);
  181. } // CopyMdlChainToBuffer
  182. ULONG
  183. CopyBufferToMdlChain(
  184. IN PVOID Source,
  185. IN ULONG SourceLength,
  186. IN PMDL DestinationMdlChain
  187. )
  188. /*++
  189. Routine Description:
  190. Copies data from a linear buffer to a MDL chain.
  191. Assumes that MDL in the right process context
  192. (virtual address is valid but it may not be mapped into system space)
  193. Arguments:
  194. Source - Points to the linear source of the data.
  195. SourceLength - The length of Source.
  196. DestinationMdlChain - chain of MDL to copy buffer to.
  197. Return Value:
  198. ULONG - The number of bytes copied.
  199. --*/
  200. {
  201. ULONG DstBytesLeft = 0;
  202. PUCHAR Dst, Src = Source;
  203. // ASSERT (DestinationMdlChain->Process==PsGetCurrentProcess ());
  204. while (SourceLength != 0) {
  205. do {
  206. if (DestinationMdlChain == NULL) {
  207. goto Done;
  208. }
  209. Dst = MmGetMdlVirtualAddress (DestinationMdlChain);
  210. DstBytesLeft = MmGetMdlByteCount (DestinationMdlChain);
  211. DestinationMdlChain = DestinationMdlChain->Next;
  212. }
  213. while (DstBytesLeft == 0);
  214. if (DstBytesLeft >= SourceLength) {
  215. RtlCopyMemory (Dst, Src, SourceLength);
  216. Src += SourceLength;
  217. break;
  218. } else {
  219. RtlCopyMemory (Dst, Src, DstBytesLeft);
  220. SourceLength -= DstBytesLeft;
  221. Src += DstBytesLeft;
  222. }
  223. }
  224. Done:
  225. return (ULONG)(Src - (PUCHAR)Source);
  226. } // CopyBufferToMdlChain