Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2372 lines
75 KiB

  1. /*++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. send.c
  5. Abstract:
  6. This module contains the code for passing on send IRPs to
  7. TDI providers.
  8. Author:
  9. David Treadwell (davidtr) 13-Mar-1992
  10. Revision History:
  11. --*/
  12. #include "afdp.h"
  13. VOID
  14. AfdCancelSend (
  15. IN PDEVICE_OBJECT DeviceObject,
  16. IN PIRP Irp
  17. );
  18. NTSTATUS
  19. AfdRestartSend (
  20. IN PDEVICE_OBJECT DeviceObject,
  21. IN PIRP Irp,
  22. IN PVOID Context
  23. );
  24. NTSTATUS
  25. AfdRestartSendConnDatagram (
  26. IN PDEVICE_OBJECT DeviceObject,
  27. IN PIRP Irp,
  28. IN PVOID Context
  29. );
  30. NTSTATUS
  31. AfdRestartSendTdiConnDatagram (
  32. IN PDEVICE_OBJECT DeviceObject,
  33. IN PIRP Irp,
  34. IN PVOID Context
  35. );
  36. NTSTATUS
  37. AfdRestartSendDatagram (
  38. IN PDEVICE_OBJECT DeviceObject,
  39. IN PIRP Irp,
  40. IN PVOID Context
  41. );
  42. typedef struct _AFD_SEND_CONN_DATAGRAM_CONTEXT {
  43. PAFD_ENDPOINT Endpoint;
  44. TDI_CONNECTION_INFORMATION ConnectionInformation;
  45. } AFD_SEND_CONN_DATAGRAM_CONTEXT, *PAFD_SEND_CONN_DATAGRAM_CONTEXT;
  46. #ifdef ALLOC_PRAGMA
  47. #pragma alloc_text( PAGEAFD, AfdSend )
  48. #pragma alloc_text( PAGEAFD, AfdSendDatagram )
  49. #pragma alloc_text( PAGEAFD, AfdCancelSend )
  50. #pragma alloc_text( PAGEAFD, AfdRestartSend )
  51. #pragma alloc_text( PAGEAFD, AfdRestartBufferSend )
  52. #pragma alloc_text( PAGEAFD, AfdProcessBufferSend )
  53. #pragma alloc_text( PAGEAFD, AfdRestartSendConnDatagram )
  54. #pragma alloc_text( PAGEAFD, AfdRestartSendTdiConnDatagram )
  55. #pragma alloc_text( PAGEAFD, AfdRestartSendDatagram )
  56. #pragma alloc_text( PAGEAFD, AfdSendPossibleEventHandler )
  57. #endif
  58. //
  59. // Macros to make the send restart code more maintainable.
  60. //
  61. #define AfdRestartSendInfo DeviceIoControl
  62. #define AfdMdlChain Type3InputBuffer
  63. #define AfdSendFlags InputBufferLength
  64. #define AfdOriginalLength OutputBufferLength
  65. #define AfdCurrentLength IoControlCode
  66. #define AFD_SEND_MDL_HAS_NOT_BEEN_MAPPED 0x80000000
  67. NTSTATUS
  68. FASTCALL
  69. AfdSend (
  70. IN PIRP Irp,
  71. IN PIO_STACK_LOCATION IrpSp
  72. )
  73. {
  74. NTSTATUS status;
  75. PAFD_ENDPOINT endpoint;
  76. ULONG sendLength;
  77. ULONG sendOffset;
  78. ULONG currentOffset;
  79. PMDL mdl;
  80. PAFD_CONNECTION connection;
  81. PAFD_BUFFER afdBuffer;
  82. PEPROCESS process;
  83. ULONG sendFlags;
  84. ULONG afdFlags;
  85. ULONG bufferCount;
  86. AFD_LOCK_QUEUE_HANDLE lockHandle;
  87. //
  88. // Make sure that the endpoint is in the correct state.
  89. //
  90. endpoint = IrpSp->FileObject->FsContext;
  91. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  92. if ( endpoint->State != AfdEndpointStateConnected) {
  93. status = STATUS_INVALID_CONNECTION;
  94. goto complete;
  95. }
  96. //
  97. // If send has been shut down on this endpoint, fail. We need to be
  98. // careful about what error code we return here: if the connection
  99. // has been aborted, be sure to return the apprpriate error code.
  100. //
  101. if ( (endpoint->DisconnectMode & AFD_PARTIAL_DISCONNECT_SEND) != 0 ) {
  102. if ( (endpoint->DisconnectMode & AFD_ABORTIVE_DISCONNECT) != 0 ) {
  103. status = STATUS_LOCAL_DISCONNECT;
  104. } else {
  105. status = STATUS_PIPE_DISCONNECTED;
  106. }
  107. goto complete;
  108. }
  109. //
  110. // Set up the IRP on the assumption that it will complete successfully.
  111. //
  112. Irp->IoStatus.Status = STATUS_SUCCESS;
  113. //
  114. // If this is an IOCTL_AFD_SEND, then grab the parameters from the
  115. // supplied AFD_SEND_INFO structure, build an MDL chain describing
  116. // the WSABUF array, and attach the MDL chain to the IRP.
  117. //
  118. // If this is an IRP_MJ_WRITE IRP, just grab the length from the IRP
  119. // and set the flags to zero.
  120. //
  121. if ( IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL ) {
  122. #ifdef _WIN64
  123. if (IoIs32bitProcess (Irp)) {
  124. PAFD_SEND_INFO32 sendInfo32;
  125. LPWSABUF32 bufferArray32;
  126. if( IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  127. sizeof(*sendInfo32) ) {
  128. AFD_W4_INIT status = STATUS_SUCCESS;
  129. try {
  130. //
  131. // Validate the input structure if it comes from the user mode
  132. // application
  133. //
  134. sendInfo32 = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  135. if( Irp->RequestorMode != KernelMode ) {
  136. ProbeForReadSmallStructure(
  137. sendInfo32,
  138. sizeof(*sendInfo32),
  139. PROBE_ALIGNMENT32(AFD_SEND_INFO32)
  140. );
  141. }
  142. //
  143. // Make local copies of the embeded pointer and parameters
  144. // that we will be using more than once in case malicios
  145. // application attempts to change them while we are
  146. // validating
  147. //
  148. sendFlags = sendInfo32->TdiFlags;
  149. afdFlags = sendInfo32->AfdFlags;
  150. bufferArray32 = UlongToPtr(sendInfo32->BufferArray);
  151. bufferCount = sendInfo32->BufferCount;
  152. //
  153. // Create the MDL chain describing the WSABUF array.
  154. // This will also validate the buffer array and individual
  155. // buffers
  156. //
  157. status = AfdAllocateMdlChain32(
  158. Irp, // Requestor mode passed along
  159. bufferArray32,
  160. bufferCount,
  161. IoReadAccess,
  162. &sendLength
  163. );
  164. if (!NT_SUCCESS(status))
  165. goto complete;
  166. } except( AFD_EXCEPTION_FILTER (status) ) {
  167. ASSERT (NT_ERROR (status));
  168. //
  169. // Exception accessing input structure.
  170. //
  171. goto complete;
  172. }
  173. } else {
  174. //
  175. // Invalid input buffer length.
  176. //
  177. status = STATUS_INVALID_PARAMETER;
  178. goto complete;
  179. }
  180. }
  181. else
  182. #endif _WIN64
  183. {
  184. PAFD_SEND_INFO sendInfo;
  185. LPWSABUF bufferArray;
  186. //
  187. // Sanity check.
  188. //
  189. ASSERT( IrpSp->Parameters.DeviceIoControl.IoControlCode==IOCTL_AFD_SEND );
  190. if( IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  191. sizeof(*sendInfo) ) {
  192. AFD_W4_INIT status = STATUS_SUCCESS;
  193. try {
  194. //
  195. // Validate the input structure if it comes from the user mode
  196. // application
  197. //
  198. sendInfo = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  199. if( Irp->RequestorMode != KernelMode ) {
  200. ProbeForReadSmallStructure(
  201. sendInfo,
  202. sizeof(*sendInfo),
  203. PROBE_ALIGNMENT (AFD_SEND_INFO)
  204. );
  205. }
  206. //
  207. // Make local copies of the embeded pointer and parameters
  208. // that we will be using more than once in case malicios
  209. // application attempts to change them while we are
  210. // validating
  211. //
  212. sendFlags = sendInfo->TdiFlags;
  213. afdFlags = sendInfo->AfdFlags;
  214. bufferArray = sendInfo->BufferArray;
  215. bufferCount = sendInfo->BufferCount;
  216. //
  217. // Create the MDL chain describing the WSABUF array.
  218. // This will also validate the buffer array and individual
  219. // buffers
  220. //
  221. status = AfdAllocateMdlChain(
  222. Irp, // Requestor mode passed along
  223. bufferArray,
  224. bufferCount,
  225. IoReadAccess,
  226. &sendLength
  227. );
  228. if( !NT_SUCCESS(status) ) {
  229. goto complete;
  230. }
  231. } except( AFD_EXCEPTION_FILTER (status) ) {
  232. ASSERT (NT_ERROR (status));
  233. //
  234. // Exception accessing input structure.
  235. //
  236. goto complete;
  237. }
  238. } else {
  239. //
  240. // Invalid input buffer length.
  241. //
  242. status = STATUS_INVALID_PARAMETER;
  243. goto complete;
  244. }
  245. }
  246. if (IS_SAN_ENDPOINT(endpoint)) {
  247. IrpSp->MajorFunction = IRP_MJ_WRITE;
  248. IrpSp->Parameters.Write.Length = sendLength;
  249. return AfdSanRedirectRequest (Irp, IrpSp);
  250. }
  251. } else {
  252. ASSERT( IrpSp->MajorFunction == IRP_MJ_WRITE );
  253. sendFlags = 0;
  254. afdFlags = AFD_OVERLAPPED;
  255. sendLength = IrpSp->Parameters.Write.Length;
  256. }
  257. //
  258. // AfdSend() will either complete fully or will fail.
  259. //
  260. Irp->IoStatus.Information = sendLength;
  261. //
  262. // Setup for possible restart if the transport completes
  263. // the send partially.
  264. //
  265. IrpSp->Parameters.AfdRestartSendInfo.AfdMdlChain = Irp->MdlAddress;
  266. IrpSp->Parameters.AfdRestartSendInfo.AfdSendFlags = sendFlags;
  267. IrpSp->Parameters.AfdRestartSendInfo.AfdOriginalLength = sendLength;
  268. IrpSp->Parameters.AfdRestartSendInfo.AfdCurrentLength = sendLength;
  269. //
  270. // Buffer sends if the TDI provider does not buffer.
  271. //
  272. if ( IS_TDI_BUFFERRING(endpoint) &&
  273. endpoint->NonBlocking) {
  274. //
  275. // If this is a nonblocking endpoint, set the TDI nonblocking
  276. // send flag so that the request will fail if the send cannot be
  277. // performed immediately.
  278. //
  279. sendFlags |= TDI_SEND_NON_BLOCKING;
  280. }
  281. //
  282. // If this is a datagram endpoint, format up a send datagram request
  283. // and pass it on to the TDI provider.
  284. //
  285. if ( IS_DGRAM_ENDPOINT(endpoint) ) {
  286. //
  287. // It is illegal to send expedited data on a datagram socket.
  288. //
  289. if ( (sendFlags & TDI_SEND_EXPEDITED) != 0 ) {
  290. status = STATUS_NOT_SUPPORTED;
  291. goto complete;
  292. }
  293. if (!IS_TDI_DGRAM_CONNECTION(endpoint)) {
  294. PAFD_SEND_CONN_DATAGRAM_CONTEXT context;
  295. ULONG remoteAddressLength;
  296. //
  297. // Allocate space to hold the connection information structure
  298. // we'll use on input.
  299. //
  300. retry:
  301. remoteAddressLength = endpoint->Common.Datagram.RemoteAddressLength;
  302. try {
  303. context = AFD_ALLOCATE_POOL_WITH_QUOTA(
  304. NonPagedPool,
  305. sizeof(*context) + remoteAddressLength,
  306. AFD_TDI_POOL_TAG
  307. );
  308. }
  309. except (EXCEPTION_EXECUTE_HANDLER) {
  310. status = GetExceptionCode ();
  311. context = NULL;
  312. goto complete;
  313. }
  314. context->Endpoint = endpoint;
  315. context->ConnectionInformation.UserDataLength = 0;
  316. context->ConnectionInformation.UserData = NULL;
  317. context->ConnectionInformation.OptionsLength = 0;
  318. context->ConnectionInformation.Options = NULL;
  319. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  320. if (remoteAddressLength <
  321. endpoint->Common.Datagram.RemoteAddressLength) {
  322. //
  323. // Apparently connection address length has changed
  324. // on us while we were allocating the buffer.
  325. // This is extremely unlikely (even if endpoint got
  326. // connected to a different address, the length is unlikely
  327. // to change), but we must handle this, just try again.
  328. //
  329. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  330. AFD_FREE_POOL(
  331. context,
  332. AFD_TDI_POOL_TAG
  333. );
  334. goto retry;
  335. }
  336. //
  337. // Copy the address to the context buffer.
  338. // endpoint->Common.Datagram.RemoteAddress can be freed
  339. // by someone else if endpoint lock is not held
  340. //
  341. RtlCopyMemory(
  342. context+1,
  343. endpoint->Common.Datagram.RemoteAddress,
  344. endpoint->Common.Datagram.RemoteAddressLength
  345. );
  346. context->ConnectionInformation.RemoteAddressLength =
  347. endpoint->Common.Datagram.RemoteAddressLength;
  348. context->ConnectionInformation.RemoteAddress =
  349. (PTRANSPORT_ADDRESS)(context+1);
  350. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  351. REFERENCE_ENDPOINT2 (endpoint,"AfdSend, length: 0x%lX", sendLength);
  352. //
  353. // Build a send datagram request.
  354. //
  355. TdiBuildSendDatagram(
  356. Irp,
  357. endpoint->AddressDeviceObject,
  358. endpoint->AddressFileObject,
  359. AfdRestartSendConnDatagram,
  360. context,
  361. Irp->MdlAddress,
  362. sendLength,
  363. &context->ConnectionInformation
  364. );
  365. }
  366. else {
  367. REFERENCE_ENDPOINT2 (endpoint,"AfdSend(conn), length: 0x%lX", sendLength);
  368. TdiBuildSend(
  369. Irp,
  370. endpoint->AddressDeviceObject,
  371. endpoint->AddressFileObject,
  372. AfdRestartSendTdiConnDatagram,
  373. endpoint,
  374. Irp->MdlAddress,
  375. 0,
  376. sendLength
  377. );
  378. //
  379. // Check if there are outstanding TPackets IRP and
  380. // delay sending to ensure in-order delivery.
  381. // We do not need to hold the lock while checking
  382. // because we do not need to maintain order if
  383. // application does not wait for send call to return
  384. // before sumbitting TPackets IRP.
  385. // Of course, we will hold the lock while enqueuing IRP
  386. //
  387. if (endpoint->Irp!=NULL) {
  388. if (AfdEnqueueTpSendIrp (endpoint, Irp, FALSE)) {
  389. return STATUS_PENDING;
  390. }
  391. }
  392. }
  393. //
  394. // Call the transport to actually perform the send operation.
  395. //
  396. return AfdIoCallDriver(
  397. endpoint,
  398. endpoint->AddressDeviceObject,
  399. Irp
  400. );
  401. }
  402. afdBuffer = NULL;
  403. process = endpoint->OwningProcess;
  404. sendOffset = 0;
  405. retry_buffer:
  406. if (!IS_TDI_BUFFERRING(endpoint) &&
  407. (!endpoint->DisableFastIoSend ||
  408. (endpoint->NonBlocking && !( afdFlags & AFD_OVERLAPPED )) ) ) {
  409. ULONG copyThreshold = AfdBlockingSendCopyThreshold;
  410. //
  411. // If application does a blocking send for more than 128k, we
  412. // copy only the last 64k and send the first part from
  413. // the application buffer to avoid huge overhead of allocating
  414. // non-paged pool and copying.
  415. //
  416. if (sendLength>=2*copyThreshold &&
  417. !IS_MESSAGE_ENDPOINT (endpoint) &&
  418. (!endpoint->NonBlocking || (afdFlags & AFD_OVERLAPPED ) ) ) {
  419. sendOffset += sendLength-copyThreshold;
  420. sendLength = copyThreshold;
  421. }
  422. //
  423. // Get AFD buffer structure that contains an IRP and a
  424. // buffer to hold the data.
  425. //
  426. retry_allocate:
  427. AFD_W4_INIT status = STATUS_SUCCESS;
  428. try {
  429. afdBuffer = AfdGetBufferRaiseOnFailure (
  430. endpoint,
  431. sendLength,
  432. 0,
  433. process );
  434. }
  435. except (AFD_EXCEPTION_FILTER (status)) {
  436. ASSERT (NT_ERROR (status));
  437. //
  438. // If we failed to get the buffer, and application request
  439. // is larger than one page, and it is blocking or overlapped,
  440. // and this is not a message-oriented socket,
  441. // allocate space for last page only (if we can) and send
  442. // the first portion from the app buffer.
  443. //
  444. if ( (sendLength>AfdBufferLengthForOnePage) &&
  445. !IS_MESSAGE_ENDPOINT (endpoint) &&
  446. (!endpoint->NonBlocking || (afdFlags & AFD_OVERLAPPED ) ) ) {
  447. sendOffset += sendLength-AfdBufferLengthForOnePage;
  448. sendLength = AfdBufferLengthForOnePage;
  449. goto retry_allocate;
  450. } // not qualified for partial allocation
  451. else {
  452. goto cleanup_buffer;
  453. }
  454. } // exception allocating big buffer.
  455. currentOffset = sendOffset;
  456. mdl = Irp->MdlAddress;
  457. if (sendOffset!=0) {
  458. //
  459. // Adjust MDL length to be in sync with IRP
  460. // send length parameter to not to confuse
  461. // the transport
  462. //
  463. while (currentOffset>MmGetMdlByteCount (mdl)) {
  464. currentOffset -= MmGetMdlByteCount (mdl);
  465. mdl = mdl->Next;
  466. }
  467. }
  468. if (sendLength != 0) {
  469. status = AfdCopyMdlChainToBufferAvoidMapping(
  470. mdl,
  471. currentOffset,
  472. sendLength,
  473. afdBuffer->Buffer,
  474. afdBuffer->BufferLength
  475. );
  476. if (!NT_SUCCESS (status)) {
  477. goto cleanup_buffer;
  478. }
  479. }
  480. else {
  481. ASSERT (IrpSp->Parameters.AfdRestartSendInfo.AfdOriginalLength == 0);
  482. }
  483. }
  484. else {
  485. AFD_W4_INIT currentOffset = 0;
  486. AFD_W4_INIT mdl = NULL;
  487. }
  488. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  489. connection = AFD_CONNECTION_FROM_ENDPOINT(endpoint);
  490. if (connection==NULL) {
  491. //
  492. // connection might have been cleaned up by transmit file.
  493. //
  494. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  495. status = STATUS_INVALID_CONNECTION;
  496. goto cleanup_buffer;
  497. }
  498. ASSERT( connection->Type == AfdBlockTypeConnection );
  499. //
  500. // Check whether the remote end has aborted the connection, in which
  501. // case we should complete the receive.
  502. //
  503. if ( connection->Aborted ) {
  504. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  505. status = STATUS_CONNECTION_RESET;
  506. goto cleanup_buffer;
  507. }
  508. //
  509. // Buffer sends if the TDI provider does not buffer
  510. // and application did not specifically requested us not
  511. // to do so
  512. //
  513. if ( !IS_TDI_BUFFERRING(endpoint)) {
  514. if ( afdBuffer!=NULL ) {
  515. BOOLEAN completeSend = FALSE;
  516. PFILE_OBJECT fileObject = NULL;
  517. if (connection->OwningProcess!=process) {
  518. //
  519. // Weird case when connection and endpoint belong to
  520. // different processes.
  521. //
  522. process = connection->OwningProcess;
  523. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  524. AfdReturnBuffer (&afdBuffer->Header, process);
  525. afdBuffer = NULL;
  526. goto retry_buffer;
  527. }
  528. ASSERT( !connection->TdiBufferring );
  529. //
  530. // First make sure that we don't have too many bytes of send
  531. // data already outstanding and that someone else isn't already
  532. // in the process of completing pended send IRPs. We can't
  533. // issue the send here if someone else is completing pended
  534. // sends because we have to preserve ordering of the sends.
  535. //
  536. // Note that we'll give the send data to the TDI provider even
  537. // if we have exceeded our send buffer limits, but that we don't
  538. // complete the user's IRP until some send buffer space has
  539. // freed up. This effects flow control by blocking the user's
  540. // thread while ensuring that the TDI provider always has lots
  541. // of data available to be sent.
  542. //
  543. if ( connection->VcBufferredSendBytes >= connection->MaxBufferredSendBytes &&
  544. endpoint->NonBlocking &&
  545. !( afdFlags & AFD_OVERLAPPED ) &&
  546. connection->VcBufferredSendBytes>0) {
  547. //
  548. // There is already as much send data bufferred on the
  549. // connection as is allowed. If this is a nonblocking
  550. // endpoint and this is not an overlapped operation and at least
  551. // on byte is buferred, fail the request.
  552. // Note, that we have already allocated the buffer and copied data
  553. // and now we are dropping it. We should only be here in some
  554. // really weird case when fast IO has been bypassed.
  555. //
  556. //
  557. // Enable the send event.
  558. //
  559. endpoint->EventsActive &= ~AFD_POLL_SEND;
  560. endpoint->EnableSendEvent = TRUE;
  561. IF_DEBUG(EVENT_SELECT) {
  562. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  563. "AfdSend: Endp %p, Active %lx\n",
  564. endpoint,
  565. endpoint->EventsActive
  566. ));
  567. }
  568. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  569. status = STATUS_DEVICE_NOT_READY;
  570. goto cleanup_buffer;
  571. }
  572. if (sendOffset==0) {
  573. if ( connection->VcBufferredSendBytes >= connection->MaxBufferredSendBytes ) {
  574. //
  575. // Special hack to prevent completion of this IRP
  576. // while we have not finished sending all the data
  577. // that came with it. If we do not do this, the
  578. // app can receive completion port notificaiton in
  579. // another thread and come back with another send
  580. // which can get in the middle of this one.
  581. //
  582. Irp->Tail.Overlay.DriverContext[0] = NULL;
  583. //
  584. // Set up the cancellation routine in the IRP. If the IRP
  585. // has already been cancelled, just complete the IRP
  586. //
  587. IoSetCancelRoutine( Irp, AfdCancelSend );
  588. if ( Irp->Cancel ) {
  589. Irp->Tail.Overlay.ListEntry.Flink = NULL;
  590. if ( IoSetCancelRoutine( Irp, NULL ) == NULL ) {
  591. IoMarkIrpPending (Irp);
  592. Irp->Tail.Overlay.DriverContext[0] = (PVOID)-1;
  593. //
  594. // The cancel routine is running and will complete the IRP
  595. //
  596. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  597. AfdReturnBuffer (&afdBuffer->Header, process);
  598. return STATUS_PENDING;
  599. }
  600. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  601. status = STATUS_CANCELLED;
  602. goto cleanup_buffer;
  603. }
  604. //
  605. // We're going to have to pend the request here in AFD.
  606. // Place the IRP on the connection's list of pended send
  607. // IRPs and mark the IRP as pended.
  608. //
  609. InsertTailList(
  610. &connection->VcSendIrpListHead,
  611. &Irp->Tail.Overlay.ListEntry
  612. );
  613. IoMarkIrpPending( Irp );
  614. }
  615. else {
  616. //
  617. // We are going to complete the IRP inline
  618. //
  619. completeSend = TRUE;
  620. }
  621. }
  622. else {
  623. connection->VcBufferredSendBytes += sendOffset;
  624. connection->VcBufferredSendCount += 1;
  625. //
  626. // Special hack to prevent completion of this IRP
  627. // while we have not finished sending all the data
  628. // that came with it. If we do not do this, the
  629. // app can receive completion port notificaiton in
  630. // another thread and come back with another send
  631. // which can get in the middle of this one.
  632. //
  633. fileObject = IrpSp->FileObject;
  634. IrpSp->FileObject = NULL;
  635. REFERENCE_CONNECTION2( connection, "AfdSend (split,non-buffered part), offset: 0x%lX", sendOffset );
  636. }
  637. //
  638. // Update count of send bytes pending on the connection.
  639. //
  640. connection->VcBufferredSendBytes += sendLength;
  641. connection->VcBufferredSendCount += 1;
  642. //
  643. // Reference the conneciton so it does not go away
  644. // until we finish with send
  645. //
  646. REFERENCE_CONNECTION2( connection, "AfdSend (buffered), length: 0x%lX", sendLength );
  647. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  648. //
  649. // Remember the connection in the AFD buffer structure. We need
  650. // this in order to access the connection in the restart routine.
  651. //
  652. afdBuffer->Context = connection;
  653. //
  654. // We have to rebuild the MDL in the AFD buffer structure to
  655. // represent exactly the number of bytes we're going to be
  656. // sending.
  657. //
  658. afdBuffer->Mdl->ByteCount = sendLength;
  659. if (sendOffset==0) {
  660. // Use the IRP in the AFD buffer structure to give to the TDI
  661. // provider. Build the TDI send request.
  662. //
  663. TdiBuildSend(
  664. afdBuffer->Irp,
  665. connection->DeviceObject,
  666. connection->FileObject,
  667. AfdRestartBufferSend,
  668. afdBuffer,
  669. afdBuffer->Mdl,
  670. sendFlags,
  671. sendLength
  672. );
  673. //
  674. // Check if there are outstanding TPackets IRP and
  675. // delay sending to ensure in-order delivery.
  676. // We do not need to hold the lock while checking
  677. // because we do not need to maintain order if
  678. // application does not wait for send call to return
  679. // before sumbitting TPackets IRP.
  680. // Of course, we will hold the lock while enqueuing IRP
  681. //
  682. if (endpoint->Irp==NULL ||
  683. !AfdEnqueueTpSendIrp (endpoint, afdBuffer->Irp, TRUE)) {
  684. //
  685. // Call the transport to actually perform the send.
  686. //
  687. status = IoCallDriver(connection->DeviceObject, afdBuffer->Irp );
  688. }
  689. else {
  690. status = STATUS_PENDING;
  691. }
  692. //
  693. // If we did not pend the Irp, complete it
  694. //
  695. if (completeSend) {
  696. if (NT_SUCCESS (status)) {
  697. ASSERT (Irp->IoStatus.Status == STATUS_SUCCESS);
  698. ASSERT (Irp->IoStatus.Information == sendLength);
  699. ASSERT ((status==STATUS_SUCCESS) || (status==STATUS_PENDING));
  700. status = STATUS_SUCCESS; // We did not mark irp as
  701. // pending, so returning
  702. // STATUS_PENDING (most likely
  703. // to be status returned by the
  704. // transport) will really confuse
  705. // io subsystem.
  706. }
  707. else {
  708. Irp->IoStatus.Status = status;
  709. Irp->IoStatus.Information = 0;
  710. }
  711. UPDATE_CONN2 (connection, "AfdSend, bytes sent/status reported 0x%lX",
  712. (NT_SUCCESS(Irp->IoStatus.Status)
  713. ? (ULONG)Irp->IoStatus.Information
  714. : (ULONG)Irp->IoStatus.Status));
  715. IoCompleteRequest (Irp, AfdPriorityBoost);
  716. }
  717. else {
  718. //
  719. // We no longer need MDL in the IRP, free it.
  720. // Do this before we release the ownership
  721. // in InterlockedOperation below.
  722. //
  723. AfdDestroyMdlChain (Irp);
  724. //
  725. // Complete the IRP if it was completed by the transport
  726. // and kept around to let us finish posting all the data
  727. // originally submitted by the app before completing it
  728. //
  729. ASSERT (Irp->Tail.Overlay.DriverContext[0]==NULL
  730. || Irp->Tail.Overlay.DriverContext[0]==(PVOID)-1);
  731. if (InterlockedExchangePointer (
  732. &Irp->Tail.Overlay.DriverContext[0],
  733. (PVOID)Irp)!=NULL) {
  734. UPDATE_CONN2 (connection, "AfdSend, bytes sent reported 0x%lX",
  735. (ULONG)Irp->IoStatus.Information);
  736. IoCompleteRequest (Irp, AfdPriorityBoost);
  737. }
  738. status = STATUS_PENDING;
  739. }
  740. }
  741. else {
  742. //
  743. // Save the original values to restore in
  744. // completion routine.
  745. //
  746. IrpSp->Parameters.AfdRestartSendInfo.AfdMdlChain = mdl->Next;
  747. IrpSp->Parameters.AfdRestartSendInfo.AfdCurrentLength =
  748. MmGetMdlByteCount (mdl);
  749. //
  750. // Note if we need to unmap MDL before completing
  751. // the IRP if it is mapped by the transport.
  752. //
  753. if ((mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)==0) {
  754. IrpSp->Parameters.AfdRestartSendInfo.AfdSendFlags |=
  755. AFD_SEND_MDL_HAS_NOT_BEEN_MAPPED;
  756. }
  757. //
  758. // Reset the last MDL to not confuse the transport
  759. // with different length values in MDL and send parameters
  760. //
  761. mdl->ByteCount = currentOffset;
  762. mdl->Next = NULL;
  763. //
  764. // Build and pass first portion of the data with original (app)
  765. // IRP
  766. //
  767. TdiBuildSend(
  768. Irp,
  769. connection->DeviceObject,
  770. connection->FileObject,
  771. AfdRestartSend,
  772. connection,
  773. Irp->MdlAddress,
  774. sendFlags,
  775. sendOffset
  776. );
  777. //
  778. // Check if there are outstanding TPackets IRP and
  779. // delay sending to ensure in-order delivery.
  780. // We do not need to hold the lock while checking
  781. // because we do not need to maintain order if
  782. // application does not wait for send call to return
  783. // before sumbitting TPackets IRP.
  784. // Of course, we will hold the lock while enqueuing IRP
  785. //
  786. if (endpoint->Irp==NULL ||
  787. !AfdEnqueueTpSendIrp (endpoint, Irp, FALSE)) {
  788. status = AfdIoCallDriver (endpoint,
  789. connection->DeviceObject,
  790. Irp);
  791. }
  792. else {
  793. status = STATUS_PENDING;
  794. }
  795. //
  796. // Build and pass buffered last page
  797. //
  798. TdiBuildSend(
  799. afdBuffer->Irp,
  800. connection->DeviceObject,
  801. connection->FileObject,
  802. AfdRestartBufferSend,
  803. afdBuffer,
  804. afdBuffer->Mdl,
  805. sendFlags,
  806. sendLength
  807. );
  808. //
  809. // Similar check for the second part of the IRP.
  810. // There might be a slight problem here since we
  811. // can end-up interleaving sends with another thread
  812. //
  813. if (endpoint->Irp==NULL ||
  814. !AfdEnqueueTpSendIrp (endpoint, afdBuffer->Irp, TRUE)) {
  815. IoCallDriver(connection->DeviceObject, afdBuffer->Irp );
  816. }
  817. //
  818. // Complete the IRP if it was completed by the transport
  819. // and kept around to let us finish posting all the data
  820. // originally submitted by the app before completing it
  821. //
  822. ASSERT (fileObject!=NULL);
  823. ASSERT (IrpSp->FileObject==NULL || IrpSp->FileObject==(PFILE_OBJECT)-1);
  824. if (InterlockedExchangePointer (
  825. (PVOID *)&IrpSp->FileObject,
  826. fileObject)!=NULL) {
  827. UPDATE_CONN2 (connection, "AfdSend(split), bytes sent reported 0x%lX",
  828. (ULONG)Irp->IoStatus.Information);
  829. IoCompleteRequest (Irp, AfdPriorityBoost);
  830. }
  831. }
  832. return status;
  833. }
  834. else {
  835. //
  836. // Count sends pended in the provider too, so
  837. // we do not buffer in excess and complete
  838. // buffered application sends before the transport
  839. // completes sends forwarded to it.
  840. //
  841. connection->VcBufferredSendBytes += sendLength;
  842. connection->VcBufferredSendCount += 1;
  843. }
  844. }
  845. else {
  846. ASSERT (afdBuffer==NULL);
  847. }
  848. //
  849. // Add a reference to the connection object since the send
  850. // request will complete asynchronously.
  851. //
  852. REFERENCE_CONNECTION2( connection, "AfdSend (non-buffered), length: 0x%lX", sendLength );
  853. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  854. TdiBuildSend(
  855. Irp,
  856. connection->DeviceObject,
  857. connection->FileObject,
  858. AfdRestartSend,
  859. connection,
  860. Irp->MdlAddress,
  861. sendFlags,
  862. sendLength
  863. );
  864. //
  865. // Check if there are outstanding TPackets IRP and
  866. // delay sending to ensure in-order delivery.
  867. // We do not need to hold the lock while checking
  868. // because we do not need to maintain order if
  869. // application does not wait for send call to return
  870. // before sumbitting TPackets IRP.
  871. // Of course, we will hold the lock while enqueuing IRP
  872. //
  873. if (endpoint->Irp==NULL ||
  874. !AfdEnqueueTpSendIrp (endpoint, Irp, FALSE)) {
  875. //
  876. // Call the transport to actually perform the send.
  877. //
  878. status = AfdIoCallDriver( endpoint, connection->DeviceObject, Irp );
  879. }
  880. else {
  881. status = STATUS_PENDING;
  882. }
  883. return status;
  884. cleanup_buffer:
  885. if (afdBuffer!=NULL) {
  886. AfdReturnBuffer (&afdBuffer->Header, process);
  887. }
  888. complete:
  889. Irp->IoStatus.Information = 0;
  890. Irp->IoStatus.Status = status;
  891. IoCompleteRequest( Irp, AfdPriorityBoost );
  892. return status;
  893. } // AfdSend
  894. NTSTATUS
  895. AfdRestartSend (
  896. IN PDEVICE_OBJECT DeviceObject,
  897. IN PIRP Irp,
  898. IN PVOID Context
  899. )
  900. {
  901. PIO_STACK_LOCATION irpSp;
  902. PAFD_ENDPOINT endpoint;
  903. PAFD_CONNECTION connection;
  904. NTSTATUS status;
  905. AFD_LOCK_QUEUE_HANDLE lockHandle;
  906. UNREFERENCED_PARAMETER (DeviceObject);
  907. connection = Context;
  908. ASSERT( connection != NULL );
  909. ASSERT( connection->Type == AfdBlockTypeConnection );
  910. endpoint = connection->Endpoint;
  911. ASSERT( endpoint != NULL );
  912. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting ||
  913. endpoint->Type == AfdBlockTypeVcBoth );
  914. irpSp = IoGetCurrentIrpStackLocation( Irp );
  915. IF_DEBUG(SEND) {
  916. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  917. "AfdRestartSend: send completed for IRP %p, endpoint %p, "
  918. "status = %X\n",
  919. Irp, Context, Irp->IoStatus.Status ));
  920. }
  921. AfdCompleteOutstandingIrp( endpoint, Irp );
  922. if (IS_TDI_BUFFERRING (endpoint)) {
  923. ASSERT (irpSp->FileObject!=NULL);
  924. //
  925. // If the request failed indicating that the send would have blocked,
  926. // and the client issues a nonblocking send, remember that nonblocking
  927. // sends won't work until we get a send possible indication. This
  928. // is required for write polls to work correctly.
  929. //
  930. // If the status code is STATUS_REQUEST_NOT_ACCEPTED, then the
  931. // transport does not want us to update our internal variable that
  932. // remembers that nonblocking sends are possible. The transport
  933. // will tell us when sends are or are not possible.
  934. //
  935. // !!! should we also say that nonblocking sends are not possible if
  936. // a send is completed with fewer bytes than were requested?
  937. if ( Irp->IoStatus.Status == STATUS_DEVICE_NOT_READY ) {
  938. //
  939. // Reenable the send event.
  940. //
  941. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  942. endpoint->EventsActive &= ~AFD_POLL_SEND;
  943. endpoint->EnableSendEvent = TRUE;
  944. IF_DEBUG(EVENT_SELECT) {
  945. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  946. "AfdRestartSend: Endp %p, Active %lx\n",
  947. endpoint,
  948. endpoint->EventsActive
  949. ));
  950. }
  951. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  952. connection->VcNonBlockingSendPossible = FALSE;
  953. }
  954. //
  955. // If this is a send IRP on a nonblocking endpoint and fewer bytes
  956. // were actually sent than were requested to be sent, reissue
  957. // another send for the remaining buffer space.
  958. //
  959. if ( !endpoint->NonBlocking && NT_SUCCESS(Irp->IoStatus.Status) &&
  960. Irp->IoStatus.Information <
  961. irpSp->Parameters.AfdRestartSendInfo.AfdCurrentLength ) {
  962. ASSERT( Irp->MdlAddress != NULL );
  963. //
  964. // Advance the MDL chain by the number of bytes actually sent.
  965. //
  966. Irp->MdlAddress = AfdAdvanceMdlChain(
  967. Irp->MdlAddress,
  968. (ULONG)Irp->IoStatus.Information
  969. );
  970. //
  971. // Update our restart info.
  972. //
  973. irpSp->Parameters.AfdRestartSendInfo.AfdCurrentLength -=
  974. (ULONG)Irp->IoStatus.Information;
  975. //
  976. // Reissue the send.
  977. //
  978. TdiBuildSend(
  979. Irp,
  980. connection->FileObject->DeviceObject,
  981. connection->FileObject,
  982. AfdRestartSend,
  983. connection,
  984. Irp->MdlAddress,
  985. irpSp->Parameters.AfdRestartSendInfo.AfdSendFlags,
  986. irpSp->Parameters.AfdRestartSendInfo.AfdCurrentLength
  987. );
  988. UPDATE_CONN2 (connection, "Restarting incomplete send, bytes: 0x%lX",
  989. (ULONG)Irp->IoStatus.Information);
  990. status = AfdIoCallDriver(
  991. endpoint,
  992. connection->FileObject->DeviceObject,
  993. Irp
  994. );
  995. IF_DEBUG(SEND) {
  996. if ( !NT_SUCCESS(status) ) {
  997. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  998. "AfdRestartSend: IoCallDriver returned %lx\n",
  999. status
  1000. ));
  1001. }
  1002. }
  1003. return STATUS_MORE_PROCESSING_REQUIRED;
  1004. }
  1005. //
  1006. // Restore the IRP to its former glory before completing it
  1007. // unless it is a non-blocking endpoint in which case
  1008. // we shouldn't have modified it in the first place and
  1009. // we also want to return the actual number of bytes sent
  1010. // by the transport.
  1011. //
  1012. if ( !endpoint->NonBlocking ) {
  1013. Irp->IoStatus.Information = irpSp->Parameters.AfdRestartSendInfo.AfdOriginalLength;
  1014. }
  1015. //
  1016. // Remove the reference added just before calling the transport.
  1017. //
  1018. DEREFERENCE_CONNECTION2( connection, "AfdRestartSend-tdib, sent/error: 0x%lX",
  1019. (NT_SUCCESS (Irp->IoStatus.Status)
  1020. ? (ULONG)Irp->IoStatus.Information
  1021. : (ULONG)Irp->IoStatus.Status));
  1022. }
  1023. else {
  1024. AfdProcessBufferSend (connection, Irp);
  1025. //
  1026. // If we buffered last page of the send, adjust last MDL
  1027. // and fix returned byte count if necessary
  1028. //
  1029. if (Irp->MdlAddress!=irpSp->Parameters.AfdRestartSendInfo.AfdMdlChain) {
  1030. PMDL mdl = Irp->MdlAddress;
  1031. ASSERT (mdl!=NULL);
  1032. while (mdl->Next!=NULL) {
  1033. mdl = mdl->Next;
  1034. }
  1035. //
  1036. // Unmap the pages that could have been mapped by
  1037. // the transport before adjusting the MDL size back
  1038. // so that MM does not try to unmap more than was
  1039. // mapped by the transport.
  1040. //
  1041. if ((mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) &&
  1042. (irpSp->Parameters.AfdRestartSendInfo.AfdSendFlags &
  1043. AFD_SEND_MDL_HAS_NOT_BEEN_MAPPED)) {
  1044. MmUnmapLockedPages (mdl->MappedSystemVa, mdl);
  1045. }
  1046. mdl->ByteCount
  1047. = irpSp->Parameters.AfdRestartSendInfo.AfdCurrentLength;
  1048. mdl->Next = irpSp->Parameters.AfdRestartSendInfo.AfdMdlChain;
  1049. //
  1050. // Remove the reference added just before calling the transport.
  1051. //
  1052. DEREFERENCE_CONNECTION2( connection, "AfdRestartSend-split, sent/error: 0x%lX",
  1053. (NT_SUCCESS (Irp->IoStatus.Status)
  1054. ? (ULONG)Irp->IoStatus.Information
  1055. : (ULONG)Irp->IoStatus.Status));
  1056. if (NT_SUCCESS (Irp->IoStatus.Status)) {
  1057. //
  1058. // Make sure that the TDI provider sent everything we requested that
  1059. // he send.
  1060. //
  1061. ASSERT (Irp->IoStatus.Information+(ULONG)AfdBufferLengthForOnePage==
  1062. irpSp->Parameters.AfdRestartSendInfo.AfdOriginalLength ||
  1063. Irp->IoStatus.Information+(ULONG)AfdBlockingSendCopyThreshold==
  1064. irpSp->Parameters.AfdRestartSendInfo.AfdOriginalLength);
  1065. Irp->IoStatus.Information =
  1066. irpSp->Parameters.AfdRestartSendInfo.AfdOriginalLength;
  1067. }
  1068. }
  1069. else {
  1070. //
  1071. // Remove the reference added just before calling the transport.
  1072. //
  1073. DEREFERENCE_CONNECTION2( connection, "AfdRestartSend, sent/error: 0x%lX",
  1074. (NT_SUCCESS (Irp->IoStatus.Status)
  1075. ? (ULONG)Irp->IoStatus.Information
  1076. : (ULONG)Irp->IoStatus.Status));
  1077. //
  1078. // Make sure that the TDI provider sent everything we requested that
  1079. // he send.
  1080. //
  1081. ASSERT (!NT_SUCCESS (Irp->IoStatus.Status) ||
  1082. (Irp->IoStatus.Information ==
  1083. irpSp->Parameters.AfdRestartSendInfo.AfdOriginalLength));
  1084. }
  1085. }
  1086. //
  1087. // If pending has be returned for this irp then mark the current
  1088. // stack as pending.
  1089. //
  1090. if ( Irp->PendingReturned ) {
  1091. IoMarkIrpPending(Irp);
  1092. }
  1093. //
  1094. // The send dispatch routine temporarily yanks the file
  1095. // object pointer if it wants to make sure that the IRP
  1096. // is not completed until it is fully done with it.
  1097. //
  1098. if (InterlockedExchangePointer (
  1099. (PVOID *)&irpSp->FileObject,
  1100. (PVOID)-1)==NULL) {
  1101. return STATUS_MORE_PROCESSING_REQUIRED;
  1102. }
  1103. else
  1104. return STATUS_SUCCESS;
  1105. } // AfdRestartSend
  1106. NTSTATUS
  1107. AfdRestartBufferSend (
  1108. IN PDEVICE_OBJECT DeviceObject,
  1109. IN PIRP Irp,
  1110. IN PVOID Context
  1111. )
  1112. {
  1113. PAFD_BUFFER afdBuffer;
  1114. PAFD_CONNECTION connection;
  1115. #if REFERENCE_DEBUG
  1116. IO_STATUS_BLOCK ioStatus = Irp->IoStatus;
  1117. #endif
  1118. UNREFERENCED_PARAMETER (DeviceObject);
  1119. afdBuffer = Context;
  1120. ASSERT (IS_VALID_AFD_BUFFER (afdBuffer));
  1121. connection = afdBuffer->Context;
  1122. ASSERT( connection != NULL );
  1123. ASSERT( connection->Type == AfdBlockTypeConnection );
  1124. ASSERT( connection->ReferenceCount > 0 );
  1125. //
  1126. // Make sure that the TDI provider sent everything we requested that
  1127. // he send.
  1128. //
  1129. ASSERT( !NT_SUCCESS (Irp->IoStatus.Status)
  1130. || (Irp->IoStatus.Information == afdBuffer->Mdl->ByteCount) );
  1131. //
  1132. // Process the Irp (note that Irp is part of the buffer)
  1133. //
  1134. AfdProcessBufferSend (connection, Irp);
  1135. //
  1136. // Now we can free the buffer
  1137. //
  1138. afdBuffer->Mdl->ByteCount = afdBuffer->BufferLength;
  1139. AfdReturnBuffer( &afdBuffer->Header, connection->OwningProcess );
  1140. //
  1141. // Remove the reference added just before calling the transport.
  1142. //
  1143. DEREFERENCE_CONNECTION2( connection, "AfdRestartBufferSend, sent/error: 0x%lX",
  1144. (NT_SUCCESS (ioStatus.Status)
  1145. ? (ULONG)ioStatus.Information
  1146. : (ULONG)ioStatus.Status));
  1147. //
  1148. // Tell the IO system to stop processing IO completion for this IRP.
  1149. // becuase it belongs to our buffer structure and we do not want
  1150. // to have it freed
  1151. //
  1152. return STATUS_MORE_PROCESSING_REQUIRED;
  1153. } // AfdRestartBufferSend
  1154. VOID
  1155. AfdProcessBufferSend (
  1156. PAFD_CONNECTION Connection,
  1157. PIRP Irp
  1158. )
  1159. {
  1160. PAFD_ENDPOINT endpoint;
  1161. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1162. PLIST_ENTRY listEntry;
  1163. PIRP irp;
  1164. BOOLEAN sendPossible;
  1165. PIRP disconnectIrp;
  1166. LIST_ENTRY irpsToComplete;
  1167. endpoint = Connection->Endpoint;
  1168. ASSERT( endpoint != NULL );
  1169. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting ||
  1170. endpoint->Type == AfdBlockTypeVcBoth);
  1171. ASSERT( !IS_TDI_BUFFERRING(endpoint) );
  1172. IF_DEBUG(SEND) {
  1173. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1174. "AfdProcessBufferSend: send completed for IRP %p, connection %p, "
  1175. "status = %X\n",
  1176. Irp, Connection, Irp->IoStatus.Status ));
  1177. }
  1178. //
  1179. // Update the count of send bytes outstanding on the connection.
  1180. // Note that we must do this BEFORE we check to see whether there
  1181. // are any pended sends--otherwise, there is a timing window where
  1182. // a new send could come in, get pended, and we would not kick
  1183. // the sends here.
  1184. //
  1185. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  1186. ASSERT( Connection->VcBufferredSendBytes >= Irp->IoStatus.Information );
  1187. ASSERT( (Connection->VcBufferredSendCount & 0x8000) == 0 );
  1188. ASSERT( Connection->VcBufferredSendCount != 0 );
  1189. Connection->VcBufferredSendBytes -= (ULONG)Irp->IoStatus.Information;
  1190. Connection->VcBufferredSendCount -= 1;
  1191. //
  1192. // If the send failed, abort the connection.
  1193. //
  1194. if ( !NT_SUCCESS(Irp->IoStatus.Status) ) {
  1195. disconnectIrp = Connection->VcDisconnectIrp;
  1196. if ( disconnectIrp != NULL ) {
  1197. Connection->VcDisconnectIrp = NULL;
  1198. }
  1199. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1200. AfdBeginAbort( Connection );
  1201. //
  1202. // If there was a disconnect IRP, rather than just freeing it
  1203. // give it to the transport. This will cause the correct cleanup
  1204. // stuff (dereferenvce objects, free IRP and disconnect context)
  1205. // to occur. Note that we do this AFTER starting to abort the
  1206. // Connection so that we do not confuse the other side.
  1207. //
  1208. if ( disconnectIrp != NULL ) {
  1209. IoCallDriver( Connection->DeviceObject, disconnectIrp );
  1210. }
  1211. AfdDeleteConnectedReference( Connection, FALSE );
  1212. return;
  1213. }
  1214. //
  1215. // Before we release the lock on the endpoint, remember
  1216. // if the number of bytes outstanding in the TDI provider exceeds
  1217. // the limit. We must grab this while holding the endpoint lock.
  1218. //
  1219. sendPossible = (BOOLEAN)(Connection->VcBufferredSendBytes<Connection->MaxBufferredSendBytes);
  1220. //
  1221. // If there are no pended sends on the connection, we're done. Tell
  1222. // the IO system to stop processing IO completion for this IRP.
  1223. //
  1224. if ( IsListEmpty( &Connection->VcSendIrpListHead ) ) {
  1225. //
  1226. // If there is no "special condition" on the endpoint, return
  1227. // immediately. We use the special condition indication so that
  1228. // we need only a single test in the typical case.
  1229. //
  1230. if ( !Connection->SpecialCondition ) {
  1231. ASSERT( Connection->TdiBufferring || Connection->VcDisconnectIrp == NULL );
  1232. ASSERT( Connection->ConnectedReferenceAdded );
  1233. //
  1234. // There are no sends outstanding on the Connection, so indicate
  1235. // that the endpoint is writable.
  1236. //
  1237. if (sendPossible) {
  1238. AfdIndicateEventSelectEvent(
  1239. endpoint,
  1240. AFD_POLL_SEND,
  1241. STATUS_SUCCESS
  1242. );
  1243. }
  1244. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1245. if (sendPossible) {
  1246. AfdIndicatePollEvent(
  1247. endpoint,
  1248. AFD_POLL_SEND,
  1249. STATUS_SUCCESS
  1250. );
  1251. }
  1252. return;
  1253. }
  1254. disconnectIrp = Connection->VcDisconnectIrp;
  1255. if ( disconnectIrp != NULL && Connection->VcBufferredSendCount == 0 ) {
  1256. Connection->VcDisconnectIrp = NULL;
  1257. } else {
  1258. disconnectIrp = NULL;
  1259. if ( sendPossible ) {
  1260. AfdIndicateEventSelectEvent(
  1261. endpoint,
  1262. AFD_POLL_SEND,
  1263. STATUS_SUCCESS
  1264. );
  1265. }
  1266. }
  1267. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1268. //
  1269. // If there is a disconnect IRP, give it to the TDI provider.
  1270. //
  1271. if ( disconnectIrp != NULL ) {
  1272. IoCallDriver( Connection->DeviceObject, disconnectIrp );
  1273. }
  1274. else if ( sendPossible ) {
  1275. AfdIndicatePollEvent(
  1276. endpoint,
  1277. AFD_POLL_SEND,
  1278. STATUS_SUCCESS
  1279. );
  1280. }
  1281. //
  1282. // If the connected reference delete is pending, attempt to
  1283. // remove it.
  1284. //
  1285. AfdDeleteConnectedReference( Connection, FALSE );
  1286. return;
  1287. }
  1288. //
  1289. // Now loop completing as many pended sends as possible. Note that
  1290. // in order to avoid a nasty race condition (between this thread and
  1291. // a thread performing sends on this connection) we must build a local
  1292. // list of IRPs to complete while holding the endpoint
  1293. // spinlock. After that list is built then we can release the lock
  1294. // and scan the list to actually complete the IRPs.
  1295. //
  1296. // We complete sends when we fall below the send bufferring limits, OR
  1297. // when there is only a single send pended. We want to be agressive
  1298. // in completing the send if there is only one because we want to
  1299. // give applications every oppurtunity to get data down to us--we
  1300. // definitely do not want to incur excessive blocking in the
  1301. // application.
  1302. //
  1303. InitializeListHead( &irpsToComplete );
  1304. while ( (Connection->VcBufferredSendBytes <=
  1305. Connection->MaxBufferredSendBytes ||
  1306. Connection->VcSendIrpListHead.Flink ==
  1307. Connection->VcSendIrpListHead.Blink)
  1308. &&
  1309. !IsListEmpty( &Connection->VcSendIrpListHead ) ) {
  1310. //
  1311. // Take the first pended user send IRP off the connection's
  1312. // list of pended send IRPs.
  1313. //
  1314. listEntry = RemoveHeadList( &Connection->VcSendIrpListHead );
  1315. irp = CONTAINING_RECORD( listEntry, IRP, Tail.Overlay.ListEntry );
  1316. //
  1317. // Reset the cancel routine in the user IRP since we're about
  1318. // to complete it.
  1319. //
  1320. if ( IoSetCancelRoutine( irp, NULL ) == NULL ) {
  1321. //
  1322. // This IRP is about to be canceled. Look for another in the
  1323. // list. Set the Flink to NULL so the cancel routine knows
  1324. // it is not on the list.
  1325. //
  1326. irp->Tail.Overlay.ListEntry.Flink = NULL;
  1327. continue;
  1328. }
  1329. //
  1330. // Append the IRP to the local list.
  1331. //
  1332. InsertTailList(
  1333. &irpsToComplete,
  1334. &irp->Tail.Overlay.ListEntry
  1335. );
  1336. }
  1337. if ( sendPossible ) {
  1338. AfdIndicateEventSelectEvent(
  1339. endpoint,
  1340. AFD_POLL_SEND,
  1341. STATUS_SUCCESS
  1342. );
  1343. }
  1344. //
  1345. // Now we can release the locks and scan the local list of IRPs
  1346. // we need to complete, and actually complete them.
  1347. //
  1348. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1349. while( !IsListEmpty( &irpsToComplete ) ) {
  1350. PIO_STACK_LOCATION irpSp;
  1351. //
  1352. // Remove the first item from the IRP list.
  1353. //
  1354. listEntry = RemoveHeadList( &irpsToComplete );
  1355. irp = CONTAINING_RECORD( listEntry, IRP, Tail.Overlay.ListEntry );
  1356. //
  1357. // Complete the user's IRP with a successful status code. The IRP
  1358. // should already be set up with the correct status and bytes
  1359. // written count.
  1360. //
  1361. irpSp = IoGetCurrentIrpStackLocation( irp );
  1362. #if DBG
  1363. if ( irp->IoStatus.Status == STATUS_SUCCESS ) {
  1364. ASSERT( irp->IoStatus.Information == irpSp->Parameters.AfdRestartSendInfo.AfdOriginalLength );
  1365. }
  1366. #endif
  1367. //
  1368. // The send dispatch routine puts NULL into this
  1369. // field if it wants to make sure that the IRP
  1370. // is not completed until it is fully done with it
  1371. //
  1372. if (InterlockedExchangePointer (
  1373. &irp->Tail.Overlay.DriverContext[0],
  1374. (PVOID)-1)!=NULL) {
  1375. UPDATE_CONN2 (Connection, "AfdProcessBufferSend, bytes sent reported 0x%lX",
  1376. (ULONG)irp->IoStatus.Information);
  1377. IoCompleteRequest( irp, AfdPriorityBoost );
  1378. }
  1379. }
  1380. if ( sendPossible ) {
  1381. AfdIndicatePollEvent(
  1382. endpoint,
  1383. AFD_POLL_SEND,
  1384. STATUS_SUCCESS
  1385. );
  1386. }
  1387. return;
  1388. } // AfdProcessBufferSend
  1389. NTSTATUS
  1390. AfdRestartSendConnDatagram (
  1391. IN PDEVICE_OBJECT DeviceObject,
  1392. IN PIRP Irp,
  1393. IN PVOID Context
  1394. )
  1395. {
  1396. PAFD_SEND_CONN_DATAGRAM_CONTEXT context = Context;
  1397. PAFD_ENDPOINT endpoint = context->Endpoint;
  1398. UNREFERENCED_PARAMETER (DeviceObject);
  1399. IF_DEBUG(SEND) {
  1400. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1401. "AfdRestartSendConnDatagram: send conn completed for "
  1402. "IRP %p, endpoint %p, status = %X\n",
  1403. Irp, endpoint, Irp->IoStatus.Status ));
  1404. }
  1405. ASSERT (Irp->IoStatus.Status!=STATUS_SUCCESS ||
  1406. Irp->IoStatus.Information
  1407. ==IoGetCurrentIrpStackLocation (Irp)->Parameters.AfdRestartSendInfo.AfdOriginalLength);
  1408. //
  1409. // Free the context structure we allocated earlier.
  1410. //
  1411. AfdCompleteOutstandingIrp( endpoint, Irp );
  1412. AFD_FREE_POOL(
  1413. context,
  1414. AFD_TDI_POOL_TAG
  1415. );
  1416. //
  1417. // If pending has be returned for this irp then mark the current
  1418. // stack as pending.
  1419. //
  1420. if ( Irp->PendingReturned ) {
  1421. IoMarkIrpPending(Irp);
  1422. }
  1423. DEREFERENCE_ENDPOINT2 (endpoint, "AfdRestartSendConnDatagram, status: 0x%lX", Irp->IoStatus.Status);
  1424. return STATUS_SUCCESS;
  1425. } // AfdRestartSendConnDatagram
  1426. NTSTATUS
  1427. AfdRestartSendTdiConnDatagram (
  1428. IN PDEVICE_OBJECT DeviceObject,
  1429. IN PIRP Irp,
  1430. IN PVOID Context
  1431. )
  1432. {
  1433. PAFD_ENDPOINT endpoint = Context;
  1434. UNREFERENCED_PARAMETER (DeviceObject);
  1435. ASSERT (Irp->IoStatus.Status!=STATUS_SUCCESS ||
  1436. Irp->IoStatus.Information
  1437. ==IoGetCurrentIrpStackLocation (Irp)->Parameters.AfdRestartSendInfo.AfdOriginalLength);
  1438. IF_DEBUG(SEND) {
  1439. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1440. "AfdRestartSendTdiConnDatagram: send conn completed for "
  1441. "IRP %p, endpoint %p, status = %X\n",
  1442. Irp, endpoint, Irp->IoStatus.Status ));
  1443. }
  1444. AfdCompleteOutstandingIrp( endpoint, Irp );
  1445. //
  1446. // If pending has be returned for this irp then mark the current
  1447. // stack as pending.
  1448. //
  1449. if ( Irp->PendingReturned ) {
  1450. IoMarkIrpPending(Irp);
  1451. }
  1452. DEREFERENCE_ENDPOINT2 (endpoint, "AfdRestartSendTdiConnDatagram, status: 0x%lX", Irp->IoStatus.Status);
  1453. return STATUS_SUCCESS;
  1454. } // AfdRestartSendTdiConnDatagram
  1455. NTSTATUS
  1456. FASTCALL
  1457. AfdSendDatagram (
  1458. IN PIRP Irp,
  1459. IN PIO_STACK_LOCATION IrpSp
  1460. )
  1461. {
  1462. NTSTATUS status;
  1463. PAFD_ENDPOINT endpoint;
  1464. PTRANSPORT_ADDRESS destinationAddress;
  1465. ULONG destinationAddressLength;
  1466. PAFD_BUFFER_TAG afdBuffer = NULL;
  1467. ULONG sendLength;
  1468. ULONG bufferCount;
  1469. //
  1470. // Make sure that the endpoint is in the correct state.
  1471. //
  1472. endpoint = IrpSp->FileObject->FsContext;
  1473. ASSERT( IS_DGRAM_ENDPOINT(endpoint) );
  1474. if ( !IS_DGRAM_ENDPOINT (endpoint) ||
  1475. ((endpoint->State != AfdEndpointStateBound )
  1476. && (endpoint->State != AfdEndpointStateConnected)) ) {
  1477. status = STATUS_INVALID_PARAMETER;
  1478. goto complete;
  1479. }
  1480. #ifdef _WIN64
  1481. if (IoIs32bitProcess (Irp)) {
  1482. PAFD_SEND_DATAGRAM_INFO32 sendInfo32;
  1483. LPWSABUF32 bufferArray32;
  1484. if( IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  1485. sizeof(*sendInfo32) ) {
  1486. AFD_W4_INIT status = STATUS_SUCCESS;
  1487. try {
  1488. //
  1489. // Validate the input structure if it comes from the user mode
  1490. // application
  1491. //
  1492. sendInfo32 = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  1493. if( Irp->RequestorMode != KernelMode ) {
  1494. ProbeForReadSmallStructure(
  1495. sendInfo32,
  1496. sizeof(*sendInfo32),
  1497. PROBE_ALIGNMENT32 (AFD_SEND_DATAGRAM_INFO32)
  1498. );
  1499. }
  1500. //
  1501. // Make local copies of the embeded pointer and parameters
  1502. // that we will be using more than once in case malicios
  1503. // application attempts to change them while we are
  1504. // validating
  1505. //
  1506. bufferArray32 = UlongToPtr(sendInfo32->BufferArray);
  1507. bufferCount = sendInfo32->BufferCount;
  1508. destinationAddress =
  1509. UlongToPtr(sendInfo32->TdiConnInfo.RemoteAddress);
  1510. destinationAddressLength =
  1511. sendInfo32->TdiConnInfo.RemoteAddressLength;
  1512. //
  1513. // Create the MDL chain describing the WSABUF array.
  1514. // This will also validate the buffer array and individual
  1515. // buffers
  1516. //
  1517. status = AfdAllocateMdlChain32(
  1518. Irp, // Requestor mode passed along
  1519. bufferArray32,
  1520. bufferCount,
  1521. IoReadAccess,
  1522. &sendLength
  1523. );
  1524. if( !NT_SUCCESS(status) ) {
  1525. goto complete;
  1526. }
  1527. } except( AFD_EXCEPTION_FILTER (status) ) {
  1528. ASSERT (NT_ERROR (status));
  1529. //
  1530. // Exception accessing input structure.
  1531. //
  1532. goto complete;
  1533. }
  1534. } else {
  1535. //
  1536. // Invalid input buffer length.
  1537. //
  1538. status = STATUS_INVALID_PARAMETER;
  1539. goto complete;
  1540. }
  1541. }
  1542. else
  1543. #endif _WIN64
  1544. {
  1545. PAFD_SEND_DATAGRAM_INFO sendInfo;
  1546. LPWSABUF bufferArray;
  1547. if( IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  1548. sizeof(*sendInfo) ) {
  1549. AFD_W4_INIT status = STATUS_SUCCESS;
  1550. try {
  1551. //
  1552. // Validate the input structure if it comes from the user mode
  1553. // application
  1554. //
  1555. sendInfo = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  1556. if( Irp->RequestorMode != KernelMode ) {
  1557. ProbeForReadSmallStructure(
  1558. sendInfo,
  1559. sizeof(*sendInfo),
  1560. PROBE_ALIGNMENT (AFD_SEND_DATAGRAM_INFO)
  1561. );
  1562. }
  1563. //
  1564. // Make local copies of the embeded pointer and parameters
  1565. // that we will be using more than once in case malicios
  1566. // application attempts to change them while we are
  1567. // validating
  1568. //
  1569. bufferArray = sendInfo->BufferArray;
  1570. bufferCount = sendInfo->BufferCount;
  1571. destinationAddress =
  1572. sendInfo->TdiConnInfo.RemoteAddress;
  1573. destinationAddressLength =
  1574. sendInfo->TdiConnInfo.RemoteAddressLength;
  1575. //
  1576. // Create the MDL chain describing the WSABUF array.
  1577. // This will also validate the buffer array and individual
  1578. // buffers
  1579. //
  1580. status = AfdAllocateMdlChain(
  1581. Irp, // Requestor mode passed along
  1582. bufferArray,
  1583. bufferCount,
  1584. IoReadAccess,
  1585. &sendLength
  1586. );
  1587. if( !NT_SUCCESS(status) ) {
  1588. goto complete;
  1589. }
  1590. } except( AFD_EXCEPTION_FILTER (status) ) {
  1591. ASSERT (NT_ERROR (status));
  1592. //
  1593. // Exception accessing input structure.
  1594. //
  1595. goto complete;
  1596. }
  1597. } else {
  1598. //
  1599. // Invalid input buffer length.
  1600. //
  1601. status = STATUS_INVALID_PARAMETER;
  1602. goto complete;
  1603. }
  1604. }
  1605. //
  1606. // If send has been shut down on this endpoint, fail.
  1607. //
  1608. if ( (endpoint->DisconnectMode & AFD_PARTIAL_DISCONNECT_SEND) ) {
  1609. status = STATUS_PIPE_DISCONNECTED;
  1610. goto complete;
  1611. }
  1612. //
  1613. // Copy the destination address to the AFD buffer.
  1614. //
  1615. AFD_W4_INIT ASSERT (status == STATUS_SUCCESS);
  1616. try {
  1617. //
  1618. // Get an AFD buffer to use for the request. We need this to
  1619. // hold the destination address for the datagram.
  1620. //
  1621. afdBuffer = AfdGetBufferTagRaiseOnFailure(
  1622. destinationAddressLength,
  1623. endpoint->OwningProcess );
  1624. //
  1625. // Probe the address buffer if it comes from the user mode
  1626. // application
  1627. //
  1628. if( Irp->RequestorMode != KernelMode ) {
  1629. ProbeForRead (
  1630. destinationAddress,
  1631. destinationAddressLength,
  1632. sizeof (UCHAR));
  1633. }
  1634. RtlCopyMemory(
  1635. afdBuffer->TdiInfo.RemoteAddress,
  1636. destinationAddress,
  1637. destinationAddressLength
  1638. );
  1639. //
  1640. // Validate internal consistency of the transport address structure.
  1641. // Note that we HAVE to do this after copying since the malicious
  1642. // application can change the content of the buffer on us any time
  1643. // and our check will be bypassed.
  1644. //
  1645. if ((((PTRANSPORT_ADDRESS)afdBuffer->TdiInfo.RemoteAddress)->TAAddressCount!=1) ||
  1646. (LONG)destinationAddressLength<
  1647. FIELD_OFFSET (TRANSPORT_ADDRESS,
  1648. Address[0].Address[((PTRANSPORT_ADDRESS)afdBuffer->TdiInfo.RemoteAddress)->Address[0].AddressLength])) {
  1649. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  1650. }
  1651. afdBuffer->TdiInfo.RemoteAddressLength = destinationAddressLength;
  1652. ASSERT (afdBuffer->TdiInfo.RemoteAddress !=NULL);
  1653. afdBuffer->TdiInfo.Options = NULL;
  1654. afdBuffer->TdiInfo.OptionsLength = 0;
  1655. afdBuffer->TdiInfo.UserData = NULL;
  1656. afdBuffer->TdiInfo.UserDataLength = 0;
  1657. } except( AFD_EXCEPTION_FILTER (status) ) {
  1658. ASSERT (NT_ERROR (status));
  1659. if (afdBuffer!=NULL) {
  1660. AfdReturnBuffer ( &afdBuffer->Header, endpoint->OwningProcess );
  1661. }
  1662. goto complete;
  1663. }
  1664. //
  1665. // Build the request to send the datagram.
  1666. //
  1667. REFERENCE_ENDPOINT2 (endpoint,"AfdSendDatagram, length: 0x%lX", sendLength);
  1668. afdBuffer->Context = endpoint;
  1669. #if DBG
  1670. //
  1671. // Store send length to check transport upon completion
  1672. //
  1673. IrpSp->Parameters.AfdRestartSendInfo.AfdOriginalLength = sendLength;
  1674. #endif
  1675. TdiBuildSendDatagram(
  1676. Irp,
  1677. endpoint->AddressDeviceObject,
  1678. endpoint->AddressFileObject,
  1679. AfdRestartSendDatagram,
  1680. afdBuffer,
  1681. Irp->MdlAddress,
  1682. sendLength,
  1683. &afdBuffer->TdiInfo
  1684. );
  1685. IF_DEBUG(SEND) {
  1686. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1687. "AfdSendDatagram: SendDGInfo at %p, len = %ld\n",
  1688. IrpSp->Parameters.DeviceIoControl.Type3InputBuffer,
  1689. IrpSp->Parameters.DeviceIoControl.InputBufferLength ));
  1690. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1691. "AfdSendDatagram: remote address at %p, len = %ld\n",
  1692. destinationAddress,
  1693. destinationAddressLength ));
  1694. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1695. "AfdSendDatagram: output buffer length = %ld\n",
  1696. IrpSp->Parameters.DeviceIoControl.OutputBufferLength ));
  1697. }
  1698. //
  1699. // Call the transport to actually perform the send datagram.
  1700. //
  1701. return AfdIoCallDriver( endpoint, endpoint->AddressDeviceObject, Irp );
  1702. complete:
  1703. Irp->IoStatus.Information = 0;
  1704. Irp->IoStatus.Status = status;
  1705. IoCompleteRequest( Irp, AfdPriorityBoost );
  1706. return status;
  1707. } // AfdSendDatagram
  1708. NTSTATUS
  1709. AfdRestartSendDatagram (
  1710. IN PDEVICE_OBJECT DeviceObject,
  1711. IN PIRP Irp,
  1712. IN PVOID Context
  1713. )
  1714. {
  1715. PAFD_BUFFER_TAG afdBuffer;
  1716. PAFD_ENDPOINT endpoint;
  1717. UNREFERENCED_PARAMETER (DeviceObject);
  1718. afdBuffer = Context;
  1719. endpoint = afdBuffer->Context;
  1720. ASSERT( IS_DGRAM_ENDPOINT(endpoint) );
  1721. ASSERT (Irp->IoStatus.Status!=STATUS_SUCCESS ||
  1722. Irp->IoStatus.Information
  1723. ==IoGetCurrentIrpStackLocation (Irp)->Parameters.AfdRestartSendInfo.AfdOriginalLength);
  1724. AfdCompleteOutstandingIrp( endpoint, Irp );
  1725. IF_DEBUG(SEND) {
  1726. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1727. "AfdRestartSendDatagram: send datagram completed for "
  1728. "IRP %p, endpoint %p, status = %X\n",
  1729. Irp, Context, Irp->IoStatus.Status ));
  1730. }
  1731. //
  1732. // If pending has be returned for this irp then mark the current
  1733. // stack as pending.
  1734. //
  1735. if ( Irp->PendingReturned ) {
  1736. IoMarkIrpPending(Irp);
  1737. }
  1738. AfdReturnBuffer( &afdBuffer->Header, endpoint->OwningProcess );
  1739. DEREFERENCE_ENDPOINT2 (endpoint, "AfdRestartSendDatagram, status: 0x%lX", Irp->IoStatus.Status);
  1740. return STATUS_SUCCESS;
  1741. } // AfdRestartSendDatagram
  1742. NTSTATUS
  1743. AfdSendPossibleEventHandler (
  1744. IN PVOID TdiEventContext,
  1745. IN PVOID ConnectionContext,
  1746. IN ULONG BytesAvailable
  1747. )
  1748. {
  1749. PAFD_CONNECTION connection;
  1750. PAFD_ENDPOINT endpoint;
  1751. BOOLEAN result;
  1752. UNREFERENCED_PARAMETER( TdiEventContext );
  1753. UNREFERENCED_PARAMETER( BytesAvailable );
  1754. connection = (PAFD_CONNECTION)ConnectionContext;
  1755. ASSERT( connection != NULL );
  1756. CHECK_REFERENCE_CONNECTION (connection, result);
  1757. if (!result) {
  1758. return STATUS_INSUFFICIENT_RESOURCES;
  1759. }
  1760. ASSERT( connection->Type == AfdBlockTypeConnection );
  1761. endpoint = connection->Endpoint;
  1762. ASSERT( endpoint != NULL );
  1763. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  1764. ASSERT( IS_TDI_BUFFERRING(endpoint) );
  1765. ASSERT( connection->TdiBufferring );
  1766. IF_DEBUG(SEND) {
  1767. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1768. "AfdSendPossibleEventHandler: send possible on endpoint %p "
  1769. " conn %p bytes=%ld\n", endpoint, connection, BytesAvailable ));
  1770. }
  1771. //
  1772. // Remember that it is now possible to do a send on this connection.
  1773. //
  1774. if ( BytesAvailable != 0 ) {
  1775. connection->VcNonBlockingSendPossible = TRUE;
  1776. //
  1777. // Complete any outstanding poll IRPs waiting for a send poll.
  1778. //
  1779. // Make sure connection was accepted/connected to prevent
  1780. // indication on listening endpoint
  1781. //
  1782. if (connection->State==AfdConnectionStateConnected) {
  1783. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1784. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  1785. AfdIndicateEventSelectEvent(
  1786. endpoint,
  1787. AFD_POLL_SEND,
  1788. STATUS_SUCCESS
  1789. );
  1790. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  1791. ASSERT (endpoint->Type & AfdBlockTypeVcConnecting);
  1792. AfdIndicatePollEvent(
  1793. endpoint,
  1794. AFD_POLL_SEND,
  1795. STATUS_SUCCESS
  1796. );
  1797. }
  1798. } else {
  1799. connection->VcNonBlockingSendPossible = FALSE;
  1800. }
  1801. DEREFERENCE_CONNECTION (connection);
  1802. return STATUS_SUCCESS;
  1803. } // AfdSendPossibleEventHandler
  1804. VOID
  1805. AfdCancelSend (
  1806. IN PDEVICE_OBJECT DeviceObject,
  1807. IN PIRP Irp
  1808. )
  1809. /*++
  1810. Routine Description:
  1811. Cancels a send IRP that is pended in AFD.
  1812. Arguments:
  1813. DeviceObject - not used.
  1814. Irp - the IRP to cancel.
  1815. Return Value:
  1816. None.
  1817. --*/
  1818. {
  1819. PIO_STACK_LOCATION irpSp;
  1820. PAFD_ENDPOINT endpoint;
  1821. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1822. UNREFERENCED_PARAMETER (DeviceObject);
  1823. //
  1824. // Get the endpoint pointer from our IRP stack location and the
  1825. // connection pointer from the endpoint.
  1826. //
  1827. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1828. endpoint = irpSp->FileObject->FsContext;
  1829. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting ||
  1830. endpoint->Type == AfdBlockTypeVcBoth );
  1831. //
  1832. // Remove the IRP from the endpoint's IRP list if it has not been
  1833. // removed already
  1834. //
  1835. ASSERT (KeGetCurrentIrql ()==DISPATCH_LEVEL);
  1836. AfdAcquireSpinLockAtDpcLevel ( &endpoint->SpinLock, &lockHandle);
  1837. if ( Irp->Tail.Overlay.ListEntry.Flink != NULL ) {
  1838. RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
  1839. }
  1840. //
  1841. // Release the cancel spin lock and complete the IRP with a
  1842. // cancellation status code.
  1843. //
  1844. AfdReleaseSpinLockFromDpcLevel ( &endpoint->SpinLock, &lockHandle);
  1845. Irp->IoStatus.Information = 0;
  1846. Irp->IoStatus.Status = STATUS_CANCELLED;
  1847. //
  1848. // The send dispatch routine puts NULL into this
  1849. // field if it wants to make sure that the IRP
  1850. // is not completed until it is fully done with it
  1851. //
  1852. if (InterlockedExchangePointer (
  1853. &Irp->Tail.Overlay.DriverContext[0],
  1854. (PVOID)-1)!=NULL) {
  1855. IoReleaseCancelSpinLock( Irp->CancelIrql );
  1856. IoCompleteRequest( Irp, AfdPriorityBoost );
  1857. }
  1858. else {
  1859. IoReleaseCancelSpinLock( Irp->CancelIrql );
  1860. }
  1861. return;
  1862. } // AfdCancelSend
  1863. BOOLEAN
  1864. AfdCleanupSendIrp (
  1865. PIRP Irp
  1866. )
  1867. {
  1868. //
  1869. // The send dispatch routine puts NULL into this
  1870. // field if it wants to make sure that the IRP
  1871. // is not completed until it is fully done with it
  1872. //
  1873. if (InterlockedExchangePointer (
  1874. &Irp->Tail.Overlay.DriverContext[0],
  1875. (PVOID)-1)!=NULL) {
  1876. return TRUE;
  1877. }
  1878. else {
  1879. return FALSE;
  1880. }
  1881. }