Leaked source code of windows server 2003
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.

588 lines
15 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. recv.c
  5. Abstract:
  6. NDIS send entry points and utility routines to handle receiving
  7. data.
  8. Environment:
  9. Kernel mode only.
  10. Revision History:
  11. alid 10/22/2001 modified for TunMp driver
  12. arvindm 4/6/2000 Created
  13. --*/
  14. #include "precomp.h"
  15. #define __FILENUMBER 'VCER'
  16. NTSTATUS
  17. TunRead(
  18. IN PDEVICE_OBJECT pDeviceObject,
  19. IN PIRP pIrp
  20. )
  21. /*++
  22. Routine Description:
  23. Dispatch routine to handle IRP_MJ_READ.
  24. Arguments:
  25. pDeviceObject - pointer to our device object
  26. pIrp - Pointer to request packet
  27. Return Value:
  28. NT status code.
  29. --*/
  30. {
  31. PIO_STACK_LOCATION pIrpSp;
  32. ULONG FunctionCode;
  33. NTSTATUS NtStatus;
  34. PTUN_ADAPTER pAdapter;
  35. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  36. pAdapter = pIrpSp->FileObject->FsContext;
  37. DEBUGP(DL_LOUD, ("==>TunRead, pAdapter %p\n",
  38. pAdapter));
  39. do
  40. {
  41. //
  42. // Validate!
  43. //
  44. if (pAdapter == NULL)
  45. {
  46. DEBUGP(DL_FATAL, ("Read: NULL FsContext on FileObject %p\n",
  47. pIrpSp->FileObject));
  48. NtStatus = STATUS_INVALID_HANDLE;
  49. break;
  50. }
  51. TUN_STRUCT_ASSERT(pAdapter, mc);
  52. if (pIrp->MdlAddress == NULL)
  53. {
  54. DEBUGP(DL_FATAL, ("Read: NULL MDL address on IRP %p\n", pIrp));
  55. NtStatus = STATUS_INVALID_PARAMETER;
  56. break;
  57. }
  58. //
  59. // Try to get a virtual address for the MDL.
  60. //
  61. if (MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority) == NULL)
  62. {
  63. DEBUGP(DL_FATAL, ("Read: MmGetSystemAddr failed for IRP %p, MDL %p\n",
  64. pIrp, pIrp->MdlAddress));
  65. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  66. break;
  67. }
  68. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  69. if (TUN_TEST_FLAGS(pAdapter, TUN_ADAPTER_OFF))
  70. {
  71. DEBUGP(DL_WARN, ("TunRead, Adapter off. pAdapter %p\n",
  72. pAdapter));
  73. TUN_RELEASE_LOCK(&pAdapter->Lock);
  74. NtStatus = STATUS_INVALID_DEVICE_STATE;
  75. break;
  76. }
  77. //
  78. // Add this IRP to the list of pended Read IRPs
  79. //
  80. TUN_INSERT_TAIL_LIST(&pAdapter->PendedReads, &pIrp->Tail.Overlay.ListEntry);
  81. TUN_REF_ADAPTER(pAdapter); // pended read IRP
  82. pAdapter->PendedReadCount++;
  83. //
  84. // Set up the IRP for possible cancellation.
  85. //
  86. pIrp->Tail.Overlay.DriverContext[0] = (PVOID)pAdapter;
  87. IoMarkIrpPending(pIrp);
  88. IoSetCancelRoutine(pIrp, TunCancelRead);
  89. TUN_RELEASE_LOCK(&pAdapter->Lock);
  90. NtStatus = STATUS_PENDING;
  91. //
  92. // Run the service routine for reads.
  93. //
  94. TunServiceReads(pAdapter);
  95. break;
  96. }
  97. while (FALSE);
  98. if (NtStatus != STATUS_PENDING)
  99. {
  100. TUN_ASSERT(NtStatus != STATUS_SUCCESS);
  101. pIrp->IoStatus.Information = 0;
  102. pIrp->IoStatus.Status = NtStatus;
  103. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  104. }
  105. DEBUGP(DL_LOUD, ("<==TunRead, pAdapter %p\n",
  106. pAdapter));
  107. return (NtStatus);
  108. }
  109. VOID
  110. TunCancelRead(
  111. IN PDEVICE_OBJECT pDeviceObject,
  112. IN PIRP pIrp
  113. )
  114. /*++
  115. Routine Description:
  116. Cancel a pending read IRP. We unlink the IRP from the open context
  117. queue and complete it.
  118. Arguments:
  119. pDeviceObject - pointer to our device object
  120. pIrp - IRP to be cancelled
  121. Return Value:
  122. None
  123. --*/
  124. {
  125. PTUN_ADAPTER pAdapter;
  126. PLIST_ENTRY pEnt;
  127. PLIST_ENTRY pIrpEntry;
  128. BOOLEAN Found;
  129. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  130. Found = FALSE;
  131. pAdapter = (PTUN_ADAPTER) pIrp->Tail.Overlay.DriverContext[0];
  132. DEBUGP(DL_LOUD, ("==>TunCancelRead, pAdapter %p\n",
  133. pAdapter));
  134. TUN_STRUCT_ASSERT(pAdapter, mc);
  135. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  136. //
  137. // Locate the IRP in the pended read queue and remove it if found.
  138. //
  139. for (pIrpEntry = pAdapter->PendedReads.Flink;
  140. pIrpEntry != &pAdapter->PendedReads;
  141. pIrpEntry = pIrpEntry->Flink)
  142. {
  143. if (pIrp == CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry))
  144. {
  145. TUN_REMOVE_ENTRY_LIST(&pIrp->Tail.Overlay.ListEntry);
  146. pAdapter->PendedReadCount--;
  147. Found = TRUE;
  148. break;
  149. }
  150. }
  151. if ((!TUN_TEST_FLAG(pAdapter, TUN_ADAPTER_ACTIVE)) &&
  152. (pAdapter->PendedSendCount == 0) &&
  153. (pAdapter->PendedReadCount == 0) &&
  154. (TUN_TEST_FLAG(pAdapter, TUN_COMPLETE_REQUEST)))
  155. {
  156. TUN_CLEAR_FLAG(pAdapter, TUN_COMPLETE_REQUEST);
  157. TUN_RELEASE_LOCK(&pAdapter->Lock);
  158. NdisMSetInformationComplete(&pAdapter->MiniportHandle,
  159. NDIS_STATUS_SUCCESS);
  160. }
  161. else
  162. {
  163. TUN_RELEASE_LOCK(&pAdapter->Lock);
  164. }
  165. if (Found)
  166. {
  167. DEBUGP(DL_LOUD, ("CancelRead: Open %p, IRP %p\n", pAdapter, pIrp));
  168. pIrp->IoStatus.Status = STATUS_CANCELLED;
  169. pIrp->IoStatus.Information = 0;
  170. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  171. TUN_DEREF_ADAPTER(pAdapter); // Cancel removed pended Read
  172. }
  173. DEBUGP(DL_LOUD, ("<==TunCancelRead, pAdapter %p\n",
  174. pAdapter));
  175. }
  176. VOID
  177. TunServiceReads(
  178. IN PTUN_ADAPTER pAdapter
  179. )
  180. /*++
  181. Routine Description:
  182. Utility routine to copy received data into user buffers and
  183. complete READ IRPs.
  184. Arguments:
  185. pAdapter - pointer to open context
  186. Return Value:
  187. None
  188. --*/
  189. {
  190. PIRP pIrp;
  191. PLIST_ENTRY pIrpEntry;
  192. PNDIS_PACKET pRcvPacket;
  193. PLIST_ENTRY pRcvPacketEntry;
  194. PUCHAR pSrc, pDst;
  195. ULONG BytesRemaining; // at pDst
  196. PNDIS_BUFFER pNdisBuffer;
  197. ULONG BytesAvailable, BytesCopied;
  198. DEBUGP(DL_VERY_LOUD, ("==>ServiceReads: Adapter %p/%x\n",
  199. pAdapter, pAdapter->Flags));
  200. TUN_REF_ADAPTER(pAdapter);
  201. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  202. while (!TUN_IS_LIST_EMPTY(&pAdapter->PendedReads) &&
  203. !TUN_IS_LIST_EMPTY(&pAdapter->RecvPktQueue))
  204. {
  205. //
  206. // Get the first pended Read IRP
  207. //
  208. pIrpEntry = pAdapter->PendedReads.Flink;
  209. pIrp = CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry);
  210. //
  211. // Check to see if it is being cancelled.
  212. //
  213. if (IoSetCancelRoutine(pIrp, NULL))
  214. {
  215. //
  216. // It isn't being cancelled, and can't be cancelled henceforth.
  217. //
  218. RemoveEntryList(pIrpEntry);
  219. //
  220. // NOTE: we decrement PendedReadCount way below in the
  221. // while loop, to avoid letting through a thread trying
  222. // to unbind.
  223. //
  224. }
  225. else
  226. {
  227. //
  228. // The IRP is being cancelled; let the cancel routine handle it.
  229. //
  230. DEBUGP(DL_LOUD, ("ServiceReads: Adapter %p, skipping cancelled IRP %p\n",
  231. pAdapter, pIrp));
  232. continue;
  233. }
  234. //
  235. // Get the first queued receive packet
  236. //
  237. pRcvPacketEntry = pAdapter->RecvPktQueue.Flink;
  238. RemoveEntryList(pRcvPacketEntry);
  239. pAdapter->RecvPktCount--;
  240. TUN_RELEASE_LOCK(&pAdapter->Lock);
  241. TUN_DEREF_ADAPTER(pAdapter); // Service: dequeue rcv packet
  242. pRcvPacket = TUN_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry);
  243. //
  244. // Copy as much data as possible from the receive packet to
  245. // the IRP MDL.
  246. //
  247. pDst = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
  248. TUN_ASSERT(pDst != NULL); // since it was already mapped
  249. BytesRemaining = MmGetMdlByteCount(pIrp->MdlAddress);
  250. pNdisBuffer = pRcvPacket->Private.Head;
  251. BytesCopied = 0;
  252. while (BytesRemaining > 0 && (pNdisBuffer != NULL))
  253. {
  254. NdisQueryBufferSafe(pNdisBuffer, &pSrc, &BytesAvailable, NormalPagePriority);
  255. if (pSrc == NULL)
  256. {
  257. DEBUGP(DL_FATAL,
  258. ("ServiceReads: Adapter %p, QueryBuffer failed for buffer %p\n",
  259. pAdapter, pNdisBuffer));
  260. break;
  261. }
  262. if (BytesAvailable)
  263. {
  264. ULONG BytesToCopy = MIN(BytesAvailable, BytesRemaining);
  265. TUN_COPY_MEM(pDst, pSrc, BytesToCopy);
  266. BytesCopied += BytesToCopy;
  267. BytesRemaining -= BytesToCopy;
  268. pDst += BytesToCopy;
  269. }
  270. NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer);
  271. }
  272. //
  273. // Complete the IRP.
  274. //
  275. //1 shouldn't we fail the read IRP if we couldn't copy the entire data?
  276. //1 check for pNdisBuffer != NULL
  277. pIrp->IoStatus.Status = STATUS_SUCCESS;
  278. pIrp->IoStatus.Information = MmGetMdlByteCount(pIrp->MdlAddress) - BytesRemaining;
  279. DEBUGP(DL_LOUD, ("ServiceReads: Adapter %p, IRP %p completed with %d bytes\n",
  280. pAdapter, pIrp, pIrp->IoStatus.Information));
  281. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  282. NdisMSendComplete(pAdapter->MiniportHandle,
  283. pRcvPacket,
  284. NDIS_STATUS_SUCCESS);
  285. TUN_DEREF_ADAPTER(pAdapter); // took out pended Read
  286. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  287. pAdapter->PendedReadCount--;
  288. pAdapter->SendPackets++;
  289. pAdapter->SendBytes += BytesCopied;
  290. }
  291. //1 convert to macro or in-line function
  292. if ((!TUN_TEST_FLAG(pAdapter, TUN_ADAPTER_ACTIVE)) &&
  293. (pAdapter->PendedSendCount == 0) &&
  294. (pAdapter->PendedReadCount == 0) &&
  295. (TUN_TEST_FLAG(pAdapter, TUN_COMPLETE_REQUEST)))
  296. {
  297. TUN_CLEAR_FLAG(pAdapter, TUN_COMPLETE_REQUEST);
  298. TUN_RELEASE_LOCK(&pAdapter->Lock);
  299. NdisMSetInformationComplete(&pAdapter->MiniportHandle,
  300. NDIS_STATUS_SUCCESS);
  301. }
  302. else
  303. {
  304. TUN_RELEASE_LOCK(&pAdapter->Lock);
  305. }
  306. TUN_DEREF_ADAPTER(pAdapter); // temp ref - service reads
  307. DEBUGP(DL_VERY_LOUD, ("<==ServiceReads: Adapter %p\n",
  308. pAdapter));
  309. }
  310. VOID
  311. TunCancelPendingReads(
  312. IN PTUN_ADAPTER pAdapter
  313. )
  314. /*++
  315. Routine Description:
  316. Cancel any pending read IRPs queued on the given open.
  317. Arguments:
  318. pAdapter - pointer to open context
  319. Return Value:
  320. None
  321. --*/
  322. {
  323. PIRP pIrp;
  324. PLIST_ENTRY pIrpEntry;
  325. DEBUGP(DL_LOUD, ("==>TunCancelPendingReads: Adapter %p/%x\n",
  326. pAdapter, pAdapter->Flags));
  327. TUN_REF_ADAPTER(pAdapter); // temp ref - cancel reads
  328. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  329. while (!TUN_IS_LIST_EMPTY(&pAdapter->PendedReads))
  330. {
  331. //
  332. // Get the first pended Read IRP
  333. //
  334. pIrpEntry = pAdapter->PendedReads.Flink;
  335. pIrp = CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry);
  336. //
  337. // Check to see if it is being cancelled.
  338. //
  339. if (IoSetCancelRoutine(pIrp, NULL))
  340. {
  341. //
  342. // It isn't being cancelled, and can't be cancelled henceforth.
  343. //
  344. TUN_REMOVE_ENTRY_LIST(pIrpEntry);
  345. TUN_RELEASE_LOCK(&pAdapter->Lock);
  346. //
  347. // Complete the IRP.
  348. //
  349. pIrp->IoStatus.Status = STATUS_CANCELLED;
  350. pIrp->IoStatus.Information = 0;
  351. DEBUGP(DL_LOUD, ("CancelPendingReads: Open %p, IRP %p cancelled\n",
  352. pAdapter, pIrp));
  353. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  354. TUN_DEREF_ADAPTER(pAdapter); // took out pended Read for cancelling
  355. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  356. pAdapter->PendedReadCount--;
  357. }
  358. else
  359. {
  360. //
  361. // It is being cancelled, let the cancel routine handle it.
  362. //
  363. TUN_RELEASE_LOCK(&pAdapter->Lock);
  364. //
  365. // Give the cancel routine some breathing space, otherwise
  366. // we might end up examining the same (cancelled) IRP over
  367. // and over again.
  368. //
  369. TUN_SLEEP(1);
  370. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  371. }
  372. }
  373. if ((!TUN_TEST_FLAG(pAdapter, TUN_ADAPTER_ACTIVE)) &&
  374. (pAdapter->PendedSendCount == 0) &&
  375. (pAdapter->PendedReadCount == 0) &&
  376. (TUN_TEST_FLAG(pAdapter, TUN_COMPLETE_REQUEST)))
  377. {
  378. TUN_CLEAR_FLAG(pAdapter, TUN_COMPLETE_REQUEST);
  379. TUN_RELEASE_LOCK(&pAdapter->Lock);
  380. NdisMSetInformationComplete(&pAdapter->MiniportHandle,
  381. NDIS_STATUS_SUCCESS);
  382. }
  383. else
  384. {
  385. TUN_RELEASE_LOCK(&pAdapter->Lock);
  386. }
  387. TUN_DEREF_ADAPTER(pAdapter); // temp ref - cancel reads
  388. DEBUGP(DL_LOUD, ("<==TunCancelPendingReads: Adapter %p/%x\n",
  389. pAdapter, pAdapter->Flags));
  390. }
  391. VOID
  392. TunFlushReceiveQueue(
  393. IN PTUN_ADAPTER pAdapter
  394. )
  395. /*++
  396. Routine Description:
  397. Free any receive packets queued up on the specified open
  398. Arguments:
  399. pAdapter - pointer to open context
  400. Return Value:
  401. None
  402. --*/
  403. {
  404. PLIST_ENTRY pRcvPacketEntry;
  405. PNDIS_PACKET pRcvPacket;
  406. DEBUGP(DL_LOUD, ("==>TunFlushReceiveQueue: Adapter %p/%x\n",
  407. pAdapter, pAdapter->Flags));
  408. TUN_REF_ADAPTER(pAdapter); // temp ref - flushRcvQueue
  409. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  410. while (!TUN_IS_LIST_EMPTY(&pAdapter->RecvPktQueue))
  411. {
  412. //
  413. // Get the first queued receive packet
  414. //
  415. pRcvPacketEntry = pAdapter->RecvPktQueue.Flink;
  416. TUN_REMOVE_ENTRY_LIST(pRcvPacketEntry);
  417. pAdapter->RecvPktCount --;
  418. pAdapter->XmitError++;
  419. TUN_RELEASE_LOCK(&pAdapter->Lock);
  420. pRcvPacket = TUN_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry);
  421. DEBUGP(DL_LOUD, ("FlushReceiveQueue: open %p, pkt %p\n",
  422. pAdapter, pRcvPacket));
  423. NdisMSendComplete(pAdapter->MiniportHandle,
  424. pRcvPacket,
  425. NDIS_STATUS_REQUEST_ABORTED);
  426. TUN_DEREF_ADAPTER(pAdapter); // took out pended Read
  427. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  428. }
  429. TUN_RELEASE_LOCK(&pAdapter->Lock);
  430. TUN_DEREF_ADAPTER(pAdapter); // temp ref - flushRcvQueue
  431. DEBUGP(DL_LOUD, ("<==TunFlushReceiveQueue: Adapter %p/%x\n",
  432. pAdapter, pAdapter->Flags));
  433. }