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.

3240 lines
95 KiB

  1. /*++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. accept.c
  5. Abstract:
  6. This module contains the handling code for IOCTL_AFD_ACCEPT.
  7. as well as IOCTL_AFD_SUPER_ACCEPT
  8. Author:
  9. David Treadwell (davidtr) 21-Feb-1992
  10. Revision History:
  11. Vadim Eydelman (vadime) 1999 - No spinlock performance path in super accept,
  12. general code restructuring.
  13. --*/
  14. #include "afdp.h"
  15. VOID
  16. AfdDoListenBacklogReplenish (
  17. IN PVOID Context
  18. );
  19. NTSTATUS
  20. AfdReplenishListenBacklog (
  21. IN PAFD_ENDPOINT Endpoint
  22. );
  23. VOID
  24. AfdReportConnectionAllocationFailure (
  25. PAFD_ENDPOINT Endpoint,
  26. NTSTATUS Status
  27. );
  28. NTSTATUS
  29. AfdContinueSuperAccept (
  30. IN PIRP Irp,
  31. PAFD_CONNECTION Connection
  32. );
  33. NTSTATUS
  34. AfdRestartSuperAcceptGetAddress (
  35. IN PDEVICE_OBJECT DeviceObject,
  36. IN PIRP Irp,
  37. IN PVOID Context
  38. );
  39. NTSTATUS
  40. AfdRestartSuperAcceptReceive (
  41. IN PDEVICE_OBJECT DeviceObject,
  42. IN PIRP Irp,
  43. IN PVOID Context
  44. );
  45. NTSTATUS
  46. AfdRestartDelayedAccept (
  47. IN PDEVICE_OBJECT DeviceObject,
  48. IN PIRP Irp,
  49. IN PVOID Context
  50. );
  51. VOID
  52. AfdSuperAcceptApcKernelRoutine (
  53. IN struct _KAPC *Apc,
  54. IN OUT PKNORMAL_ROUTINE *NormalRoutine,
  55. IN OUT PVOID *NormalContext,
  56. IN OUT PVOID *SystemArgument1,
  57. IN OUT PVOID *SystemArgument2
  58. );
  59. VOID
  60. AfdSuperAcceptApcRundownRoutine (
  61. IN struct _KAPC *Apc
  62. );
  63. #ifdef ALLOC_PRAGMA
  64. #pragma alloc_text( PAGEAFD, AfdAccept )
  65. #pragma alloc_text( PAGEAFD, AfdSuperAccept )
  66. #pragma alloc_text( PAGEAFD, AfdDeferAccept )
  67. #pragma alloc_text( PAGE, AfdDoListenBacklogReplenish )
  68. #pragma alloc_text( PAGEAFD, AfdSetupAcceptEndpoint )
  69. #pragma alloc_text( PAGE, AfdReplenishListenBacklog )
  70. #pragma alloc_text( PAGEAFD, AfdReportConnectionAllocationFailure )
  71. #pragma alloc_text( PAGEAFD, AfdInitiateListenBacklogReplenish )
  72. #pragma alloc_text( PAGEAFD, AfdRestartSuperAccept )
  73. #pragma alloc_text( PAGEAFD, AfdRestartSuperAcceptListen )
  74. #pragma alloc_text( PAGEAFD, AfdContinueSuperAccept )
  75. #pragma alloc_text( PAGEAFD, AfdServiceSuperAccept )
  76. #pragma alloc_text( PAGEAFD, AfdRestartSuperAcceptGetAddress )
  77. #pragma alloc_text( PAGEAFD, AfdRestartSuperAcceptReceive )
  78. #pragma alloc_text( PAGE, AfdSuperAcceptApcKernelRoutine )
  79. #pragma alloc_text( PAGE, AfdSuperAcceptApcRundownRoutine )
  80. #pragma alloc_text( PAGEAFD, AfdCancelSuperAccept )
  81. #pragma alloc_text( PAGEAFD, AfdCleanupSuperAccept )
  82. #pragma alloc_text( PAGEAFD, AfdRestartDelayedAccept)
  83. #pragma alloc_text( PAGEAFD, AfdRestartDelayedSuperAccept)
  84. #endif
  85. //
  86. // Macros to make the super accept restart code more maintainable.
  87. //
  88. #define AfdRestartSuperAcceptInfo DeviceIoControl
  89. // Used while IRP is in AFD queue (otherwise AfdAcceptFileObject
  90. // is stored as completion routine context).
  91. #define AfdAcceptFileObject Type3InputBuffer
  92. // Used when IRP is passed to the transport (otherwise MdlAddress
  93. // is stored in the IRP itself).
  94. #define AfdMdlAddress Type3InputBuffer
  95. #define AfdReceiveDataLength OutputBufferLength
  96. #define AfdRemoteAddressLength InputBufferLength
  97. #define AfdLocalAddressLength IoControlCode
  98. //
  99. // Similar macros for delayed accept restart code.
  100. //
  101. #define AfdRestartDelayedAcceptInfo DeviceIoControl
  102. #define AfdSystemBuffer Type3InputBuffer
  103. NTSTATUS
  104. FASTCALL
  105. AfdAccept (
  106. IN PIRP Irp,
  107. IN PIO_STACK_LOCATION IrpSp
  108. )
  109. /*++
  110. Routine Description:
  111. Accepts an incoming connection. The connection is identified by the
  112. sequence number returned in the wait for listen IRP, and then
  113. associated with the endpoint specified in this request. When this
  114. request completes, the connection is fully established and ready for
  115. data transfer.
  116. Arguments:
  117. Irp - a pointer to a transmit file IRP.
  118. IrpSp - Our stack location for this IRP.
  119. Return Value:
  120. STATUS_SUCCESS if the request was completed successfully, or a
  121. failure status code if there was an error.
  122. --*/
  123. {
  124. NTSTATUS status;
  125. PAFD_ACCEPT_INFO acceptInfo;
  126. PAFD_ENDPOINT listenEndpoint;
  127. PFILE_OBJECT acceptFileObject;
  128. PAFD_ENDPOINT acceptEndpoint;
  129. PAFD_CONNECTION connection;
  130. //
  131. // Set up local variables.
  132. //
  133. listenEndpoint = IrpSp->FileObject->FsContext;
  134. Irp->IoStatus.Information = 0;
  135. #ifdef _WIN64
  136. if (IoIs32bitProcess (Irp)) {
  137. PAFD_ACCEPT_INFO newSystemBuffer;
  138. PAFD_ACCEPT_INFO32 oldSystemBuffer = Irp->AssociatedIrp.SystemBuffer;
  139. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  140. sizeof(AFD_ACCEPT_INFO32) ) {
  141. status = STATUS_INVALID_PARAMETER;
  142. goto complete;
  143. }
  144. try {
  145. newSystemBuffer = ExAllocatePoolWithQuota (NonPagedPool, sizeof (AFD_ACCEPT_INFO));
  146. }
  147. except (EXCEPTION_EXECUTE_HANDLER) {
  148. status = GetExceptionCode ();
  149. goto complete;
  150. }
  151. newSystemBuffer->AcceptHandle = oldSystemBuffer->AcceptHandle;
  152. newSystemBuffer->Sequence = oldSystemBuffer->Sequence;
  153. ExFreePool (Irp->AssociatedIrp.SystemBuffer);
  154. Irp->AssociatedIrp.SystemBuffer = newSystemBuffer;
  155. IrpSp->Parameters.DeviceIoControl.InputBufferLength = sizeof (AFD_ACCEPT_INFO);
  156. }
  157. #endif // _WIN64
  158. acceptInfo = Irp->AssociatedIrp.SystemBuffer;
  159. //
  160. // Make sure that this request is valid.
  161. //
  162. if ( !listenEndpoint->Listening ||
  163. IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  164. sizeof(AFD_ACCEPT_INFO) ||
  165. Irp->MdlAddress!=NULL) {
  166. status = STATUS_INVALID_PARAMETER;
  167. goto complete;
  168. }
  169. ASSERT ((listenEndpoint->Type & AfdBlockTypeVcListening)==AfdBlockTypeVcListening);
  170. //
  171. // Check for if the caller is unaware of the SAN
  172. // provider activation and report the error.
  173. //
  174. if (!acceptInfo->SanActive && AfdSanServiceHelper!=NULL) {
  175. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  176. "AFD: Process %p is being told to enable SAN on accept\n",
  177. PsGetCurrentProcessId ()));
  178. status = STATUS_INVALID_PARAMETER_12;
  179. goto complete;
  180. }
  181. //
  182. // Add another free connection to replace the one we're accepting.
  183. // Also, add extra to account for past failures in calls to
  184. // AfdAddFreeConnection().
  185. //
  186. InterlockedIncrement(
  187. &listenEndpoint->Common.VcListening.FailedConnectionAdds
  188. );
  189. AfdReplenishListenBacklog( listenEndpoint );
  190. //
  191. // Obtain a pointer to the endpoint on which we're going to
  192. // accept the connection.
  193. //
  194. status = ObReferenceObjectByHandle(
  195. acceptInfo->AcceptHandle,
  196. (IrpSp->Parameters.DeviceIoControl.IoControlCode>>14) & 3,
  197. // DesiredAccess
  198. *IoFileObjectType,
  199. Irp->RequestorMode,
  200. (PVOID *)&acceptFileObject,
  201. NULL
  202. );
  203. if ( !NT_SUCCESS(status) ) {
  204. goto complete;
  205. }
  206. //
  207. // We may have a file object that is not an AFD endpoint. Make sure
  208. // that this is an actual AFD endpoint.
  209. //
  210. if ( acceptFileObject->DeviceObject!=AfdDeviceObject) {
  211. status = STATUS_INVALID_HANDLE;
  212. goto complete_deref;
  213. }
  214. acceptEndpoint = acceptFileObject->FsContext;
  215. if (acceptEndpoint->TransportInfo!=listenEndpoint->TransportInfo) {
  216. status = STATUS_INVALID_PARAMETER;
  217. goto complete_deref;
  218. }
  219. ASSERT( InterlockedIncrement( &acceptEndpoint->ObReferenceBias ) > 0 );
  220. IF_DEBUG(ACCEPT) {
  221. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  222. "AfdAccept: file object %p, accept endpoint %p, listen endpoint %p\n",
  223. acceptFileObject, acceptEndpoint, listenEndpoint ));
  224. }
  225. if (AFD_START_STATE_CHANGE (acceptEndpoint, AfdEndpointStateConnected)) {
  226. if (acceptEndpoint->State!=AfdEndpointStateOpen) {
  227. status = STATUS_INVALID_PARAMETER;
  228. }
  229. else {
  230. AFD_LOCK_QUEUE_HANDLE lockHandle;
  231. AfdAcquireSpinLock (&listenEndpoint->SpinLock, &lockHandle);
  232. connection = AfdGetReturnedConnection (listenEndpoint,
  233. acceptInfo->Sequence);
  234. if (connection==NULL) {
  235. AfdReleaseSpinLock (&listenEndpoint->SpinLock, &lockHandle);
  236. status = STATUS_INVALID_PARAMETER;
  237. }
  238. else if (connection->SanConnection) {
  239. Irp->Tail.Overlay.DriverContext[3] = acceptInfo->AcceptHandle;
  240. IrpSp->Parameters.AfdRestartSuperAcceptInfo.AfdAcceptFileObject = acceptFileObject;
  241. IrpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength = 0;
  242. IrpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength = 0;
  243. IrpSp->Parameters.AfdRestartSuperAcceptInfo.AfdRemoteAddressLength = 0;
  244. status = AfdSanAcceptCore (Irp, acceptFileObject, connection, &lockHandle);
  245. if (status==STATUS_PENDING) {
  246. return STATUS_PENDING;
  247. }
  248. }
  249. else {
  250. status = AfdAcceptCore (Irp, acceptEndpoint, connection);
  251. AfdReleaseSpinLock (&listenEndpoint->SpinLock, &lockHandle);
  252. AFD_RETURN_REMOTE_ADDRESS (
  253. connection->RemoteAddress,
  254. connection->RemoteAddressLength
  255. );
  256. connection->RemoteAddress = NULL;
  257. if (status==STATUS_SUCCESS) {
  258. NOTHING;
  259. }
  260. else if (status==STATUS_PENDING) {
  261. //
  262. // Remember that a TDI accept has started on this endpoint.
  263. //
  264. InterlockedIncrement(
  265. &listenEndpoint->Common.VcListening.TdiAcceptPendingCount
  266. );
  267. IrpSp->Parameters.AfdRestartDelayedAcceptInfo.AfdSystemBuffer =
  268. Irp->AssociatedIrp.SystemBuffer;
  269. Irp->AssociatedIrp.SystemBuffer = NULL;
  270. ASSERT (Irp->MdlAddress==NULL);
  271. IoSetCompletionRoutine(
  272. Irp,
  273. AfdRestartDelayedAccept,
  274. acceptFileObject,
  275. TRUE,
  276. TRUE,
  277. TRUE
  278. );
  279. AfdIoCallDriver (
  280. acceptEndpoint,
  281. acceptEndpoint->Common.VcConnecting.Connection->DeviceObject,
  282. Irp
  283. );
  284. return STATUS_PENDING;
  285. }
  286. else {
  287. AfdAbortConnection (connection);
  288. ASSERT (status==STATUS_CANCELLED);
  289. }
  290. }
  291. }
  292. AFD_END_STATE_CHANGE (acceptEndpoint);
  293. }
  294. else {
  295. status = STATUS_INVALID_PARAMETER;
  296. }
  297. ASSERT( InterlockedDecrement( &acceptEndpoint->ObReferenceBias ) >= 0 );
  298. complete_deref:
  299. ObDereferenceObject( acceptFileObject );
  300. complete:
  301. Irp->IoStatus.Status = status;
  302. ASSERT( Irp->CancelRoutine == NULL );
  303. IoCompleteRequest( Irp, AfdPriorityBoost );
  304. return status;
  305. } // AfdAccept
  306. NTSTATUS
  307. AfdAcceptCore (
  308. IN PIRP AcceptIrp,
  309. IN PAFD_ENDPOINT AcceptEndpoint,
  310. IN PAFD_CONNECTION Connection
  311. )
  312. /*++
  313. Routine Description:
  314. Performs the key functions of associating a connection accepted
  315. on a listening endpoint with a new endpoint.
  316. Arguments:
  317. AcceptIrp - Irp used for accept operation
  318. AcceptEndpoint - the new endpoint with which to associate the
  319. connectuion.
  320. Connection - the connection being accepted.
  321. Return Value:
  322. STATUS_SUCCESS if the operation was completed successfully,
  323. STATUS_PENDING if IRP was passed further to the transport
  324. failure status code if there was an error.
  325. --*/
  326. {
  327. PAFD_ENDPOINT listenEndpoint;
  328. NTSTATUS status;
  329. PIO_STACK_LOCATION irpSp;
  330. AFD_LOCK_QUEUE_HANDLE lockHandle;
  331. irpSp = IoGetCurrentIrpStackLocation (AcceptIrp);
  332. listenEndpoint = irpSp->FileObject->FsContext;
  333. //
  334. // Reenable the accept event bit, and if there are additional
  335. // unaccepted connections on the endpoint, post another event.
  336. //
  337. listenEndpoint->EventsActive &= ~AFD_POLL_ACCEPT;
  338. IF_DEBUG(EVENT_SELECT) {
  339. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  340. "AfdAcceptCore: Endp %08lX, Active %08lX\n",
  341. listenEndpoint,
  342. listenEndpoint->EventsActive
  343. ));
  344. }
  345. if( !IsListEmpty( &listenEndpoint->Common.VcListening.UnacceptedConnectionListHead ) ) {
  346. AfdIndicateEventSelectEvent(
  347. listenEndpoint,
  348. AFD_POLL_ACCEPT,
  349. STATUS_SUCCESS
  350. );
  351. }
  352. //
  353. // Do not release the listening endpoint spinlock here.
  354. // We are going to be chaning connection object which assumes
  355. // protection from listening endpoint spinlock until it is associated
  356. // with accept endpoint (this plugs nasty racing conditions when
  357. // receive is indicated rigth before connection object is updated, so
  358. // it takes listening endpoint spinlock, and rigth before it queues
  359. // the buffer to the connection object, it gets associated with accept
  360. // endpoint and AcceptEx'es receive does not notice the buffer because
  361. // it takes accept endpoint spinlock)
  362. //
  363. // AfdReleaseSpinLock( &ListenEndpoint->SpinLock, &lockHandle );
  364. //
  365. // Check the state of the accepting endpoint under the guard
  366. // of the endpoint's spinlock.
  367. //
  368. AfdAcquireSpinLockAtDpcLevel( &AcceptEndpoint->SpinLock, &lockHandle);
  369. status = AfdSetupAcceptEndpoint (listenEndpoint, AcceptEndpoint, Connection);
  370. if (status==STATUS_SUCCESS) {
  371. if (IS_DELAYED_ACCEPTANCE_ENDPOINT (listenEndpoint)) {
  372. PTDI_CONNECTION_INFORMATION requestConnectionInformation;
  373. if( Connection->ConnectDataBuffers != NULL ) {
  374. //
  375. // We allocated extra space at the end of the connect data
  376. // buffers structure. We'll use this for the
  377. // TDI_CONNECTION_INFORMATION structure that holds response
  378. // connect data and options. Not pretty, but the fastest
  379. // and easiest way to accomplish this.
  380. //
  381. requestConnectionInformation =
  382. &Connection->ConnectDataBuffers->RequestConnectionInfo;
  383. RtlZeroMemory(
  384. requestConnectionInformation,
  385. sizeof(*requestConnectionInformation)
  386. );
  387. requestConnectionInformation->UserData =
  388. Connection->ConnectDataBuffers->SendConnectData.Buffer;
  389. requestConnectionInformation->UserDataLength =
  390. Connection->ConnectDataBuffers->SendConnectData.BufferLength;
  391. requestConnectionInformation->Options =
  392. Connection->ConnectDataBuffers->SendConnectOptions.Buffer;
  393. requestConnectionInformation->OptionsLength =
  394. Connection->ConnectDataBuffers->SendConnectOptions.BufferLength;
  395. } else {
  396. requestConnectionInformation = NULL;
  397. }
  398. TdiBuildAccept(
  399. AcceptIrp,
  400. Connection->DeviceObject,
  401. Connection->FileObject,
  402. NULL,
  403. NULL,
  404. requestConnectionInformation,
  405. NULL
  406. );
  407. status = STATUS_PENDING;
  408. }
  409. else {
  410. //
  411. // Set the endpoint to the connected state.
  412. //
  413. AcceptEndpoint->State = AfdEndpointStateConnected;
  414. Connection->State = AfdConnectionStateConnected;
  415. //
  416. // Set events active field base on data accumulated on the connection.
  417. //
  418. if( IS_DATA_ON_CONNECTION( Connection ) ||
  419. ( AcceptEndpoint->InLine &&
  420. IS_EXPEDITED_DATA_ON_CONNECTION( Connection ) ) ) {
  421. AcceptEndpoint->EventsActive |= AFD_POLL_RECEIVE;
  422. }
  423. if( !AcceptEndpoint->InLine &&
  424. IS_EXPEDITED_DATA_ON_CONNECTION( Connection ) ) {
  425. AcceptEndpoint->EventsActive |= AFD_POLL_RECEIVE_EXPEDITED;
  426. }
  427. AcceptEndpoint->EventsActive |= AFD_POLL_SEND;
  428. if( Connection->DisconnectIndicated ) {
  429. AcceptEndpoint->EventsActive |= AFD_POLL_DISCONNECT;
  430. }
  431. if( Connection->AbortIndicated ) {
  432. AcceptEndpoint->EventsActive |= AFD_POLL_ABORT;
  433. }
  434. IF_DEBUG(EVENT_SELECT) {
  435. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  436. "AfdAcceptCore: Endp %08lX, Active %08lX\n",
  437. AcceptEndpoint,
  438. AcceptEndpoint->EventsActive
  439. ));
  440. }
  441. status = STATUS_SUCCESS;
  442. }
  443. }
  444. AfdReleaseSpinLockFromDpcLevel( &AcceptEndpoint->SpinLock, &lockHandle);
  445. return status;
  446. } // AfdAcceptCore
  447. VOID
  448. AfdInitiateListenBacklogReplenish (
  449. IN PAFD_ENDPOINT Endpoint
  450. )
  451. /*++
  452. Routine Description:
  453. Queues a work item to begin replenishing the listen backlog
  454. on a listening endpoint.
  455. Arguments:
  456. Endpoint - the listening endpoint on which to replenish the
  457. backlog.
  458. Return Value:
  459. None.
  460. --*/
  461. {
  462. AFD_LOCK_QUEUE_HANDLE lockHandle;
  463. //
  464. // Check if backlog replenish is active already.
  465. //
  466. AfdAcquireSpinLock (&Endpoint->SpinLock, &lockHandle);
  467. if (!Endpoint->Common.VcListening.BacklogReplenishActive) {
  468. Endpoint->Common.VcListening.BacklogReplenishActive = TRUE;
  469. //
  470. // Reference the endpoint so that it won't go away until we're
  471. // done with it.
  472. //
  473. REFERENCE_ENDPOINT( Endpoint );
  474. AfdQueueWorkItem(
  475. AfdDoListenBacklogReplenish,
  476. &Endpoint->WorkItem
  477. );
  478. }
  479. AfdReleaseSpinLock (&Endpoint->SpinLock, &lockHandle);
  480. return;
  481. } // AfdInitiateListenBacklogReplenish
  482. VOID
  483. AfdDoListenBacklogReplenish (
  484. IN PVOID Context
  485. )
  486. /*++
  487. Routine Description:
  488. The worker routine for replenishing the listen backlog on a
  489. listening endpoint. This routine only runs in the context of
  490. an executive worker thread.
  491. Arguments:
  492. Context - Points to an AFD_WORK_ITEM structure. The Context field
  493. of this structure points to the endpoint on which to replenish
  494. the listen backlog.
  495. Return Value:
  496. None.
  497. --*/
  498. {
  499. PAFD_ENDPOINT endpoint;
  500. PAGED_CODE( );
  501. endpoint = CONTAINING_RECORD(
  502. Context,
  503. AFD_ENDPOINT,
  504. WorkItem
  505. );
  506. ASSERT( endpoint->Type == AfdBlockTypeVcListening ||
  507. endpoint->Type == AfdBlockTypeVcBoth );
  508. ASSERT (endpoint->Common.VcListening.BacklogReplenishActive == TRUE);
  509. //
  510. // It is ok to do this without spinlock protection
  511. // because only one thread can do this at a time
  512. // inside of the worker routine.
  513. //
  514. endpoint->Common.VcListening.BacklogReplenishActive = FALSE;
  515. //
  516. // If the endpoint's state changed, don't replenish the backlog.
  517. //
  518. if ( endpoint->Listening ) {
  519. NTSTATUS status;
  520. //
  521. // Fill up the free connection backlog.
  522. //
  523. status = AfdReplenishListenBacklog( endpoint );
  524. if (!NT_SUCCESS (status)) {
  525. //
  526. // If we failed, try to notify application
  527. //
  528. AfdReportConnectionAllocationFailure (endpoint, status);
  529. }
  530. }
  531. //
  532. // Clean up and return.
  533. //
  534. DEREFERENCE_ENDPOINT( endpoint );
  535. return;
  536. } // AfdDoListenBacklogReplenish
  537. NTSTATUS
  538. AfdReplenishListenBacklog (
  539. IN PAFD_ENDPOINT Endpoint
  540. )
  541. /*++
  542. Routine Description:
  543. Does the actual work of filling up the listen backlog on a listening
  544. endpoint.
  545. Arguments:
  546. Endpoint - the listening endpoint on which to replenish the
  547. listen backlog.
  548. Return Value:
  549. STATUS_SUCCESS - if new connection was allocated or we already
  550. had enough
  551. status of conneciton allocation failure otherwise
  552. --*/
  553. {
  554. NTSTATUS status;
  555. LONG result;
  556. PAGED_CODE( );
  557. ASSERT( Endpoint->Type == AfdBlockTypeVcListening ||
  558. Endpoint->Type == AfdBlockTypeVcBoth );
  559. //
  560. // Decrement the count of failed connection additions.
  561. //
  562. result = InterlockedDecrement(
  563. &Endpoint->Common.VcListening.FailedConnectionAdds
  564. );
  565. //
  566. // Continue opening new free conections until we've hit the
  567. // backlog or a connection open fails.
  568. //
  569. // If the result of the decrement is negative, then we are either
  570. // all set on the connection count or else have available extra
  571. // connection objects on the listening endpoint. These connections
  572. // have been reused from prior connections which have now
  573. // terminated.
  574. //
  575. while ( result >= 0 ) {
  576. status = AfdAddFreeConnection( Endpoint );
  577. if ( !NT_SUCCESS(status) ) {
  578. InterlockedIncrement(
  579. &Endpoint->Common.VcListening.FailedConnectionAdds
  580. );
  581. IF_DEBUG(LISTEN) {
  582. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  583. "AfdReplenishListenBacklog: AfdAddFreeConnection failed: %X, fail count = %ld\n", status,
  584. Endpoint->Common.VcListening.FailedConnectionAdds ));
  585. }
  586. //
  587. // Return connection allocation failure to the application
  588. // if it cares to know (posted accept request).
  589. //
  590. return status;
  591. }
  592. result = InterlockedDecrement(
  593. &Endpoint->Common.VcListening.FailedConnectionAdds
  594. );
  595. }
  596. //
  597. // Correct the counter to reflect the number of connections
  598. // we have available. Then just return from here.
  599. //
  600. InterlockedIncrement(
  601. &Endpoint->Common.VcListening.FailedConnectionAdds
  602. );
  603. return STATUS_SUCCESS;
  604. } // AfdReplenishListenBacklog
  605. VOID
  606. AfdReportConnectionAllocationFailure (
  607. PAFD_ENDPOINT Endpoint,
  608. NTSTATUS Status
  609. )
  610. /*++
  611. Routine Description:
  612. Reports connection allocation failure to the application by
  613. failing then first wait for listen irp in the queue (if application
  614. has AcceptEx or blockin accept outstanding, it will get this notification).
  615. Arguments:
  616. Endpoint - the listening endpoint on which to report an error
  617. Status - status code to report
  618. Return Value:
  619. None
  620. --*/
  621. {
  622. AFD_LOCK_QUEUE_HANDLE lockHandle;
  623. AfdAcquireSpinLock (&Endpoint->SpinLock, &lockHandle);
  624. if ((Endpoint->Common.VcListening.FailedConnectionAdds>0) &&
  625. IsListEmpty (&Endpoint->Common.VcListening.UnacceptedConnectionListHead) &&
  626. !IsListEmpty (&Endpoint->Common.VcListening.ListeningIrpListHead)) {
  627. PIRP irp;
  628. PIO_STACK_LOCATION irpSp;
  629. irp = CONTAINING_RECORD (Endpoint->Common.VcListening.ListeningIrpListHead.Flink,
  630. IRP,
  631. Tail.Overlay.ListEntry);
  632. irpSp = IoGetCurrentIrpStackLocation (irp);
  633. RemoveEntryList (&irp->Tail.Overlay.ListEntry);
  634. irp->Tail.Overlay.ListEntry.Flink = NULL;
  635. AfdReleaseSpinLock (&Endpoint->SpinLock, &lockHandle);
  636. if (IoSetCancelRoutine (irp, NULL)==NULL) {
  637. KIRQL cancelIrql;
  638. //
  639. // If the cancel routine was NULL then cancel routine
  640. // may be running. Wait on the cancel spinlock until
  641. // the cancel routine is done.
  642. //
  643. // Note: The cancel routine will not find the IRP
  644. // since it is not in the list.
  645. //
  646. IoAcquireCancelSpinLock( &cancelIrql );
  647. ASSERT( irp->Cancel );
  648. IoReleaseCancelSpinLock( cancelIrql );
  649. }
  650. if (irpSp->MajorFunction==IRP_MJ_INTERNAL_DEVICE_CONTROL) {
  651. AfdCleanupSuperAccept (irp, Status);
  652. }
  653. else {
  654. irp->IoStatus.Status = Status;
  655. irp->IoStatus.Information = 0;
  656. }
  657. IoCompleteRequest (irp, AfdPriorityBoost);
  658. }
  659. else {
  660. AfdReleaseSpinLock (&Endpoint->SpinLock, &lockHandle);
  661. }
  662. }
  663. NTSTATUS
  664. FASTCALL
  665. AfdSuperAccept (
  666. IN PIRP Irp,
  667. IN PIO_STACK_LOCATION IrpSp
  668. )
  669. /*++
  670. Routine Description:
  671. Initial entrypoint for handling super accept IRPs. A super accept
  672. combines several operations for high-performance connection
  673. acceptance. The combined operations are waiting for an incoming
  674. connection, accepting it, retrieving the local and remote socket
  675. addresses, and receiving the first chunk of data on the connection.
  676. This routine verifies parameters, initializes data structures to be
  677. used for the request, and initiates the I/O.
  678. Arguments:
  679. Irp - a pointer to a transmit file IRP.
  680. IrpSp - Our stack location for this IRP.
  681. Return Value:
  682. STATUS_PENDING if the request was initiated successfully, or a
  683. failure status code if there was an error.
  684. --*/
  685. {
  686. PAFD_ENDPOINT listenEndpoint;
  687. PAFD_ENDPOINT acceptEndpoint;
  688. PFILE_OBJECT acceptFileObject;
  689. HANDLE acceptHandle;
  690. ULONG receiveDataLength, localAddressLength, remoteAddressLength;
  691. BOOLEAN sanActive;
  692. #ifndef i386
  693. BOOLEAN fixAddressAlignment;
  694. #endif
  695. NTSTATUS status;
  696. ULONG totalLength;
  697. PSINGLE_LIST_ENTRY listEntry;
  698. PAFD_CONNECTION connection;
  699. AFD_LOCK_QUEUE_HANDLE lockHandle;
  700. //
  701. // Set up local variables.
  702. //
  703. listenEndpoint = IrpSp->FileObject->FsContext;
  704. acceptFileObject = NULL;
  705. acceptEndpoint = NULL;
  706. #ifdef _WIN64
  707. if (IoIs32bitProcess (Irp)) {
  708. PAFD_SUPER_ACCEPT_INFO32 superAcceptInfo32;
  709. superAcceptInfo32 = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  710. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  711. sizeof(AFD_SUPER_ACCEPT_INFO32) ) {
  712. status = STATUS_INVALID_PARAMETER;
  713. goto complete;
  714. }
  715. try {
  716. if (Irp->RequestorMode!=KernelMode) {
  717. ProbeForRead (superAcceptInfo32,
  718. sizeof (*superAcceptInfo32),
  719. PROBE_ALIGNMENT32 (AFD_SUPER_ACCEPT_INFO32));
  720. }
  721. acceptHandle = superAcceptInfo32->AcceptHandle;
  722. receiveDataLength = superAcceptInfo32->ReceiveDataLength;
  723. localAddressLength = superAcceptInfo32->LocalAddressLength;
  724. remoteAddressLength = superAcceptInfo32->RemoteAddressLength;
  725. sanActive = superAcceptInfo32->SanActive;
  726. fixAddressAlignment = superAcceptInfo32->FixAddressAlignment;
  727. }
  728. except (AFD_EXCEPTION_FILTER (&status)) {
  729. goto complete;
  730. }
  731. }
  732. else
  733. #endif // _WIN64
  734. {
  735. PAFD_SUPER_ACCEPT_INFO superAcceptInfo;
  736. superAcceptInfo = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  737. try {
  738. if (Irp->RequestorMode!=KernelMode) {
  739. ProbeForRead (superAcceptInfo,
  740. sizeof (*superAcceptInfo),
  741. PROBE_ALIGNMENT (AFD_SUPER_ACCEPT_INFO));
  742. }
  743. acceptHandle = superAcceptInfo->AcceptHandle;
  744. receiveDataLength = superAcceptInfo->ReceiveDataLength;
  745. localAddressLength = superAcceptInfo->LocalAddressLength;
  746. remoteAddressLength = superAcceptInfo->RemoteAddressLength;
  747. sanActive = superAcceptInfo->SanActive;
  748. #ifndef i386
  749. fixAddressAlignment = superAcceptInfo->FixAddressAlignment;
  750. #endif
  751. }
  752. except (AFD_EXCEPTION_FILTER (&status)) {
  753. goto complete;
  754. }
  755. }
  756. //
  757. // Check for if the caller is unaware of the SAN
  758. // provider activation and report the error.
  759. //
  760. if (!sanActive && AfdSanServiceHelper!=NULL) {
  761. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  762. "AFD: Process %p is being told to enable SAN on AcceptEx\n",
  763. PsGetCurrentProcessId ()));
  764. status = STATUS_INVALID_PARAMETER_12;
  765. goto complete;
  766. }
  767. //
  768. // Validate the input information. The input buffer must be large
  769. // enough to hold all the input information, plus some extra to use
  770. // here to hold the local address. The output buffer must be
  771. // non-NULL and large enough to hold the specified information.
  772. //
  773. //
  774. if ( !listenEndpoint->Listening
  775. ||
  776. remoteAddressLength < (ULONG)FIELD_OFFSET (TRANSPORT_ADDRESS,
  777. Address[0].Address)
  778. ||
  779. //
  780. // Do the check in such a manner that integer overflow
  781. // (which is not enabled by the compiler) does not
  782. // affect the validity of the result.
  783. //
  784. (totalLength=IrpSp->Parameters.DeviceIoControl.OutputBufferLength)<
  785. receiveDataLength
  786. ||
  787. (totalLength-=receiveDataLength) < localAddressLength
  788. ||
  789. (totalLength-=localAddressLength) < remoteAddressLength
  790. ) {
  791. if( !listenEndpoint->Listening ) {
  792. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  793. "AfdSuperAccept: non-listening endpoint @ %08lX\n",
  794. listenEndpoint
  795. ));
  796. status = STATUS_INVALID_PARAMETER;
  797. }
  798. else {
  799. status = STATUS_BUFFER_TOO_SMALL;
  800. }
  801. goto complete;
  802. }
  803. try {
  804. if (IoAllocateMdl(Irp->UserBuffer,
  805. IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  806. FALSE, // Secondary buffer
  807. TRUE, // Charge quota
  808. Irp
  809. )==NULL) {
  810. status = STATUS_INSUFFICIENT_RESOURCES;
  811. goto complete;
  812. }
  813. MmProbeAndLockPages (Irp->MdlAddress, Irp->RequestorMode, IoWriteAccess);
  814. }
  815. except (AFD_EXCEPTION_FILTER (&status)) {
  816. goto complete;
  817. }
  818. ASSERT ((listenEndpoint->Type & AfdBlockTypeVcListening) == AfdBlockTypeVcListening);
  819. //
  820. // Obtain a pointer to the endpoint on which we're going to
  821. // accept the connection.
  822. //
  823. status = ObReferenceObjectByHandle(
  824. acceptHandle,
  825. (IrpSp->Parameters.DeviceIoControl.IoControlCode>>14) & 3,
  826. // DesiredAccess
  827. *IoFileObjectType,
  828. Irp->RequestorMode,
  829. &acceptFileObject,
  830. NULL
  831. );
  832. if ( !NT_SUCCESS(status) ) {
  833. goto complete;
  834. }
  835. //
  836. // We may have a file object that is not an AFD endpoint. Make sure
  837. // that this is an actual AFD endpoint.
  838. //
  839. if (acceptFileObject->DeviceObject!= AfdDeviceObject) {
  840. status = STATUS_INVALID_HANDLE;
  841. goto complete;
  842. }
  843. acceptEndpoint = acceptFileObject->FsContext;
  844. ASSERT( InterlockedIncrement( &acceptEndpoint->ObReferenceBias ) > 0 );
  845. if (!AFD_START_STATE_CHANGE (acceptEndpoint, AfdEndpointStateConnected)) {
  846. status = STATUS_INVALID_PARAMETER;
  847. goto complete;
  848. }
  849. if (acceptEndpoint->TransportInfo!=listenEndpoint->TransportInfo ||
  850. acceptEndpoint->State != AfdEndpointStateOpen ) {
  851. status = STATUS_INVALID_PARAMETER;
  852. goto complete_state_change;
  853. }
  854. #ifndef i386
  855. acceptEndpoint->Common.VcConnecting.FixAddressAlignment = fixAddressAlignment;
  856. #endif
  857. Irp->Tail.Overlay.DriverContext[3] = acceptHandle;
  858. //
  859. // Save common IRP parameters in our stack location so
  860. // we can retreive them when necessary
  861. //
  862. IrpSp->Parameters.AfdRestartSuperAcceptInfo.AfdAcceptFileObject = acceptFileObject;
  863. IrpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength = receiveDataLength;
  864. IrpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength = localAddressLength;
  865. IrpSp->Parameters.AfdRestartSuperAcceptInfo.AfdRemoteAddressLength = remoteAddressLength;
  866. //
  867. // Add another free connection to replace the one we're accepting.
  868. // Also, add extra to account for past failures in calls to
  869. // AfdAddFreeConnection().
  870. //
  871. InterlockedIncrement(
  872. &listenEndpoint->Common.VcListening.FailedConnectionAdds
  873. );
  874. status = AfdReplenishListenBacklog( listenEndpoint );
  875. //
  876. // Save the IRP, so that accept enpoint cleanup can find it.
  877. // Note, that even if found, the cleanup won't touch the IRP
  878. // until cancel routine is set in it.
  879. //
  880. ASSERT (acceptEndpoint->Irp==NULL);
  881. acceptEndpoint->Irp = Irp;
  882. //
  883. // Get free connection from the list, if none is available,
  884. // or direct super accept is disabled, go through the regular
  885. // listen-accept path.
  886. //
  887. if (AfdDisableDirectSuperAccept ||
  888. IS_DELAYED_ACCEPTANCE_ENDPOINT (listenEndpoint) ||
  889. ExQueryDepthSList (&listenEndpoint->Common.VcListening.PreacceptedConnectionsListHead)
  890. > AFD_MAXIMUM_FREE_CONNECTIONS ||
  891. ((listEntry = InterlockedPopEntrySList (
  892. &listenEndpoint->Common.VcListening.FreeConnectionListHead
  893. ))==NULL)) {
  894. //
  895. // Setup super accept IRP to be put into the wait for
  896. // listen queue. Internal device control distinguishes this
  897. // from the regular wait for listen IRPs that come directly
  898. // from the application.
  899. //
  900. IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  901. //
  902. // Mark this IRP as pending since we are going to return
  903. // STATUS_PENDING no matter what (sometimes the actual
  904. // status is hidden very deep inside the call stack and
  905. // it is impossible to propagate it all the way up).
  906. //
  907. IoMarkIrpPending (Irp);
  908. AfdWaitForListen (Irp, IrpSp);
  909. //
  910. // If connection allocation failed above, we need to report
  911. // this to application. We delay this call in case there is
  912. // already a preaccepted connection, so the allocation failure
  913. // is not important.
  914. //
  915. if (!NT_SUCCESS (status)) {
  916. AfdReportConnectionAllocationFailure (listenEndpoint, status);
  917. }
  918. return STATUS_PENDING;
  919. }
  920. //
  921. // Get connection object of the list entry
  922. //
  923. connection = CONTAINING_RECORD(
  924. listEntry,
  925. AFD_CONNECTION,
  926. SListEntry
  927. );
  928. //
  929. // Stuff special constant into the connection object accept IRP
  930. // pointer, so that cancel routine does not complete the IRP
  931. // while we are still looking at it, but in the same time we
  932. // can detect that the IRP was cancelled (cancel routine will
  933. // replace the -1 with NULL to indicate that it has been ran).
  934. // This technique avoids extra spinlock acquire/release and
  935. // associated IRQL raise/lower on an extremely performance-sensitive
  936. // code path.
  937. //
  938. connection->AcceptIrp = (PIRP)-1;
  939. Irp->Tail.Overlay.DriverContext[0] = connection;
  940. //
  941. // We are going to pend this Irp, so mark it as pending
  942. // and set up the cancel routine.
  943. //
  944. IoMarkIrpPending (Irp);
  945. IoSetCancelRoutine( Irp, AfdCancelSuperAccept );
  946. //
  947. // Check if the IRP has already been canceled.
  948. // If the cancel routine ran, it just reset the connection
  949. // object accept pointer to NULL (instead of -1 that we stuffed
  950. // in it above), but it did not complete the IRP.
  951. //
  952. if ( !Irp->Cancel &&
  953. (InterlockedCompareExchangePointer (
  954. (PVOID *)&connection->AcceptIrp,
  955. Irp,
  956. (PVOID)-1)==(PVOID)-1)) {
  957. //
  958. // Can't touch the IRP after this point since it may have already
  959. // been canceled.
  960. //
  961. DEBUG Irp = NULL;
  962. //
  963. // Push the connection and associated Irp/endpoint
  964. // onto preaccepted connection list.
  965. //
  966. if (InterlockedPushEntrySList(
  967. &listenEndpoint->Common.VcListening.PreacceptedConnectionsListHead,
  968. &connection->SListEntry
  969. )==NULL) {
  970. //
  971. // This is the first Irp in the list, we need to check
  972. // if there are any unaccepted connections that we
  973. // can use to satisfy super accept.
  974. //
  975. AfdAcquireSpinLock (&listenEndpoint->SpinLock, &lockHandle);
  976. if (!listenEndpoint->EndpointCleanedUp) {
  977. LIST_ENTRY irpList;
  978. InitializeListHead (&irpList);
  979. //
  980. // First see if there is an unaccepted connection
  981. //
  982. while (!IsListEmpty (&listenEndpoint->Common.VcListening.UnacceptedConnectionListHead)) {
  983. connection = CONTAINING_RECORD(
  984. listenEndpoint->Common.VcListening.UnacceptedConnectionListHead.Flink,
  985. AFD_CONNECTION,
  986. ListEntry
  987. );
  988. RemoveEntryList (&connection->ListEntry);
  989. //
  990. // Now make sure we still have super accept irp
  991. //
  992. if (AfdServiceSuperAccept (listenEndpoint, connection, &lockHandle, &irpList)) {
  993. //
  994. // The routine has found and completed super accept IRP
  995. // Reaquire a spinlock and continue searching for more.
  996. //
  997. AfdAcquireSpinLock (&listenEndpoint->SpinLock, &lockHandle);
  998. }
  999. else {
  1000. //
  1001. // No super accept Irps, put connection back onto the list
  1002. // while we are still holding the lock and bail out.
  1003. //
  1004. InsertHeadList (&listenEndpoint->Common.VcListening.UnacceptedConnectionListHead,
  1005. &connection->ListEntry);
  1006. break;
  1007. }
  1008. }
  1009. AfdReleaseSpinLock (&listenEndpoint->SpinLock, &lockHandle);
  1010. //
  1011. // Complete failed super accept IRPs (if any)
  1012. //
  1013. if (!IsListEmpty (&irpList)) {
  1014. KIRQL cancelIrql;
  1015. //
  1016. // Make sure cancel routines will
  1017. // not access the completed IRPs
  1018. //
  1019. IoAcquireCancelSpinLock (&cancelIrql);
  1020. IoReleaseCancelSpinLock (cancelIrql);
  1021. while (!IsListEmpty (&irpList)) {
  1022. PIRP irp;
  1023. irp = CONTAINING_RECORD (irpList.Flink, IRP, Tail.Overlay.ListEntry);
  1024. RemoveEntryList (&irp->Tail.Overlay.ListEntry);
  1025. IoCompleteRequest (irp, AfdPriorityBoost);
  1026. }
  1027. }
  1028. }
  1029. else {
  1030. AfdReleaseSpinLock (&listenEndpoint->SpinLock, &lockHandle);
  1031. AfdFreeQueuedConnections (listenEndpoint);
  1032. }
  1033. }
  1034. else {
  1035. USHORT depth =
  1036. ExQueryDepthSList (&listenEndpoint->Common.VcListening.PreacceptedConnectionsListHead);
  1037. if (depth > listenEndpoint->Common.VcListening.MaxExtraConnections) {
  1038. //
  1039. // Update under the lock, so we do not corrupt
  1040. // other fields in the same memory access granularity unit.
  1041. // This should be infrequent operation anyway.
  1042. //
  1043. AfdAcquireSpinLock (&listenEndpoint->SpinLock, &lockHandle);
  1044. listenEndpoint->Common.VcListening.MaxExtraConnections = depth;
  1045. AfdReleaseSpinLock (&listenEndpoint->SpinLock, &lockHandle);
  1046. }
  1047. }
  1048. }
  1049. else {
  1050. //
  1051. // Reset and call the cancel routine, since
  1052. // even if cancel routine ran, it could not complete
  1053. // the irp because it was not set in the connection
  1054. // object. Note that cancel routine is done with the IRP
  1055. // once it releases cancel spinlock which we acquire here.
  1056. //
  1057. AfdCleanupSuperAccept (Irp, STATUS_CANCELLED);
  1058. if (IoSetCancelRoutine (Irp, NULL)==NULL) {
  1059. KIRQL cancelIrql;
  1060. IoAcquireCancelSpinLock (&cancelIrql);
  1061. IoReleaseCancelSpinLock (cancelIrql);
  1062. }
  1063. IoCompleteRequest (Irp, AfdPriorityBoost);
  1064. //
  1065. // We have to return pending because we have already
  1066. // marked the Irp as pending.
  1067. //
  1068. }
  1069. return STATUS_PENDING;
  1070. complete_state_change:
  1071. AFD_END_STATE_CHANGE (acceptEndpoint);
  1072. complete:
  1073. if ( acceptFileObject != NULL ) {
  1074. if (acceptEndpoint!=NULL) {
  1075. ASSERT( InterlockedDecrement( &acceptEndpoint->ObReferenceBias ) >= 0 );
  1076. }
  1077. ObDereferenceObject( acceptFileObject );
  1078. }
  1079. //
  1080. // Free MDL here as IO system can't do it if it is
  1081. // not locked.
  1082. //
  1083. if (Irp->MdlAddress!=NULL) {
  1084. if (Irp->MdlAddress->MdlFlags & MDL_PAGES_LOCKED) {
  1085. MmUnlockPages (Irp->MdlAddress);
  1086. }
  1087. IoFreeMdl (Irp->MdlAddress);
  1088. Irp->MdlAddress = NULL;
  1089. }
  1090. Irp->IoStatus.Information = 0;
  1091. Irp->IoStatus.Status = status;
  1092. IoCompleteRequest( Irp, 0 );
  1093. return status;
  1094. } // AfdSuperAccept
  1095. NTSTATUS
  1096. AfdRestartSuperAccept (
  1097. IN PDEVICE_OBJECT DeviceObject,
  1098. IN PIRP Irp,
  1099. IN PVOID Context
  1100. )
  1101. /*++
  1102. Routine Description:
  1103. The completion routine for the AFD wait for listen IRP portion
  1104. of a super accept.
  1105. Arguments:
  1106. DeviceObject - the devoce object on which the request is completing.
  1107. Irp - The super accept IRP.
  1108. Context - points to accept file object.
  1109. Return Value:
  1110. STATUS_SUCCESS if the I/O system should complete the super accept
  1111. request, or STATUS_MORE_PROCESSING_REQUIRED if the super accept
  1112. request is still being processed.
  1113. --*/
  1114. {
  1115. PAFD_ENDPOINT listenEndpoint;
  1116. PFILE_OBJECT acceptFileObject;
  1117. PAFD_ENDPOINT acceptEndpoint;
  1118. PAFD_CONNECTION connection;
  1119. PIO_STACK_LOCATION irpSp;
  1120. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1121. //
  1122. // Initialize some locals.
  1123. //
  1124. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1125. listenEndpoint = irpSp->FileObject->FsContext;
  1126. acceptFileObject = Context;
  1127. acceptEndpoint = acceptFileObject->FsContext;
  1128. ASSERT (IS_AFD_ENDPOINT_TYPE (acceptEndpoint));
  1129. connection = acceptEndpoint->Common.VcConnecting.Connection;
  1130. ASSERT (connection->Type==AfdBlockTypeConnection);
  1131. ASSERT (connection->Endpoint==acceptEndpoint);
  1132. //
  1133. // Overwrite listen file object with accept file object
  1134. // since we won't be using listen file object anymore,
  1135. // while we still need to deference accept file object
  1136. // upon IRP completion.
  1137. //
  1138. irpSp->FileObject = acceptFileObject;
  1139. //
  1140. // Fix up the MDL pointer in the IRP.
  1141. //
  1142. ASSERT (Irp->MdlAddress==NULL);
  1143. Irp->MdlAddress = irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdMdlAddress;
  1144. //
  1145. // If pending has been returned for this irp then mark the current
  1146. // stack as pending.
  1147. //
  1148. if ( Irp->PendingReturned ) {
  1149. IoMarkIrpPending( Irp );
  1150. }
  1151. //
  1152. // Remember that a TDI accept has completed on this endpoint.
  1153. //
  1154. InterlockedDecrement(
  1155. &listenEndpoint->Common.VcListening.TdiAcceptPendingCount
  1156. );
  1157. connection->ConnectTime = KeQueryInterruptTime();
  1158. if ( NT_SUCCESS(Irp->IoStatus.Status)) {
  1159. //
  1160. // Set the endpoint to the connected state.
  1161. //
  1162. AfdAcquireSpinLock (&acceptEndpoint->SpinLock, &lockHandle);
  1163. acceptEndpoint->State = AfdEndpointStateConnected;
  1164. connection->State = AfdConnectionStateConnected;
  1165. acceptEndpoint->EventsActive |= AFD_POLL_SEND;
  1166. //
  1167. // Reference connection to prevent it from going away during
  1168. // accept process as the result of transmit file completion.
  1169. // (transmit file can now occur at any time since we
  1170. // marked the endpoint as connected and about to end state change)
  1171. //
  1172. REFERENCE_CONNECTION (connection);
  1173. AfdReleaseSpinLock (&acceptEndpoint->SpinLock, &lockHandle);
  1174. AFD_END_STATE_CHANGE(acceptEndpoint);
  1175. return AfdContinueSuperAccept (Irp, connection);
  1176. }
  1177. else {
  1178. //
  1179. // If the accept failed, treat it like an abortive disconnect.
  1180. // This way the application still gets a new endpoint, but it gets
  1181. // told about the reset.
  1182. //
  1183. AFD_END_STATE_CHANGE(acceptEndpoint);
  1184. AfdDisconnectEventHandler(
  1185. NULL,
  1186. connection,
  1187. 0,
  1188. NULL,
  1189. 0,
  1190. NULL,
  1191. TDI_DISCONNECT_ABORT
  1192. );
  1193. ASSERT( InterlockedDecrement( &acceptEndpoint->ObReferenceBias ) >= 0 );
  1194. ObDereferenceObject( acceptFileObject );
  1195. //
  1196. // Check if we have secondary MDL for local address query and
  1197. // free it.
  1198. //
  1199. if (Irp->MdlAddress->Next!=NULL) {
  1200. //
  1201. // We never lock pages for this one (they are locked
  1202. // as part of main MDL).
  1203. //
  1204. ASSERT (irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength>0);
  1205. ASSERT ((Irp->MdlAddress->Next->MdlFlags & MDL_PAGES_LOCKED)==0);
  1206. IoFreeMdl (Irp->MdlAddress->Next);
  1207. Irp->MdlAddress->Next = NULL;
  1208. }
  1209. return STATUS_SUCCESS;
  1210. }
  1211. } // AfdRestartSuperAccept
  1212. VOID
  1213. AfdRestartSuperAcceptListen (
  1214. IN PIRP Irp,
  1215. IN PAFD_CONNECTION Connection
  1216. )
  1217. /*++
  1218. Routine Description:
  1219. The completion routine for the AFD wait for listen IRP portion
  1220. of a super accept.
  1221. Arguments:
  1222. Irp - The super accept IRP.
  1223. Connection - points to the connection object
  1224. Return Value:
  1225. None
  1226. --*/
  1227. {
  1228. PAFD_ENDPOINT acceptEndpoint;
  1229. PIO_STACK_LOCATION irpSp;
  1230. NTSTATUS status;
  1231. //
  1232. // Initialize some locals.
  1233. //
  1234. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1235. acceptEndpoint = irpSp->FileObject->FsContext;
  1236. ASSERT (IS_AFD_ENDPOINT_TYPE (acceptEndpoint));
  1237. AFD_END_STATE_CHANGE(acceptEndpoint);
  1238. //
  1239. // Fix up the system buffer and MDL pointers in the IRP.
  1240. //
  1241. ASSERT (Irp->MdlAddress==NULL);
  1242. ASSERT (Irp->AssociatedIrp.SystemBuffer == NULL);
  1243. Irp->MdlAddress = irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdMdlAddress;
  1244. //
  1245. // This routine shouldn't have been called if accept failed
  1246. //
  1247. ASSERT ( NT_SUCCESS(Irp->IoStatus.Status) );
  1248. //
  1249. // Reference connection to prevent it from going away during
  1250. // accept process as the result of transmit file completion.
  1251. // (transmit file can now occur at any time since we
  1252. // marked the endpoint as connected and about to end state change)
  1253. //
  1254. REFERENCE_CONNECTION (Connection);
  1255. status = AfdContinueSuperAccept (Irp, Connection);
  1256. //
  1257. // If completion routine return anything other
  1258. // than STATUS_MORE_PROCESSING_REQUIRED, the IRP
  1259. // is ready to be completed. Otherwise, is was
  1260. // reused to call transport driver and will be completed
  1261. // by the driver. Note that in the latter case
  1262. // the IRP cannot be touched because
  1263. // it could have been completed inside of the
  1264. // completion routine or by the driver before the
  1265. // completion routine returned.
  1266. //
  1267. if (status!=STATUS_MORE_PROCESSING_REQUIRED) {
  1268. IoCompleteRequest (Irp, AfdPriorityBoost);
  1269. }
  1270. } // AfdRestartSuperAcceptListen
  1271. NTSTATUS
  1272. AfdRestartDelayedSuperAccept (
  1273. IN PDEVICE_OBJECT DeviceObject,
  1274. IN PIRP Irp,
  1275. IN PVOID Context
  1276. )
  1277. /*++
  1278. Routine Description:
  1279. The completion routine for the AFD wait for delayed accept IRP portion
  1280. of a super accept.
  1281. Arguments:
  1282. DeviceObject - the devoce object on which the request is completing.
  1283. Irp - The super accept IRP.
  1284. Context - points to accept file object
  1285. Return Value:
  1286. STATUS_SUCCESS if the I/O system should complete the super accept
  1287. request, or STATUS_MORE_PROCESSING_REQUIRED if the super accept
  1288. request is still being processed.
  1289. --*/
  1290. {
  1291. PAFD_ENDPOINT listenEndpoint;
  1292. PFILE_OBJECT acceptFileObject;
  1293. PAFD_ENDPOINT acceptEndpoint;
  1294. PAFD_CONNECTION connection;
  1295. PIO_STACK_LOCATION irpSp;
  1296. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1297. //
  1298. // Initialize some locals.
  1299. //
  1300. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1301. listenEndpoint = irpSp->FileObject->FsContext;
  1302. acceptFileObject = Context;
  1303. acceptEndpoint = acceptFileObject->FsContext;
  1304. ASSERT (IS_AFD_ENDPOINT_TYPE (acceptEndpoint));
  1305. //
  1306. // Overwrite listen file object with accept file object
  1307. // since we won't be using listen file object anymore,
  1308. // while we still need to deference accept file object
  1309. // upon IRP completion.
  1310. //
  1311. irpSp->FileObject = acceptFileObject;
  1312. //
  1313. // Fix up the MDL pointer in the IRP.
  1314. //
  1315. ASSERT (Irp->MdlAddress==NULL);
  1316. Irp->MdlAddress = irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdMdlAddress;
  1317. AfdCompleteOutstandingIrp (acceptEndpoint, Irp);
  1318. //
  1319. // If pending has been returned for this irp then mark the current
  1320. // stack as pending.
  1321. //
  1322. if ( Irp->PendingReturned ) {
  1323. IoMarkIrpPending( Irp );
  1324. }
  1325. //
  1326. // Remember that a TDI accept has completed on this endpoint.
  1327. //
  1328. InterlockedDecrement(
  1329. &listenEndpoint->Common.VcListening.TdiAcceptPendingCount
  1330. );
  1331. AfdAcquireSpinLock (&acceptEndpoint->SpinLock, &lockHandle);
  1332. //
  1333. // The AFD connection object should now be in the endpoiont.
  1334. //
  1335. connection = AFD_CONNECTION_FROM_ENDPOINT( acceptEndpoint );
  1336. if (connection!=NULL) {
  1337. //
  1338. // If the IRP failed, quit processing.
  1339. //
  1340. if ( NT_SUCCESS(Irp->IoStatus.Status) ) {
  1341. acceptEndpoint->State = AfdEndpointStateConnected;
  1342. connection->State = AfdConnectionStateConnected;
  1343. acceptEndpoint->EventsActive |= AFD_POLL_SEND;
  1344. //
  1345. // Reference connection to prevent it from going away during
  1346. // accept process as the result of transmit file completion.
  1347. // (transmit file can now occur at any time since we
  1348. // marked the endpoint as connected and about to end state change)
  1349. //
  1350. REFERENCE_CONNECTION (connection);
  1351. AfdReleaseSpinLock (&acceptEndpoint->SpinLock, &lockHandle);
  1352. AFD_END_STATE_CHANGE(acceptEndpoint);
  1353. return AfdContinueSuperAccept (Irp, connection);
  1354. }
  1355. else {
  1356. //
  1357. // If the accept failed, treat it like an abortive disconnect.
  1358. // This way the application still gets a new endpoint, but it gets
  1359. // told about the reset.
  1360. //
  1361. AfdReleaseSpinLock (&acceptEndpoint->SpinLock, &lockHandle);
  1362. AFD_END_STATE_CHANGE(acceptEndpoint);
  1363. AfdDisconnectEventHandler(
  1364. NULL,
  1365. connection,
  1366. 0,
  1367. NULL,
  1368. 0,
  1369. NULL,
  1370. TDI_DISCONNECT_ABORT
  1371. );
  1372. ASSERT( InterlockedDecrement( &acceptEndpoint->ObReferenceBias ) >= 0 );
  1373. ObDereferenceObject( acceptFileObject );
  1374. //
  1375. // After dereferencing file object we shouldn't be accessing it
  1376. // or associated endpoint structure
  1377. //
  1378. }
  1379. }
  1380. else {
  1381. // this could happed if transmit file cleaned up the object
  1382. // really quickly somehow,
  1383. AfdReleaseSpinLock (&acceptEndpoint->SpinLock, &lockHandle);
  1384. ASSERT( InterlockedDecrement( &acceptEndpoint->ObReferenceBias ) >= 0 );
  1385. ObDereferenceObject( acceptFileObject );
  1386. //
  1387. // After dereferencing file object we shouldn't be accessing it
  1388. // or associated endpoint structure
  1389. //
  1390. }
  1391. //
  1392. // Check if we have secondary MDL for local address query and
  1393. // free it.
  1394. //
  1395. if (Irp->MdlAddress->Next!=NULL) {
  1396. //
  1397. // We never lock pages for this one (they are locked
  1398. // as part of main MDL).
  1399. //
  1400. ASSERT (irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength>0);
  1401. ASSERT ((Irp->MdlAddress->Next->MdlFlags & MDL_PAGES_LOCKED)==0);
  1402. IoFreeMdl (Irp->MdlAddress->Next);
  1403. Irp->MdlAddress->Next = NULL;
  1404. }
  1405. return STATUS_SUCCESS;
  1406. } // AfdRestartDelayedSuperAccept
  1407. NTSTATUS
  1408. AfdContinueSuperAccept (
  1409. IN PIRP Irp,
  1410. PAFD_CONNECTION Connection
  1411. )
  1412. /*++
  1413. Routine Description:
  1414. Continues super accept IRP processing after the initial accept
  1415. phase by requesting local address and/or first portion of the
  1416. received data.
  1417. Arguments:
  1418. Irp - a pointer to the super accept IRP
  1419. Connection - pointer to the accepted connection
  1420. Return Value:
  1421. STATUS_SUCCESS if Irp processing is completed
  1422. STATUS_MORE_PROCESSING_REQUIRED if it submits another request
  1423. and processing will ocurr in the completion routine.
  1424. --*/
  1425. {
  1426. PAFD_ENDPOINT acceptEndpoint;
  1427. PIO_STACK_LOCATION irpSp;
  1428. ULONG length;
  1429. //
  1430. // Initialize locals
  1431. //
  1432. irpSp = IoGetCurrentIrpStackLocation (Irp);
  1433. acceptEndpoint = irpSp->FileObject->FsContext;
  1434. //
  1435. // See if we need to get local address.
  1436. //
  1437. if (irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength>0) {
  1438. ASSERT (Irp->MdlAddress->Next!=NULL);
  1439. //
  1440. // Get the MDL that describes local address part of the user buffer
  1441. // The oritinal mdl chain address is safe in our stack location
  1442. //
  1443. Irp->MdlAddress = Irp->MdlAddress->Next;
  1444. //
  1445. // Unchain the address MDL from the receive MDL - we will
  1446. // free it upon completion of the address query operation
  1447. //
  1448. ((PMDL)irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdMdlAddress)->Next = NULL;
  1449. ASSERT (irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength
  1450. == MmGetMdlByteCount (Irp->MdlAddress));
  1451. IoBuildPartialMdl (
  1452. irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdMdlAddress,
  1453. Irp->MdlAddress,
  1454. MmGetMdlVirtualAddress (Irp->MdlAddress),
  1455. MmGetMdlByteCount (Irp->MdlAddress)
  1456. );
  1457. TdiBuildQueryInformation(
  1458. Irp,
  1459. Connection->DeviceObject,
  1460. Connection->FileObject,
  1461. AfdRestartSuperAcceptGetAddress,
  1462. Connection,
  1463. TDI_QUERY_ADDRESS_INFO,
  1464. Irp->MdlAddress
  1465. );
  1466. //
  1467. // Perform the local address query. We'll continue processing from
  1468. // the completion routine.
  1469. //
  1470. AfdIoCallDriver( acceptEndpoint, Connection->DeviceObject, Irp );
  1471. return STATUS_MORE_PROCESSING_REQUIRED;
  1472. }
  1473. //
  1474. // See if want to get first portion of the data
  1475. //
  1476. else if (irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength>0) {
  1477. PIO_STACK_LOCATION nextIrpSp;
  1478. ASSERT (Irp->MdlAddress->Next==NULL);
  1479. //
  1480. // Get the length of the receive portion of the buffer
  1481. // and save the length of the MDL to restore in the completion routine
  1482. // Set the length of the MDL to match that of the receive request
  1483. //
  1484. length = irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength;
  1485. irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength =
  1486. MmGetMdlByteCount (Irp->MdlAddress);
  1487. Irp->MdlAddress->ByteCount = length;
  1488. //
  1489. // Prepare the IRP to be used to receive the first chunk of data on
  1490. // the connection.
  1491. //
  1492. // Also note that we send ourselves an IRP_MJ_READ IRP because
  1493. // the I/O subsystem has already probed & locked the output buffer,
  1494. // which just happens to look just like an IRP_MJ_READ IRP.
  1495. //
  1496. nextIrpSp = IoGetNextIrpStackLocation( Irp );
  1497. nextIrpSp->FileObject = irpSp->FileObject;
  1498. nextIrpSp->DeviceObject = IoGetRelatedDeviceObject( nextIrpSp->FileObject );
  1499. nextIrpSp->MajorFunction = IRP_MJ_READ;
  1500. nextIrpSp->Parameters.Read.Length = length;
  1501. nextIrpSp->Parameters.Read.Key = 0;
  1502. nextIrpSp->Parameters.Read.ByteOffset.QuadPart = 0;
  1503. IoSetCompletionRoutine(
  1504. Irp,
  1505. AfdRestartSuperAcceptReceive,
  1506. Connection,
  1507. TRUE,
  1508. TRUE,
  1509. TRUE
  1510. );
  1511. //
  1512. // Perform the receive. We'll continue processing from
  1513. // the completion routine.
  1514. //
  1515. AfdIoCallDriver( acceptEndpoint, nextIrpSp->DeviceObject, Irp );
  1516. return STATUS_MORE_PROCESSING_REQUIRED;
  1517. }
  1518. Irp->IoStatus.Information = 0;
  1519. if (Connection->AbortIndicated && NT_SUCCESS (Irp->IoStatus.Status)) {
  1520. Irp->IoStatus.Status = STATUS_CONNECTION_RESET;
  1521. }
  1522. if (NT_SUCCESS (Irp->IoStatus.Status) &&
  1523. (Connection->RemoteAddress!=NULL) &&
  1524. (KeInitializeApc (&acceptEndpoint->Common.VcConnecting.Apc,
  1525. PsGetThreadTcb (Irp->Tail.Overlay.Thread),
  1526. Irp->ApcEnvironment,
  1527. AfdSuperAcceptApcKernelRoutine,
  1528. AfdSuperAcceptApcRundownRoutine,
  1529. (PKNORMAL_ROUTINE)NULL,
  1530. KernelMode,
  1531. NULL
  1532. ),
  1533. KeInsertQueueApc (&acceptEndpoint->Common.VcConnecting.Apc,
  1534. Irp,
  1535. Connection,
  1536. AfdPriorityBoost))) {
  1537. return STATUS_MORE_PROCESSING_REQUIRED;
  1538. }
  1539. else {
  1540. //
  1541. // Dereference the accept file object and tell IO to complete this IRP.
  1542. //
  1543. ASSERT( InterlockedDecrement( &acceptEndpoint->ObReferenceBias ) >= 0 );
  1544. ObDereferenceObject( irpSp->FileObject );
  1545. //
  1546. // After dereferencing file object we shouldn't be accessing it
  1547. // or associated endpoint structure
  1548. //
  1549. DEREFERENCE_CONNECTION (Connection);
  1550. return STATUS_SUCCESS;
  1551. }
  1552. }
  1553. NTSTATUS
  1554. AfdRestartSuperAcceptGetAddress (
  1555. IN PDEVICE_OBJECT DeviceObject,
  1556. IN PIRP Irp,
  1557. IN PVOID Context
  1558. )
  1559. /*++
  1560. Routine Description:
  1561. The completion routine for the AFD wait for query local address
  1562. portion of a super accept.
  1563. Arguments:
  1564. DeviceObject - the devoce object on which the request is completing.
  1565. Irp - The super accept IRP.
  1566. Context - points to the accepted connection
  1567. Return Value:
  1568. STATUS_SUCCESS if the I/O system should complete the super accept
  1569. request, or STATUS_MORE_PROCESSING_REQUIRED if the super accept
  1570. request is still being processed.
  1571. --*/
  1572. {
  1573. PAFD_ENDPOINT acceptEndpoint;
  1574. PAFD_CONNECTION connection;
  1575. PIO_STACK_LOCATION irpSp;
  1576. //
  1577. // Initialize some locals.
  1578. //
  1579. irpSp = IoGetCurrentIrpStackLocation (Irp);
  1580. acceptEndpoint = irpSp->FileObject->FsContext;
  1581. ASSERT (IS_AFD_ENDPOINT_TYPE (acceptEndpoint));
  1582. connection = Context;
  1583. ASSERT (connection->Type==AfdBlockTypeConnection);
  1584. ASSERT (connection->Endpoint==acceptEndpoint);
  1585. AfdCompleteOutstandingIrp (acceptEndpoint, Irp);
  1586. //
  1587. // If pending has been returned for this irp then mark the current
  1588. // stack as pending.
  1589. //
  1590. if ( Irp->PendingReturned ) {
  1591. IoMarkIrpPending( Irp );
  1592. }
  1593. ASSERT (Irp->MdlAddress->MdlFlags & MDL_PARTIAL);
  1594. IoFreeMdl( Irp->MdlAddress );
  1595. //
  1596. // Fix up the MDL pointer in the IRP and set local address length
  1597. // to 0 to use the common routine for receive part of the super
  1598. // accept Irp
  1599. //
  1600. Irp->MdlAddress = irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdMdlAddress;
  1601. if (NT_SUCCESS (Irp->IoStatus.Status)) {
  1602. #ifndef i386
  1603. if (acceptEndpoint->Common.VcConnecting.FixAddressAlignment) {
  1604. PTDI_ADDRESS_INFO addressInfo = (PVOID)
  1605. ((PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress)
  1606. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength);
  1607. USHORT addressLength = addressInfo->Address.Address[0].AddressLength+sizeof(USHORT);
  1608. USHORT UNALIGNED *pAddrLength = (PVOID)
  1609. ((PUCHAR)addressInfo
  1610. +irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength
  1611. -sizeof(USHORT));
  1612. RtlMoveMemory (addressInfo,
  1613. &addressInfo->Address.Address[0].AddressType,
  1614. addressLength);
  1615. *pAddrLength = addressLength;
  1616. }
  1617. #endif // ifndef i386
  1618. irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength = 0;
  1619. return AfdContinueSuperAccept (Irp, connection);
  1620. }
  1621. else {
  1622. //
  1623. // Dereference the accept file object and tell IO to complete this IRP.
  1624. //
  1625. ASSERT( InterlockedDecrement( &acceptEndpoint->ObReferenceBias ) >= 0 );
  1626. ObDereferenceObject( irpSp->FileObject );
  1627. //
  1628. // After dereferencing file object we shouldn't be accessing it
  1629. // or associated endpoint structure
  1630. //
  1631. DEREFERENCE_CONNECTION (connection);
  1632. return STATUS_SUCCESS;
  1633. }
  1634. } // AfdRestartSuperAcceptGetAddress
  1635. NTSTATUS
  1636. AfdRestartSuperAcceptReceive (
  1637. IN PDEVICE_OBJECT DeviceObject,
  1638. IN PIRP Irp,
  1639. IN PVOID Context
  1640. )
  1641. /*++
  1642. Routine Description:
  1643. The completion routine for the AFD receive portion of a super accept.
  1644. Arguments:
  1645. DeviceObject - the devoce object on which the request is completing.
  1646. Irp - The super accept IRP.
  1647. Context - points to the accepted connection
  1648. Return Value:
  1649. STATUS_SUCCESS if the I/O system should complete the super accept
  1650. request, or STATUS_MORE_PROCESSING_REQUIRED if the super accept
  1651. request is still being processed.
  1652. --*/
  1653. {
  1654. PAFD_ENDPOINT acceptEndpoint;
  1655. PAFD_CONNECTION connection;
  1656. PIO_STACK_LOCATION irpSp;
  1657. //
  1658. // Initialize some locals.
  1659. //
  1660. irpSp = IoGetCurrentIrpStackLocation (Irp);
  1661. acceptEndpoint = irpSp->FileObject->FsContext;
  1662. ASSERT (IS_AFD_ENDPOINT_TYPE (acceptEndpoint));
  1663. connection = Context;
  1664. ASSERT (connection->Type == AfdBlockTypeConnection);
  1665. ASSERT (connection->Endpoint==acceptEndpoint);
  1666. AfdCompleteOutstandingIrp (acceptEndpoint, Irp);
  1667. //
  1668. // Restore MDL length so that IO system can properly unmap
  1669. // and unlock it when it completes the IRP
  1670. //
  1671. ASSERT (Irp->MdlAddress!=NULL);
  1672. ASSERT (Irp->MdlAddress->Next==NULL);
  1673. Irp->MdlAddress->ByteCount =
  1674. irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength;
  1675. //
  1676. // If pending has been returned for this irp then mark the current
  1677. // stack as pending.
  1678. //
  1679. if ( Irp->PendingReturned ) {
  1680. IoMarkIrpPending( Irp );
  1681. }
  1682. if (NT_SUCCESS (Irp->IoStatus.Status) &&
  1683. (connection->RemoteAddress!=NULL) &&
  1684. (KeInitializeApc (&acceptEndpoint->Common.VcConnecting.Apc,
  1685. PsGetThreadTcb (Irp->Tail.Overlay.Thread),
  1686. Irp->ApcEnvironment,
  1687. AfdSuperAcceptApcKernelRoutine,
  1688. AfdSuperAcceptApcRundownRoutine,
  1689. (PKNORMAL_ROUTINE)NULL,
  1690. KernelMode,
  1691. NULL
  1692. ),
  1693. KeInsertQueueApc (&acceptEndpoint->Common.VcConnecting.Apc,
  1694. Irp,
  1695. connection,
  1696. AfdPriorityBoost))) {
  1697. return STATUS_MORE_PROCESSING_REQUIRED;
  1698. }
  1699. else {
  1700. //
  1701. // Dereference the accept file object and tell IO to complete this IRP.
  1702. //
  1703. ASSERT( InterlockedDecrement( &acceptEndpoint->ObReferenceBias ) >= 0 );
  1704. ObDereferenceObject( irpSp->FileObject );
  1705. //
  1706. // After dereferencing file object we shouldn't be accessing it
  1707. // or associated endpoint structure
  1708. //
  1709. DEREFERENCE_CONNECTION (connection);
  1710. return STATUS_SUCCESS;
  1711. }
  1712. } // AfdRestartSuperAcceptReceive
  1713. VOID
  1714. AfdSuperAcceptApcKernelRoutine (
  1715. IN struct _KAPC *Apc,
  1716. IN OUT PKNORMAL_ROUTINE *NormalRoutine,
  1717. IN OUT PVOID *NormalContext,
  1718. IN OUT PVOID *SystemArgument1,
  1719. IN OUT PVOID *SystemArgument2
  1720. )
  1721. {
  1722. PIRP irp;
  1723. PIO_STACK_LOCATION irpSp;
  1724. PAFD_ENDPOINT endpoint;
  1725. PAFD_CONNECTION connection;
  1726. PVOID context;
  1727. PAGED_CODE ();
  1728. #if DBG
  1729. try {
  1730. #endif
  1731. ASSERT (*NormalRoutine == NULL);
  1732. endpoint = CONTAINING_RECORD (Apc, AFD_ENDPOINT, Common.VcConnecting.Apc);
  1733. ASSERT (IS_AFD_ENDPOINT_TYPE (endpoint));
  1734. irp = *SystemArgument1;
  1735. irpSp = IoGetCurrentIrpStackLocation( irp );
  1736. ASSERT (irpSp->FileObject->FsContext==endpoint);
  1737. connection = *SystemArgument2;
  1738. ASSERT( connection->Type == AfdBlockTypeConnection );
  1739. ASSERT (connection->Endpoint==endpoint);
  1740. //
  1741. // Copy remote address to the user mode context
  1742. //
  1743. context = AfdLockEndpointContext (endpoint);
  1744. if ( (((CLONG)(endpoint->Common.VcConnecting.RemoteSocketAddressOffset+
  1745. endpoint->Common.VcConnecting.RemoteSocketAddressLength)) <
  1746. endpoint->ContextLength) &&
  1747. (endpoint->Common.VcConnecting.RemoteSocketAddressLength >=
  1748. connection->RemoteAddress->Address[0].AddressLength +
  1749. sizeof(u_short))) {
  1750. RtlMoveMemory ((PUCHAR)context +
  1751. endpoint->Common.VcConnecting.RemoteSocketAddressOffset,
  1752. &connection->RemoteAddress->Address[0].AddressType,
  1753. connection->RemoteAddress->Address[0].AddressLength +
  1754. sizeof(u_short));
  1755. }
  1756. else {
  1757. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_WARNING_LEVEL,
  1758. "AfdSuperAcceptApcKernelRoutine: Could not copy remote address for AcceptEx on endpoint: %p, process: %p\n",
  1759. endpoint, endpoint->OwningProcess));
  1760. }
  1761. AfdUnlockEndpointContext (endpoint, context);
  1762. AFD_RETURN_REMOTE_ADDRESS (
  1763. connection->RemoteAddress,
  1764. connection->RemoteAddressLength
  1765. );
  1766. connection->RemoteAddress = NULL;
  1767. //
  1768. // Dereference the accept file object and tell IO to complete this IRP.
  1769. //
  1770. ASSERT( InterlockedDecrement( &endpoint->ObReferenceBias ) >= 0 );
  1771. ObDereferenceObject( irpSp->FileObject );
  1772. //
  1773. // After dereferencing file object we shouldn't be accessing it
  1774. // or associated endpoint structure
  1775. //
  1776. DEREFERENCE_CONNECTION (connection);
  1777. IoCompleteRequest (irp, AfdPriorityBoost);
  1778. #if DBG
  1779. }
  1780. except (AfdApcExceptionFilter (
  1781. GetExceptionInformation(),
  1782. (LPSTR)__FILE__,
  1783. (LONG)__LINE__)) {
  1784. DbgBreakPoint ();
  1785. }
  1786. #endif
  1787. }
  1788. VOID
  1789. AfdSuperAcceptApcRundownRoutine (
  1790. IN struct _KAPC *Apc
  1791. )
  1792. {
  1793. PIRP irp;
  1794. PIO_STACK_LOCATION irpSp;
  1795. PAFD_ENDPOINT endpoint;
  1796. PAFD_CONNECTION connection;
  1797. PAGED_CODE ();
  1798. endpoint = CONTAINING_RECORD (Apc, AFD_ENDPOINT, Common.VcConnecting.Apc);
  1799. ASSERT (IS_AFD_ENDPOINT_TYPE (endpoint));
  1800. irp = Apc->SystemArgument1;
  1801. irpSp = IoGetCurrentIrpStackLocation( irp );
  1802. ASSERT (irpSp->FileObject->FsContext==endpoint);
  1803. connection = Apc->SystemArgument2;
  1804. ASSERT( connection->Type == AfdBlockTypeConnection );
  1805. ASSERT (connection->Endpoint==endpoint);
  1806. //
  1807. // Dereference the accept file object and tell IO to complete this IRP.
  1808. //
  1809. ASSERT( InterlockedDecrement( &endpoint->ObReferenceBias ) >= 0 );
  1810. ObDereferenceObject( irpSp->FileObject );
  1811. //
  1812. // After dereferencing file object we shouldn't be accessing it
  1813. // or associated endpoint structure
  1814. //
  1815. DEREFERENCE_CONNECTION (connection);
  1816. IoCompleteRequest (irp, AfdPriorityBoost);
  1817. }
  1818. NTSTATUS
  1819. FASTCALL
  1820. AfdDeferAccept (
  1821. IN PIRP Irp,
  1822. IN PIO_STACK_LOCATION IrpSp
  1823. )
  1824. /*++
  1825. Routine Description:
  1826. Defers acceptance of an incoming connection for which an
  1827. AFD_WAIT_FOR_LISTEN IOCTL has already completed. The caller
  1828. may specify that the connection be deferred for later acceptance
  1829. or rejected totally.
  1830. Arguments:
  1831. Irp - a pointer to a transmit file IRP.
  1832. IrpSp - Our stack location for this IRP.
  1833. Return Value:
  1834. STATUS_SUCCESS if the request was completed successfully, or a
  1835. failure status code if there was an error.
  1836. --*/
  1837. {
  1838. NTSTATUS status;
  1839. PAFD_DEFER_ACCEPT_INFO deferAcceptInfo;
  1840. PAFD_ENDPOINT endpoint;
  1841. PAFD_CONNECTION connection;
  1842. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1843. //
  1844. // Set up local variables.
  1845. //
  1846. endpoint = IrpSp->FileObject->FsContext;
  1847. deferAcceptInfo = Irp->AssociatedIrp.SystemBuffer;
  1848. Irp->IoStatus.Information = 0;
  1849. //
  1850. // Make sure that this request is valid.
  1851. //
  1852. if( !endpoint->Listening ||
  1853. IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  1854. sizeof(AFD_DEFER_ACCEPT_INFO) ) {
  1855. status = STATUS_INVALID_PARAMETER;
  1856. goto complete;
  1857. }
  1858. ASSERT ((endpoint->Type & AfdBlockTypeVcListening) == AfdBlockTypeVcListening);
  1859. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  1860. //
  1861. // Find the specified connection. If it cannot be found, then this
  1862. // is a bogus request.
  1863. //
  1864. connection = AfdGetReturnedConnection(
  1865. endpoint,
  1866. deferAcceptInfo->Sequence
  1867. );
  1868. if( connection == NULL ) {
  1869. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1870. status = STATUS_INVALID_PARAMETER;
  1871. goto complete;
  1872. }
  1873. ASSERT( connection->Type == AfdBlockTypeConnection );
  1874. //
  1875. // If this is a request to reject the accepted connection, then
  1876. // abort the connection. Otherwise (this is a request to defer
  1877. // acceptance until later) then insert the connection at the *head*
  1878. // of the endpoint's unaccepted connection queue.
  1879. //
  1880. if( deferAcceptInfo->Reject ) {
  1881. //
  1882. // Reenable the accept event bit, and if there are additional
  1883. // unaccepted connections on the endpoint, post another event.
  1884. //
  1885. endpoint->EventsActive &= ~AFD_POLL_ACCEPT;
  1886. IF_DEBUG(EVENT_SELECT) {
  1887. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1888. "AfdDeferAccept: Endp %08lX, Active %08lX\n",
  1889. endpoint,
  1890. endpoint->EventsActive
  1891. ));
  1892. }
  1893. if( !IsListEmpty( &endpoint->Common.VcListening.UnacceptedConnectionListHead ) ) {
  1894. AfdIndicateEventSelectEvent(
  1895. endpoint,
  1896. AFD_POLL_ACCEPT,
  1897. STATUS_SUCCESS
  1898. );
  1899. }
  1900. //
  1901. // Special handling for SAN connections
  1902. //
  1903. if (connection->SanConnection) {
  1904. PIRP connectIrp;
  1905. //
  1906. // Snag the connect indication IRP
  1907. //
  1908. connectIrp = connection->ConnectIrp;
  1909. ASSERT (connectIrp!=NULL);
  1910. connection->ConnectIrp = NULL;
  1911. //
  1912. // We can now release listen endpoint spinlock
  1913. // The cancel routine will not find IRP in the connection
  1914. //
  1915. if (IoSetCancelRoutine (connectIrp, NULL)==NULL) {
  1916. KIRQL cancelIrql;
  1917. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1918. //
  1919. // Cancel routine is running, make sure
  1920. // it finishes before proceeding further
  1921. //
  1922. IoAcquireCancelSpinLock (&cancelIrql);
  1923. IoReleaseCancelSpinLock (cancelIrql);
  1924. connectIrp->IoStatus.Status = STATUS_CANCELLED;
  1925. }
  1926. else {
  1927. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1928. connectIrp->IoStatus.Status = STATUS_CONNECTION_REFUSED;
  1929. }
  1930. //
  1931. // Return the connection and complete SAN provider IRP
  1932. //
  1933. connection->Endpoint = NULL;
  1934. connection->SanConnection = FALSE;
  1935. AfdSanReleaseConnection (endpoint, connection, FALSE);
  1936. DEREFERENCE_ENDPOINT (endpoint);
  1937. connectIrp->IoStatus.Information = 0;
  1938. IoCompleteRequest (connectIrp, AfdPriorityBoost);
  1939. }
  1940. else {
  1941. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1942. //
  1943. // Abort the connection.
  1944. //
  1945. AfdAbortConnection( connection );
  1946. //
  1947. // Add another free connection to replace the one we're rejecting.
  1948. // Also, add extra to account for past failures in calls to
  1949. // AfdAddFreeConnection().
  1950. //
  1951. InterlockedIncrement(
  1952. &endpoint->Common.VcListening.FailedConnectionAdds
  1953. );
  1954. AfdReplenishListenBacklog( endpoint );
  1955. }
  1956. } else {
  1957. //
  1958. // Restore the connection's state before putting it back
  1959. // on the queue.
  1960. //
  1961. connection->State = AfdConnectionStateUnaccepted;
  1962. InsertHeadList(
  1963. &endpoint->Common.VcListening.UnacceptedConnectionListHead,
  1964. &connection->ListEntry
  1965. );
  1966. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1967. }
  1968. status = STATUS_SUCCESS;
  1969. complete:
  1970. Irp->IoStatus.Status = status;
  1971. ASSERT( Irp->CancelRoutine == NULL );
  1972. IoCompleteRequest( Irp, AfdPriorityBoost );
  1973. return status;
  1974. } // AfdDeferAccept
  1975. NTSTATUS
  1976. AfdRestartDelayedAccept (
  1977. IN PDEVICE_OBJECT DeviceObject,
  1978. IN PIRP Irp,
  1979. IN PVOID Context
  1980. )
  1981. /*++
  1982. Routine Description:
  1983. The completion routine for the AFD wait for delayed accept IRP portion
  1984. of an accept.
  1985. Arguments:
  1986. DeviceObject - the devoce object on which the request is completing.
  1987. Irp - The accept IRP.
  1988. Context - points to accept file object
  1989. Return Value:
  1990. STATUS_SUCCESS if the I/O system should complete the super accept
  1991. request, or STATUS_MORE_PROCESSING_REQUIRED if the super accept
  1992. request is still being processed.
  1993. --*/
  1994. {
  1995. PIO_STACK_LOCATION irpSp;
  1996. PFILE_OBJECT acceptFileObject;
  1997. PAFD_ENDPOINT acceptEndpoint;
  1998. PAFD_CONNECTION connection;
  1999. PAFD_ENDPOINT listenEndpoint;
  2000. AFD_LOCK_QUEUE_HANDLE lockHandle;
  2001. acceptFileObject = Context;
  2002. acceptEndpoint = acceptFileObject->FsContext;
  2003. irpSp = IoGetCurrentIrpStackLocation (Irp);
  2004. listenEndpoint = irpSp->FileObject->FsContext;
  2005. //
  2006. // Remember that a TDI accept has completed on this endpoint.
  2007. //
  2008. InterlockedDecrement(
  2009. &listenEndpoint->Common.VcListening.TdiAcceptPendingCount
  2010. );
  2011. AfdCompleteOutstandingIrp (acceptEndpoint, Irp);
  2012. if ( Irp->PendingReturned ) {
  2013. IoMarkIrpPending( Irp );
  2014. }
  2015. AfdAcquireSpinLock (&acceptEndpoint->SpinLock, &lockHandle);
  2016. //
  2017. // The AFD connection object should now be in the endpoiont.
  2018. //
  2019. connection = AFD_CONNECTION_FROM_ENDPOINT( acceptEndpoint );
  2020. if (connection!=NULL) {
  2021. if (NT_SUCCESS (Irp->IoStatus.Status)) {
  2022. acceptEndpoint->State = AfdEndpointStateConnected;
  2023. connection->State = AfdConnectionStateConnected;
  2024. acceptEndpoint->EventsActive |= AFD_POLL_SEND;
  2025. acceptEndpoint->EnableSendEvent = TRUE;
  2026. AfdReleaseSpinLock (&acceptEndpoint->SpinLock, &lockHandle);
  2027. AFD_END_STATE_CHANGE (acceptEndpoint);
  2028. }
  2029. else {
  2030. //
  2031. // If the accept failed, treat it like an abortive disconnect.
  2032. // This way the application still gets a new endpoint, but it gets
  2033. // told about the reset.
  2034. //
  2035. REFERENCE_CONNECTION (connection);
  2036. AfdReleaseSpinLock (&acceptEndpoint->SpinLock, &lockHandle);
  2037. AFD_END_STATE_CHANGE (acceptEndpoint);
  2038. AfdDisconnectEventHandler(
  2039. NULL,
  2040. connection,
  2041. 0,
  2042. NULL,
  2043. 0,
  2044. NULL,
  2045. TDI_DISCONNECT_ABORT
  2046. );
  2047. DEREFERENCE_CONNECTION (connection);
  2048. }
  2049. }
  2050. ASSERT( InterlockedDecrement( &acceptEndpoint->ObReferenceBias ) >= 0 );
  2051. ObDereferenceObject( acceptFileObject );
  2052. Irp->AssociatedIrp.SystemBuffer = irpSp->Parameters.AfdRestartDelayedAcceptInfo.AfdSystemBuffer;
  2053. return STATUS_SUCCESS;
  2054. }
  2055. VOID
  2056. AfdCleanupSuperAccept (
  2057. IN PIRP Irp,
  2058. IN NTSTATUS Status
  2059. )
  2060. /*++
  2061. Routine Description:
  2062. Cleans up a super accept IRP and prepeares it for completion
  2063. Arguments:
  2064. Irp - the IRP to cleanup.
  2065. Status - failure status
  2066. Return Value:
  2067. None.
  2068. --*/
  2069. {
  2070. PAFD_ENDPOINT listenEndpoint;
  2071. PFILE_OBJECT acceptFileObject;
  2072. PAFD_ENDPOINT acceptEndpoint;
  2073. PIO_STACK_LOCATION irpSp;
  2074. AFD_LOCK_QUEUE_HANDLE lockHandle;
  2075. ASSERT (!NT_SUCCESS (Status));
  2076. //
  2077. // Initialize some locals.
  2078. //
  2079. irpSp = IoGetCurrentIrpStackLocation (Irp);
  2080. listenEndpoint = irpSp->FileObject->FsContext;
  2081. //
  2082. // Reduce the count of failed connection adds on the listening
  2083. // endpoint to account for this connection object which we're
  2084. // adding back onto the queue once it is pulled from pre-accepted connection
  2085. // list.
  2086. //
  2087. InterlockedDecrement (&listenEndpoint->Common.VcListening.FailedConnectionAdds);
  2088. acceptFileObject = irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdAcceptFileObject;
  2089. acceptEndpoint = acceptFileObject->FsContext;
  2090. ASSERT (IS_AFD_ENDPOINT_TYPE (acceptEndpoint));
  2091. //
  2092. // Cleanup super accept IRP out of endpoint.
  2093. //
  2094. AfdAcquireSpinLock (&acceptEndpoint->SpinLock, &lockHandle);
  2095. ASSERT (acceptEndpoint->Irp==Irp); // May need to remove this assert
  2096. // in the future.
  2097. acceptEndpoint->Irp = NULL;
  2098. AfdReleaseSpinLock (&acceptEndpoint->SpinLock, &lockHandle);
  2099. //
  2100. // Mark the end of state change letting the endpoint
  2101. // to be used again in state change operation (e.g. accept).
  2102. //
  2103. AFD_END_STATE_CHANGE (acceptEndpoint);
  2104. //
  2105. // Dereference accept file object
  2106. //
  2107. ASSERT( InterlockedDecrement( &acceptEndpoint->ObReferenceBias ) >= 0 );
  2108. ObDereferenceObject( acceptFileObject );
  2109. //
  2110. // Check if we have secondary MDL for local address query and
  2111. // free it.
  2112. //
  2113. if (Irp->MdlAddress->Next!=NULL) {
  2114. //
  2115. // We never lock pages for this one (they are locked
  2116. // as part of main MDL).
  2117. //
  2118. ASSERT (irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength>0);
  2119. ASSERT ((Irp->MdlAddress->Next->MdlFlags & MDL_PAGES_LOCKED)==0);
  2120. IoFreeMdl (Irp->MdlAddress->Next);
  2121. Irp->MdlAddress->Next = NULL;
  2122. }
  2123. //
  2124. // Set the status specified in the IRP and return
  2125. // The caller will eventually complete it.
  2126. //
  2127. Irp->IoStatus.Status = Status;
  2128. Irp->IoStatus.Information = 0;
  2129. return;
  2130. }
  2131. VOID
  2132. AfdCancelSuperAccept (
  2133. IN PDEVICE_OBJECT DeviceObject,
  2134. IN PIRP Irp
  2135. )
  2136. /*++
  2137. Routine Description:
  2138. Cancels a super accept IRP that is pended in AFD.
  2139. Arguments:
  2140. DeviceObject - not used.
  2141. Irp - the IRP to cancel.
  2142. Return Value:
  2143. None.
  2144. --*/
  2145. {
  2146. PAFD_CONNECTION connection;
  2147. connection = Irp->Tail.Overlay.DriverContext[0];
  2148. ASSERT (connection->Type==AfdBlockTypeConnection);
  2149. ASSERT (connection->Endpoint==NULL);
  2150. //
  2151. // If IRP is in the connection object, cleanup and complete it
  2152. //
  2153. if (InterlockedExchangePointer (
  2154. (PVOID *)&connection->AcceptIrp,
  2155. NULL)==Irp) {
  2156. IoReleaseCancelSpinLock( Irp->CancelIrql );
  2157. AfdCleanupSuperAccept (Irp, STATUS_CANCELLED);
  2158. IoCompleteRequest( Irp, AfdPriorityBoost );
  2159. }
  2160. else {
  2161. IoReleaseCancelSpinLock( Irp->CancelIrql );
  2162. }
  2163. return;
  2164. }
  2165. BOOLEAN
  2166. AfdServiceSuperAccept (
  2167. IN PAFD_ENDPOINT Endpoint,
  2168. IN PAFD_CONNECTION Connection,
  2169. IN PAFD_LOCK_QUEUE_HANDLE LockHandle,
  2170. OUT PLIST_ENTRY AcceptIrpList
  2171. )
  2172. /*++
  2173. Routine Description:
  2174. Attemts to satisfy super accept irp using the incoming
  2175. connection. This routine must be called with listening endpoint
  2176. spinlock held.
  2177. Arguments:
  2178. Endpoint - listening endpoint on which connection is
  2179. being accepted
  2180. Connection - connection being accepted.
  2181. AcceptIrpList - returns a list of accept Irps which were failed and
  2182. need to be completed after listening endpoint spinlock
  2183. is released.
  2184. Return Value:
  2185. TRUE - the super accept IRP was found and is in the head of the list
  2186. FALSE - no usable super accept IRP exists.
  2187. --*/
  2188. {
  2189. PSINGLE_LIST_ENTRY listEntry;
  2190. PIRP acceptIrp;
  2191. PAFD_CONNECTION oldConnection;
  2192. //
  2193. // Keep removing super accept IRPs while there are any there
  2194. //
  2195. while ((listEntry = InterlockedPopEntrySList (
  2196. &Endpoint->Common.VcListening.PreacceptedConnectionsListHead
  2197. ))!=NULL) {
  2198. NTSTATUS status;
  2199. //
  2200. // Find the connection pointer from the list entry and return a
  2201. // pointer to the connection object.
  2202. //
  2203. oldConnection = CONTAINING_RECORD(
  2204. listEntry,
  2205. AFD_CONNECTION,
  2206. SListEntry
  2207. );
  2208. acceptIrp = InterlockedExchangePointer ((PVOID *)&oldConnection->AcceptIrp, NULL);
  2209. //
  2210. // Check if there is accept irp associated with
  2211. // this connection, if not just put it back on the free list
  2212. // (the IRP must have been cancelled)
  2213. //
  2214. if (acceptIrp!=NULL) {
  2215. if (IoSetCancelRoutine (acceptIrp, NULL)!=NULL) {
  2216. PFILE_OBJECT acceptFileObject;
  2217. PAFD_ENDPOINT acceptEndpoint;
  2218. PIO_STACK_LOCATION irpSp;
  2219. //
  2220. // Initialize some locals.
  2221. //
  2222. irpSp = IoGetCurrentIrpStackLocation (acceptIrp);
  2223. acceptFileObject = irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdAcceptFileObject;
  2224. acceptEndpoint = acceptFileObject->FsContext;
  2225. ASSERT (IS_AFD_ENDPOINT_TYPE (acceptEndpoint));
  2226. //
  2227. // Check if super accept Irp has enough space for
  2228. // the remote address
  2229. //
  2230. if (Connection->RemoteAddressLength>
  2231. irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdRemoteAddressLength) {
  2232. status = STATUS_BUFFER_TOO_SMALL;
  2233. }
  2234. //
  2235. // Check if we have enough system PTE's to map
  2236. // the buffer.
  2237. //
  2238. else if ((status = AfdMapMdlChain (acceptIrp->MdlAddress)),
  2239. !NT_SUCCESS (status)) {
  2240. NOTHING;
  2241. }
  2242. else if (Connection->SanConnection) {
  2243. status = AfdSanAcceptCore (acceptIrp, acceptFileObject, Connection, LockHandle);
  2244. if (status==STATUS_PENDING) {
  2245. //
  2246. // Accept IRP is pending waiting for Switch
  2247. // completion notification
  2248. // Release old connection object
  2249. //
  2250. ASSERT (oldConnection->Endpoint==NULL);
  2251. InterlockedPushEntrySList (
  2252. &Endpoint->Common.VcListening.FreeConnectionListHead,
  2253. &oldConnection->SListEntry);
  2254. }
  2255. else {
  2256. //
  2257. // Something failed, we need to complete accept IRP
  2258. //
  2259. ASSERT (NT_ERROR (status));
  2260. AfdCleanupSuperAccept (acceptIrp, status);
  2261. IoCompleteRequest (acceptIrp, AfdPriorityBoost);
  2262. //
  2263. // This connection has already been diassociated from endpoint.
  2264. // If backlog is below the level we need, put it on the free
  2265. // list, otherwise, get rid of it.
  2266. //
  2267. ASSERT (oldConnection->Endpoint==NULL);
  2268. if (InterlockedIncrement (&Endpoint->Common.VcListening.FailedConnectionAdds)>0) {
  2269. InterlockedDecrement (&Endpoint->Common.VcListening.FailedConnectionAdds);
  2270. InterlockedPushEntrySList (
  2271. &Endpoint->Common.VcListening.FreeConnectionListHead,
  2272. &oldConnection->SListEntry);
  2273. }
  2274. else {
  2275. DEREFERENCE_CONNECTION (oldConnection);
  2276. }
  2277. }
  2278. //
  2279. // Complete previously failed accept irps if any.
  2280. //
  2281. while (!IsListEmpty (AcceptIrpList)) {
  2282. PIRP irp;
  2283. irp = CONTAINING_RECORD (AcceptIrpList->Flink, IRP, Tail.Overlay.ListEntry);
  2284. RemoveEntryList (&irp->Tail.Overlay.ListEntry);
  2285. IoCompleteRequest (irp, AfdPriorityBoost);
  2286. }
  2287. return TRUE;
  2288. }
  2289. //
  2290. // Allocate MDL for local address query if requested
  2291. //
  2292. else if ((irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength>0) &&
  2293. (IoAllocateMdl ((PUCHAR)acceptIrp->UserBuffer+irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength,
  2294. irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength,
  2295. TRUE,
  2296. FALSE,
  2297. acceptIrp)==NULL)){
  2298. status = STATUS_INSUFFICIENT_RESOURCES;
  2299. }
  2300. else {
  2301. //
  2302. // Copy over the address information to the user's buffer.
  2303. //
  2304. #ifndef i386
  2305. if (acceptEndpoint->Common.VcConnecting.FixAddressAlignment) {
  2306. USHORT addressLength =
  2307. Connection->RemoteAddress->Address[0].AddressLength
  2308. + sizeof (USHORT);
  2309. USHORT UNALIGNED *pAddrLength = (PVOID)
  2310. ((PUCHAR)MmGetSystemAddressForMdl (acceptIrp->MdlAddress)
  2311. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength
  2312. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength
  2313. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdRemoteAddressLength
  2314. - sizeof (USHORT));
  2315. RtlMoveMemory (
  2316. (PUCHAR)MmGetSystemAddressForMdl (acceptIrp->MdlAddress)
  2317. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength
  2318. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength,
  2319. &Connection->RemoteAddress->Address[0].AddressType,
  2320. addressLength);
  2321. *pAddrLength = addressLength;
  2322. }
  2323. else
  2324. #endif
  2325. {
  2326. RtlMoveMemory (
  2327. (PUCHAR)MmGetSystemAddressForMdl (acceptIrp->MdlAddress)
  2328. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength
  2329. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength,
  2330. Connection->RemoteAddress,
  2331. Connection->RemoteAddressLength);
  2332. }
  2333. status = AfdAcceptCore (acceptIrp, acceptEndpoint, Connection);
  2334. if (status==STATUS_SUCCESS) {
  2335. AfdReleaseSpinLock (&Endpoint->SpinLock, LockHandle);
  2336. //
  2337. // Decrement counter to account for connection being
  2338. // returned to the free pool. No need to do this because
  2339. // we are picking up a connection from the free pool
  2340. // InterlockedDecrement (&Endpoint->Common.VcListening.FailedConnectionAdds);
  2341. //
  2342. ASSERT (oldConnection->Endpoint==NULL);
  2343. InterlockedPushEntrySList (
  2344. &Endpoint->Common.VcListening.FreeConnectionListHead,
  2345. &oldConnection->SListEntry);
  2346. //
  2347. // Complete previously failed accept irps if any.
  2348. //
  2349. while (!IsListEmpty (AcceptIrpList)) {
  2350. PIRP irp;
  2351. irp = CONTAINING_RECORD (AcceptIrpList->Flink, IRP, Tail.Overlay.ListEntry);
  2352. RemoveEntryList (&irp->Tail.Overlay.ListEntry);
  2353. IoCompleteRequest (irp, AfdPriorityBoost);
  2354. }
  2355. //
  2356. // Make irp look like it is completed by the
  2357. // transport.
  2358. //
  2359. acceptIrp->IoStatus.Status = STATUS_SUCCESS;
  2360. irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdMdlAddress = acceptIrp->MdlAddress;
  2361. acceptIrp->MdlAddress = NULL;
  2362. irpSp->FileObject = acceptFileObject;
  2363. //
  2364. // Call completion routine directly to simulate
  2365. // completion by the transport stack
  2366. //
  2367. AfdRestartSuperAcceptListen (acceptIrp, Connection);
  2368. return TRUE;
  2369. }
  2370. else {
  2371. ASSERT (status!=STATUS_PENDING);
  2372. }
  2373. }
  2374. }
  2375. else { // if (IoSetCancelRoutine (accpetIrp, NULL)!=NULL)
  2376. status = STATUS_CANCELLED;
  2377. }
  2378. //
  2379. // Cleanup the IRP and insert it into the completion list
  2380. //
  2381. AfdCleanupSuperAccept (acceptIrp, status);
  2382. InsertTailList (AcceptIrpList,
  2383. &acceptIrp->Tail.Overlay.ListEntry);
  2384. } // if (acceptIrp!=NULL)
  2385. else {
  2386. status = STATUS_CANCELLED;
  2387. }
  2388. //
  2389. // This connection has already been diassociated from endpoint.
  2390. // If backlog is below the level we need, put it on the free
  2391. // list, otherwise, get rid of it.
  2392. //
  2393. ASSERT (oldConnection->Endpoint==NULL);
  2394. if (Endpoint->Common.VcListening.FailedConnectionAdds>=0 &&
  2395. status!=STATUS_INSUFFICIENT_RESOURCES &&
  2396. ExQueryDepthSList (&Endpoint->Common.VcListening.FreeConnectionListHead)<AFD_MAXIMUM_FREE_CONNECTIONS) {
  2397. InterlockedPushEntrySList (
  2398. &Endpoint->Common.VcListening.FreeConnectionListHead,
  2399. &oldConnection->SListEntry);
  2400. }
  2401. else {
  2402. InterlockedIncrement (&Endpoint->Common.VcListening.FailedConnectionAdds);
  2403. DEREFERENCE_CONNECTION (oldConnection);
  2404. }
  2405. }
  2406. return FALSE;
  2407. }
  2408. NTSTATUS
  2409. AfdSetupAcceptEndpoint (
  2410. PAFD_ENDPOINT ListenEndpoint,
  2411. PAFD_ENDPOINT AcceptEndpoint,
  2412. PAFD_CONNECTION Connection
  2413. )
  2414. /*++
  2415. Routine Description:
  2416. Sets up the accept endpoint to get ready to accept connection
  2417. (copies parameters of the listening endpoint on which connection
  2418. was indicated)
  2419. Arguments:
  2420. ListenEndpoint - endpoint on which connection was indicated
  2421. AcceptEndpoint - endpoint on which to accept the connection
  2422. Connection - connection to accept
  2423. Return Value:
  2424. STATUS_SUCCESS - endpoint state/parameters adjusted OK
  2425. STATUS_CANCELLED - endpoint has already been cleaned up.
  2426. Note:
  2427. Both accepting and listening endpoint spinlocks must be held when
  2428. calling this routine.
  2429. --*/
  2430. {
  2431. //
  2432. // Check the state of the accepting endpoint.
  2433. //
  2434. if ( AcceptEndpoint->EndpointCleanedUp ) {
  2435. return STATUS_CANCELLED;
  2436. }
  2437. //
  2438. // Remove super accept IRP from the endpoint
  2439. //
  2440. AcceptEndpoint->Irp = NULL;
  2441. //
  2442. // Note that the returned connection structure already has a
  2443. // referenced pointer to the listening endpoint. Rather than
  2444. // removing the reference here, only to re-add it later, we'll
  2445. // just not touch the reference count.
  2446. //
  2447. ASSERT( Connection->Endpoint == ListenEndpoint );
  2448. //
  2449. // Set up the accept endpoint's type, and remember blocking
  2450. // characteristics of the TDI provider.
  2451. //
  2452. AcceptEndpoint->Type = AfdBlockTypeVcConnecting;
  2453. AcceptEndpoint->TdiServiceFlags = ListenEndpoint->TdiServiceFlags;
  2454. ASSERT (AcceptEndpoint->TransportInfo == ListenEndpoint->TransportInfo);
  2455. ASSERT (AcceptEndpoint->TransportInfo->ReferenceCount>0);
  2456. //
  2457. // Place the connection on the endpoint we'll accept it on. It is
  2458. // still referenced from when it was created.
  2459. //
  2460. AcceptEndpoint->Common.VcConnecting.Connection = Connection;
  2461. //
  2462. // Set up a referenced pointer from the connection to the accept
  2463. // endpoint. Note that we actually already have a refernce to
  2464. // the endpoint by the virtue of its file object
  2465. //
  2466. REFERENCE_ENDPOINT( AcceptEndpoint );
  2467. Connection->Endpoint = AcceptEndpoint;
  2468. //
  2469. // Set up a referenced pointer to the listening endpoint. This is
  2470. // necessary so that the endpoint does not go away until all
  2471. // accepted endpoints have gone away. Without this, a connect
  2472. // indication could occur on a TDI address object held open
  2473. // by an accepted endpoint after the listening endpoint has
  2474. // been closed and the memory for it deallocated.
  2475. //
  2476. // Note that, since we didn't remove the reference above, we don't
  2477. // need to add it here.
  2478. //
  2479. AcceptEndpoint->Common.VcConnecting.ListenEndpoint = ListenEndpoint;
  2480. //
  2481. // Set up a referenced pointer in the accepted endpoint to the
  2482. // TDI address object.
  2483. //
  2484. ObReferenceObject( ListenEndpoint->AddressFileObject );
  2485. AfdRecordAddrRef();
  2486. AcceptEndpoint->AddressFileObject = ListenEndpoint->AddressFileObject;
  2487. AcceptEndpoint->AddressDeviceObject = ListenEndpoint->AddressDeviceObject;
  2488. //
  2489. // Copy the pointer to the local address. Because we keep listen
  2490. // endpoint alive for as long as any of its connection is
  2491. // active, we can rely on the fact that address structure won't go
  2492. // away as well.
  2493. //
  2494. AcceptEndpoint->LocalAddress = ListenEndpoint->LocalAddress;
  2495. AcceptEndpoint->LocalAddressLength = ListenEndpoint->LocalAddressLength;
  2496. return STATUS_SUCCESS;
  2497. }