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.

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