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.

3315 lines
107 KiB

  1. /*++
  2. Copyright (c) 1993-1999 Microsoft Corporation
  3. Module Name:
  4. recvvc.c
  5. Abstract:
  6. This module contains routines for handling data receive for connection-
  7. oriented endpoints on non-buffering TDI transports.
  8. Author:
  9. David Treadwell (davidtr) 21-Oct-1993
  10. Revision History:
  11. Vadim Eydelman (vadime)
  12. 1998-1999 NT5.0 low-memory tolerance and perf changes
  13. --*/
  14. #include "afdp.h"
  15. VOID
  16. AfdCancelReceive (
  17. IN PDEVICE_OBJECT DeviceObject,
  18. IN PIRP Irp
  19. );
  20. PIRP
  21. AfdGetPendedReceiveIrp (
  22. IN PAFD_CONNECTION Connection,
  23. IN BOOLEAN Expedited
  24. );
  25. NTSTATUS
  26. AfdRestartBufferReceiveWithUserIrp (
  27. IN PDEVICE_OBJECT DeviceObject,
  28. IN PIRP Irp,
  29. IN PVOID Context
  30. );
  31. ULONG
  32. AfdBFillPendingIrps (
  33. PAFD_CONNECTION Connection,
  34. PMDL Mdl,
  35. ULONG DataOffset,
  36. ULONG DataLength,
  37. ULONG Flags,
  38. PLIST_ENTRY CompleteIrpListHead
  39. );
  40. #define AFD_RECEIVE_STREAM 0x80000000
  41. C_ASSERT (AFD_RECEIVE_STREAM!=TDI_RECEIVE_ENTIRE_MESSAGE);
  42. C_ASSERT (AFD_RECEIVE_STREAM!=TDI_RECEIVE_EXPEDITED);
  43. #define AFD_RECEIVE_CHAINED 0x40000000
  44. C_ASSERT (AFD_RECEIVE_CHAINED!=TDI_RECEIVE_ENTIRE_MESSAGE);
  45. C_ASSERT (AFD_RECEIVE_CHAINED!=TDI_RECEIVE_EXPEDITED);
  46. PAFD_BUFFER_HEADER
  47. AfdGetReceiveBuffer (
  48. IN PAFD_CONNECTION Connection,
  49. IN ULONG ReceiveFlags,
  50. IN PAFD_BUFFER_HEADER StartingAfdBuffer OPTIONAL
  51. );
  52. #ifdef ALLOC_PRAGMA
  53. #pragma alloc_text( PAGEAFD, AfdBReceive )
  54. #pragma alloc_text( PAGEAFD, AfdBReceiveEventHandler )
  55. #pragma alloc_text( PAGEAFD, AfdBReceiveExpeditedEventHandler )
  56. #pragma alloc_text( PAGEAFD, AfdCancelReceive )
  57. #pragma alloc_text( PAGEAFD, AfdGetPendedReceiveIrp )
  58. #pragma alloc_text( PAGEAFD, AfdGetReceiveBuffer )
  59. #pragma alloc_text( PAGEAFD, AfdRestartBufferReceive )
  60. #pragma alloc_text( PAGEAFD, AfdRestartBufferReceiveWithUserIrp )
  61. #pragma alloc_text( PAGEAFD, AfdLRRepostReceive)
  62. #pragma alloc_text( PAGEAFD, AfdBChainedReceiveEventHandler )
  63. #pragma alloc_text( PAGEAFD, AfdBFillPendingIrps )
  64. #endif
  65. //
  66. // Macros to make the send restart code more maintainable.
  67. //
  68. #define AfdRestartRecvInfo DeviceIoControl
  69. #define AfdRecvFlags IoControlCode
  70. #define AfdOriginalLength OutputBufferLength
  71. #define AfdCurrentLength InputBufferLength
  72. #define AfdAdjustedLength Type3InputBuffer
  73. NTSTATUS
  74. AfdBReceive (
  75. IN PIRP Irp,
  76. IN PIO_STACK_LOCATION IrpSp,
  77. IN ULONG RecvFlags,
  78. IN ULONG AfdFlags,
  79. IN ULONG RecvLength
  80. )
  81. {
  82. NTSTATUS status;
  83. AFD_LOCK_QUEUE_HANDLE lockHandle;
  84. PAFD_ENDPOINT endpoint;
  85. PAFD_CONNECTION connection;
  86. ULONG bytesReceived;
  87. BOOLEAN peek;
  88. PAFD_BUFFER_HEADER afdBuffer;
  89. BOOLEAN completeMessage;
  90. BOOLEAN partialReceivePossible;
  91. PAFD_BUFFER newAfdBuffer;
  92. //
  93. // Set up some local variables.
  94. //
  95. endpoint = IrpSp->FileObject->FsContext;
  96. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting ||
  97. endpoint->Type == AfdBlockTypeVcBoth );
  98. connection = NULL;
  99. //
  100. // Determine if this is a peek operation.
  101. //
  102. ASSERT( ( RecvFlags & TDI_RECEIVE_EITHER ) != 0 );
  103. ASSERT( ( RecvFlags & TDI_RECEIVE_EITHER ) != TDI_RECEIVE_EITHER );
  104. peek = ( RecvFlags & TDI_RECEIVE_PEEK ) != 0;
  105. //
  106. // Determine whether it is legal to complete this receive with a
  107. // partial message.
  108. //
  109. if ( !IS_MESSAGE_ENDPOINT(endpoint)) {
  110. partialReceivePossible = TRUE;
  111. } else {
  112. if ( (RecvFlags & TDI_RECEIVE_PARTIAL) != 0 ) {
  113. partialReceivePossible = TRUE;
  114. } else {
  115. partialReceivePossible = FALSE;
  116. }
  117. }
  118. //
  119. // Reset the InputBufferLength field of our stack location. We'll
  120. // use this to keep track of how much data we've placed into the IRP
  121. // so far.
  122. //
  123. IrpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength = 0;
  124. Irp->IoStatus.Information = 0;
  125. //
  126. // If this is an inline endpoint, then either type of receive data
  127. // can be used to satisfy this receive.
  128. //
  129. if ( endpoint->InLine ) {
  130. RecvFlags |= TDI_RECEIVE_EITHER;
  131. }
  132. newAfdBuffer = NULL;
  133. //
  134. // Try to get data already bufferred on the connection to satisfy
  135. // this receive.
  136. //
  137. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  138. //
  139. // Check if endpoint was cleaned-up and cancel the request.
  140. //
  141. if (endpoint->EndpointCleanedUp) {
  142. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  143. status = STATUS_CANCELLED;
  144. goto complete;
  145. }
  146. connection = endpoint->Common.VcConnecting.Connection;
  147. if (connection==NULL) {
  148. //
  149. // connection might have been cleaned up by transmit file.
  150. //
  151. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  152. status = STATUS_INVALID_CONNECTION;
  153. goto complete;
  154. }
  155. ASSERT( connection->Type == AfdBlockTypeConnection );
  156. //
  157. // Check whether the remote end has aborted the connection, in which
  158. // case we should complete the receive.
  159. //
  160. if ( connection->AbortIndicated ) {
  161. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  162. status = STATUS_CONNECTION_RESET;
  163. goto complete;
  164. }
  165. if( RecvFlags & TDI_RECEIVE_EXPEDITED ) {
  166. endpoint->EventsActive &= ~AFD_POLL_RECEIVE_EXPEDITED;
  167. }
  168. if( RecvFlags & TDI_RECEIVE_NORMAL ) {
  169. endpoint->EventsActive &= ~AFD_POLL_RECEIVE;
  170. }
  171. IF_DEBUG(EVENT_SELECT) {
  172. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  173. "AfdBReceive: Endp %p, Active %lx\n",
  174. endpoint,
  175. endpoint->EventsActive
  176. ));
  177. }
  178. afdBuffer = AfdGetReceiveBuffer( connection, RecvFlags, NULL);
  179. while ( afdBuffer != NULL ) {
  180. //
  181. // Copy the data to the MDL in the IRP.
  182. //
  183. if ( Irp->MdlAddress != NULL ) {
  184. if (IrpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength==0) {
  185. //
  186. // First time through the loop - make sure we can map the
  187. // entire buffer. We can't afford failing on second entry
  188. // to the loop as we may loose the data we copied on
  189. // the first path.
  190. //
  191. status = AfdMapMdlChain (Irp->MdlAddress);
  192. if (!NT_SUCCESS (status)) {
  193. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  194. goto complete;
  195. }
  196. }
  197. ASSERTMSG (
  198. "NIC Driver freed the packet before it was returned!!!",
  199. !afdBuffer->NdisPacket ||
  200. (MmIsAddressValid (afdBuffer->Context) &&
  201. MmIsAddressValid (MmGetSystemAddressForMdl (afdBuffer->Mdl))) );
  202. status = AfdCopyMdlChainToMdlChain (
  203. Irp->MdlAddress,
  204. IrpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength,
  205. afdBuffer->Mdl,
  206. afdBuffer->DataOffset,
  207. afdBuffer->DataLength,
  208. &bytesReceived
  209. );
  210. } else {
  211. if ( afdBuffer->DataLength == 0 ) {
  212. status = STATUS_SUCCESS;
  213. } else {
  214. status = STATUS_BUFFER_OVERFLOW;
  215. }
  216. bytesReceived = 0;
  217. }
  218. ASSERT( status == STATUS_SUCCESS || status == STATUS_BUFFER_OVERFLOW );
  219. ASSERT( afdBuffer->PartialMessage == TRUE || afdBuffer->PartialMessage == FALSE );
  220. completeMessage = !afdBuffer->PartialMessage;
  221. //
  222. // If this wasn't a peek IRP, update information on the
  223. // connection based on whether the entire buffer of data was
  224. // taken.
  225. //
  226. if ( !peek ) {
  227. //
  228. // If all the data in the buffer was taken, remove the buffer
  229. // from the connection's list and return it to the buffer pool.
  230. //
  231. if (status == STATUS_SUCCESS) {
  232. ASSERT(afdBuffer->DataLength == bytesReceived);
  233. //
  234. // Update the counts of bytes bufferred on the connection.
  235. //
  236. if ( afdBuffer->ExpeditedData ) {
  237. ASSERT( connection->VcBufferredExpeditedBytes >= bytesReceived );
  238. ASSERT( connection->VcBufferredExpeditedCount > 0 );
  239. connection->VcBufferredExpeditedBytes -= bytesReceived;
  240. connection->VcBufferredExpeditedCount -= 1;
  241. afdBuffer->ExpeditedData = FALSE;
  242. } else {
  243. ASSERT( connection->VcBufferredReceiveBytes >= bytesReceived );
  244. ASSERT( connection->VcBufferredReceiveCount > 0 );
  245. connection->VcBufferredReceiveBytes -= bytesReceived;
  246. connection->VcBufferredReceiveCount -= 1;
  247. }
  248. RemoveEntryList( &afdBuffer->BufferListEntry );
  249. DEBUG afdBuffer->BufferListEntry.Flink = NULL;
  250. if (afdBuffer->RefCount==1 || // Can't change once off the list
  251. InterlockedDecrement (&afdBuffer->RefCount)==0) {
  252. AfdReturnBuffer( afdBuffer, connection->OwningProcess );
  253. }
  254. //
  255. // Reset the afdBuffer local so that we know that the
  256. // buffer is gone.
  257. //
  258. afdBuffer = NULL;
  259. } else {
  260. //
  261. // Update the counts of bytes bufferred on the connection.
  262. //
  263. if ( afdBuffer->ExpeditedData ) {
  264. ASSERT( connection->VcBufferredExpeditedBytes >= bytesReceived );
  265. connection->VcBufferredExpeditedBytes -= bytesReceived;
  266. } else {
  267. ASSERT( connection->VcBufferredReceiveBytes >= bytesReceived );
  268. connection->VcBufferredReceiveBytes -= bytesReceived;
  269. }
  270. //
  271. // Not all of the buffer's data was taken. Update the
  272. // counters in the AFD buffer structure to reflect the
  273. // amount of data that was actually received.
  274. //
  275. ASSERT(afdBuffer->DataLength > bytesReceived);
  276. afdBuffer->DataOffset += bytesReceived;
  277. afdBuffer->DataLength -= bytesReceived;
  278. ASSERT( afdBuffer->BufferLength==AfdBufferTagSize
  279. || afdBuffer->DataOffset < afdBuffer->BufferLength );
  280. }
  281. //
  282. // If there is indicated but unreceived data in the TDI
  283. // provider, and we have available buffer space, fire off an
  284. // IRP to receive the data.
  285. //
  286. if ( connection->VcReceiveBytesInTransport > 0
  287. &&
  288. connection->VcBufferredReceiveBytes <
  289. connection->MaxBufferredReceiveBytes
  290. ) {
  291. ULONG bytesToReceive;
  292. //
  293. // Remember the count of data that we're going to
  294. // receive, then reset the fields in the connection
  295. // where we keep track of how much data is available in
  296. // the transport. We reset it here before releasing the
  297. // lock so that another thread doesn't try to receive
  298. // the data at the same time as us.
  299. //
  300. if ( connection->VcReceiveBytesInTransport > AfdLargeBufferSize ) {
  301. bytesToReceive = connection->VcReceiveBytesInTransport;
  302. } else {
  303. bytesToReceive = AfdLargeBufferSize;
  304. }
  305. //
  306. // Get an AFD buffer structure to hold the data.
  307. //
  308. ASSERT (newAfdBuffer==NULL);
  309. newAfdBuffer = AfdGetBuffer( bytesToReceive, 0,
  310. connection->OwningProcess );
  311. if ( newAfdBuffer != NULL) {
  312. connection->VcReceiveBytesInTransport = 0;
  313. ASSERT (InterlockedDecrement (&connection->VcReceiveIrpsInTransport)==-1);
  314. //
  315. // We need to remember the connection in the AFD buffer
  316. // because we'll need to access it in the completion
  317. // routine.
  318. //
  319. newAfdBuffer->Context = connection;
  320. //
  321. // Acquire connection reference to be released in completion routine
  322. //
  323. REFERENCE_CONNECTION (connection);
  324. //
  325. // Finish building the receive IRP to give to the TDI
  326. // provider.
  327. //
  328. TdiBuildReceive(
  329. newAfdBuffer->Irp,
  330. connection->DeviceObject,
  331. connection->FileObject,
  332. AfdRestartBufferReceive,
  333. newAfdBuffer,
  334. newAfdBuffer->Mdl,
  335. TDI_RECEIVE_NORMAL,
  336. bytesToReceive
  337. );
  338. //
  339. // Wait to hand off the IRP until we can safely release
  340. // the endpoint lock.
  341. //
  342. }
  343. else {
  344. if (connection->VcBufferredReceiveBytes == 0 &&
  345. !connection->OnLRList) {
  346. //
  347. // Since we do not have any data buffered, application
  348. // is not notified and will never call with recv.
  349. // We will have to put this on low resource list
  350. // and attempt to allocate memory and pull the data
  351. // later.
  352. //
  353. connection->OnLRList = TRUE;
  354. REFERENCE_CONNECTION (connection);
  355. AfdLRListAddItem (&connection->LRListItem, AfdLRRepostReceive);
  356. }
  357. }
  358. }
  359. }
  360. //
  361. // Update the count of bytes we've received so far into the IRP,
  362. // and see if we can get another buffer of data to continue.
  363. //
  364. IrpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength += bytesReceived;
  365. afdBuffer = AfdGetReceiveBuffer( connection, RecvFlags, afdBuffer );
  366. //
  367. // We've set up all return information. If we got a full
  368. // message OR if we can complete with a partial message OR if
  369. // the IRP is full of data, clean up and complete the IRP.
  370. //
  371. if ( IS_MESSAGE_ENDPOINT (endpoint) && completeMessage
  372. ||
  373. status == STATUS_BUFFER_OVERFLOW
  374. ||
  375. (partialReceivePossible
  376. &&
  377. ((RecvLength==IrpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength)
  378. ||
  379. (afdBuffer==NULL))
  380. )
  381. ) {
  382. if( RecvFlags & TDI_RECEIVE_NORMAL ) {
  383. if (IS_DATA_ON_CONNECTION( connection )) {
  384. ASSERT (endpoint->DisableFastIoRecv==FALSE);
  385. AfdIndicateEventSelectEvent(
  386. endpoint,
  387. AFD_POLL_RECEIVE,
  388. STATUS_SUCCESS
  389. );
  390. }
  391. else {
  392. //
  393. // Disable fast IO path to avoid performance penalty
  394. // of unneccessarily going through it.
  395. //
  396. if (!endpoint->NonBlocking)
  397. endpoint->DisableFastIoRecv = TRUE;
  398. }
  399. }
  400. if( ( RecvFlags & TDI_RECEIVE_EXPEDITED ) &&
  401. IS_EXPEDITED_DATA_ON_CONNECTION( connection ) ) {
  402. AfdIndicateEventSelectEvent(
  403. endpoint,
  404. endpoint->InLine
  405. ? AFD_POLL_RECEIVE
  406. : AFD_POLL_RECEIVE_EXPEDITED,
  407. STATUS_SUCCESS
  408. );
  409. }
  410. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  411. //
  412. // For stream type endpoints, it does not make sense to return
  413. // STATUS_BUFFER_OVERFLOW. That status is only sensible for
  414. // message-oriented transports for which we convert it
  415. // to partial receive status to properly set the flags
  416. //
  417. if ( !IS_MESSAGE_ENDPOINT(endpoint) ) {
  418. status = STATUS_SUCCESS;
  419. }
  420. else if (status==STATUS_BUFFER_OVERFLOW || !completeMessage) {
  421. if (RecvFlags & TDI_RECEIVE_EXPEDITED)
  422. status = STATUS_RECEIVE_PARTIAL_EXPEDITED;
  423. else
  424. status = STATUS_RECEIVE_PARTIAL;
  425. }
  426. Irp->IoStatus.Information = IrpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength;
  427. UPDATE_CONN2 (connection, "Irp receive, 0x%lX bytes", (ULONG)Irp->IoStatus.Information);
  428. goto complete;
  429. }
  430. }
  431. //
  432. // We should have copied all buffered data of appropriate type
  433. // to the apps's buffer.
  434. //
  435. ASSERT ((!(RecvFlags & TDI_RECEIVE_NORMAL) || (connection->VcBufferredReceiveBytes == 0)) &&
  436. (!(RecvFlags & TDI_RECEIVE_EXPEDITED) || (connection->VcBufferredExpeditedBytes == 0)));
  437. //
  438. // There must be some more space in the buffer if we are here
  439. // or it could also be a 0-byte recv.
  440. //
  441. ASSERT ((RecvLength>IrpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength)
  442. || (RecvLength==0));
  443. //
  444. // Also, if we could complete with partial data we should have done so.
  445. //
  446. ASSERT (IrpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength==0 ||
  447. !partialReceivePossible);
  448. //
  449. // We'll have to pend the IRP. Remember the receive flags in the
  450. // IoControlCode field of our IO stack location and make sure
  451. // we have the length field set (it is no longer done by the IO
  452. // system because we use METHOD_NEITHER and WSABUFs to pass recv
  453. // parameters). Initialize adjusted length in case we need to advance
  454. // the MDL to receive next part of the message
  455. //
  456. IrpSp->Parameters.AfdRestartRecvInfo.AfdRecvFlags = RecvFlags;
  457. IrpSp->Parameters.AfdRestartRecvInfo.AfdOriginalLength = RecvLength;
  458. IrpSp->Parameters.AfdRestartRecvInfo.AfdAdjustedLength = (PVOID)0;
  459. //
  460. // If there was no data bufferred on the endpoint and the connection
  461. // has been disconnected by the remote end, complete the receive
  462. // with 0 bytes read if this is a stream endpoint, or a failure
  463. // code if this is a message endpoint.
  464. //
  465. if ( IrpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength == 0 &&
  466. connection->DisconnectIndicated ) {
  467. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  468. ASSERT (newAfdBuffer==NULL);
  469. if ( !IS_MESSAGE_ENDPOINT(endpoint) ) {
  470. status = STATUS_SUCCESS;
  471. } else {
  472. status = STATUS_GRACEFUL_DISCONNECT;
  473. }
  474. goto complete;
  475. }
  476. //
  477. // If this is a nonblocking endpoint and the request was a normal
  478. // receive (as opposed to a read IRP), fail the request. We don't
  479. // fail reads under the asumption that if the application is doing
  480. // reads they don't want nonblocking behavior.
  481. //
  482. if ( IrpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength == 0 &&
  483. endpoint->NonBlocking && !( AfdFlags & AFD_OVERLAPPED ) ) {
  484. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  485. ASSERT (newAfdBuffer==NULL);
  486. status = STATUS_DEVICE_NOT_READY;
  487. goto complete;
  488. }
  489. //
  490. // Place the IRP on the connection's list of pended receive IRPs and
  491. // mark the IRP ad pended.
  492. //
  493. InsertTailList(
  494. &connection->VcReceiveIrpListHead,
  495. &Irp->Tail.Overlay.ListEntry
  496. );
  497. Irp->IoStatus.Status = STATUS_SUCCESS;
  498. //
  499. // Set up the cancellation routine in the IRP. If the IRP has already
  500. // been cancelled, just call the cancellation routine here.
  501. //
  502. IoSetCancelRoutine( Irp, AfdCancelReceive );
  503. if ( Irp->Cancel ) {
  504. RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
  505. if (IoSetCancelRoutine( Irp, NULL ) != NULL) {
  506. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  507. if (IrpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength == 0 ||
  508. endpoint->EndpointCleanedUp) {
  509. status = STATUS_CANCELLED;
  510. goto complete;
  511. }
  512. else {
  513. //
  514. // We cannot set STATUS_CANCELLED
  515. // since we loose data already placed in the IRP.
  516. //
  517. Irp->IoStatus.Information = IrpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength;
  518. UPDATE_CONN2(connection, "Cancelled receive, 0x%lX bytes", (ULONG)Irp->IoStatus.Information);
  519. status = STATUS_SUCCESS;
  520. goto complete;
  521. }
  522. }
  523. else {
  524. //
  525. // This IRP is about to be canceled. Set the Flink to NULL
  526. // so the cancel routine knows it is not on the list.
  527. Irp->Tail.Overlay.ListEntry.Flink = NULL;
  528. }
  529. //
  530. // The cancel routine will run and complete the irp.
  531. //
  532. }
  533. IoMarkIrpPending( Irp );
  534. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  535. //
  536. // If there was data bufferred in the transport, fire off the IRP to
  537. // receive it. We have to wait until here because it is not legal
  538. // to do an IoCallDriver() while holding a spin lock.
  539. //
  540. if ( newAfdBuffer != NULL ) {
  541. (VOID)IoCallDriver( connection->DeviceObject, newAfdBuffer->Irp );
  542. }
  543. return STATUS_PENDING;
  544. complete:
  545. //
  546. // If there was data bufferred in the transport, fire off
  547. // the IRP to receive it.
  548. //
  549. if ( newAfdBuffer != NULL ) {
  550. (VOID)IoCallDriver( connection->DeviceObject, newAfdBuffer->Irp );
  551. }
  552. Irp->IoStatus.Status = status;
  553. if (!NT_SUCCESS (status)) {
  554. UPDATE_CONN2 (connection, "Receive failed, status: %lX", Irp->IoStatus.Status);
  555. }
  556. IoCompleteRequest( Irp, AfdPriorityBoost );
  557. return status;
  558. } // AfdBReceive
  559. NTSTATUS
  560. AfdBChainedReceiveEventHandler(
  561. IN PVOID TdiEventContext,
  562. IN CONNECTION_CONTEXT ConnectionContext,
  563. IN ULONG ReceiveFlags,
  564. IN ULONG ReceiveLength,
  565. IN ULONG StartingOffset,
  566. IN PMDL Tsdu,
  567. IN PVOID TsduDescriptor
  568. )
  569. /*++
  570. Routine Description:
  571. Handles chained receive events for nonbufferring transports.
  572. Arguments:
  573. Return Value:
  574. --*/
  575. {
  576. AFD_LOCK_QUEUE_HANDLE lockHandle;
  577. PAFD_ENDPOINT endpoint;
  578. PAFD_CONNECTION connection;
  579. PAFD_BUFFER_TAG afdBufferTag;
  580. LIST_ENTRY completeIrpListHead;
  581. PIRP irp;
  582. PIO_STACK_LOCATION irpSp;
  583. NTSTATUS status;
  584. ULONG offset;
  585. BOOLEAN result;
  586. connection = (PAFD_CONNECTION)ConnectionContext;
  587. ASSERT( connection != NULL );
  588. CHECK_REFERENCE_CONNECTION2 (connection,"AfdBChainedReceiveEventHandler, receive length:%lx", ReceiveLength, result );
  589. if (!result) {
  590. return STATUS_DATA_NOT_ACCEPTED;
  591. }
  592. ASSERT( connection->Type == AfdBlockTypeConnection );
  593. endpoint = connection->Endpoint;
  594. ASSERT( endpoint != NULL );
  595. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting ||
  596. endpoint->Type == AfdBlockTypeVcListening ||
  597. endpoint->Type == AfdBlockTypeVcBoth );
  598. ASSERT( !connection->DisconnectIndicated );
  599. ASSERT( !IS_TDI_BUFFERRING(endpoint) );
  600. #if DBG
  601. {
  602. PMDL tstMdl = Tsdu;
  603. ULONG count = 0;
  604. while (tstMdl) {
  605. count += MmGetMdlByteCount (tstMdl);
  606. tstMdl = tstMdl->Next;
  607. }
  608. ASSERT (count>=StartingOffset+ReceiveLength);
  609. }
  610. #endif
  611. #if AFD_PERF_DBG
  612. AfdFullReceiveIndications++;
  613. #endif
  614. IF_DEBUG (RECEIVE) {
  615. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  616. "AfdBChainedReceiveEventHandler>>: Connection %p, TdsuDescr: %p, Length: %ld.\n",
  617. connection, TsduDescriptor, ReceiveLength));
  618. }
  619. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  620. //
  621. // Check if connection was accepted and use accept endpoint instead
  622. // of the listening. Note that accept cannot happen while we are
  623. // holding listening endpoint spinlock, nor can endpoint change after
  624. // the accept, so it is safe to release listening spinlock if
  625. // we discover that endpoint was accepted.
  626. //
  627. if (((endpoint->Type & AfdBlockTypeVcListening) == AfdBlockTypeVcListening)
  628. && (connection->Endpoint != endpoint)) {
  629. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  630. endpoint = connection->Endpoint;
  631. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting );
  632. ASSERT( !IS_TDI_BUFFERRING(endpoint) );
  633. ASSERT( IS_VC_ENDPOINT (endpoint) );
  634. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  635. }
  636. //
  637. // If the receive side of the endpoint has been shut down, tell the
  638. // provider that we took all the data and reset the connection.
  639. // Same if we are shutting down.
  640. //
  641. if ((endpoint->DisconnectMode & AFD_PARTIAL_DISCONNECT_RECEIVE) != 0 ||
  642. endpoint->EndpointCleanedUp ) {
  643. IF_DEBUG (RECEIVE) {
  644. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  645. "AfdBChainedReceiveEventHandler: receive shutdown, "
  646. "%ld bytes, aborting endp %p\n",
  647. ReceiveLength, endpoint ));
  648. }
  649. //
  650. // Abort the connection. Note that if the abort attempt fails
  651. // we can't do anything about it.
  652. //
  653. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  654. (VOID)AfdBeginAbort( connection );
  655. DEREFERENCE_CONNECTION (connection);
  656. return STATUS_SUCCESS;
  657. }
  658. if (ReceiveFlags & TDI_RECEIVE_EXPEDITED) {
  659. //
  660. // We're being indicated with expedited data. Buffer it and
  661. // complete any pended IRPs in the restart routine. We always
  662. // buffer expedited data to save complexity and because expedited
  663. // data is not an important performance case.
  664. //
  665. // !!! do we need to perform flow control with expedited data?
  666. //
  667. PAFD_BUFFER afdBuffer;
  668. if (connection->VcBufferredExpeditedCount==MAXUSHORT ||
  669. (afdBuffer=AfdGetBuffer (ReceiveLength, 0, connection->OwningProcess))==NULL) {
  670. //
  671. // If we couldn't get a buffer, abort the connection. This is
  672. // pretty brutal, but the only alternative is to attempt to
  673. // receive the data sometime later, which is very complicated to
  674. // implement.
  675. //
  676. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  677. (VOID)AfdBeginAbort( connection );
  678. DEREFERENCE_CONNECTION (connection);
  679. return STATUS_SUCCESS;
  680. }
  681. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  682. status = TdiCopyMdlToBuffer (Tsdu,
  683. StartingOffset,
  684. afdBuffer->Buffer,
  685. 0,
  686. afdBuffer->BufferLength,
  687. &ReceiveLength);
  688. ASSERT (status==STATUS_SUCCESS);
  689. //
  690. // We need to remember the connection in the AFD buffer because
  691. // we'll need to access it in the completion routine.
  692. //
  693. afdBuffer->Context = connection;
  694. //
  695. // Remember the type of data that we're receiving.
  696. //
  697. afdBuffer->ExpeditedData = TRUE;
  698. afdBuffer->PartialMessage = (BOOLEAN)((ReceiveFlags & TDI_RECEIVE_ENTIRE_MESSAGE) == 0);
  699. afdBuffer->Irp->IoStatus.Status = status;
  700. afdBuffer->Irp->IoStatus.Information = ReceiveLength;
  701. status = AfdRestartBufferReceive (AfdDeviceObject, afdBuffer->Irp, afdBuffer);
  702. ASSERT (status==STATUS_MORE_PROCESSING_REQUIRED);
  703. return STATUS_SUCCESS;
  704. }
  705. //
  706. // If we are indicated data, we need to reset our record
  707. // of amount of data buffered by the transport.
  708. //
  709. connection->VcReceiveBytesInTransport = 0;
  710. RetryReceive:
  711. InitializeListHead( &completeIrpListHead );
  712. offset = AfdBFillPendingIrps (
  713. connection,
  714. Tsdu,
  715. StartingOffset,
  716. ReceiveLength,
  717. (ReceiveFlags & TDI_RECEIVE_ENTIRE_MESSAGE) |
  718. AFD_RECEIVE_CHAINED |
  719. (!IS_MESSAGE_ENDPOINT(endpoint) ?
  720. AFD_RECEIVE_STREAM : 0),
  721. &completeIrpListHead
  722. );
  723. if (offset==(ULONG)-1) {
  724. //
  725. // If the IRP had more space than in this packet and this
  726. // was not set a complete message, we will pass the IRP to
  727. // the transport and refuse the indicated data (the transport
  728. // can fill the rest of the IRP).
  729. //
  730. //
  731. // This receive indication cannot be expedited or a complete message
  732. // becuase it does not make sense to pass the IRP back in such
  733. // cases.
  734. //
  735. ASSERT (!IsListEmpty (&completeIrpListHead));
  736. ASSERT ((ReceiveFlags &
  737. (TDI_RECEIVE_EXPEDITED|TDI_RECEIVE_ENTIRE_MESSAGE))==0);
  738. ASSERT (!AfdIgnorePushBitOnReceives);
  739. irp = CONTAINING_RECORD (completeIrpListHead.Flink,
  740. IRP,
  741. Tail.Overlay.ListEntry);
  742. irpSp = IoGetCurrentIrpStackLocation (irp);
  743. ASSERT (irpSp->Parameters.AfdRestartRecvInfo.AfdOriginalLength-
  744. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength >
  745. ReceiveLength);
  746. //
  747. // Reference connection (to be released in restart routine).
  748. // Keep reference added in the beginning of this routine.
  749. // REFERENCE_CONNECTION (connection);
  750. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  751. //
  752. // Note that we have outstanding user IRP in transport.
  753. //
  754. ASSERT (InterlockedIncrement (&connection->VcReceiveIrpsInTransport)==1);
  755. //
  756. // IRP is already partially filled.
  757. //
  758. if (irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength>0) {
  759. irp->MdlAddress = AfdAdvanceMdlChain (
  760. irp->MdlAddress,
  761. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength
  762. - PtrToUlong(irpSp->Parameters.AfdRestartRecvInfo.AfdAdjustedLength)
  763. );
  764. ASSERT (irp->MdlAddress!=NULL);
  765. //
  766. // Remeber the length by which we adjusted MDL, so we know where
  767. // to start next time.
  768. //
  769. irpSp->Parameters.AfdRestartRecvInfo.AfdAdjustedLength =
  770. UlongToPtr(irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength);
  771. }
  772. //
  773. // Build the receive IRP to give to the TDI provider.
  774. //
  775. TdiBuildReceive(
  776. irp,
  777. connection->DeviceObject,
  778. connection->FileObject,
  779. AfdRestartBufferReceiveWithUserIrp,
  780. connection,
  781. irp->MdlAddress,
  782. irpSp->Parameters.AfdRestartRecvInfo.AfdRecvFlags & TDI_RECEIVE_EITHER,
  783. irpSp->Parameters.AfdRestartRecvInfo.AfdOriginalLength -
  784. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength
  785. );
  786. if (AfdRecordOutstandingIrp (endpoint, connection->DeviceObject, irp)) {
  787. (VOID)IoCallDriver(connection->DeviceObject, irp );
  788. }
  789. else {
  790. //
  791. // On debug build, AFD might have complete this IRP if it could not allocate
  792. // tracking structure. In this case the transport does not get a call
  793. // and as the result does not restart indications. Also, the data already
  794. // placed in the IRP gets lost.
  795. //
  796. // To avoid this, we retry the indication ourselves.
  797. //
  798. CHECK_REFERENCE_CONNECTION (connection, result);
  799. if (result) {
  800. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  801. goto RetryReceive;
  802. }
  803. }
  804. return STATUS_DATA_NOT_ACCEPTED;
  805. }
  806. ASSERT (offset-StartingOffset<=ReceiveLength);
  807. //
  808. // If there is any data left, place the buffer at the end of the
  809. // connection's list of bufferred data and update counts of data on
  810. // the connection.
  811. //
  812. if (ReceiveLength > offset-StartingOffset) {
  813. //
  814. // If offset is not zero we should not have had anything buffered.
  815. //
  816. ASSERT (offset==StartingOffset || connection->VcBufferredReceiveCount==0);
  817. if ( offset>StartingOffset ||
  818. (connection->VcBufferredReceiveBytes <=
  819. connection->MaxBufferredReceiveBytes &&
  820. connection->VcBufferredReceiveCount<MAXUSHORT) ){
  821. //
  822. // We should attempt to buffer the data.
  823. //
  824. afdBufferTag = AfdGetBufferTag (0, connection->OwningProcess);
  825. }
  826. else {
  827. ASSERT (offset==StartingOffset);
  828. //
  829. // We are over the limit, don't take the data.
  830. //
  831. afdBufferTag = NULL;
  832. }
  833. if (afdBufferTag!=NULL) {
  834. AFD_VERIFY_MDL (connection, Tsdu, StartingOffset, ReceiveLength);
  835. afdBufferTag->Mdl = Tsdu;
  836. afdBufferTag->DataLength = ReceiveLength - (offset-StartingOffset);
  837. afdBufferTag->DataOffset = offset;
  838. afdBufferTag->RefCount = 1;
  839. afdBufferTag->Context = TsduDescriptor;
  840. afdBufferTag->NdisPacket = TRUE;
  841. afdBufferTag->PartialMessage = (BOOLEAN)((ReceiveFlags & TDI_RECEIVE_ENTIRE_MESSAGE) == 0);
  842. InsertTailList(
  843. &connection->VcReceiveBufferListHead,
  844. &afdBufferTag->BufferListEntry
  845. );
  846. connection->VcBufferredReceiveBytes += afdBufferTag->DataLength;
  847. ASSERT (connection->VcBufferredReceiveCount<MAXUSHORT);
  848. connection->VcBufferredReceiveCount += 1;
  849. endpoint->DisableFastIoRecv = FALSE;
  850. // Make sure connection was accepted/connected to prevent
  851. // indication on listening endpoint
  852. //
  853. if (connection->State==AfdConnectionStateConnected) {
  854. ASSERT (endpoint->Type & AfdBlockTypeVcConnecting);
  855. AfdIndicateEventSelectEvent(
  856. endpoint,
  857. AFD_POLL_RECEIVE,
  858. STATUS_SUCCESS
  859. );
  860. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  861. AfdIndicatePollEvent(
  862. endpoint,
  863. AFD_POLL_RECEIVE,
  864. STATUS_SUCCESS
  865. );
  866. }
  867. else {
  868. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  869. }
  870. status = STATUS_PENDING;
  871. }
  872. else {
  873. if (offset==StartingOffset) {
  874. //
  875. // If no IRPs were pending on the endpoint just remember the
  876. // amount of data that is available. When application
  877. // reposts the receive, we'll actually pull this data.
  878. //
  879. connection->VcReceiveBytesInTransport += ReceiveLength;
  880. if (connection->VcBufferredReceiveBytes == 0 &&
  881. !connection->OnLRList) {
  882. //
  883. // Since we do not have any data buffered, application
  884. // is not notified and will never call with recv.
  885. // We will have to put this on low resource list
  886. // and attempt to allocate memory and pull the data
  887. // later.
  888. //
  889. connection->OnLRList = TRUE;
  890. REFERENCE_CONNECTION (connection);
  891. AfdLRListAddItem (&connection->LRListItem, AfdLRRepostReceive);
  892. }
  893. else {
  894. UPDATE_CONN (connection);
  895. }
  896. }
  897. else {
  898. PLIST_ENTRY listEntry;
  899. //
  900. // We need to put back the IRPs that we were going to complete
  901. //
  902. listEntry = completeIrpListHead.Blink;
  903. while ( listEntry!=&completeIrpListHead ) {
  904. irp = CONTAINING_RECORD( listEntry, IRP, Tail.Overlay.ListEntry );
  905. listEntry = listEntry->Blink;
  906. // Set up the cancellation routine back in the IRP.
  907. //
  908. IoSetCancelRoutine( irp, AfdCancelReceive );
  909. if ( !irp->Cancel ) {
  910. RemoveEntryList (&irp->Tail.Overlay.ListEntry);
  911. InsertHeadList (&connection->VcReceiveIrpListHead,
  912. &irp->Tail.Overlay.ListEntry);
  913. }
  914. else if (IoSetCancelRoutine( irp, NULL ) == NULL) {
  915. //
  916. // The cancel routine was never called.
  917. // Have to handle cancellation here, just let the
  918. // IRP remain in completed list and set the
  919. // status appropriately keeping in mind that
  920. // we cannot complete IRP as cancelled if it
  921. // already has some data in it.
  922. //
  923. irpSp = IoGetCurrentIrpStackLocation (irp);
  924. if (irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength!=0) {
  925. ASSERT (!endpoint->EndpointCleanedUp); // checked above.
  926. irp->IoStatus.Status = STATUS_SUCCESS;
  927. irp->IoStatus.Information = irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength;
  928. }
  929. else {
  930. irp->IoStatus.Status = STATUS_CANCELLED;
  931. }
  932. }
  933. else {
  934. RemoveEntryList (&irp->Tail.Overlay.ListEntry);
  935. //
  936. // The cancel routine is about to be run.
  937. // Set the Flink to NULL so the cancel routine knows
  938. // it is not on the list
  939. //
  940. irp->Tail.Overlay.ListEntry.Flink = NULL;
  941. }
  942. }
  943. UPDATE_CONN (connection);
  944. }
  945. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  946. status = STATUS_DATA_NOT_ACCEPTED;
  947. }
  948. }
  949. else {
  950. AFD_VERIFY_MDL (connection, Tsdu, StartingOffset, offset-StartingOffset);
  951. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  952. status = STATUS_SUCCESS;
  953. }
  954. while ( !IsListEmpty( &completeIrpListHead ) ) {
  955. PLIST_ENTRY listEntry;
  956. listEntry = RemoveHeadList( &completeIrpListHead );
  957. irp = CONTAINING_RECORD( listEntry, IRP, Tail.Overlay.ListEntry );
  958. irpSp = IoGetCurrentIrpStackLocation (irp);
  959. //
  960. // Copy the data into the IRP if it is not errored out and
  961. // we accepted the data.
  962. //
  963. if (status!=STATUS_DATA_NOT_ACCEPTED && !NT_ERROR (irp->IoStatus.Status)) {
  964. ULONG bytesCopied;
  965. if (irp->MdlAddress!=NULL) {
  966. #if DBG
  967. NTSTATUS status1 =
  968. #endif
  969. AfdCopyMdlChainToMdlChain(
  970. irp->MdlAddress,
  971. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength
  972. - PtrToUlong(irpSp->Parameters.AfdRestartRecvInfo.AfdAdjustedLength),
  973. Tsdu,
  974. StartingOffset,
  975. ReceiveLength,
  976. &bytesCopied
  977. );
  978. ASSERT (status1==STATUS_SUCCESS ||
  979. status1==STATUS_BUFFER_OVERFLOW);
  980. ASSERT (irpSp->Parameters.AfdRestartRecvInfo.AfdOriginalLength-
  981. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength>=bytesCopied);
  982. irp->IoStatus.Information =
  983. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength + bytesCopied;
  984. }
  985. else {
  986. bytesCopied = 0;
  987. ASSERT (irp->IoStatus.Information == 0);
  988. ASSERT (irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength==0);
  989. ASSERT (irpSp->Parameters.AfdRestartRecvInfo.AfdOriginalLength==0);
  990. }
  991. if ((irpSp->Parameters.AfdRestartRecvInfo.AfdRecvFlags& TDI_RECEIVE_PEEK) == 0) {
  992. StartingOffset += bytesCopied;
  993. ReceiveLength -= bytesCopied;
  994. }
  995. }
  996. else {
  997. //
  998. // Either we failing the irp or we already filled in some data
  999. // or this irp was for 0 bytes to begin with in which case
  1000. // we just succeed it.
  1001. //
  1002. ASSERT (NT_ERROR (irp->IoStatus.Status) ||
  1003. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength!=0||
  1004. irpSp->Parameters.AfdRestartRecvInfo.AfdOriginalLength==0);
  1005. }
  1006. IF_DEBUG (RECEIVE) {
  1007. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1008. "AfdBChainedReceiveEventHandler: endpoint: %p, completing IRP: %p, status %lx, info: %ld.\n",
  1009. endpoint,
  1010. irp,
  1011. irp->IoStatus.Status,
  1012. irp->IoStatus.Information));
  1013. }
  1014. UPDATE_CONN2(connection, "Completing chained receive with error/bytes read: 0x%lX",
  1015. (!NT_ERROR(irp->IoStatus.Status)
  1016. ? (ULONG)irp->IoStatus.Information
  1017. : (ULONG)irp->IoStatus.Status));
  1018. IoCompleteRequest( irp, AfdPriorityBoost );
  1019. }
  1020. DEREFERENCE_CONNECTION (connection);
  1021. IF_DEBUG (RECEIVE) {
  1022. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1023. "AfdBChainedReceiveEventHandler<<: %ld\n", status));
  1024. }
  1025. return status;
  1026. }
  1027. NTSTATUS
  1028. AfdBReceiveEventHandler (
  1029. IN PVOID TdiEventContext,
  1030. IN CONNECTION_CONTEXT ConnectionContext,
  1031. IN ULONG ReceiveFlags,
  1032. IN ULONG BytesIndicated,
  1033. IN ULONG BytesAvailable,
  1034. OUT ULONG *BytesTaken,
  1035. IN PVOID Tsdu,
  1036. OUT PIRP *IoRequestPacket
  1037. )
  1038. /*++
  1039. Routine Description:
  1040. Handles receive events for nonbufferring transports.
  1041. Arguments:
  1042. Return Value:
  1043. --*/
  1044. {
  1045. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1046. PAFD_ENDPOINT endpoint;
  1047. PAFD_CONNECTION connection;
  1048. PAFD_BUFFER afdBuffer;
  1049. PIRP irp;
  1050. PLIST_ENTRY listEntry;
  1051. ULONG requiredAfdBufferSize;
  1052. NTSTATUS status;
  1053. ULONG receiveLength;
  1054. BOOLEAN expedited;
  1055. BOOLEAN completeMessage, result;
  1056. DEBUG receiveLength = 0xFFFFFFFF;
  1057. connection = (PAFD_CONNECTION)ConnectionContext;
  1058. ASSERT( connection != NULL );
  1059. CHECK_REFERENCE_CONNECTION2 (connection,"AfdBReceiveEventHandler, bytes available: %lx", BytesAvailable, result );
  1060. if (!result) {
  1061. return STATUS_DATA_NOT_ACCEPTED;
  1062. }
  1063. ASSERT( connection->Type == AfdBlockTypeConnection );
  1064. endpoint = connection->Endpoint;
  1065. ASSERT( endpoint != NULL );
  1066. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting ||
  1067. endpoint->Type == AfdBlockTypeVcListening ||
  1068. endpoint->Type == AfdBlockTypeVcBoth );
  1069. ASSERT( !connection->DisconnectIndicated );
  1070. ASSERT( !IS_TDI_BUFFERRING(endpoint) );
  1071. ASSERT( IS_VC_ENDPOINT (endpoint) );
  1072. *BytesTaken = 0;
  1073. #if AFD_PERF_DBG
  1074. if ( BytesAvailable == BytesIndicated ) {
  1075. AfdFullReceiveIndications++;
  1076. } else {
  1077. AfdPartialReceiveIndications++;
  1078. }
  1079. #endif
  1080. //
  1081. // Figure out whether this is a receive indication for normal
  1082. // or expedited data, and whether this is a complete message.
  1083. //
  1084. expedited = (BOOLEAN)( (ReceiveFlags & TDI_RECEIVE_EXPEDITED) != 0 );
  1085. completeMessage = (BOOLEAN)((ReceiveFlags & TDI_RECEIVE_ENTIRE_MESSAGE) != 0);
  1086. //
  1087. // If the receive side of the endpoint has been shut down, tell the
  1088. // provider that we took all the data and reset the connection.
  1089. // Also, account for these bytes in our count of bytes taken from
  1090. // the transport.
  1091. //
  1092. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  1093. //
  1094. // Check if connection was accepted and use accept endpoint instead
  1095. // of the listening. Note that accept cannot happen while we are
  1096. // holding listening endpoint spinlock, nor can endpoint change after
  1097. // the accept and while connection is referenced, so it is safe to
  1098. // release listening spinlock if we discover that endpoint was accepted.
  1099. //
  1100. if (((endpoint->Type & AfdBlockTypeVcListening) == AfdBlockTypeVcListening)
  1101. && (connection->Endpoint != endpoint)) {
  1102. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  1103. endpoint = connection->Endpoint;
  1104. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting );
  1105. ASSERT( !IS_TDI_BUFFERRING(endpoint) );
  1106. ASSERT( IS_VC_ENDPOINT (endpoint) );
  1107. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  1108. }
  1109. if ( (endpoint->DisconnectMode & AFD_PARTIAL_DISCONNECT_RECEIVE) != 0 ||
  1110. endpoint->EndpointCleanedUp ) {
  1111. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  1112. "AfdBReceiveEventHandler: receive shutdown, "
  1113. "%ld bytes, aborting endp %p\n",
  1114. BytesAvailable, endpoint ));
  1115. *BytesTaken = BytesAvailable;
  1116. //
  1117. // Abort the connection. Note that if the abort attempt fails
  1118. // we can't do anything about it.
  1119. //
  1120. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1121. (VOID)AfdBeginAbort( connection );
  1122. DEREFERENCE_CONNECTION (connection);
  1123. return STATUS_SUCCESS;
  1124. }
  1125. //
  1126. // If we are indicated data, we need to reset our record
  1127. // of amount of data buffered by the transport.
  1128. //
  1129. connection->VcReceiveBytesInTransport = 0;
  1130. //
  1131. // Check whether there are any IRPs waiting on the connection. If
  1132. // there is such an IRP and normal data is being indicated, use the
  1133. // IRP to receive the data.
  1134. //
  1135. if ( !expedited ) {
  1136. while (!IsListEmpty( &connection->VcReceiveIrpListHead )) {
  1137. PIO_STACK_LOCATION irpSp;
  1138. ASSERT( *BytesTaken == 0 );
  1139. listEntry = RemoveHeadList( &connection->VcReceiveIrpListHead );
  1140. //
  1141. // Get a pointer to the IRP and our stack location in it
  1142. //
  1143. irp = CONTAINING_RECORD( listEntry, IRP, Tail.Overlay.ListEntry );
  1144. irpSp = IoGetCurrentIrpStackLocation( irp );
  1145. receiveLength = irpSp->Parameters.AfdRestartRecvInfo.AfdOriginalLength-
  1146. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength;
  1147. //
  1148. // If the IRP is not large enough to hold the available data, or
  1149. // if it is a peek or expedited (exclusively, not both normal and
  1150. // expedited) receive IRP, then we'll just buffer the
  1151. // data manually and complete the IRP in the receive completion
  1152. // routine.
  1153. //
  1154. if ( (receiveLength>=BytesAvailable) &&
  1155. ((irpSp->Parameters.AfdRestartRecvInfo.AfdRecvFlags
  1156. & TDI_RECEIVE_PEEK) == 0) &&
  1157. ((irpSp->Parameters.AfdRestartRecvInfo.AfdRecvFlags
  1158. & TDI_RECEIVE_NORMAL) != 0)) {
  1159. if ( IoSetCancelRoutine( irp, NULL ) == NULL ) {
  1160. //
  1161. // This IRP is about to be canceled. Look for another in the
  1162. // list. Set the Flink to NULL so the cancel routine knows
  1163. // it is not on the list.
  1164. //
  1165. irp->Tail.Overlay.ListEntry.Flink = NULL;
  1166. continue;
  1167. }
  1168. //
  1169. // If all of the data was indicated to us here AND this is a
  1170. // complete message in and of itself, then just copy the
  1171. // data to the IRP and complete the IRP.
  1172. //
  1173. if ( completeMessage &&
  1174. (BytesIndicated == BytesAvailable)) {
  1175. AFD_VERIFY_BUFFER (connection, Tsdu, BytesAvailable);
  1176. //
  1177. // The IRP is off the endpoint's list and is no longer
  1178. // cancellable. We can release the locks we hold.
  1179. //
  1180. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1181. //
  1182. // Copy the data to the IRP.
  1183. //
  1184. if ( irp->MdlAddress != NULL ) {
  1185. status = AfdMapMdlChain (irp->MdlAddress);
  1186. if (NT_SUCCESS (status)) {
  1187. status = TdiCopyBufferToMdl(
  1188. Tsdu,
  1189. 0,
  1190. BytesAvailable,
  1191. irp->MdlAddress,
  1192. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength
  1193. - PtrToUlong(irpSp->Parameters.AfdRestartRecvInfo.AfdAdjustedLength),
  1194. &receiveLength
  1195. );
  1196. irp->IoStatus.Information =
  1197. receiveLength + irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength;
  1198. ASSERT (status == STATUS_SUCCESS);
  1199. }
  1200. else {
  1201. irp->IoStatus.Status = status;
  1202. irp->IoStatus.Information = 0;
  1203. UPDATE_CONN(connection);
  1204. IoCompleteRequest (irp, AfdPriorityBoost);
  1205. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  1206. continue;
  1207. }
  1208. } else {
  1209. ASSERT (irpSp->Parameters.AfdRestartRecvInfo.AfdOriginalLength==0);
  1210. ASSERT ( BytesAvailable == 0 );
  1211. irp->IoStatus.Information = irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength;
  1212. }
  1213. //
  1214. // We have already set up the status field of the IRP
  1215. // when we pended the IRP, so there's no need to
  1216. // set it again here.
  1217. //
  1218. ASSERT( irp->IoStatus.Status == STATUS_SUCCESS );
  1219. //
  1220. // Complete the IRP.
  1221. //
  1222. IF_DEBUG (RECEIVE) {
  1223. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1224. "AfdBReceiveEventHandler: endpoint: %p, completing IRP: %p, status %lx, info: %ld.\n",
  1225. endpoint,
  1226. irp,
  1227. irp->IoStatus.Status,
  1228. irp->IoStatus.Information));
  1229. }
  1230. UPDATE_CONN2(connection, "Completing receive with error/bytes: 0x%lX",
  1231. (!NT_ERROR(irp->IoStatus.Status)
  1232. ? (ULONG)irp->IoStatus.Information
  1233. : (ULONG)irp->IoStatus.Status));
  1234. IoCompleteRequest( irp, AfdPriorityBoost );
  1235. DEREFERENCE_CONNECTION (connection);
  1236. //
  1237. // Set BytesTaken to tell the provider that we have taken all the data.
  1238. //
  1239. *BytesTaken = BytesAvailable;
  1240. return STATUS_SUCCESS;
  1241. }
  1242. //
  1243. // Some of the data was not indicated, so remember that we
  1244. // want to pass back this IRP to the TDI provider. Passing
  1245. // back this IRP directly is good because it avoids having
  1246. // to copy the data from one of our buffers into the user's
  1247. // buffer.
  1248. //
  1249. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1250. ASSERT (InterlockedIncrement (&connection->VcReceiveIrpsInTransport)==1);
  1251. requiredAfdBufferSize = 0;
  1252. if (AfdIgnorePushBitOnReceives ||
  1253. IS_TDI_MESSAGE_MODE(endpoint)) {
  1254. receiveLength = BytesAvailable;
  1255. }
  1256. if (irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength>0) {
  1257. irp->MdlAddress = AfdAdvanceMdlChain (irp->MdlAddress,
  1258. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength
  1259. -PtrToUlong(irpSp->Parameters.AfdRestartRecvInfo.AfdAdjustedLength)
  1260. );
  1261. ASSERT (irp->MdlAddress!=NULL);
  1262. irpSp->Parameters.AfdRestartRecvInfo.AfdAdjustedLength =
  1263. UlongToPtr(irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength);
  1264. }
  1265. TdiBuildReceive(
  1266. irp,
  1267. connection->DeviceObject,
  1268. connection->FileObject,
  1269. AfdRestartBufferReceiveWithUserIrp,
  1270. connection,
  1271. irp->MdlAddress,
  1272. ReceiveFlags & TDI_RECEIVE_EITHER,
  1273. receiveLength
  1274. );
  1275. if (AfdRecordOutstandingIrp (endpoint, connection->DeviceObject, irp)) {
  1276. //
  1277. // Make the next stack location current. Normally IoCallDriver would
  1278. // do this, but since we're bypassing that, we do it directly.
  1279. //
  1280. IoSetNextIrpStackLocation( irp );
  1281. *IoRequestPacket = irp;
  1282. ASSERT (*BytesTaken == 0);
  1283. //
  1284. // Keep connection reference to be released in IRP completion routine
  1285. //
  1286. return STATUS_MORE_PROCESSING_REQUIRED;
  1287. }
  1288. else {
  1289. //
  1290. // Could not allocate IRP tracking info (only in debug builds)
  1291. // The IRP has aready been completed, go and try another one.
  1292. // Add extra reference to the connection to compensate for
  1293. // the one released in the completion routine.
  1294. //
  1295. CHECK_REFERENCE_CONNECTION (connection,result);
  1296. if (result) {
  1297. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  1298. continue;
  1299. }
  1300. else
  1301. return STATUS_DATA_NOT_ACCEPTED;
  1302. }
  1303. }
  1304. //
  1305. // The first pended IRP is too tiny to hold all the
  1306. // available data or else it is a peek or expedited receive
  1307. // IRP. Put the IRP back on the head of the list and buffer
  1308. // the data and complete the IRP in the restart routine.
  1309. //
  1310. InsertHeadList(
  1311. &connection->VcReceiveIrpListHead,
  1312. &irp->Tail.Overlay.ListEntry
  1313. );
  1314. break;
  1315. }
  1316. //
  1317. // Check whether we've already bufferred the maximum amount of
  1318. // data that we'll allow ourselves to buffer for this
  1319. // connection. If we're at the limit, then we need to exert
  1320. // back pressure by not accepting this indicated data (flow
  1321. // control).
  1322. //
  1323. // Note that we have no flow control mechanisms for expedited
  1324. // data. We always accept any expedited data that is indicated
  1325. // to us.
  1326. //
  1327. if ( connection->VcBufferredReceiveBytes >=
  1328. connection->MaxBufferredReceiveBytes ||
  1329. connection->VcBufferredReceiveCount==MAXUSHORT
  1330. ) {
  1331. //
  1332. // Just remember the amount of data that is available. When
  1333. // buffer space frees up, we'll actually receive this data.
  1334. //
  1335. connection->VcReceiveBytesInTransport += BytesAvailable;
  1336. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1337. DEREFERENCE_CONNECTION (connection);
  1338. return STATUS_DATA_NOT_ACCEPTED;
  1339. }
  1340. // There were no prepended IRPs, we'll have to buffer the data
  1341. // here in AFD. If all of the available data is being indicated
  1342. // to us AND this is a complete message, just copy the data
  1343. // here.
  1344. //
  1345. if ( completeMessage &&
  1346. BytesIndicated == BytesAvailable &&
  1347. IsListEmpty (&connection->VcReceiveIrpListHead)) {
  1348. afdBuffer = AfdGetBuffer( BytesAvailable, 0,
  1349. connection->OwningProcess );
  1350. if (afdBuffer!=NULL) {
  1351. AFD_VERIFY_BUFFER (connection, Tsdu, BytesAvailable);
  1352. //
  1353. // Use the special function to copy the data instead of
  1354. // RtlCopyMemory in case the data is coming from a special
  1355. // place (DMA, etc.) which cannot work with RtlCopyMemory.
  1356. //
  1357. TdiCopyLookaheadData(
  1358. afdBuffer->Buffer,
  1359. Tsdu,
  1360. BytesAvailable,
  1361. ReceiveFlags
  1362. );
  1363. //
  1364. // Store the data length and set the offset to 0.
  1365. //
  1366. afdBuffer->DataLength = BytesAvailable;
  1367. afdBuffer->DataOffset = 0;
  1368. afdBuffer->RefCount = 1;
  1369. afdBuffer->PartialMessage = FALSE;
  1370. //
  1371. // Place the buffer on this connection's list of bufferred data
  1372. // and update the count of data bytes on the connection.
  1373. //
  1374. InsertTailList(
  1375. &connection->VcReceiveBufferListHead,
  1376. &afdBuffer->BufferListEntry
  1377. );
  1378. connection->VcBufferredReceiveBytes += BytesAvailable;
  1379. ASSERT (connection->VcBufferredReceiveCount<MAXUSHORT);
  1380. connection->VcBufferredReceiveCount += 1;
  1381. //
  1382. // All done. Release the lock and tell the provider that we
  1383. // took all the data.
  1384. //
  1385. *BytesTaken = BytesAvailable;
  1386. //
  1387. // Indicate that it is possible to receive on the endpoint now.
  1388. //
  1389. endpoint->DisableFastIoRecv = FALSE;
  1390. // Make sure connection was accepted/connected to prevent
  1391. // indication on listening endpoint
  1392. //
  1393. if (connection->State==AfdConnectionStateConnected) {
  1394. ASSERT (endpoint->Type & AfdBlockTypeVcConnecting);
  1395. AfdIndicateEventSelectEvent(
  1396. endpoint,
  1397. AFD_POLL_RECEIVE,
  1398. STATUS_SUCCESS
  1399. );
  1400. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1401. AfdIndicatePollEvent(
  1402. endpoint,
  1403. AFD_POLL_RECEIVE,
  1404. STATUS_SUCCESS
  1405. );
  1406. }
  1407. else {
  1408. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1409. }
  1410. DEREFERENCE_CONNECTION (connection);
  1411. return STATUS_SUCCESS;
  1412. }
  1413. }
  1414. else {
  1415. //
  1416. // There were no prepended IRPs and not all of the data was
  1417. // indicated to us. We'll have to buffer it by handing an IRP
  1418. // back to the TDI privider.
  1419. //
  1420. // Note that in this case we sometimes hand a large buffer to
  1421. // the TDI provider. We do this so that it can hold off
  1422. // completion of our IRP until it gets EOM or the buffer is
  1423. // filled. This reduces the number of receive indications that
  1424. // the TDI provider has to perform and also reduces the number
  1425. // of kernel/user transitions the application will perform
  1426. // because we'll tend to complete receives with larger amounts
  1427. // of data.
  1428. //
  1429. // We do not hand back a "large" AFD buffer if the indicated data
  1430. // is greater than the large buffer size or if the TDI provider
  1431. // is message mode. The reason for not giving big buffers back
  1432. // to message providers is that they will hold on to the buffer
  1433. // until a full message is received and this would be incorrect
  1434. // behavior on a SOCK_STREAM.
  1435. //
  1436. if ( AfdLargeBufferSize >= BytesAvailable &&
  1437. !AfdIgnorePushBitOnReceives &&
  1438. !IS_TDI_MESSAGE_MODE(endpoint) ) {
  1439. requiredAfdBufferSize = AfdLargeBufferSize;
  1440. receiveLength = AfdLargeBufferSize;
  1441. } else {
  1442. requiredAfdBufferSize = BytesAvailable;
  1443. receiveLength = BytesAvailable;
  1444. }
  1445. //
  1446. // We're able to buffer the data. First acquire a buffer of
  1447. // appropriate size.
  1448. //
  1449. afdBuffer = AfdGetBuffer( requiredAfdBufferSize, 0,
  1450. connection->OwningProcess );
  1451. if ( afdBuffer != NULL ) {
  1452. //
  1453. // Note that we posted our own receive IRP to transport,
  1454. // so that user IRPs do not get forwarded there
  1455. //
  1456. ASSERT (InterlockedDecrement (&connection->VcReceiveIrpsInTransport)==-1);
  1457. goto FormatReceive;
  1458. }
  1459. }
  1460. // We failed to allocate the buffer.
  1461. // Just remember the amount of data that is available. When
  1462. // buffer space frees up, we'll actually receive this data.
  1463. //
  1464. connection->VcReceiveBytesInTransport += BytesAvailable;
  1465. if (connection->VcBufferredReceiveBytes == 0 &&
  1466. !connection->OnLRList) {
  1467. //
  1468. // Since we do not have any data buffered, application
  1469. // is not notified and will never call with recv.
  1470. // We will have to put this on low resource list
  1471. // and attempt to allocate memory and pull the data
  1472. // later.
  1473. //
  1474. connection->OnLRList = TRUE;
  1475. REFERENCE_CONNECTION (connection);
  1476. AfdLRListAddItem (&connection->LRListItem, AfdLRRepostReceive);
  1477. }
  1478. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1479. DEREFERENCE_CONNECTION (connection);
  1480. return STATUS_DATA_NOT_ACCEPTED;
  1481. } else {
  1482. //
  1483. // We're being indicated with expedited data. Buffer it and
  1484. // complete any pended IRPs in the restart routine. We always
  1485. // buffer expedited data to save complexity and because expedited
  1486. // data is not an important performance case.
  1487. //
  1488. // !!! do we need to perform flow control with expedited data?
  1489. //
  1490. requiredAfdBufferSize = BytesAvailable;
  1491. receiveLength = BytesAvailable;
  1492. //
  1493. // We're able to buffer the data. First acquire a buffer of
  1494. // appropriate size.
  1495. //
  1496. if ( connection->VcBufferredExpeditedCount==MAXUSHORT ||
  1497. (afdBuffer=AfdGetBuffer (requiredAfdBufferSize, 0,
  1498. connection->OwningProcess))== NULL ) {
  1499. // If we couldn't get a buffer, abort the connection. This is
  1500. // pretty brutal, but the only alternative is to attempt to
  1501. // receive the data sometime later, which is very complicated to
  1502. // implement.
  1503. //
  1504. AfdBeginAbort( connection );
  1505. *BytesTaken = BytesAvailable;
  1506. DEREFERENCE_CONNECTION (connection);
  1507. return STATUS_SUCCESS;
  1508. }
  1509. }
  1510. FormatReceive:
  1511. //
  1512. // We'll have to format up an IRP and give it to the provider to
  1513. // handle. We don't need any locks to do this--the restart routine
  1514. // will check whether new receive IRPs were pended on the endpoint.
  1515. //
  1516. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1517. ASSERT (afdBuffer!=NULL);
  1518. //
  1519. // Use the IRP in the AFD buffer if appropriate. If userIrp is
  1520. // TRUE, then the local variable irp will already point to the
  1521. // user's IRP which we'll use for this IO.
  1522. //
  1523. irp = afdBuffer->Irp;
  1524. ASSERT( afdBuffer->Mdl == irp->MdlAddress );
  1525. //
  1526. // We need to remember the connection in the AFD buffer because
  1527. // we'll need to access it in the completion routine.
  1528. //
  1529. afdBuffer->Context = connection;
  1530. //
  1531. // Remember the type of data that we're receiving.
  1532. //
  1533. afdBuffer->ExpeditedData = expedited;
  1534. afdBuffer->PartialMessage = !completeMessage;
  1535. TdiBuildReceive(
  1536. irp,
  1537. connection->DeviceObject,
  1538. connection->FileObject,
  1539. AfdRestartBufferReceive,
  1540. afdBuffer,
  1541. irp->MdlAddress,
  1542. ReceiveFlags & TDI_RECEIVE_EITHER,
  1543. receiveLength
  1544. );
  1545. //
  1546. // Finish building the receive IRP to give to the TDI provider.
  1547. //
  1548. ASSERT( receiveLength != 0xFFFFFFFF );
  1549. //
  1550. // Make the next stack location current. Normally IoCallDriver would
  1551. // do this, but since we're bypassing that, we do it directly.
  1552. //
  1553. IoSetNextIrpStackLocation( irp );
  1554. *IoRequestPacket = irp;
  1555. ASSERT (*BytesTaken == 0);
  1556. //
  1557. // Keep connection reference to be released in IRP completion routine
  1558. //
  1559. return STATUS_MORE_PROCESSING_REQUIRED;
  1560. } // AfdBReceiveEventHandler
  1561. NTSTATUS
  1562. AfdBReceiveExpeditedEventHandler (
  1563. IN PVOID TdiEventContext,
  1564. IN CONNECTION_CONTEXT ConnectionContext,
  1565. IN ULONG ReceiveFlags,
  1566. IN ULONG BytesIndicated,
  1567. IN ULONG BytesAvailable,
  1568. OUT ULONG *BytesTaken,
  1569. IN PVOID Tsdu,
  1570. OUT PIRP *IoRequestPacket
  1571. )
  1572. /*++
  1573. Routine Description:
  1574. Handles receive expedited events for nonbufferring transports.
  1575. Arguments:
  1576. Return Value:
  1577. --*/
  1578. {
  1579. return AfdBReceiveEventHandler (
  1580. TdiEventContext,
  1581. ConnectionContext,
  1582. ReceiveFlags | TDI_RECEIVE_EXPEDITED,
  1583. BytesIndicated,
  1584. BytesAvailable,
  1585. BytesTaken,
  1586. Tsdu,
  1587. IoRequestPacket
  1588. );
  1589. } // AfdBReceiveExpeditedEventHandler
  1590. NTSTATUS
  1591. AfdRestartBufferReceiveWithUserIrp (
  1592. IN PDEVICE_OBJECT DeviceObject,
  1593. IN PIRP Irp,
  1594. IN PVOID Context
  1595. )
  1596. /*++
  1597. Routine Description:
  1598. Handles completion of bufferred receives that were started in the
  1599. receive indication handler or receive routine with application
  1600. IRP passed directly to the transport.
  1601. Arguments:
  1602. DeviceObject - not used.
  1603. Irp - the IRP that is completing.
  1604. Context - connection on which we receive the data
  1605. Return Value:
  1606. STATUS_SUCCESS if user IRP is completed,
  1607. STATUS_MORE_PROCESSING_REQUIRED if we can't complete it.
  1608. --*/
  1609. {
  1610. PAFD_ENDPOINT endpoint;
  1611. PAFD_CONNECTION connection;
  1612. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1613. PIO_STACK_LOCATION irpSp;
  1614. //
  1615. // The IRP being completed is actually a user's IRP, set it up
  1616. // for completion and allow IO completion to finish.
  1617. //
  1618. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1619. connection = Context;
  1620. ASSERT( connection->Type == AfdBlockTypeConnection );
  1621. endpoint = connection->Endpoint;
  1622. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting ||
  1623. endpoint->Type == AfdBlockTypeVcBoth);
  1624. ASSERT( IS_VC_ENDPOINT(endpoint) );
  1625. ASSERT( !IS_TDI_BUFFERRING(endpoint) );
  1626. AfdCompleteOutstandingIrp (endpoint, Irp);
  1627. //
  1628. // We could not have any buffered data if we are completing user
  1629. // IRP
  1630. // Only true for expedited data. We sometimes give user Irp
  1631. // to only be filled with some of the available data.
  1632. //
  1633. // ASSERT( !(irpSp->Parameters.AfdRestartRecvInfo.AfdRecvFlags&TDI_RECEIVE_NORMAL)
  1634. // || !IS_DATA_ON_CONNECTION( connection ));
  1635. ASSERT( !(irpSp->Parameters.AfdRestartRecvInfo.AfdRecvFlags&TDI_RECEIVE_EXPEDITED)
  1636. || !IS_EXPEDITED_DATA_ON_CONNECTION( connection ));
  1637. AFD_VERIFY_MDL (connection, Irp->MdlAddress, 0, Irp->IoStatus.Information);
  1638. ASSERT (InterlockedDecrement (&connection->VcReceiveIrpsInTransport)>=0);
  1639. //
  1640. // If pending has be returned for this IRP then mark the current
  1641. // stack as pending.
  1642. //
  1643. if ( Irp->PendingReturned ) {
  1644. IoMarkIrpPending( Irp );
  1645. }
  1646. UPDATE_CONN2 (connection, "Completing user receive with error/bytes: 0x%lX",
  1647. !NT_ERROR (Irp->IoStatus.Status)
  1648. ? (ULONG)Irp->IoStatus.Information
  1649. : (ULONG)Irp->IoStatus.Status);
  1650. //
  1651. // If transport cancelled the IRP and we already had some data
  1652. // in it, do not complete with STATUS_CANCELLED since this will
  1653. // result in data loss.
  1654. //
  1655. if (Irp->IoStatus.Status==STATUS_CANCELLED &&
  1656. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength>0 &&
  1657. !endpoint->EndpointCleanedUp) {
  1658. Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
  1659. }
  1660. else if (!NT_ERROR (Irp->IoStatus.Status)) {
  1661. Irp->IoStatus.Information += irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength;
  1662. }
  1663. if (Irp->IoStatus.Status==STATUS_BUFFER_OVERFLOW ||
  1664. Irp->IoStatus.Status == STATUS_RECEIVE_PARTIAL ||
  1665. Irp->IoStatus.Status == STATUS_RECEIVE_PARTIAL_EXPEDITED) {
  1666. if (!IS_MESSAGE_ENDPOINT(endpoint)) {
  1667. //
  1668. // For stream endpoint partial message does not make
  1669. // sense (unless this is the special hack for transports that
  1670. // terminate the connection when we cancel IRPs), ignore it.
  1671. //
  1672. Irp->IoStatus.Status = STATUS_SUCCESS;
  1673. }
  1674. else if ((Irp->IoStatus.Information
  1675. <irpSp->Parameters.AfdRestartRecvInfo.AfdOriginalLength) &&
  1676. ((irpSp->Parameters.AfdRestartRecvInfo.AfdRecvFlags & TDI_RECEIVE_PARTIAL) == 0 )) {
  1677. NTSTATUS status = STATUS_MORE_PROCESSING_REQUIRED;
  1678. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  1679. //
  1680. // Reset the status to success if we need to complete the IRP
  1681. // This is not entirely correct for message endpoints since
  1682. // we should not be completing the IRP unless we received the
  1683. // entire message. However, the only way this can happen is
  1684. // when the part of the message was received as IRP is cancelled
  1685. // and the only other this we possibly do is to try to copy data
  1686. // in our own buffer and reinsert it back to the queue.
  1687. //
  1688. Irp->IoStatus.Status = STATUS_SUCCESS;
  1689. //
  1690. // Set up the cancellation routine back in the IRP.
  1691. //
  1692. IoSetCancelRoutine( Irp, AfdCancelReceive );
  1693. if ( Irp->Cancel ) {
  1694. if (IoSetCancelRoutine( Irp, NULL ) != NULL) {
  1695. //
  1696. // Completion routine has not been reset,
  1697. // let the system complete the IRP on return
  1698. //
  1699. status = STATUS_SUCCESS;
  1700. }
  1701. else {
  1702. //
  1703. // The cancel routine is about to be run.
  1704. // Set the Flink to NULL so the cancel routine knows
  1705. // it is not on the list and tell the system
  1706. // not to touch the irp
  1707. //
  1708. Irp->Tail.Overlay.ListEntry.Flink = NULL;
  1709. }
  1710. }
  1711. else {
  1712. //
  1713. // Reinset IRP back in the list if partial completion
  1714. // is impossible and tell the system not to touch it
  1715. //
  1716. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength = (ULONG)Irp->IoStatus.Information;
  1717. InsertHeadList (&connection->VcReceiveIrpListHead,
  1718. &Irp->Tail.Overlay.ListEntry);
  1719. }
  1720. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  1721. //
  1722. // Release connection reference acquired when we handed IRP to transport
  1723. //
  1724. DEREFERENCE_CONNECTION (connection);
  1725. return status;
  1726. }
  1727. }
  1728. IF_DEBUG (RECEIVE) {
  1729. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1730. "AfdRestartBufferReceiveWithUserIrp: endpoint: %p, letting IRP: %p, status %lx, info: %ld.\n",
  1731. endpoint,
  1732. Irp,
  1733. Irp->IoStatus.Status,
  1734. Irp->IoStatus.Information));
  1735. }
  1736. //
  1737. // Release connection reference acquired when we handed IRP to transport
  1738. //
  1739. DEREFERENCE_CONNECTION (connection);
  1740. //
  1741. // Tell the IO system that it is OK to continue with IO
  1742. // completion.
  1743. //
  1744. return STATUS_SUCCESS;
  1745. } //AfdRestartBufferReceiveWithUserIrp
  1746. NTSTATUS
  1747. AfdRestartBufferReceive (
  1748. IN PDEVICE_OBJECT DeviceObject,
  1749. IN PIRP Irp,
  1750. IN PVOID Context
  1751. )
  1752. /*++
  1753. Routine Description:
  1754. Handles completion of bufferred receives that were started in the
  1755. receive indication handler or AfdBReceive using Afds buffer and
  1756. associated IRP.
  1757. Arguments:
  1758. DeviceObject - not used.
  1759. Irp - the IRP that is completing.
  1760. Context - AfdBuffer in which we receive the data.
  1761. Return Value:
  1762. NTSTATUS - this is our IRP, so we always return
  1763. STATUS_MORE_PROCESSING_REQUIRED to indicate to the IO system that we
  1764. own the IRP and the IO system should stop processing the it.
  1765. --*/
  1766. {
  1767. PAFD_ENDPOINT endpoint;
  1768. PAFD_CONNECTION connection;
  1769. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1770. PAFD_BUFFER afdBuffer;
  1771. PLIST_ENTRY listEntry;
  1772. LIST_ENTRY completeIrpListHead;
  1773. PIRP userIrp;
  1774. BOOLEAN expedited;
  1775. NTSTATUS irpStatus;
  1776. afdBuffer = Context;
  1777. ASSERT (IS_VALID_AFD_BUFFER (afdBuffer));
  1778. irpStatus = Irp->IoStatus.Status;
  1779. //
  1780. // We treat STATUS_BUFFER_OVERFLOW just like STATUS_RECEIVE_PARTIAL.
  1781. //
  1782. if ( irpStatus == STATUS_BUFFER_OVERFLOW )
  1783. irpStatus = STATUS_RECEIVE_PARTIAL;
  1784. connection = afdBuffer->Context;
  1785. ASSERT( connection->Type == AfdBlockTypeConnection );
  1786. endpoint = connection->Endpoint;
  1787. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting ||
  1788. endpoint->Type == AfdBlockTypeVcListening ||
  1789. endpoint->Type == AfdBlockTypeVcBoth );
  1790. ASSERT( !IS_TDI_BUFFERRING(endpoint) );
  1791. ASSERT( IS_VC_ENDPOINT (endpoint) );
  1792. if ( !NT_SUCCESS(irpStatus) ) {
  1793. afdBuffer->Mdl->ByteCount = afdBuffer->BufferLength;
  1794. AfdReturnBuffer( &afdBuffer->Header, connection->OwningProcess );
  1795. //
  1796. // !!! We can't abort the connection if the connection has
  1797. // not yet been accepted because we'll still be pointing
  1798. // at the listening endpoint. We should do something,
  1799. // however. How common is this failure?
  1800. //
  1801. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_WARNING_LEVEL,
  1802. "AfdRestartBufferReceive: IRP %p failed on endp %p\n",
  1803. irpStatus, endpoint ));
  1804. DEREFERENCE_CONNECTION (connection);
  1805. return STATUS_MORE_PROCESSING_REQUIRED;
  1806. }
  1807. AFD_VERIFY_MDL (connection, Irp->MdlAddress, 0, Irp->IoStatus.Information);
  1808. //
  1809. // Remember the length of the received data.
  1810. //
  1811. afdBuffer->DataLength = (ULONG)Irp->IoStatus.Information;
  1812. //
  1813. // Initialize the local list we'll use to complete any receive IRPs.
  1814. // We use a list like this because we may need to complete multiple
  1815. // IRPs and we usually cannot complete IRPs at any random point due
  1816. // to any locks we might hold.
  1817. //
  1818. InitializeListHead( &completeIrpListHead );
  1819. //
  1820. // If there are any pended IRPs on the connection, complete as
  1821. // appropriate with the new information. Note that we'll try to
  1822. // complete as many pended IRPs as possible with this new buffer of
  1823. // data.
  1824. //
  1825. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  1826. //
  1827. // Check if connection was accepted and use accept endpoint instead
  1828. // of the listening. Note that accept cannot happen while we are
  1829. // holding listening endpoint spinlock, nor can endpoint change after
  1830. // the accept and while connections is referenced, so it is safe to
  1831. // release listening spinlock if we discover that endpoint was accepted.
  1832. //
  1833. if (((endpoint->Type & AfdBlockTypeVcListening) == AfdBlockTypeVcListening)
  1834. && (connection->Endpoint != endpoint)) {
  1835. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  1836. endpoint = connection->Endpoint;
  1837. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting );
  1838. ASSERT( !IS_TDI_BUFFERRING(endpoint) );
  1839. ASSERT( IS_VC_ENDPOINT (endpoint) );
  1840. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  1841. }
  1842. expedited = afdBuffer->ExpeditedData;
  1843. //
  1844. // Note that there are no more of our own receive IRPs in transport
  1845. // and we can start forwarding application IRPs if necessary.
  1846. //
  1847. ASSERT (expedited || InterlockedIncrement (&connection->VcReceiveIrpsInTransport)==0);
  1848. afdBuffer->DataOffset = AfdBFillPendingIrps (
  1849. connection,
  1850. afdBuffer->Mdl,
  1851. 0,
  1852. afdBuffer->DataLength,
  1853. (expedited ? TDI_RECEIVE_EXPEDITED : 0) |
  1854. ((irpStatus==STATUS_SUCCESS) ? TDI_RECEIVE_ENTIRE_MESSAGE : 0) |
  1855. (!IS_MESSAGE_ENDPOINT(endpoint) ? AFD_RECEIVE_STREAM : 0),
  1856. &completeIrpListHead
  1857. );
  1858. ASSERT (afdBuffer->DataOffset<=afdBuffer->DataLength);
  1859. afdBuffer->DataLength -= afdBuffer->DataOffset;
  1860. //
  1861. // If there is any data left, place the buffer at the end of the
  1862. // connection's list of bufferred data and update counts of data on
  1863. // the connection.
  1864. //
  1865. if (afdBuffer->DataLength>0) {
  1866. afdBuffer->RefCount = 1;
  1867. InsertTailList(
  1868. &connection->VcReceiveBufferListHead,
  1869. &afdBuffer->BufferListEntry
  1870. );
  1871. if ( expedited ) {
  1872. connection->VcBufferredExpeditedBytes += afdBuffer->DataLength;
  1873. ASSERT (connection->VcBufferredExpeditedCount<MAXUSHORT);
  1874. connection->VcBufferredExpeditedCount += 1;
  1875. } else {
  1876. connection->VcBufferredReceiveBytes += afdBuffer->DataLength;
  1877. ASSERT (connection->VcBufferredReceiveCount<MAXUSHORT);
  1878. connection->VcBufferredReceiveCount += 1;
  1879. }
  1880. //
  1881. // Remember whether we got a full or partial receive in the
  1882. // AFD buffer.
  1883. //
  1884. if ( irpStatus == STATUS_RECEIVE_PARTIAL ||
  1885. irpStatus == STATUS_RECEIVE_PARTIAL_EXPEDITED ) {
  1886. afdBuffer->PartialMessage = TRUE;
  1887. } else {
  1888. afdBuffer->PartialMessage = FALSE;
  1889. }
  1890. //
  1891. // We queued the buffer and thus we can't use it after releasing
  1892. // the spinlock. This will also signify the fact that we do not
  1893. // need to free the buffer.
  1894. //
  1895. afdBuffer = NULL;
  1896. if (connection->State==AfdConnectionStateConnected) {
  1897. endpoint->DisableFastIoRecv = FALSE;
  1898. if ( expedited && !endpoint->InLine ) {
  1899. AfdIndicateEventSelectEvent(
  1900. endpoint,
  1901. AFD_POLL_RECEIVE_EXPEDITED,
  1902. STATUS_SUCCESS
  1903. );
  1904. } else {
  1905. AfdIndicateEventSelectEvent(
  1906. endpoint,
  1907. AFD_POLL_RECEIVE,
  1908. STATUS_SUCCESS
  1909. );
  1910. }
  1911. }
  1912. }
  1913. //
  1914. // Release locks and indicate that there is bufferred data on the
  1915. // endpoint.
  1916. //
  1917. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1918. //
  1919. // If there was leftover data (we queued the buffer), complete polls
  1920. // as necessary. Indicate expedited data if the endpoint is not
  1921. // InLine and expedited data was received; otherwise, indicate normal data.
  1922. //
  1923. if ( afdBuffer==NULL ) {
  1924. // Make sure connection was accepted/connected to prevent
  1925. // indication on listening endpoint
  1926. //
  1927. if (connection->State==AfdConnectionStateConnected) {
  1928. ASSERT (endpoint->Type & AfdBlockTypeVcConnecting);
  1929. if ( expedited && !endpoint->InLine ) {
  1930. AfdIndicatePollEvent(
  1931. endpoint,
  1932. AFD_POLL_RECEIVE_EXPEDITED,
  1933. STATUS_SUCCESS
  1934. );
  1935. } else {
  1936. AfdIndicatePollEvent(
  1937. endpoint,
  1938. AFD_POLL_RECEIVE,
  1939. STATUS_SUCCESS
  1940. );
  1941. }
  1942. }
  1943. }
  1944. else {
  1945. ASSERT (afdBuffer->DataLength==0);
  1946. afdBuffer->ExpeditedData = FALSE;
  1947. AfdReturnBuffer (&afdBuffer->Header, connection->OwningProcess);
  1948. }
  1949. //
  1950. // Complete IRPs as necessary.
  1951. //
  1952. while ( !IsListEmpty( &completeIrpListHead ) ) {
  1953. listEntry = RemoveHeadList( &completeIrpListHead );
  1954. userIrp = CONTAINING_RECORD( listEntry, IRP, Tail.Overlay.ListEntry );
  1955. IF_DEBUG (RECEIVE) {
  1956. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1957. "AfdRestartBufferReceive: endpoint: %p, completing IRP: %p, status %lx, info: %ld.\n",
  1958. endpoint,
  1959. userIrp,
  1960. userIrp->IoStatus.Status,
  1961. userIrp->IoStatus.Information));
  1962. }
  1963. UPDATE_CONN2(connection, "Completing buffered receive with error/bytes: 0x%lX",
  1964. (!NT_ERROR(userIrp->IoStatus.Status)
  1965. ? (ULONG)userIrp->IoStatus.Information
  1966. : (ULONG)userIrp->IoStatus.Status));
  1967. IoCompleteRequest( userIrp, AfdPriorityBoost );
  1968. }
  1969. //
  1970. // Release connection reference acquired when we handed IRP to transport
  1971. //
  1972. DEREFERENCE_CONNECTION (connection);
  1973. //
  1974. // Tell the IO system to stop processing the AFD IRP, since we now
  1975. // own it as part of the AFD buffer.
  1976. //
  1977. return STATUS_MORE_PROCESSING_REQUIRED;
  1978. } // AfdRestartBufferReceive
  1979. ULONG
  1980. AfdBFillPendingIrps (
  1981. PAFD_CONNECTION Connection,
  1982. PMDL Mdl,
  1983. ULONG DataOffset,
  1984. ULONG DataLength,
  1985. ULONG Flags,
  1986. PLIST_ENTRY CompleteIrpListHead
  1987. ) {
  1988. PIRP userIrp;
  1989. NTSTATUS status;
  1990. BOOLEAN expedited = ((Flags & TDI_RECEIVE_EXPEDITED)!=0);
  1991. while ((DataLength>0)
  1992. && (userIrp = AfdGetPendedReceiveIrp(
  1993. Connection,
  1994. expedited )) != NULL ) {
  1995. PIO_STACK_LOCATION irpSp;
  1996. ULONG receiveFlags;
  1997. ULONG spaceInIrp;
  1998. ULONG bytesCopied=(ULONG)-1;
  1999. BOOLEAN peek;
  2000. BOOLEAN partialReceivePossible;
  2001. if ( IoSetCancelRoutine( userIrp, NULL ) == NULL ) {
  2002. //
  2003. // This IRP is about to be canceled. Look for another in the
  2004. // list. Set the Flink to NULL so the cancel routine knows
  2005. // it is not on the list.
  2006. //
  2007. userIrp->Tail.Overlay.ListEntry.Flink = NULL;
  2008. continue;
  2009. }
  2010. //
  2011. // Set up some locals.
  2012. //
  2013. irpSp = IoGetCurrentIrpStackLocation( userIrp );
  2014. receiveFlags = (ULONG)irpSp->Parameters.AfdRestartRecvInfo.AfdRecvFlags;
  2015. spaceInIrp = irpSp->Parameters.AfdRestartRecvInfo.AfdOriginalLength-
  2016. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength;
  2017. peek = (BOOLEAN)( (receiveFlags & TDI_RECEIVE_PEEK) != 0 );
  2018. if ( (Flags & AFD_RECEIVE_STREAM) ||
  2019. (receiveFlags & TDI_RECEIVE_PARTIAL) != 0 ) {
  2020. partialReceivePossible = TRUE;
  2021. } else {
  2022. partialReceivePossible = FALSE;
  2023. }
  2024. //
  2025. // If we were not indicated a entire message and the first
  2026. // IRP has more space, do not take the data, instead pass
  2027. // it back to the transport to wait for a push bit and fill
  2028. // as much as possible. Non-chained receive handles this case
  2029. // outside of this routine.
  2030. // Note that endpoint must be of stream type or the IRP
  2031. // should not allow partial receive.
  2032. // Also, peek and expedited receive are not eligible for this
  2033. // performance optimization.
  2034. //
  2035. if (!peek &&
  2036. (Flags & AFD_RECEIVE_CHAINED) &&
  2037. ((Flags & (TDI_RECEIVE_EXPEDITED|TDI_RECEIVE_ENTIRE_MESSAGE))==0) &&
  2038. ((Flags & AFD_RECEIVE_STREAM) || ((receiveFlags & TDI_RECEIVE_PARTIAL)==0)) &&
  2039. (DataLength<spaceInIrp) &&
  2040. IsListEmpty (CompleteIrpListHead) &&
  2041. !AfdIgnorePushBitOnReceives) {
  2042. InsertTailList (CompleteIrpListHead, &userIrp->Tail.Overlay.ListEntry);
  2043. return (ULONG)-1;
  2044. }
  2045. //
  2046. // Copy data to the user's IRP.
  2047. //
  2048. if ( userIrp->MdlAddress != NULL ) {
  2049. status = AfdMapMdlChain (userIrp->MdlAddress);
  2050. if (NT_SUCCESS (status)) {
  2051. if (Flags & AFD_RECEIVE_CHAINED) {
  2052. status = (DataLength<=spaceInIrp)
  2053. ? STATUS_SUCCESS
  2054. : STATUS_BUFFER_OVERFLOW;
  2055. }
  2056. else {
  2057. status = AfdCopyMdlChainToMdlChain(
  2058. userIrp->MdlAddress,
  2059. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength
  2060. - PtrToUlong(irpSp->Parameters.AfdRestartRecvInfo.AfdAdjustedLength),
  2061. Mdl,
  2062. DataOffset,
  2063. DataLength,
  2064. &bytesCopied
  2065. );
  2066. userIrp->IoStatus.Information =
  2067. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength + bytesCopied;
  2068. }
  2069. }
  2070. else {
  2071. ASSERT (irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength==0);
  2072. userIrp->IoStatus.Status = status;
  2073. userIrp->IoStatus.Information = 0;
  2074. //
  2075. // Add the IRP to the list of IRPs we'll need to complete once we
  2076. // can release locks.
  2077. //
  2078. InsertTailList(
  2079. CompleteIrpListHead,
  2080. &userIrp->Tail.Overlay.ListEntry
  2081. );
  2082. continue;
  2083. }
  2084. } else {
  2085. status = STATUS_BUFFER_OVERFLOW;
  2086. userIrp->IoStatus.Information = 0;
  2087. }
  2088. ASSERT( status == STATUS_SUCCESS || status == STATUS_BUFFER_OVERFLOW );
  2089. //
  2090. // For stream type endpoints, it does not make sense to return
  2091. // STATUS_BUFFER_OVERFLOW. That status is only sensible for
  2092. // message-oriented transports. We have already set up the
  2093. // status field of the IRP when we pended it, so we don't
  2094. // need to do it again here.
  2095. //
  2096. if ( Flags & AFD_RECEIVE_STREAM ) {
  2097. ASSERT( userIrp->IoStatus.Status == STATUS_SUCCESS );
  2098. } else {
  2099. userIrp->IoStatus.Status = status;
  2100. }
  2101. //
  2102. // We can complete the IRP under any of the following
  2103. // conditions:
  2104. //
  2105. // - the buffer contains a complete message of data.
  2106. //
  2107. // - it is OK to complete the IRP with a partial message.
  2108. //
  2109. // - the IRP is already full of data.
  2110. //
  2111. if ( (Flags & TDI_RECEIVE_ENTIRE_MESSAGE)
  2112. ||
  2113. partialReceivePossible
  2114. ||
  2115. status == STATUS_BUFFER_OVERFLOW ) {
  2116. //
  2117. // Convert overflow status for message endpoints
  2118. // (either we overflowed the buffer or transport
  2119. // indicated us incomplete message. For the latter
  2120. // we have already decided that we can complete the
  2121. // receive - partialReceivePossible).
  2122. //
  2123. if (!(Flags & AFD_RECEIVE_STREAM) &&
  2124. ((status==STATUS_BUFFER_OVERFLOW) ||
  2125. ((Flags & TDI_RECEIVE_ENTIRE_MESSAGE)==0))) {
  2126. userIrp->IoStatus.Status =
  2127. (receiveFlags & TDI_RECEIVE_EXPEDITED)
  2128. ? STATUS_RECEIVE_PARTIAL_EXPEDITED
  2129. : STATUS_RECEIVE_PARTIAL;
  2130. }
  2131. //
  2132. // Add the IRP to the list of IRPs we'll need to complete once we
  2133. // can release locks.
  2134. //
  2135. InsertTailList(
  2136. CompleteIrpListHead,
  2137. &userIrp->Tail.Overlay.ListEntry
  2138. );
  2139. } else {
  2140. //
  2141. // Set up the cancellation routine back in the IRP. If the IRP
  2142. // has already been cancelled, continue with the next one.
  2143. //
  2144. IoSetCancelRoutine( userIrp, AfdCancelReceive );
  2145. if ( userIrp->Cancel ) {
  2146. if (IoSetCancelRoutine( userIrp, NULL ) != NULL) {
  2147. //
  2148. // Completion routine has not been reset,
  2149. // we have to complete it ourselves, so add it
  2150. // to our completion list.
  2151. //
  2152. if (irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength==0 ||
  2153. Connection->Endpoint->EndpointCleanedUp) {
  2154. userIrp->IoStatus.Status = STATUS_CANCELLED;
  2155. }
  2156. else {
  2157. //
  2158. // We cannot set STATUS_CANCELLED
  2159. // since we loose data already placed in the IRP.
  2160. //
  2161. userIrp->IoStatus.Information = irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength;
  2162. userIrp->IoStatus.Status = STATUS_SUCCESS;
  2163. }
  2164. InsertTailList(
  2165. CompleteIrpListHead,
  2166. &userIrp->Tail.Overlay.ListEntry
  2167. );
  2168. }
  2169. else {
  2170. //
  2171. // The cancel routine is about to be run.
  2172. // Set the Flink to NULL so the cancel routine knows
  2173. // it is not on the list.
  2174. //
  2175. userIrp->Tail.Overlay.ListEntry.Flink = NULL;
  2176. }
  2177. continue;
  2178. }
  2179. else {
  2180. if (Flags & AFD_RECEIVE_CHAINED) {
  2181. status = AfdCopyMdlChainToMdlChain(
  2182. userIrp->MdlAddress,
  2183. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength
  2184. - PtrToUlong(irpSp->Parameters.AfdRestartRecvInfo.AfdAdjustedLength),
  2185. Mdl,
  2186. DataOffset,
  2187. DataLength,
  2188. &bytesCopied
  2189. );
  2190. }
  2191. ASSERT (status==STATUS_SUCCESS);
  2192. ASSERT (bytesCopied<=spaceInIrp);
  2193. //
  2194. // Update the count of data placed into the IRP thus far.
  2195. //
  2196. irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength += bytesCopied;
  2197. //
  2198. // Put the IRP back on the connection's list of pended IRPs.
  2199. //
  2200. InsertHeadList(
  2201. &Connection->VcReceiveIrpListHead,
  2202. &userIrp->Tail.Overlay.ListEntry
  2203. );
  2204. }
  2205. }
  2206. //
  2207. // If the IRP was not a peek IRP, update the AFD buffer
  2208. // accordingly. If it was a peek IRP then the data should be
  2209. // reread, so keep it around.
  2210. //
  2211. if ( !peek ) {
  2212. //
  2213. // If we copied all of the data from the buffer to the IRP,
  2214. // free the AFD buffer structure.
  2215. //
  2216. if ( status == STATUS_SUCCESS ) {
  2217. DataOffset += DataLength;
  2218. DataLength = 0;
  2219. } else {
  2220. //
  2221. // There is more data left in the buffer. Update counts in
  2222. // the AFD buffer structure.
  2223. //
  2224. ASSERT(DataLength > spaceInIrp);
  2225. DataOffset += spaceInIrp;
  2226. DataLength -= spaceInIrp;
  2227. }
  2228. }
  2229. if (Connection->VcReceiveIrpListHead.Flink
  2230. ==&userIrp->Tail.Overlay.ListEntry)
  2231. //
  2232. // We reinserted IRP back on pending list, so
  2233. // stop processing this buffer for now.
  2234. //
  2235. // !!! This could cause a problem if there is a regular
  2236. // receive pended behind a peek IRP! But that is a
  2237. // pretty unlikely scenario.
  2238. //
  2239. break;
  2240. }
  2241. return DataOffset;
  2242. }
  2243. VOID
  2244. AfdCancelReceive (
  2245. IN PDEVICE_OBJECT DeviceObject,
  2246. IN PIRP Irp
  2247. )
  2248. /*++
  2249. Routine Description:
  2250. Cancels a receive IRP that is pended in AFD.
  2251. Arguments:
  2252. DeviceObject - not used.
  2253. Irp - the IRP to cancel.
  2254. Return Value:
  2255. None.
  2256. --*/
  2257. {
  2258. PIO_STACK_LOCATION irpSp;
  2259. PAFD_ENDPOINT endpoint;
  2260. AFD_LOCK_QUEUE_HANDLE lockHandle;
  2261. //
  2262. // Get the endpoint pointer from our IRP stack location and the
  2263. // connection pointer from the endpoint.
  2264. //
  2265. irpSp = IoGetCurrentIrpStackLocation( Irp );
  2266. endpoint = irpSp->FileObject->FsContext;
  2267. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting ||
  2268. endpoint->Type == AfdBlockTypeVcBoth );
  2269. //
  2270. // Remove the IRP from the endpoint's IRP list, synchronizing with
  2271. // the endpoint lock which protects the lists. Note that the
  2272. // IRP *must* be on one of the endpoint's lists or the Flink is NULL
  2273. // if we are getting called here--anybody that removes the IRP from
  2274. // the list must reset the cancel routine to NULL and set the
  2275. // Flink to NULL before releasing the endpoint spin lock.
  2276. //
  2277. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  2278. if ( Irp->Tail.Overlay.ListEntry.Flink != NULL ) {
  2279. RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
  2280. }
  2281. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  2282. //
  2283. // Release the cancel spin lock and complete the IRP with a
  2284. // cancellation status code.
  2285. //
  2286. IoReleaseCancelSpinLock( Irp->CancelIrql );
  2287. if (irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength==0 ||
  2288. endpoint->EndpointCleanedUp) {
  2289. Irp->IoStatus.Information = 0;
  2290. Irp->IoStatus.Status = STATUS_CANCELLED;
  2291. UPDATE_CONN(endpoint->Common.VcConnecting.Connection);
  2292. }
  2293. else {
  2294. //
  2295. // There was some data in the IRP, do not complete with
  2296. // STATUS_CANCELLED, since this will result in data loss
  2297. //
  2298. Irp->IoStatus.Information = irpSp->Parameters.AfdRestartRecvInfo.AfdCurrentLength;
  2299. Irp->IoStatus.Status = STATUS_SUCCESS;
  2300. UPDATE_CONN2 (endpoint->Common.VcConnecting.Connection,
  2301. "Completing cancelled irp with 0x%lX bytes",
  2302. (ULONG)Irp->IoStatus.Information);
  2303. }
  2304. IoCompleteRequest( Irp, AfdPriorityBoost );
  2305. return;
  2306. } // AfdCancelReceive
  2307. PAFD_BUFFER_HEADER
  2308. AfdGetReceiveBuffer (
  2309. IN PAFD_CONNECTION Connection,
  2310. IN ULONG ReceiveFlags,
  2311. IN PAFD_BUFFER_HEADER StartingAfdBuffer OPTIONAL
  2312. )
  2313. /*++
  2314. Routine Description:
  2315. Returns a pointer to a receive data buffer that contains the
  2316. appropriate type of data. Note that this routine DOES NOT remove
  2317. the buffer structure from the list it is on.
  2318. This routine MUST be called with the connection's endpoint lock
  2319. held!
  2320. Arguments:
  2321. Connection - a pointer to the connection to search for data.
  2322. ReceiveFlags - the type of receive data to look for.
  2323. StartingAfdBuffer - if non-NULL, start looking for a buffer AFTER
  2324. this buffer.
  2325. Return Value:
  2326. PAFD_BUFFER - a pointer to an AFD buffer of the appropriate data type,
  2327. or NULL if there was no appropriate buffer on the connection.
  2328. --*/
  2329. {
  2330. PLIST_ENTRY listEntry;
  2331. PAFD_BUFFER_HEADER afdBuffer;
  2332. ASSERT( KeGetCurrentIrql( ) == DISPATCH_LEVEL );
  2333. //
  2334. // Start with the first AFD buffer on the connection.
  2335. //
  2336. listEntry = Connection->VcReceiveBufferListHead.Flink;
  2337. afdBuffer = CONTAINING_RECORD( listEntry, AFD_BUFFER_HEADER, BufferListEntry );
  2338. //
  2339. // If a starting AFD buffer was specified, walk past that buffer in
  2340. // the connection list.
  2341. //
  2342. if ( ARGUMENT_PRESENT( StartingAfdBuffer ) ) {
  2343. while ( TRUE ) {
  2344. if ( afdBuffer == StartingAfdBuffer ) {
  2345. listEntry = listEntry->Flink;
  2346. afdBuffer = CONTAINING_RECORD( listEntry, AFD_BUFFER_HEADER, BufferListEntry );
  2347. //
  2348. // Don't mix expedited and non-expedited data.
  2349. //
  2350. if (afdBuffer->ExpeditedData!=StartingAfdBuffer->ExpeditedData)
  2351. return NULL;
  2352. break;
  2353. }
  2354. listEntry = listEntry->Flink;
  2355. afdBuffer = CONTAINING_RECORD( listEntry, AFD_BUFFER_HEADER, BufferListEntry );
  2356. ASSERT( listEntry != &Connection->VcReceiveBufferListHead );
  2357. }
  2358. }
  2359. //
  2360. // Act based on the type of data we're trying to get.
  2361. //
  2362. switch ( ReceiveFlags & TDI_RECEIVE_EITHER ) {
  2363. case TDI_RECEIVE_NORMAL:
  2364. //
  2365. // Walk the connection's list of data buffers until we find the
  2366. // first data buffer that is of the appropriate type.
  2367. //
  2368. while ( listEntry != &Connection->VcReceiveBufferListHead &&
  2369. afdBuffer->ExpeditedData ) {
  2370. listEntry = afdBuffer->BufferListEntry.Flink;
  2371. afdBuffer = CONTAINING_RECORD( listEntry, AFD_BUFFER_HEADER, BufferListEntry );
  2372. }
  2373. if ( listEntry != &Connection->VcReceiveBufferListHead ) {
  2374. return afdBuffer;
  2375. } else {
  2376. return NULL;
  2377. }
  2378. case TDI_RECEIVE_EITHER :
  2379. //
  2380. // Just return the first buffer, if there is one.
  2381. //
  2382. if ( listEntry != &Connection->VcReceiveBufferListHead ) {
  2383. return afdBuffer;
  2384. } else {
  2385. return NULL;
  2386. }
  2387. case TDI_RECEIVE_EXPEDITED:
  2388. if ( Connection->VcBufferredExpeditedCount == 0 ) {
  2389. return NULL;
  2390. }
  2391. //
  2392. // Walk the connection's list of data buffers until we find the
  2393. // first data buffer that is of the appropriate type.
  2394. //
  2395. while ( listEntry != &Connection->VcReceiveBufferListHead &&
  2396. !afdBuffer->ExpeditedData ) {
  2397. listEntry = afdBuffer->BufferListEntry.Flink;
  2398. afdBuffer = CONTAINING_RECORD( listEntry, AFD_BUFFER_HEADER, BufferListEntry );
  2399. }
  2400. if ( listEntry != &Connection->VcReceiveBufferListHead ) {
  2401. return afdBuffer;
  2402. } else {
  2403. return NULL;
  2404. }
  2405. default:
  2406. ASSERT( !"Invalid ReceiveFlags" );
  2407. __assume (0);
  2408. return NULL;
  2409. }
  2410. } // AfdGetReceiveBuffer
  2411. PIRP
  2412. AfdGetPendedReceiveIrp (
  2413. IN PAFD_CONNECTION Connection,
  2414. IN BOOLEAN Expedited
  2415. )
  2416. /*++
  2417. Routine Description:
  2418. Removes a receive IRP from the connection's list of receive IRPs.
  2419. Only returns an IRP which is valid for the specified type of
  2420. data, normal or expedited. If there are no IRPs pended or only
  2421. IRPs of the wrong type, returns NULL.
  2422. This routine MUST be called with the connection's endpoint lock
  2423. held!
  2424. Arguments:
  2425. Connection - a pointer to the connection to search for an IRP.
  2426. Expedited - TRUE if this routine should return a receive IRP which
  2427. can receive expedited data.
  2428. Return Value:
  2429. PIRP - a pointer to an IRP which can receive data of the specified
  2430. type. The IRP IS removed from the connection's list of pended
  2431. receive IRPs.
  2432. --*/
  2433. {
  2434. PIRP irp;
  2435. PIO_STACK_LOCATION irpSp;
  2436. ULONG receiveFlags;
  2437. PLIST_ENTRY listEntry;
  2438. ASSERT( KeGetCurrentIrql( ) == DISPATCH_LEVEL );
  2439. //
  2440. // Walk the list of pended receive IRPs looking for one which can
  2441. // be completed with the specified type of data.
  2442. //
  2443. for ( listEntry = Connection->VcReceiveIrpListHead.Flink;
  2444. listEntry != &Connection->VcReceiveIrpListHead;
  2445. listEntry = listEntry->Flink ) {
  2446. //
  2447. // Get a pointer to the IRP and our stack location in the IRP.
  2448. //
  2449. irp = CONTAINING_RECORD( listEntry, IRP, Tail.Overlay.ListEntry );
  2450. irpSp = IoGetCurrentIrpStackLocation( irp );
  2451. //
  2452. // Determine whether this IRP can receive the data type we need.
  2453. //
  2454. receiveFlags = irpSp->Parameters.AfdRestartRecvInfo.AfdRecvFlags;
  2455. receiveFlags &= TDI_RECEIVE_EITHER;
  2456. ASSERT( receiveFlags != 0 );
  2457. if ( receiveFlags == TDI_RECEIVE_NORMAL && !Expedited ) {
  2458. //
  2459. // We have a normal receive and normal data. Remove this
  2460. // IRP from the connection's list and return it.
  2461. //
  2462. RemoveEntryList( listEntry );
  2463. return irp;
  2464. }
  2465. if ( receiveFlags == TDI_RECEIVE_EITHER ) {
  2466. //
  2467. // This is an "either" receive. It can take the data
  2468. // regardless of the data type.
  2469. //
  2470. RemoveEntryList( listEntry );
  2471. return irp;
  2472. }
  2473. if ( receiveFlags == TDI_RECEIVE_EXPEDITED && Expedited ) {
  2474. //
  2475. // We have an expedited receive and expedited data. Remove
  2476. // this IRP from the connection's list and return it.
  2477. //
  2478. RemoveEntryList( listEntry );
  2479. return irp;
  2480. }
  2481. //
  2482. // This IRP did not meet our criteria. Continue scanning the
  2483. // connection's list of pended IRPs for a good IRP.
  2484. //
  2485. }
  2486. //
  2487. // There were no IRPs which could be completed with the specified
  2488. // type of data.
  2489. //
  2490. return NULL;
  2491. } // AfdGetPendedReceiveIrp
  2492. BOOLEAN
  2493. AfdLRRepostReceive (
  2494. PAFD_LR_LIST_ITEM Item
  2495. )
  2496. /*++
  2497. Routine Description:
  2498. Attempts to restart receive on a connection where AFD returned
  2499. STATUS_DATA_NO_ACCEPTED to the transport due to low resource condition.
  2500. Arguments:
  2501. Connection - connection of interest
  2502. Return Value:
  2503. TRUE - was able to restart receives (or connection is gone)
  2504. FALSE - still problem with resources
  2505. --*/
  2506. {
  2507. AFD_LOCK_QUEUE_HANDLE lockHandle;
  2508. PAFD_ENDPOINT endpoint;
  2509. PAFD_CONNECTION connection;
  2510. PAFD_BUFFER afdBuffer;
  2511. connection = CONTAINING_RECORD (Item, AFD_CONNECTION, LRListItem);
  2512. ASSERT( connection->Type == AfdBlockTypeConnection );
  2513. endpoint = connection->Endpoint;
  2514. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting ||
  2515. endpoint->Type == AfdBlockTypeVcListening ||
  2516. endpoint->Type == AfdBlockTypeVcBoth );
  2517. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  2518. ASSERT (connection->OnLRList == TRUE);
  2519. //
  2520. // Check if connection was accepted and use accept endpoint instead
  2521. // of the listening. Note that accept cannot happen while we are
  2522. // holding listening endpoint spinlock, nor can endpoint change after
  2523. // the accept, so it is safe to release listening spinlock if
  2524. // we discover that endpoint was accepted.
  2525. //
  2526. if (((endpoint->Type & AfdBlockTypeVcListening) == AfdBlockTypeVcListening)
  2527. && (connection->Endpoint != endpoint)) {
  2528. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  2529. endpoint = connection->Endpoint;
  2530. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting );
  2531. ASSERT( !IS_TDI_BUFFERRING(endpoint) );
  2532. ASSERT( IS_VC_ENDPOINT (endpoint) );
  2533. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  2534. }
  2535. //
  2536. // Check if connection is still alive.
  2537. //
  2538. if (connection->AbortIndicated ||
  2539. connection->DisconnectIndicated ||
  2540. connection->VcReceiveBytesInTransport==0 ||
  2541. (endpoint->DisconnectMode & AFD_PARTIAL_DISCONNECT_RECEIVE) != 0 ||
  2542. endpoint->EndpointCleanedUp ) {
  2543. connection->OnLRList = FALSE;
  2544. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  2545. DEREFERENCE_CONNECTION (connection);
  2546. return TRUE;
  2547. }
  2548. //
  2549. // Attempt to allocate receive buffer for the amount that the
  2550. // transport indicated to us last.
  2551. //
  2552. afdBuffer = AfdGetBuffer (connection->VcReceiveBytesInTransport, 0, connection->OwningProcess);
  2553. if (afdBuffer==NULL) {
  2554. //
  2555. // The caller will automatically put this connection back on LR list
  2556. //
  2557. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  2558. UPDATE_CONN (connection);
  2559. return FALSE;
  2560. }
  2561. //
  2562. // Finish building the receive IRP to give to the TDI
  2563. // provider.
  2564. //
  2565. TdiBuildReceive(
  2566. afdBuffer->Irp,
  2567. connection->DeviceObject,
  2568. connection->FileObject,
  2569. AfdRestartBufferReceive,
  2570. afdBuffer,
  2571. afdBuffer->Mdl,
  2572. TDI_RECEIVE_NORMAL,
  2573. connection->VcReceiveBytesInTransport
  2574. );
  2575. //
  2576. // Acquire connection reference to be released in completion routine
  2577. // We already have one by virtue of being here
  2578. // REFERENCE_CONNECTION (connection);
  2579. UPDATE_CONN2 (connection, "Reposting LR receive for 0x%lX bytes",
  2580. connection->VcReceiveBytesInTransport);
  2581. connection->VcReceiveBytesInTransport = 0;
  2582. ASSERT (InterlockedDecrement (&connection->VcReceiveIrpsInTransport)==-1);
  2583. //
  2584. // We need to remember the connection in the AFD buffer
  2585. // because we'll need to access it in the completion
  2586. // routine.
  2587. //
  2588. afdBuffer->Context = connection;
  2589. connection->OnLRList = FALSE;
  2590. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  2591. IoCallDriver (connection->DeviceObject, afdBuffer->Irp);
  2592. return TRUE;
  2593. }