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.

822 lines
23 KiB

  1. /*++
  2. Copyright (c) 1989, 1990, 1991 Microsoft Corporation
  3. Module Name:
  4. rcveng.c
  5. Abstract:
  6. This module contains code that implements the receive engine for the
  7. Jetbeui transport provider. This code is responsible for the following
  8. basic activities:
  9. 1. Transitioning a TdiReceive request from an inactive state on the
  10. connection's ReceiveQueue to the active state on that connection
  11. (ActivateReceive).
  12. 2. Advancing the status of the active receive request by copying 0 or
  13. more bytes of data from an incoming DATA_FIRST_MIDDLE or DATA_ONLY_LAST
  14. NBF frame.
  15. 3. Completing receive requests.
  16. Author:
  17. David Beaver (dbeaver) 1-July-1991
  18. Environment:
  19. Kernel mode
  20. Revision History:
  21. --*/
  22. #include "precomp.h"
  23. #pragma hdrstop
  24. VOID
  25. ActivateReceive(
  26. PTP_CONNECTION Connection
  27. )
  28. /*++
  29. Routine Description:
  30. This routine activates the next TdiReceive request on the specified
  31. connection object if there is no active request on that connection
  32. already. This allows the request to accept data on the connection.
  33. NOTE: THIS FUNCTION MUST BE CALLED AT DPC LEVEL.
  34. Arguments:
  35. Connection - Pointer to a TP_CONNECTION object.
  36. Return Value:
  37. none.
  38. --*/
  39. {
  40. PIRP Irp;
  41. ASSERT (KeGetCurrentIrql() == DISPATCH_LEVEL);
  42. IF_NBFDBG (NBF_DEBUG_RCVENG) {
  43. NbfPrint0 (" ActivateReceive: Entered.\n");
  44. }
  45. //
  46. // The ACTIVE_RECEIVE bitflag will be set on the connection if
  47. // the receive-fields in the CONNECTION object are valid. If
  48. // this flag is cleared, then we try to make the next TdiReceive
  49. // request in the ReceiveQueue the active request.
  50. //
  51. ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  52. if (!(Connection->Flags & CONNECTION_FLAGS_ACTIVE_RECEIVE)) {
  53. if (!IsListEmpty (&Connection->ReceiveQueue)) {
  54. //
  55. // Found a receive, so make it the active one.
  56. //
  57. Connection->Flags |= CONNECTION_FLAGS_ACTIVE_RECEIVE;
  58. Irp = CONTAINING_RECORD(
  59. Connection->ReceiveQueue.Flink,
  60. IRP,
  61. Tail.Overlay.ListEntry);
  62. Connection->MessageBytesReceived = 0;
  63. Connection->MessageBytesAcked = 0;
  64. Connection->MessageInitAccepted = 0;
  65. Connection->CurrentReceiveIrp = Irp;
  66. Connection->CurrentReceiveSynchronous =
  67. Connection->Provider->MacInfo.SingleReceive;
  68. Connection->CurrentReceiveMdl = Irp->MdlAddress;
  69. Connection->ReceiveLength = IRP_RECEIVE_LENGTH(IoGetCurrentIrpStackLocation(Irp));
  70. Connection->ReceiveByteOffset = 0;
  71. }
  72. }
  73. RELEASE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  74. IF_NBFDBG (NBF_DEBUG_RCVENG) {
  75. NbfPrint0 (" ActivateReceive: Exiting.\n");
  76. }
  77. } /* ActivateReceive */
  78. VOID
  79. AwakenReceive(
  80. PTP_CONNECTION Connection
  81. )
  82. /*++
  83. Routine Description:
  84. This routine is called to reactivate a sleeping connection with the
  85. RECEIVE_WAKEUP bitflag set because data arrived for which no receive
  86. was available. The caller has made a receive available at the connection,
  87. so here we activate the next receive, and send the appropriate protocol
  88. to restart the message at the first byte offset past the one received
  89. by the last receive.
  90. NOTE: THIS FUNCTION MUST BE CALLED AT DPC LEVEL. IT IS CALLED
  91. WITH CONNECTION->LINKSPINLOCK HELD.
  92. Arguments:
  93. Connection - Pointer to a TP_CONNECTION object.
  94. Return Value:
  95. none.
  96. --*/
  97. {
  98. IF_NBFDBG (NBF_DEBUG_RCVENG) {
  99. NbfPrint0 (" AwakenReceive: Entered.\n");
  100. }
  101. //
  102. // If the RECEIVE_WAKEUP bitflag is set, then awaken the connection.
  103. //
  104. if (Connection->Flags & CONNECTION_FLAGS_RECEIVE_WAKEUP) {
  105. if (Connection->ReceiveQueue.Flink != &Connection->ReceiveQueue) {
  106. Connection->Flags &= ~CONNECTION_FLAGS_RECEIVE_WAKEUP;
  107. //
  108. // Found a receive, so turn off the wakeup flag, activate
  109. // the next receive, and send the protocol.
  110. //
  111. //
  112. // Quick fix: So there is no window where a receive
  113. // is active but the bit is not on (otherwise we could
  114. // accept whatever data happens to show up in the
  115. // interim).
  116. //
  117. Connection->Flags |= CONNECTION_FLAGS_W_RESYNCH;
  118. NbfReferenceConnection ("temp AwakenReceive", Connection, CREF_BY_ID); // release lookup hold.
  119. RELEASE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  120. ActivateReceive (Connection);
  121. //
  122. // What if this fails? The successful queueing
  123. // of a RCV_O should cause ActivateReceive to be called.
  124. //
  125. // NOTE: Send this after ActivateReceive, since that
  126. // is where the MessageBytesAcked/Received variables
  127. // are initialized.
  128. //
  129. NbfSendReceiveOutstanding (Connection);
  130. IF_NBFDBG (NBF_DEBUG_RCVENG) {
  131. NbfPrint0 (" AwakenReceive: Returned from NbfSendReceive.\n");
  132. }
  133. NbfDereferenceConnection("temp AwakenReceive", Connection, CREF_BY_ID);
  134. return;
  135. }
  136. }
  137. RELEASE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  138. } /* AwakenReceive */
  139. VOID
  140. CompleteReceive(
  141. PTP_CONNECTION Connection,
  142. BOOLEAN EndOfMessage,
  143. IN ULONG BytesTransferred
  144. )
  145. /*++
  146. Routine Description:
  147. This routine is called by ProcessIncomingData when the current receive
  148. must be completed. Depending on whether the current frame being
  149. processed is a DATA_FIRST_MIDDLE or DATA_ONLY_LAST, and also whether
  150. all of the data was processed, the EndOfMessage flag will be set accordingly
  151. by the caller to indicate that a message boundary was received.
  152. NOTE: THIS FUNCTION MUST BE CALLED AT DPC LEVEL.
  153. Arguments:
  154. Connection - Pointer to a TP_CONNECTION object.
  155. EndOfMessage - BOOLEAN set to true if TDI_END_OF_RECORD should be reported.
  156. BytesTransferred - Number of bytes copied in this receive.
  157. Return Value:
  158. none.
  159. --*/
  160. {
  161. PLIST_ENTRY p;
  162. PIRP Irp;
  163. ULONG BytesReceived;
  164. PIO_STACK_LOCATION IrpSp;
  165. IF_NBFDBG (NBF_DEBUG_RCVENG) {
  166. NbfPrint0 (" CompleteReceive: Entered.\n");
  167. }
  168. if (Connection->SpecialReceiveIrp) {
  169. PIRP Irp = Connection->SpecialReceiveIrp;
  170. Irp->IoStatus.Status = STATUS_SUCCESS;
  171. Irp->IoStatus.Information = BytesTransferred;
  172. ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  173. Connection->Flags |= CONNECTION_FLAGS_RC_PENDING;
  174. Connection->Flags &= ~CONNECTION_FLAGS_ACTIVE_RECEIVE;
  175. Connection->SpecialReceiveIrp = FALSE;
  176. ++Connection->ReceivedTsdus;
  177. ExInterlockedInsertHeadList(
  178. &Connection->Provider->IrpCompletionQueue,
  179. &Irp->Tail.Overlay.ListEntry,
  180. Connection->ProviderInterlock);
  181. //
  182. // NOTE: NbfAcknowledgeDataOnlyLast releases
  183. // the connection spinlock.
  184. //
  185. NbfAcknowledgeDataOnlyLast(
  186. Connection,
  187. Connection->MessageBytesReceived
  188. );
  189. } else {
  190. KIRQL cancelIrql;
  191. if (EndOfMessage) {
  192. //
  193. // The messages has been completely received, ack it.
  194. //
  195. // We set DEFERRED_ACK and DEFERRED_NOT_Q here, which
  196. // will cause an ack to be piggybacked if any data is
  197. // sent during the call to CompleteReceive. If this
  198. // does not happen, then we will call AcknowledgeDataOnlyLast
  199. // which will will send a DATA ACK or queue a request for
  200. // a piggyback ack. We do this *after* calling CompleteReceive
  201. // so we know that we will complete the receive back to
  202. // the client before we ack the data, to prevent the
  203. // next receive from being sent before this one is
  204. // completed.
  205. //
  206. IoAcquireCancelSpinLock(&cancelIrql);
  207. ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  208. Connection->DeferredFlags |=
  209. (CONNECTION_FLAGS_DEFERRED_ACK | CONNECTION_FLAGS_DEFERRED_NOT_Q);
  210. Connection->Flags |= CONNECTION_FLAGS_RC_PENDING;
  211. } else {
  212. //
  213. // Send a receive outstanding (even though we don't
  214. // know that we have a receive) to get him to
  215. // reframe his send. Pre-2.0 clients require a
  216. // no receive before the receive outstanding.
  217. //
  218. // what if this fails (due to no send packets)?
  219. //
  220. if ((Connection->Flags & CONNECTION_FLAGS_VERSION2) == 0) {
  221. NbfSendNoReceive (Connection);
  222. }
  223. NbfSendReceiveOutstanding (Connection);
  224. //
  225. // If there is a receive posted, make it current and
  226. // send a receive outstanding.
  227. //
  228. // need general function for this, which sends NO_RECEIVE if appropriate.
  229. //
  230. ActivateReceive (Connection);
  231. IoAcquireCancelSpinLock(&cancelIrql);
  232. ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  233. }
  234. //
  235. // If we indicated to the client, adjust this down by the
  236. // amount of data taken, when it hits zero we can reindicate.
  237. //
  238. if (Connection->ReceiveBytesUnaccepted) {
  239. if (Connection->MessageBytesReceived >= Connection->ReceiveBytesUnaccepted) {
  240. Connection->ReceiveBytesUnaccepted = 0;
  241. } else {
  242. Connection->ReceiveBytesUnaccepted -= Connection->MessageBytesReceived;
  243. }
  244. }
  245. //
  246. // NOTE: The connection lock is held here.
  247. //
  248. if (IsListEmpty (&Connection->ReceiveQueue)) {
  249. ASSERT ((Connection->Flags2 & CONNECTION_FLAGS2_STOPPING) != 0);
  250. //
  251. // Release the cancel spinlock out of order. Since we were
  252. // already at DPC level when it was acquired, there is no
  253. // need to swap irqls.
  254. //
  255. ASSERT(cancelIrql == DISPATCH_LEVEL);
  256. IoReleaseCancelSpinLock(cancelIrql);
  257. } else {
  258. Connection->Flags &= ~CONNECTION_FLAGS_ACTIVE_RECEIVE;
  259. BytesReceived = Connection->MessageBytesReceived;
  260. //
  261. // Complete the TdiReceive request at the head of the
  262. // connection's ReceiveQueue.
  263. //
  264. IF_NBFDBG (NBF_DEBUG_RCVENG) {
  265. NbfPrint0 (" CompleteReceive: Normal IRP is present.\n");
  266. }
  267. p = RemoveHeadList (&Connection->ReceiveQueue);
  268. Irp = CONTAINING_RECORD (p, IRP, Tail.Overlay.ListEntry);
  269. IoSetCancelRoutine(Irp, NULL);
  270. //
  271. // Release the cancel spinlock out of order. Since we were
  272. // already at DPC level when it was acquired, there is no
  273. // need to swap irqls.
  274. //
  275. ASSERT(cancelIrql == DISPATCH_LEVEL);
  276. IoReleaseCancelSpinLock(cancelIrql);
  277. //
  278. // If this request should generate no back traffic, then
  279. // disable piggyback acks for it.
  280. //
  281. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  282. if (IRP_RECEIVE_FLAGS(IrpSp) & TDI_RECEIVE_NO_RESPONSE_EXP) {
  283. Connection->CurrentReceiveAckQueueable = FALSE;
  284. }
  285. #if DBG
  286. NbfCompletedReceives[NbfCompletedReceivesNext].Irp = Irp;
  287. NbfCompletedReceives[NbfCompletedReceivesNext].Request = NULL;
  288. NbfCompletedReceives[NbfCompletedReceivesNext].Status =
  289. EndOfMessage ? STATUS_SUCCESS : STATUS_BUFFER_OVERFLOW;
  290. {
  291. ULONG i,j,k;
  292. PUCHAR va;
  293. PMDL mdl;
  294. mdl = Irp->MdlAddress;
  295. if (BytesReceived > TRACK_TDI_CAPTURE) {
  296. NbfCompletedReceives[NbfCompletedReceivesNext].Contents[0] = 0xFF;
  297. } else {
  298. NbfCompletedReceives[NbfCompletedReceivesNext].Contents[0] = (UCHAR)BytesReceived;
  299. }
  300. i = 1;
  301. while (i<TRACK_TDI_CAPTURE) {
  302. if (mdl == NULL) break;
  303. va = MmGetSystemAddressForMdl (mdl);
  304. j = MmGetMdlByteCount (mdl);
  305. for (i=i,k=0;(i<TRACK_TDI_CAPTURE)&&(k<j);i++,k++) {
  306. NbfCompletedReceives[NbfCompletedReceivesNext].Contents[i] = *va++;
  307. }
  308. mdl = mdl->Next;
  309. }
  310. }
  311. NbfCompletedReceivesNext = (NbfCompletedReceivesNext++) % TRACK_TDI_LIMIT;
  312. #endif
  313. ++Connection->ReceivedTsdus;
  314. //
  315. // This can be called with locks held.
  316. //
  317. NbfCompleteReceiveIrp(
  318. Irp,
  319. EndOfMessage ? STATUS_SUCCESS : STATUS_BUFFER_OVERFLOW,
  320. BytesReceived);
  321. }
  322. //
  323. // If NOT_Q is still set, that means that the deferred ack was
  324. // not satisfied by anything resulting from the call to
  325. // CompleteReceive, so we need to ack or queue an ack here.
  326. //
  327. if ((Connection->DeferredFlags & CONNECTION_FLAGS_DEFERRED_NOT_Q) != 0) {
  328. Connection->DeferredFlags &=
  329. ~(CONNECTION_FLAGS_DEFERRED_ACK | CONNECTION_FLAGS_DEFERRED_NOT_Q);
  330. //
  331. // NOTE: NbfAcknowledgeDataOnlyLast releases
  332. // the connection spinlock.
  333. //
  334. NbfAcknowledgeDataOnlyLast(
  335. Connection,
  336. Connection->MessageBytesReceived
  337. );
  338. } else {
  339. RELEASE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  340. }
  341. }
  342. } /* CompleteReceive */
  343. VOID
  344. NbfCancelReceive(
  345. IN PDEVICE_OBJECT DeviceObject,
  346. IN PIRP Irp
  347. )
  348. /*++
  349. Routine Description:
  350. This routine is called by the I/O system to cancel a receive.
  351. The receive is found on the connection's receive queue; if it
  352. is the current request it is cancelled and the connection
  353. goes into "cancelled receive" mode, otherwise it is cancelled
  354. silently.
  355. In "cancelled receive" mode the connection makes it appear to
  356. the remote the data is being received, but in fact it is not
  357. indicated to the transport or buffered on our end
  358. NOTE: This routine is called with the CancelSpinLock held and
  359. is responsible for releasing it.
  360. Arguments:
  361. DeviceObject - Pointer to the device object for this driver.
  362. Irp - Pointer to the request packet representing the I/O request.
  363. Return Value:
  364. none.
  365. --*/
  366. {
  367. KIRQL oldirql;
  368. PIO_STACK_LOCATION IrpSp;
  369. PIRP ReceiveIrp;
  370. PTP_CONNECTION Connection;
  371. PLIST_ENTRY p;
  372. ULONG BytesReceived;
  373. BOOLEAN Found;
  374. UNREFERENCED_PARAMETER (DeviceObject);
  375. //
  376. // Get a pointer to the current stack location in the IRP. This is where
  377. // the function codes and parameters are stored.
  378. //
  379. IrpSp = IoGetCurrentIrpStackLocation (Irp);
  380. ASSERT ((IrpSp->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) &&
  381. (IrpSp->MinorFunction == TDI_RECEIVE));
  382. Connection = IrpSp->FileObject->FsContext;
  383. //
  384. // Since this IRP is still in the cancellable state, we know
  385. // that the connection is still around (although it may be in
  386. // the process of being torn down).
  387. //
  388. //
  389. // See if this is the IRP for the current receive request.
  390. //
  391. ACQUIRE_SPIN_LOCK (Connection->LinkSpinLock, &oldirql);
  392. BytesReceived = Connection->MessageBytesReceived;
  393. p = Connection->ReceiveQueue.Flink;
  394. //
  395. // If there is a receive active and it is not a special
  396. // IRP, then see if this is it.
  397. //
  398. if (((Connection->Flags & CONNECTION_FLAGS_ACTIVE_RECEIVE) != 0) &&
  399. (!Connection->SpecialReceiveIrp)) {
  400. ReceiveIrp = CONTAINING_RECORD (p, IRP, Tail.Overlay.ListEntry);
  401. if (ReceiveIrp == Irp) {
  402. //
  403. // yes, it is the active receive. Turn on the RCV_CANCELLED
  404. // bit instructing the connection to drop the rest of the
  405. // data received (until the DOL comes in).
  406. //
  407. Connection->Flags |= CONNECTION_FLAGS_RCV_CANCELLED;
  408. Connection->Flags &= ~CONNECTION_FLAGS_ACTIVE_RECEIVE;
  409. (VOID)RemoveHeadList (&Connection->ReceiveQueue);
  410. #if DBG
  411. NbfCompletedReceives[NbfCompletedReceivesNext].Irp = ReceiveIrp;
  412. NbfCompletedReceives[NbfCompletedReceivesNext].Request = NULL;
  413. NbfCompletedReceives[NbfCompletedReceivesNext].Status = STATUS_CANCELLED;
  414. {
  415. ULONG i,j,k;
  416. PUCHAR va;
  417. PMDL mdl;
  418. mdl = ReceiveIrp->MdlAddress;
  419. if (BytesReceived > TRACK_TDI_CAPTURE) {
  420. NbfCompletedReceives[NbfCompletedReceivesNext].Contents[0] = 0xFF;
  421. } else {
  422. NbfCompletedReceives[NbfCompletedReceivesNext].Contents[0] = (UCHAR)BytesReceived;
  423. }
  424. i = 1;
  425. while (i<TRACK_TDI_CAPTURE) {
  426. if (mdl == NULL) break;
  427. va = MmGetSystemAddressForMdl (mdl);
  428. j = MmGetMdlByteCount (mdl);
  429. for (i=i,k=0;(i<TRACK_TDI_CAPTURE)&&(k<j);i++,k++) {
  430. NbfCompletedReceives[NbfCompletedReceivesNext].Contents[i] = *va++;
  431. }
  432. mdl = mdl->Next;
  433. }
  434. }
  435. NbfCompletedReceivesNext = (NbfCompletedReceivesNext++) % TRACK_TDI_LIMIT;
  436. #endif
  437. RELEASE_SPIN_LOCK (Connection->LinkSpinLock, oldirql);
  438. IoReleaseCancelSpinLock (Irp->CancelIrql);
  439. #if DBG
  440. DbgPrint("NBF: Canceled in-progress receive %lx on %lx\n",
  441. Irp, Connection);
  442. #endif
  443. //
  444. // The following dereference will complete the I/O, provided removes
  445. // the last reference on the request object. The I/O will complete
  446. // with the status and information stored in the Irp. Therefore,
  447. // we set those values here before the dereference.
  448. //
  449. NbfCompleteReceiveIrp (ReceiveIrp, STATUS_CANCELLED, 0);
  450. return;
  451. }
  452. }
  453. //
  454. // If we fall through to here, the IRP was not the active receive.
  455. // Scan through the list, looking for this IRP.
  456. //
  457. Found = FALSE;
  458. while (p != &Connection->ReceiveQueue) {
  459. ReceiveIrp = CONTAINING_RECORD (p, IRP, Tail.Overlay.ListEntry);
  460. if (ReceiveIrp == Irp) {
  461. //
  462. // Found it, remove it from the list here.
  463. //
  464. RemoveEntryList (p);
  465. Found = TRUE;
  466. #if DBG
  467. NbfCompletedReceives[NbfCompletedReceivesNext].Irp = ReceiveIrp;
  468. NbfCompletedReceives[NbfCompletedReceivesNext].Request = NULL;
  469. NbfCompletedReceives[NbfCompletedReceivesNext].Status = STATUS_CANCELLED;
  470. {
  471. ULONG i,j,k;
  472. PUCHAR va;
  473. PMDL mdl;
  474. mdl = ReceiveIrp->MdlAddress;
  475. if (BytesReceived > TRACK_TDI_CAPTURE) {
  476. NbfCompletedReceives[NbfCompletedReceivesNext].Contents[0] = 0xFF;
  477. } else {
  478. NbfCompletedReceives[NbfCompletedReceivesNext].Contents[0] = (UCHAR)BytesReceived;
  479. }
  480. i = 1;
  481. while (i<TRACK_TDI_CAPTURE) {
  482. if (mdl == NULL) break;
  483. va = MmGetSystemAddressForMdl (mdl);
  484. j = MmGetMdlByteCount (mdl);
  485. for (i=i,k=0;(i<TRACK_TDI_CAPTURE)&&(k<j);i++,k++) {
  486. NbfCompletedReceives[NbfCompletedReceivesNext].Contents[i] = *va++;
  487. }
  488. mdl = mdl->Next;
  489. }
  490. }
  491. NbfCompletedReceivesNext = (NbfCompletedReceivesNext++) % TRACK_TDI_LIMIT;
  492. #endif
  493. RELEASE_SPIN_LOCK (Connection->LinkSpinLock, oldirql);
  494. IoReleaseCancelSpinLock (Irp->CancelIrql);
  495. #if DBG
  496. DbgPrint("NBF: Canceled receive %lx on %lx\n",
  497. ReceiveIrp, Connection);
  498. #endif
  499. //
  500. // The following dereference will complete the I/O, provided removes
  501. // the last reference on the request object. The I/O will complete
  502. // with the status and information stored in the Irp. Therefore,
  503. // we set those values here before the dereference.
  504. //
  505. NbfCompleteReceiveIrp (ReceiveIrp, STATUS_CANCELLED, 0);
  506. break;
  507. }
  508. p = p->Flink;
  509. }
  510. if (!Found) {
  511. //
  512. // We didn't find it!
  513. //
  514. #if DBG
  515. DbgPrint("NBF: Tried to cancel receive %lx on %lx, not found\n",
  516. Irp, Connection);
  517. #endif
  518. RELEASE_SPIN_LOCK (Connection->LinkSpinLock, oldirql);
  519. IoReleaseCancelSpinLock (Irp->CancelIrql);
  520. }
  521. }
  522. VOID
  523. NbfCancelReceiveDatagram(
  524. IN PDEVICE_OBJECT DeviceObject,
  525. IN PIRP Irp
  526. )
  527. /*++
  528. Routine Description:
  529. This routine is called by the I/O system to cancel a receive
  530. datagram. The receive is looked for on the address file's
  531. receive datagram queue; if it is found it is cancelled.
  532. NOTE: This routine is called with the CancelSpinLock held and
  533. is responsible for releasing it.
  534. Arguments:
  535. DeviceObject - Pointer to the device object for this driver.
  536. Irp - Pointer to the request packet representing the I/O request.
  537. Return Value:
  538. none.
  539. --*/
  540. {
  541. KIRQL oldirql;
  542. PIO_STACK_LOCATION IrpSp;
  543. PTP_ADDRESS_FILE AddressFile;
  544. PTP_ADDRESS Address;
  545. PLIST_ENTRY p;
  546. BOOLEAN Found;
  547. UNREFERENCED_PARAMETER (DeviceObject);
  548. //
  549. // Get a pointer to the current stack location in the IRP. This is where
  550. // the function codes and parameters are stored.
  551. //
  552. IrpSp = IoGetCurrentIrpStackLocation (Irp);
  553. ASSERT ((IrpSp->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) &&
  554. (IrpSp->MinorFunction == TDI_RECEIVE_DATAGRAM));
  555. AddressFile = IrpSp->FileObject->FsContext;
  556. Address = AddressFile->Address;
  557. //
  558. // Since this IRP is still in the cancellable state, we know
  559. // that the address file is still around (although it may be in
  560. // the process of being torn down). See if the IRP is on the list.
  561. //
  562. Found = FALSE;
  563. ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
  564. for (p = AddressFile->ReceiveDatagramQueue.Flink;
  565. p != &AddressFile->ReceiveDatagramQueue;
  566. p = p->Flink) {
  567. if (CONTAINING_RECORD(p, IRP, Tail.Overlay.ListEntry) == Irp) {
  568. RemoveEntryList (p);
  569. Found = TRUE;
  570. break;
  571. }
  572. }
  573. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  574. IoReleaseCancelSpinLock (Irp->CancelIrql);
  575. if (Found) {
  576. #if DBG
  577. DbgPrint("NBF: Canceled receive datagram %lx on %lx\n",
  578. Irp, AddressFile);
  579. #endif
  580. Irp->IoStatus.Information = 0;
  581. Irp->IoStatus.Status = STATUS_CANCELLED;
  582. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  583. NbfDereferenceAddress ("Receive DG cancelled", Address, AREF_REQUEST);
  584. } else {
  585. #if DBG
  586. DbgPrint("NBF: Tried to cancel receive datagram %lx on %lx, not found\n",
  587. Irp, AddressFile);
  588. #endif
  589. }
  590. } /* NbfCancelReceiveDatagram */