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.

395 lines
7.7 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. recv.c
  5. Abstract:
  6. This module contains the Recv code for SPUD.
  7. Author:
  8. John Ballard (jballard) 21-Oct-1996
  9. Revision History:
  10. Keith Moore (keithmo) 04-Feb-1998
  11. Cleanup, added much needed comments.
  12. --*/
  13. #include "spudp.h"
  14. #ifdef ALLOC_PRAGMA
  15. #pragma alloc_text( PAGE, SpudAfdRecvFastReq )
  16. #endif
  17. #if 0
  18. NOT PAGEABLE -- SpudAfdContinueRecv
  19. NOT PAGEABLE -- SpudAfdCompleteRecv
  20. #endif
  21. //
  22. // Public functions.
  23. //
  24. NTSTATUS
  25. SpudAfdRecvFastReq(
  26. PFILE_OBJECT fileObject,
  27. PAFD_RECV_INFO recvInfo,
  28. PSPUD_REQ_CONTEXT reqContext
  29. )
  30. /*++
  31. Routine Description:
  32. Attempts a fast-path AFD receive.
  33. Arguments:
  34. fileObject - The file object for the target socket.
  35. recvInfo - Information describing the receive.
  36. reqContext - The user-mode context for the request.
  37. Return Value:
  38. NTSTATUS - Completion status.
  39. --*/
  40. {
  41. NTSTATUS status;
  42. IO_STATUS_BLOCK localIoStatus;
  43. PSPUD_AFD_REQ_CONTEXT SpudReqContext;
  44. PIRP irp;
  45. PIO_STACK_LOCATION irpSp;
  46. PVOID completionPort;
  47. //
  48. // Sanity check.
  49. //
  50. PAGED_CODE();
  51. //
  52. // Let's check to see if fast I/O will work.
  53. //
  54. if( SpudAfdFastIoDeviceControl(
  55. fileObject,
  56. TRUE,
  57. (PVOID)recvInfo,
  58. sizeof(AFD_RECV_INFO),
  59. NULL,
  60. 0,
  61. IOCTL_AFD_RECEIVE,
  62. &localIoStatus,
  63. SpudAfdDeviceObject
  64. ) ) {
  65. //
  66. // Fast I/O succeeded.
  67. //
  68. if( reqContext->ReqType == TransmitFileAndRecv ) {
  69. BumpCount(CtrTransRecvFastRecv);
  70. } else {
  71. BumpCount(CtrSendRecvFastRecv);
  72. }
  73. //
  74. // Remember the completion status for this operation.
  75. //
  76. try {
  77. reqContext->IoStatus2 = localIoStatus;
  78. } except( EXCEPTION_EXECUTE_HANDLER) {
  79. localIoStatus.Status = GetExceptionCode();
  80. localIoStatus.Information = 0;
  81. }
  82. return localIoStatus.Status;
  83. }
  84. //
  85. // Fast I/O failed.
  86. //
  87. if (reqContext->ReqType == TransmitFileAndRecv) {
  88. BumpCount(CtrTransRecvSlowRecv);
  89. } else {
  90. BumpCount(CtrSendRecvSlowRecv);
  91. }
  92. //
  93. // It looks like we will have to it the hard way.
  94. // We will now build an IRP for AFD.
  95. //
  96. KeClearEvent( &fileObject->Event );
  97. //
  98. // Reference the completion port.
  99. //
  100. completionPort = SpudReferenceCompletionPort();
  101. if( completionPort == NULL ) {
  102. return STATUS_INVALID_DEVICE_REQUEST;
  103. }
  104. //
  105. // Allocate the IRP.
  106. //
  107. irp = IoAllocateIrp( SpudAfdDeviceObject->StackSize, TRUE );
  108. if (!irp) {
  109. SpudDereferenceCompletionPort();
  110. return STATUS_INSUFFICIENT_RESOURCES;
  111. }
  112. //
  113. // Allocate and initialize a kernel-mode context for this request.
  114. //
  115. status = SpudAllocateRequestContext(
  116. &SpudReqContext,
  117. reqContext,
  118. recvInfo,
  119. irp,
  120. &reqContext->IoStatus1
  121. );
  122. if( !NT_SUCCESS(status) ) {
  123. IoFreeIrp( irp );
  124. SpudDereferenceCompletionPort();
  125. return status;
  126. }
  127. //
  128. // Initialize the IRP, call the driver.
  129. //
  130. irp->RequestorMode = UserMode;
  131. irp->Tail.Overlay.OriginalFileObject = fileObject;
  132. irp->Tail.Overlay.Thread = PsGetCurrentThread();
  133. IoQueueThreadIrp( irp );
  134. irpSp = IoGetNextIrpStackLocation( irp );
  135. irp->MdlAddress = SpudReqContext->Mdl;
  136. SpudReqContext->Mdl = NULL;
  137. irpSp->MajorFunction = IRP_MJ_READ;
  138. irpSp->FileObject = fileObject;
  139. irpSp->DeviceObject = SpudAfdDeviceObject;
  140. irpSp->Parameters.Read.Length = (ULONG)SpudReqContext->IoStatus2.Information;
  141. // irpSp->Parameters.Read.Key = 0;
  142. // irpSp->Parameters.Read.ByteOffset.QuadPart = 0;
  143. IoSetCompletionRoutine(
  144. irp,
  145. SpudAfdCompleteRecv,
  146. SpudReqContext,
  147. TRUE,
  148. TRUE,
  149. TRUE
  150. );
  151. IoCallDriver( SpudAfdDeviceObject, irp );
  152. return STATUS_PENDING;
  153. } // SpudAfdRecvFastReq
  154. NTSTATUS
  155. SpudAfdContinueRecv(
  156. PDEVICE_OBJECT DeviceObject,
  157. PIRP Irp,
  158. PVOID Context
  159. )
  160. /*++
  161. Routine Description:
  162. Completion handler for IOCTL_AFD_SEND and IOCTL_AFD_TRANSMIT_FILE
  163. IRPs. This completion handler is responsible for initiating the
  164. receive part of the XxxAndRecv() API.
  165. Arguments:
  166. DeviceObject - The device object completing the request (unused).
  167. Irp - The IRP being completed.
  168. Context - The context associated with the request. This is actually
  169. the kernel-mode SPUD_REQ_CONTEXT for this request.
  170. Return Value:
  171. NTSTATUS - Completion status.
  172. --*/
  173. {
  174. NTSTATUS status;
  175. PSPUD_AFD_REQ_CONTEXT SpudReqContext = Context;
  176. PIO_STACK_LOCATION irpSp;
  177. PULONG majorFunction;
  178. PMDL mdl, nextMdl;
  179. //
  180. // Snag the completion status.
  181. //
  182. SpudReqContext->IoStatus1 = Irp->IoStatus;
  183. status = Irp->IoStatus.Status;
  184. //
  185. // Cleanup the IRP.
  186. //
  187. if( Irp->MdlAddress != NULL ) {
  188. for( mdl = Irp->MdlAddress ; mdl != NULL ; mdl = nextMdl ) {
  189. nextMdl = mdl->Next;
  190. MmUnlockPages( mdl );
  191. IoFreeMdl( mdl );
  192. }
  193. Irp->MdlAddress = NULL;
  194. }
  195. //
  196. // If the initial operation failed, then complete the request now
  197. // without issuing the receive.
  198. //
  199. if( !NT_SUCCESS(status) ) {
  200. SpudReqContext->IoStatus2.Status = 0;
  201. SpudReqContext->IoStatus2.Information = 0;
  202. SpudCompleteRequest( SpudReqContext );
  203. return STATUS_MORE_PROCESSING_REQUIRED;
  204. }
  205. //
  206. // Reinitialize the IRP and initiate the receive operation.
  207. //
  208. Irp->MdlAddress = SpudReqContext->Mdl;
  209. SpudReqContext->Mdl = NULL;
  210. irpSp = IoGetNextIrpStackLocation( Irp );
  211. irpSp->MajorFunction = IRP_MJ_READ;
  212. irpSp->MinorFunction = 0;
  213. irpSp->FileObject = Irp->Tail.Overlay.OriginalFileObject;
  214. irpSp->DeviceObject = SpudAfdDeviceObject;
  215. irpSp->Parameters.Read.Length = (ULONG)SpudReqContext->IoStatus2.Information;
  216. irpSp->Parameters.Read.Key = 0;
  217. irpSp->Parameters.Read.ByteOffset.QuadPart = 0;
  218. IoSetCompletionRoutine(
  219. Irp,
  220. SpudAfdCompleteRecv,
  221. SpudReqContext,
  222. TRUE,
  223. TRUE,
  224. TRUE
  225. );
  226. IoCallDriver( SpudAfdDeviceObject, Irp );
  227. //
  228. // Tell IO to stop processing this IRP.
  229. //
  230. return STATUS_MORE_PROCESSING_REQUIRED;
  231. } // SpudAfdContinueRecv
  232. NTSTATUS
  233. SpudAfdCompleteRecv(
  234. PDEVICE_OBJECT DeviceObject,
  235. PIRP Irp,
  236. PVOID Context
  237. )
  238. /*++
  239. Routine Description:
  240. Completion routine for receive IRPs issued as part of an XxxAndRecv().
  241. Arguments:
  242. DeviceObject - The device object completing the request (unused).
  243. Irp - The IRP being completed.
  244. Context - The context associated with the request. This is actually
  245. the kernel-mode SPUD_REQ_CONTEXT for this request.
  246. Return Value:
  247. NTSTATUS - Completion status.
  248. --*/
  249. {
  250. NTSTATUS status;
  251. PSPUD_AFD_REQ_CONTEXT SpudReqContext = Context;
  252. PMDL mdl, nextMdl;
  253. //
  254. // Snag the completion status.
  255. //
  256. SpudReqContext->IoStatus2 = Irp->IoStatus;
  257. status = Irp->IoStatus.Status;
  258. //
  259. // Cleanup the IRP.
  260. //
  261. if( Irp->MdlAddress != NULL ) {
  262. for( mdl = Irp->MdlAddress ; mdl != NULL ; mdl = nextMdl ) {
  263. nextMdl = mdl->Next;
  264. MmUnlockPages( mdl );
  265. IoFreeMdl( mdl );
  266. }
  267. Irp->MdlAddress = NULL;
  268. }
  269. //
  270. // Complete the original request.
  271. //
  272. SpudCompleteRequest( SpudReqContext );
  273. //
  274. // Tell IO to stop processing this IRP.
  275. //
  276. return STATUS_MORE_PROCESSING_REQUIRED;
  277. } // SpudAfdCompleteRecv