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

2685 lines
83 KiB

  1. /*++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. connect.c
  5. Abstract:
  6. This module contains the code for passing on connect IRPs to
  7. TDI providers.
  8. Author:
  9. David Treadwell (davidtr) 2-Mar-1992
  10. Revision History:
  11. Vadim Eydelman (vadime) 1999 JoinLeaf implementation
  12. Datagram connect via transport
  13. Connect optimizations and syncronization with
  14. user mode code.
  15. --*/
  16. #include "afdp.h"
  17. NTSTATUS
  18. AfdDoDatagramConnect (
  19. IN PFILE_OBJECT FileObject,
  20. IN PIRP Irp,
  21. IN BOOLEAN HalfConnect
  22. );
  23. NTSTATUS
  24. AfdRestartConnect (
  25. IN PDEVICE_OBJECT DeviceObject,
  26. IN PIRP Irp,
  27. IN PVOID Context
  28. );
  29. NTSTATUS
  30. AfdRestartDgConnect (
  31. IN PDEVICE_OBJECT DeviceObject,
  32. IN PIRP Irp,
  33. IN PVOID Context
  34. );
  35. VOID
  36. AfdSetupConnectDataBuffers (
  37. IN PAFD_ENDPOINT Endpoint,
  38. IN PAFD_CONNECTION Connection,
  39. IN OUT PTDI_CONNECTION_INFORMATION *RequestConnectionInformation,
  40. IN OUT PTDI_CONNECTION_INFORMATION *ReturnConnectionInformation
  41. );
  42. BOOLEAN
  43. AfdConnectionStart (
  44. IN PAFD_ENDPOINT Endpoint
  45. );
  46. VOID
  47. AfdEnableFailedConnectEvent(
  48. IN PAFD_ENDPOINT Endpoint
  49. );
  50. NTSTATUS
  51. AfdRestartJoin (
  52. IN PDEVICE_OBJECT DeviceObject,
  53. IN PIRP Irp,
  54. IN PVOID Context
  55. );
  56. VOID
  57. AfdJoinInviteSetup (
  58. PAFD_ENDPOINT RootEndpoint,
  59. PAFD_ENDPOINT LeafEndpoint
  60. );
  61. VOID
  62. AfdConnectApcKernelRoutine (
  63. IN struct _KAPC *Apc,
  64. IN OUT PKNORMAL_ROUTINE *NormalRoutine,
  65. IN OUT PVOID *NormalContext,
  66. IN OUT PVOID *SystemArgument1,
  67. IN OUT PVOID *SystemArgument2
  68. );
  69. VOID
  70. AfdConnectApcRundownRoutine (
  71. IN struct _KAPC *Apc
  72. );
  73. VOID
  74. AfdFinishConnect (
  75. PAFD_ENDPOINT Endpoint,
  76. PIRP Irp,
  77. PAFD_ENDPOINT RootEndpoint
  78. );
  79. NTSTATUS
  80. AfdRestartSuperConnect (
  81. IN PDEVICE_OBJECT DeviceObject,
  82. IN PIRP Irp,
  83. IN PVOID Context
  84. );
  85. #ifdef ALLOC_PRAGMA
  86. #pragma alloc_text( PAGE, AfdConnect )
  87. #pragma alloc_text( PAGEAFD, AfdDoDatagramConnect )
  88. #pragma alloc_text( PAGEAFD, AfdRestartConnect )
  89. #pragma alloc_text( PAGEAFD, AfdRestartDgConnect )
  90. #pragma alloc_text( PAGEAFD, AfdSetupConnectDataBuffers )
  91. #pragma alloc_text( PAGEAFD, AfdEnableFailedConnectEvent )
  92. #pragma alloc_text( PAGE, AfdJoinLeaf )
  93. #pragma alloc_text( PAGEAFD, AfdRestartJoin )
  94. #pragma alloc_text( PAGEAFD, AfdJoinInviteSetup )
  95. #pragma alloc_text( PAGE, AfdConnectApcKernelRoutine )
  96. #pragma alloc_text( PAGE, AfdConnectApcRundownRoutine )
  97. #pragma alloc_text( PAGEAFD, AfdFinishConnect )
  98. #pragma alloc_text( PAGE, AfdSuperConnect )
  99. #pragma alloc_text( PAGEAFD, AfdRestartSuperConnect )
  100. #endif
  101. typedef struct _AFD_CONNECT_CONTEXT {
  102. TDI_CONNECTION_INFORMATION RequestConnectionInfo;
  103. TDI_CONNECTION_INFORMATION ReturnConnectionInfo;
  104. TRANSPORT_ADDRESS RemoteAddress;
  105. } AFD_CONNECT_CONTEXT, *PAFD_CONNECT_CONTEXT;
  106. C_ASSERT ( (FIELD_OFFSET (AFD_CONNECTION, SListEntry) % MEMORY_ALLOCATION_ALIGNMENT) == 0 );
  107. NTSTATUS
  108. FASTCALL
  109. AfdConnect (
  110. IN PIRP Irp,
  111. IN PIO_STACK_LOCATION IrpSp
  112. )
  113. /*++
  114. Routine Description:
  115. Handles the IOCTL_AFD_CONNECT IOCTL.
  116. Arguments:
  117. Irp - Pointer to I/O request packet.
  118. IrpSp - pointer to the IO stack location to use for this request.
  119. Return Value:
  120. NTSTATUS -- Indicates whether the request was successfully queued.
  121. --*/
  122. {
  123. NTSTATUS status;
  124. PAFD_ENDPOINT endpoint;
  125. PAFD_CONNECTION connection;
  126. PAFD_CONNECT_CONTEXT context;
  127. HANDLE connectEndpointHandle;
  128. PFILE_OBJECT fileObject;
  129. PTRANSPORT_ADDRESS remoteAddress;
  130. ULONG remoteAddressLength;
  131. BOOLEAN sanActive;
  132. PTDI_CONNECTION_INFORMATION requestConnectionInfo, returnConnectionInfo;
  133. PAGED_CODE( );
  134. //
  135. // Initialize for proper cleanup
  136. //
  137. fileObject = NULL;
  138. context = NULL;
  139. #ifdef _WIN64
  140. if (IoIs32bitProcess (Irp)) {
  141. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength<
  142. (ULONG)FIELD_OFFSET(AFD_CONNECT_JOIN_INFO32, RemoteAddress.Address[0].Address) ||
  143. (IrpSp->Parameters.DeviceIoControl.OutputBufferLength!=0
  144. && IrpSp->Parameters.DeviceIoControl.OutputBufferLength<
  145. sizeof (IO_STATUS_BLOCK32))){
  146. status = STATUS_INVALID_PARAMETER;
  147. goto complete;
  148. }
  149. AFD_W4_INIT status = STATUS_SUCCESS;
  150. try {
  151. if( Irp->RequestorMode != KernelMode ) {
  152. ProbeForRead(
  153. IrpSp->Parameters.DeviceIoControl.Type3InputBuffer,
  154. IrpSp->Parameters.DeviceIoControl.InputBufferLength,
  155. PROBE_ALIGNMENT32 (AFD_CONNECT_JOIN_INFO32)
  156. );
  157. }
  158. sanActive = ((PAFD_CONNECT_JOIN_INFO32)IrpSp->Parameters.DeviceIoControl.Type3InputBuffer)->SanActive;
  159. connectEndpointHandle =
  160. ((PAFD_CONNECT_JOIN_INFO32)IrpSp->Parameters.DeviceIoControl.Type3InputBuffer)->ConnectEndpoint;
  161. remoteAddress = (PTRANSPORT_ADDRESS)
  162. &((PAFD_CONNECT_JOIN_INFO32)IrpSp->Parameters.DeviceIoControl.Type3InputBuffer)->RemoteAddress;
  163. ASSERT (((ULONG_PTR)remoteAddress & (PROBE_ALIGNMENT(TRANSPORT_ADDRESS)-1))==0);
  164. remoteAddressLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength
  165. - FIELD_OFFSET (AFD_CONNECT_JOIN_INFO32, RemoteAddress);
  166. }
  167. except (AFD_EXCEPTION_FILTER (status)) {
  168. ASSERT (NT_ERROR (status));
  169. goto complete;
  170. }
  171. }
  172. else
  173. #endif //_WIN64
  174. {
  175. //
  176. // Determine where in the system buffer the request and return
  177. // connection information structures exist. Pass pointers to
  178. // these locations instead of the user-mode pointers in the
  179. // tdiRequest structure so that the memory will be nonpageable.
  180. //
  181. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength<
  182. (ULONG)FIELD_OFFSET(AFD_CONNECT_JOIN_INFO, RemoteAddress.Address[0].Address) ||
  183. (IrpSp->Parameters.DeviceIoControl.OutputBufferLength!=0 &&
  184. IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  185. sizeof (IO_STATUS_BLOCK))) {
  186. status = STATUS_INVALID_PARAMETER;
  187. goto complete;
  188. }
  189. AFD_W4_INIT status = STATUS_SUCCESS;
  190. try {
  191. PAFD_CONNECT_JOIN_INFO connectInfo;
  192. if( Irp->RequestorMode != KernelMode ) {
  193. ProbeForRead(
  194. IrpSp->Parameters.DeviceIoControl.Type3InputBuffer,
  195. IrpSp->Parameters.DeviceIoControl.InputBufferLength,
  196. PROBE_ALIGNMENT (AFD_CONNECT_JOIN_INFO)
  197. );
  198. }
  199. connectInfo = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  200. sanActive = connectInfo->SanActive;
  201. connectEndpointHandle = connectInfo->ConnectEndpoint;
  202. remoteAddress = &connectInfo->RemoteAddress;
  203. remoteAddressLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength
  204. - FIELD_OFFSET (AFD_CONNECT_JOIN_INFO, RemoteAddress);
  205. }
  206. except (AFD_EXCEPTION_FILTER (status)) {
  207. ASSERT (NT_ERROR (status));
  208. goto complete;
  209. }
  210. }
  211. //
  212. // Do sanity check on remoteAddressLength to prevent addition overflow below
  213. //
  214. if ((LONG)remoteAddressLength < 0) {
  215. //
  216. // address length is unreasonably large
  217. //
  218. status = STATUS_INVALID_PARAMETER;
  219. goto complete;
  220. }
  221. //
  222. // Check for if the caller is unaware of the SAN
  223. // provider activation and report the error.
  224. //
  225. if (!sanActive && AfdSanServiceHelper!=NULL) {
  226. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  227. "AFD: Process %p is being told to enable SAN on connect\n",
  228. PsGetCurrentProcessId ()));
  229. status = STATUS_INVALID_PARAMETER_12;
  230. goto complete;
  231. }
  232. AFD_W4_INIT ASSERT (status == STATUS_SUCCESS);
  233. try {
  234. context = AFD_ALLOCATE_POOL_WITH_QUOTA (NonPagedPool,
  235. FIELD_OFFSET (AFD_CONNECT_CONTEXT, RemoteAddress)
  236. + remoteAddressLength,
  237. AFD_TDI_POOL_TAG
  238. );
  239. // AFD_ALLOCATE_POOL_WITH_QUOTA macro sets POOL_RAISE_IF_ALLOCATION_FAILURE flag
  240. ASSERT (context!=NULL);
  241. Irp->AssociatedIrp.SystemBuffer = context;
  242. RtlZeroMemory (context,
  243. FIELD_OFFSET (AFD_CONNECT_CONTEXT, RemoteAddress));
  244. RtlCopyMemory (&context->RemoteAddress,
  245. remoteAddress,
  246. remoteAddressLength);
  247. //
  248. // Validate internal consistency of the transport address structure.
  249. // Note that we HAVE to do this after copying since the malicious
  250. // application can change the content of the buffer on us any time
  251. // and our check will be bypassed.
  252. //
  253. if ((context->RemoteAddress.TAAddressCount!=1) ||
  254. (LONG)remoteAddressLength<
  255. FIELD_OFFSET (TRANSPORT_ADDRESS,
  256. Address[0].Address[context->RemoteAddress.Address[0].AddressLength])) {
  257. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  258. }
  259. context->RequestConnectionInfo.RemoteAddress = &context->RemoteAddress;
  260. context->RequestConnectionInfo.RemoteAddressLength = remoteAddressLength;
  261. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength>0 &&
  262. Irp->RequestorMode==UserMode) {
  263. ProbeForWriteIoStatusEx (
  264. ((PIO_STATUS_BLOCK)Irp->UserBuffer),
  265. IoIs32bitProcess (Irp));
  266. }
  267. }
  268. except (AFD_EXCEPTION_FILTER(status)) {
  269. ASSERT (NT_ERROR (status));
  270. goto complete;
  271. }
  272. fileObject = IrpSp->FileObject;
  273. endpoint = fileObject->FsContext;
  274. if (endpoint->Type==AfdBlockTypeHelper) {
  275. //
  276. // This is async connect which uses helper endpoint to
  277. // communicate to AFD. Get the real endpoint.
  278. //
  279. status = ObReferenceObjectByHandle(
  280. connectEndpointHandle,
  281. (IrpSp->Parameters.DeviceIoControl.IoControlCode>>14) & 3,
  282. // DesiredAccess
  283. *IoFileObjectType, // ObjectType
  284. Irp->RequestorMode,
  285. (PVOID *)&fileObject,
  286. NULL
  287. );
  288. if (!NT_SUCCESS (status)) {
  289. goto complete;
  290. }
  291. if (fileObject->DeviceObject!=AfdDeviceObject) {
  292. status = STATUS_INVALID_HANDLE;
  293. goto complete_deref;
  294. }
  295. endpoint = fileObject->FsContext;
  296. IrpSp->FileObject = fileObject;
  297. }
  298. else {
  299. ObReferenceObject (fileObject);
  300. }
  301. IF_DEBUG(CONNECT) {
  302. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  303. "AfdConnect: starting connect on endpoint %p\n",
  304. endpoint ));
  305. }
  306. //
  307. // If this is a datagram endpoint, simply remember the specified
  308. // address so that we can use it on sends, receives, writes, and
  309. // reads.
  310. //
  311. if ( IS_DGRAM_ENDPOINT(endpoint) ) {
  312. return AfdDoDatagramConnect( fileObject, Irp, FALSE );
  313. }
  314. if (!AFD_START_STATE_CHANGE (endpoint, AfdEndpointStateConnected)) {
  315. status = STATUS_INVALID_PARAMETER;
  316. goto complete_deref;
  317. }
  318. if ( endpoint->Type != AfdBlockTypeEndpoint &&
  319. endpoint->Type != AfdBlockTypeVcConnecting ) {
  320. status = STATUS_INVALID_PARAMETER;
  321. goto complete_state_change;
  322. }
  323. //
  324. // If the endpoint is not bound, then this is an invalid request.
  325. // Listening endpoints are not allowed as well.
  326. //
  327. if ( endpoint->Listening ||
  328. endpoint->State != AfdEndpointStateBound ) {
  329. status = STATUS_INVALID_PARAMETER;
  330. goto complete_state_change;
  331. }
  332. //
  333. // Create a connection object to use for the connect operation.
  334. //
  335. status = AfdCreateConnection(
  336. endpoint->TransportInfo,
  337. endpoint->AddressHandle,
  338. IS_TDI_BUFFERRING(endpoint),
  339. endpoint->InLine,
  340. endpoint->OwningProcess,
  341. &connection
  342. );
  343. if ( !NT_SUCCESS(status) ) {
  344. goto complete_state_change;
  345. }
  346. //
  347. // Set up a referenced pointer from the connection to the endpoint.
  348. // Note that we set up the connection's pointer to the endpoint
  349. // BEFORE the endpoint's pointer to the connection so that AfdPoll
  350. // doesn't try to back reference the endpoint from the connection.
  351. //
  352. REFERENCE_ENDPOINT( endpoint );
  353. connection->Endpoint = endpoint;
  354. //
  355. // Remember that this is now a connecting type of endpoint, and set
  356. // up a pointer to the connection in the endpoint. This is
  357. // implicitly a referenced pointer.
  358. //
  359. endpoint->Common.VcConnecting.Connection = connection;
  360. endpoint->Type = AfdBlockTypeVcConnecting;
  361. ASSERT( IS_TDI_BUFFERRING(endpoint) == connection->TdiBufferring );
  362. //
  363. // Add an additional reference to the connection. This prevents the
  364. // connection from being closed until the disconnect event handler
  365. // is called.
  366. //
  367. AfdAddConnectedReference( connection );
  368. //
  369. // If there are connect data buffers, move them from the endpoint
  370. // structure to the connection structure and set up the necessary
  371. // pointers in the connection request we're going to give to the TDI
  372. // provider. Do this in a subroutine so this routine can be pageable.
  373. //
  374. requestConnectionInfo = &context->RequestConnectionInfo;
  375. returnConnectionInfo = &context->ReturnConnectionInfo;
  376. if ( endpoint->Common.VirtualCircuit.ConnectDataBuffers != NULL ) {
  377. AfdSetupConnectDataBuffers(
  378. endpoint,
  379. connection,
  380. &requestConnectionInfo,
  381. &returnConnectionInfo
  382. );
  383. }
  384. //
  385. // Since we may be reissuing a connect after a previous failed connect,
  386. // reenable the failed connect event bit.
  387. //
  388. AfdEnableFailedConnectEvent( endpoint );
  389. //
  390. // Reference the connection block so it does not go away even if
  391. // endpoint's reference to it is removed (in cleanup)
  392. //
  393. REFERENCE_CONNECTION (connection);
  394. //
  395. // Build a TDI kernel-mode connect request in the next stack location
  396. // of the IRP.
  397. //
  398. TdiBuildConnect(
  399. Irp,
  400. connection->DeviceObject,
  401. connection->FileObject,
  402. AfdRestartConnect,
  403. connection,
  404. &AfdInfiniteTimeout,
  405. requestConnectionInfo,
  406. returnConnectionInfo
  407. );
  408. AFD_VERIFY_ADDRESS (connection, &requestConnectionInfo->RemoteAddress);
  409. //
  410. // Call the transport to actually perform the connect operation.
  411. //
  412. return AfdIoCallDriver( endpoint, connection->DeviceObject, Irp );
  413. complete_state_change:
  414. AFD_END_STATE_CHANGE (endpoint);
  415. complete_deref:
  416. ASSERT (fileObject!=NULL);
  417. ObDereferenceObject (fileObject);
  418. complete:
  419. if (context!=NULL) {
  420. AFD_FREE_POOL (context, AFD_TDI_POOL_TAG);
  421. ASSERT (Irp->AssociatedIrp.SystemBuffer==context);
  422. Irp->AssociatedIrp.SystemBuffer = NULL;
  423. }
  424. Irp->IoStatus.Information = 0;
  425. Irp->IoStatus.Status = status;
  426. IoCompleteRequest( Irp, AfdPriorityBoost );
  427. return status;
  428. } // AfdConnect
  429. NTSTATUS
  430. AfdDoDatagramConnect (
  431. IN PFILE_OBJECT FileObject,
  432. IN PIRP Irp,
  433. IN BOOLEAN HalfConnect
  434. )
  435. {
  436. PAFD_ENDPOINT endpoint;
  437. AFD_LOCK_QUEUE_HANDLE lockHandle;
  438. NTSTATUS status;
  439. PAFD_CONNECT_CONTEXT context;
  440. endpoint = FileObject->FsContext;
  441. context = Irp->AssociatedIrp.SystemBuffer;
  442. if (!AFD_START_STATE_CHANGE (endpoint, AfdEndpointStateConnected)) {
  443. status = STATUS_INVALID_PARAMETER;
  444. goto complete;
  445. }
  446. if (endpoint->State!=AfdEndpointStateBound &&
  447. endpoint->State!=AfdEndpointStateConnected) {
  448. status = STATUS_INVALID_PARAMETER;
  449. goto complete_state_change;
  450. }
  451. //
  452. // Save the remote address on the endpoint. We'll use this to
  453. // send datagrams in the future and to compare received datagram's
  454. // source addresses.
  455. //
  456. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  457. if ((endpoint->Common.Datagram.RemoteAddress==NULL) ||
  458. (endpoint->Common.Datagram.RemoteAddressLength<
  459. (ULONG)context->RequestConnectionInfo.RemoteAddressLength)) {
  460. PTRANSPORT_ADDRESS remoteAddress;
  461. remoteAddress =
  462. AFD_ALLOCATE_REMOTE_ADDRESS (
  463. context->RequestConnectionInfo.RemoteAddressLength);
  464. if (remoteAddress == NULL) {
  465. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  466. status = STATUS_INSUFFICIENT_RESOURCES;
  467. goto complete_state_change;
  468. }
  469. if ( endpoint->Common.Datagram.RemoteAddress != NULL ) {
  470. AFD_RETURN_REMOTE_ADDRESS (
  471. endpoint->Common.Datagram.RemoteAddress,
  472. endpoint->Common.Datagram.RemoteAddressLength
  473. );
  474. }
  475. endpoint->Common.Datagram.RemoteAddress = remoteAddress;
  476. }
  477. RtlCopyMemory(
  478. endpoint->Common.Datagram.RemoteAddress,
  479. context->RequestConnectionInfo.RemoteAddress,
  480. context->RequestConnectionInfo.RemoteAddressLength
  481. );
  482. endpoint->Common.Datagram.RemoteAddressLength =
  483. context->RequestConnectionInfo.RemoteAddressLength;
  484. endpoint->DisconnectMode = 0;
  485. endpoint->Common.Datagram.HalfConnect = HalfConnect;
  486. if (!IS_TDI_DGRAM_CONNECTION(endpoint)) {
  487. endpoint->State = AfdEndpointStateConnected;
  488. //
  489. // Indicate that the connect completed. Implicitly, the
  490. // successful completion of a connect also means that the caller
  491. // can do a send on the socket.
  492. //
  493. endpoint->EnableSendEvent = TRUE;
  494. AfdIndicateEventSelectEvent(
  495. endpoint,
  496. AFD_POLL_CONNECT | AFD_POLL_SEND,
  497. STATUS_SUCCESS
  498. );
  499. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  500. AfdIndicatePollEvent(
  501. endpoint,
  502. AFD_POLL_CONNECT | AFD_POLL_SEND,
  503. STATUS_SUCCESS
  504. );
  505. status = STATUS_SUCCESS;
  506. }
  507. else {
  508. //
  509. // Reset the connect status to success so that the poll code will
  510. // know if a connect failure occurs.
  511. // Do this inline as we already hold spinlock
  512. //
  513. endpoint->EventsActive &= ~AFD_POLL_CONNECT_FAIL;
  514. endpoint->EventStatus[AFD_POLL_CONNECT_FAIL_BIT] = STATUS_SUCCESS;
  515. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  516. //
  517. // Build a TDI kernel-mode connect request in the next stack location
  518. // of the IRP.
  519. //
  520. TdiBuildConnect(
  521. Irp,
  522. endpoint->AddressDeviceObject,
  523. endpoint->AddressFileObject,
  524. AfdRestartDgConnect,
  525. endpoint,
  526. &AfdInfiniteTimeout,
  527. &context->RequestConnectionInfo,
  528. &context->ReturnConnectionInfo
  529. );
  530. //
  531. // Call the transport to actually perform the connect operation.
  532. //
  533. return AfdIoCallDriver( endpoint, endpoint->AddressDeviceObject, Irp );
  534. }
  535. complete_state_change:
  536. AFD_END_STATE_CHANGE (endpoint);
  537. complete:
  538. ObDereferenceObject (FileObject);
  539. AFD_FREE_POOL (context, AFD_TDI_POOL_TAG);
  540. ASSERT (Irp->AssociatedIrp.SystemBuffer==context);
  541. Irp->AssociatedIrp.SystemBuffer = NULL;
  542. Irp->IoStatus.Information = 0;
  543. Irp->IoStatus.Status = status;
  544. IoCompleteRequest( Irp, AfdPriorityBoost );
  545. return status;
  546. } // AfdDoDatagramConnect
  547. VOID
  548. AfdSetupConnectDataBuffers (
  549. IN PAFD_ENDPOINT Endpoint,
  550. IN PAFD_CONNECTION Connection,
  551. IN OUT PTDI_CONNECTION_INFORMATION *RequestConnectionInformation,
  552. IN OUT PTDI_CONNECTION_INFORMATION *ReturnConnectionInformation
  553. )
  554. {
  555. AFD_LOCK_QUEUE_HANDLE lockHandle;
  556. ASSERT (Endpoint->Type!=AfdBlockTypeDatagram);
  557. AfdAcquireSpinLock( &Endpoint->SpinLock, &lockHandle );
  558. if ( Endpoint->Common.VirtualCircuit.ConnectDataBuffers != NULL ) {
  559. PTDI_CONNECTION_INFORMATION requestConnectionInformation,
  560. returnConnectionInformation;
  561. ASSERT( Connection->ConnectDataBuffers == NULL );
  562. Connection->ConnectDataBuffers = Endpoint->Common.VirtualCircuit.ConnectDataBuffers;
  563. Endpoint->Common.VirtualCircuit.ConnectDataBuffers = NULL;
  564. requestConnectionInformation = &Connection->ConnectDataBuffers->RequestConnectionInfo,
  565. requestConnectionInformation->UserData =
  566. Connection->ConnectDataBuffers->SendConnectData.Buffer;
  567. requestConnectionInformation->UserDataLength =
  568. Connection->ConnectDataBuffers->SendConnectData.BufferLength;
  569. requestConnectionInformation->Options =
  570. Connection->ConnectDataBuffers->SendConnectOptions.Buffer;
  571. requestConnectionInformation->OptionsLength =
  572. Connection->ConnectDataBuffers->SendConnectOptions.BufferLength;
  573. requestConnectionInformation->RemoteAddress =
  574. (*RequestConnectionInformation)->RemoteAddress;
  575. requestConnectionInformation->RemoteAddressLength =
  576. (*RequestConnectionInformation)->RemoteAddressLength;
  577. *RequestConnectionInformation = requestConnectionInformation;
  578. returnConnectionInformation = &Connection->ConnectDataBuffers->ReturnConnectionInfo;
  579. returnConnectionInformation->UserData =
  580. Connection->ConnectDataBuffers->ReceiveConnectData.Buffer;
  581. returnConnectionInformation->UserDataLength =
  582. Connection->ConnectDataBuffers->ReceiveConnectData.BufferLength;
  583. returnConnectionInformation->Options =
  584. Connection->ConnectDataBuffers->ReceiveConnectOptions.Buffer;
  585. returnConnectionInformation->OptionsLength =
  586. Connection->ConnectDataBuffers->ReceiveConnectOptions.BufferLength;
  587. returnConnectionInformation->RemoteAddress =
  588. (*ReturnConnectionInformation)->RemoteAddress;
  589. returnConnectionInformation->RemoteAddressLength =
  590. (*ReturnConnectionInformation)->RemoteAddressLength;
  591. *ReturnConnectionInformation = returnConnectionInformation;
  592. }
  593. AfdReleaseSpinLock( &Endpoint->SpinLock, &lockHandle );
  594. } // AfdSetupConnectDataBuffers
  595. NTSTATUS
  596. AfdRestartConnect (
  597. IN PDEVICE_OBJECT DeviceObject,
  598. IN PIRP Irp,
  599. IN PVOID Context
  600. )
  601. /*++
  602. Routine Description:
  603. Handles the IOCTL_AFD_CONNECT IOCTL.
  604. Arguments:
  605. Irp - Pointer to I/O request packet.
  606. IrpSp - pointer to the IO stack location to use for this request.
  607. Return Value:
  608. NTSTATUS -- Indicates whether the request was successfully queued.
  609. --*/
  610. {
  611. PAFD_ENDPOINT endpoint;
  612. PAFD_CONNECTION connection;
  613. AFD_LOCK_QUEUE_HANDLE lockHandle;
  614. PIO_STACK_LOCATION irpSp;
  615. PFILE_OBJECT fileObject;
  616. PAFD_CONNECT_CONTEXT context;
  617. UNREFERENCED_PARAMETER (DeviceObject);
  618. connection = Context;
  619. ASSERT( connection->Type == AfdBlockTypeConnection );
  620. irpSp = IoGetCurrentIrpStackLocation( Irp );
  621. fileObject = irpSp->FileObject;
  622. ASSERT( fileObject->DeviceObject==AfdDeviceObject );
  623. endpoint = fileObject->FsContext;
  624. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting );
  625. ASSERT( endpoint==connection->Endpoint );
  626. context = Irp->AssociatedIrp.SystemBuffer;
  627. ASSERT( context != NULL );
  628. IF_DEBUG(CONNECT) {
  629. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  630. "AfdRestartConnect: connect completed, status = %X, endpoint = %p\n",
  631. Irp->IoStatus.Status, endpoint ));
  632. }
  633. if ( connection->ConnectDataBuffers != NULL ) {
  634. //
  635. // If there are connect buffers on this endpoint, remember the
  636. // size of the return connect data.
  637. //
  638. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  639. //
  640. // Double-check under the lock
  641. //
  642. if ( connection->ConnectDataBuffers != NULL ) {
  643. NTSTATUS status;
  644. status = AfdSaveReceivedConnectData(
  645. &connection->ConnectDataBuffers,
  646. IOCTL_AFD_SET_CONNECT_DATA,
  647. connection->ConnectDataBuffers->ReturnConnectionInfo.UserData,
  648. connection->ConnectDataBuffers->ReturnConnectionInfo.UserDataLength
  649. );
  650. ASSERT (NT_SUCCESS (status));
  651. status = AfdSaveReceivedConnectData(
  652. &connection->ConnectDataBuffers,
  653. IOCTL_AFD_SET_CONNECT_OPTIONS,
  654. connection->ConnectDataBuffers->ReturnConnectionInfo.Options,
  655. connection->ConnectDataBuffers->ReturnConnectionInfo.OptionsLength
  656. );
  657. ASSERT (NT_SUCCESS (status));
  658. }
  659. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  660. }
  661. //
  662. // Indicate that the connect completed. Implicitly, the successful
  663. // completion of a connect also means that the caller can do a send
  664. // on the socket.
  665. //
  666. if ( NT_SUCCESS(Irp->IoStatus.Status)) {
  667. //
  668. // If the request succeeded, set the endpoint to the connected
  669. // state. The endpoint type has already been set to
  670. // AfdBlockTypeVcConnecting.
  671. //
  672. endpoint->State = AfdEndpointStateConnected;
  673. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting );
  674. //
  675. // Remember the time that the connection started.
  676. //
  677. connection->ConnectTime = KeQueryInterruptTime();
  678. } else {
  679. //
  680. // The connect failed, so reset the type to open.
  681. // Otherwise, we won't be able to start another connect
  682. //
  683. endpoint->Type = AfdBlockTypeEndpoint;
  684. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  685. if (endpoint->Common.VcConnecting.Connection!=NULL) {
  686. ASSERT (connection==endpoint->Common.VcConnecting.Connection);
  687. endpoint->Common.VcConnecting.Connection = NULL;
  688. //
  689. // Manually delete the connected reference if somebody else
  690. // hasn't already done so. We can't use
  691. // AfdDeleteConnectedReference() because it refuses to delete
  692. // the connected reference until the endpoint has been cleaned
  693. // up.
  694. //
  695. if ( connection->ConnectedReferenceAdded ) {
  696. connection->ConnectedReferenceAdded = FALSE;
  697. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  698. DEREFERENCE_CONNECTION( connection );
  699. } else {
  700. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  701. }
  702. //
  703. // Dereference the connection block stored on the endpoint.
  704. // This should cause the connection object reference count to go
  705. // to zero to the connection object can be deleted.
  706. //
  707. DEREFERENCE_CONNECTION( connection );
  708. }
  709. else {
  710. //
  711. // The endpoint's reference to connection was removed
  712. // (perhaps in cleanup);
  713. //
  714. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  715. }
  716. }
  717. AFD_FREE_POOL (context, AFD_TDI_POOL_TAG);
  718. Irp->AssociatedIrp.SystemBuffer = NULL;
  719. //
  720. // If pending has be returned for this irp then mark the current
  721. // stack as pending.
  722. //
  723. if ( Irp->PendingReturned ) {
  724. IoMarkIrpPending(Irp);
  725. }
  726. AfdCompleteOutstandingIrp( endpoint, Irp );
  727. //
  728. // Dereference connection to account for reference we added in AfdConnect
  729. //
  730. DEREFERENCE_CONNECTION( connection );
  731. //
  732. // Try to queue kernel APC to the user thread that
  733. // started the connection operation, so we can
  734. // communicate the status of the connect operation to
  735. // msafd.dll before we inform the application through
  736. // the select or EventSelect. Otherwise, we run into the
  737. // race condition when application learns about connect first,
  738. // calls msafd.dll that is not aware of the completion and
  739. // returns WSAENOTCONN.
  740. //
  741. if ((Irp->RequestorMode==UserMode) && // Must be user mode calls
  742. (Irp->UserBuffer!=NULL) && // Must be interested in status
  743. // Thread should be able to
  744. // run APCs.
  745. (KeInitializeApc (&endpoint->Common.VcConnecting.Apc,
  746. PsGetThreadTcb (Irp->Tail.Overlay.Thread),
  747. Irp->ApcEnvironment,
  748. AfdConnectApcKernelRoutine,
  749. AfdConnectApcRundownRoutine,
  750. (PKNORMAL_ROUTINE)NULL,
  751. KernelMode,
  752. NULL
  753. ),
  754. KeInsertQueueApc (&endpoint->Common.VcConnecting.Apc,
  755. Irp,
  756. NULL,
  757. AfdPriorityBoost))) {
  758. //
  759. // We will complete the IRP in the APC.
  760. //
  761. return STATUS_MORE_PROCESSING_REQUIRED;
  762. }
  763. else {
  764. //
  765. // APC was not necessary or did not work.
  766. // Complete it here.
  767. //
  768. AfdFinishConnect (endpoint, Irp, NULL);
  769. return STATUS_SUCCESS;
  770. }
  771. } // AfdRestartConnect
  772. VOID
  773. AfdConnectApcKernelRoutine (
  774. IN struct _KAPC *Apc,
  775. IN OUT PKNORMAL_ROUTINE *NormalRoutine,
  776. IN OUT PVOID *NormalContext,
  777. IN OUT PVOID *SystemArgument1,
  778. IN OUT PVOID *SystemArgument2
  779. )
  780. {
  781. PIRP irp;
  782. PIO_STACK_LOCATION irpSp;
  783. PAFD_ENDPOINT endpoint, rootEndpoint;
  784. UNREFERENCED_PARAMETER (NormalContext);
  785. #if DBG
  786. try {
  787. ASSERT (*NormalRoutine==NULL);
  788. #else
  789. UNREFERENCED_PARAMETER (NormalRoutine);
  790. #endif
  791. //
  792. // Validate parameters.
  793. //
  794. endpoint = CONTAINING_RECORD (Apc, AFD_ENDPOINT, Common.VcConnecting.Apc);
  795. ASSERT (IS_AFD_ENDPOINT_TYPE (endpoint));
  796. irp = *SystemArgument1;
  797. ASSERT (irp->UserBuffer!=NULL && irp->RequestorMode==UserMode);
  798. irpSp = IoGetCurrentIrpStackLocation( irp );
  799. rootEndpoint = *SystemArgument2;
  800. ASSERT (rootEndpoint==NULL || IS_AFD_ENDPOINT_TYPE (endpoint));
  801. //
  802. // Update the status for the user mode caller before
  803. // signalling events.
  804. //
  805. try {
  806. #ifdef _WIN64
  807. if (IoIs32bitProcess (irp)) {
  808. ((PIO_STATUS_BLOCK32)irp->UserBuffer)->Status = (LONG)irp->IoStatus.Status;
  809. }
  810. else
  811. #endif //_WIN64
  812. {
  813. ((PIO_STATUS_BLOCK)irp->UserBuffer)->Status = irp->IoStatus.Status;
  814. }
  815. }
  816. except (AFD_EXCEPTION_FILTER_NO_STATUS()) {
  817. NOTHING;
  818. }
  819. AfdFinishConnect (endpoint, irp, rootEndpoint);
  820. IoCompleteRequest (irp, AfdPriorityBoost);
  821. #if DBG
  822. }
  823. except (AfdApcExceptionFilter (GetExceptionInformation (),
  824. __FILE__,
  825. __LINE__)) {
  826. DbgBreakPoint ();
  827. }
  828. #endif
  829. }
  830. VOID
  831. AfdConnectApcRundownRoutine (
  832. IN struct _KAPC *Apc
  833. )
  834. {
  835. PIRP irp;
  836. PAFD_ENDPOINT endpoint, rootEndpoint;
  837. #if DBG
  838. try {
  839. #endif
  840. endpoint = CONTAINING_RECORD (Apc, AFD_ENDPOINT, Common.VcConnecting.Apc);
  841. ASSERT (IS_AFD_ENDPOINT_TYPE (endpoint));
  842. irp = Apc->SystemArgument1;
  843. rootEndpoint = Apc->SystemArgument2;
  844. ASSERT (rootEndpoint==NULL || IS_AFD_ENDPOINT_TYPE (endpoint));
  845. ASSERT (irp->UserBuffer!=NULL && irp->RequestorMode==UserMode);
  846. //
  847. // Thread is exiting, don't bother updating user mode status.
  848. // Just signal the events and complet the IRP.
  849. //
  850. AfdFinishConnect (endpoint, irp, rootEndpoint);
  851. IoCompleteRequest (irp, AfdPriorityBoost);
  852. #if DBG
  853. }
  854. except (AfdApcExceptionFilter (GetExceptionInformation (),
  855. __FILE__,
  856. __LINE__)) {
  857. DbgBreakPoint ();
  858. }
  859. #endif
  860. }
  861. VOID
  862. AfdFinishConnect (
  863. PAFD_ENDPOINT Endpoint,
  864. PIRP Irp,
  865. PAFD_ENDPOINT RootEndpoint
  866. )
  867. {
  868. PIO_STACK_LOCATION irpSp;
  869. PFILE_OBJECT fileObject;
  870. AFD_LOCK_QUEUE_HANDLE lockHandle;
  871. ULONG eventMask;
  872. if (NT_SUCCESS(Irp->IoStatus.Status)) {
  873. eventMask = AFD_POLL_CONNECT;
  874. }
  875. else {
  876. eventMask = AFD_POLL_CONNECT_FAIL;
  877. }
  878. irpSp = IoGetCurrentIrpStackLocation( Irp );
  879. fileObject = irpSp->FileObject;
  880. if (RootEndpoint != NULL) {
  881. AfdAcquireSpinLock(&RootEndpoint->SpinLock, &lockHandle);
  882. //
  883. // mswsock.dll will reissue join leaf call for non-blocking sockets
  884. // in its async helper if the original requesting thread exits
  885. // causing the connect IRP to cancel. We only want to signal events
  886. // based upon the final resolution of the join leaf call (once only)!
  887. // However if the endpoint is now cleaning up, a followup call to
  888. // join leaf will fail without signalling the events.
  889. //
  890. if (RootEndpoint->EndpointCleanedUp ||
  891. (Irp->IoStatus.Status != STATUS_CANCELLED) ||
  892. !RootEndpoint->NonBlocking) {
  893. AfdIndicateEventSelectEvent(RootEndpoint, eventMask, Irp->IoStatus.Status);
  894. AfdReleaseSpinLock(&RootEndpoint->SpinLock, &lockHandle);
  895. AfdIndicatePollEvent(RootEndpoint, eventMask, Irp->IoStatus.Status);
  896. //
  897. // Only indicate connection once to the root control plane.
  898. //
  899. eventMask = 0;
  900. } else {
  901. AfdReleaseSpinLock(&RootEndpoint->SpinLock, &lockHandle);
  902. }
  903. AFD_END_STATE_CHANGE(RootEndpoint);
  904. if (!NT_SUCCESS(Irp->IoStatus.Status))
  905. DEREFERENCE_ENDPOINT(RootEndpoint);
  906. } // if (RootEndpoint != NULL)
  907. AfdAcquireSpinLock(&Endpoint->SpinLock, &lockHandle);
  908. if (NT_SUCCESS(Irp->IoStatus.Status)) {
  909. eventMask |= AFD_POLL_SEND;
  910. Endpoint->EnableSendEvent = TRUE;
  911. if (Endpoint->Common.VcConnecting.Connection != NULL) {
  912. Endpoint->Common.VcConnecting.Connection->State = AfdConnectionStateConnected;
  913. if (IS_DATA_ON_CONNECTION(Endpoint->Common.VcConnecting.Connection)) {
  914. eventMask |= AFD_POLL_RECEIVE;
  915. }
  916. }
  917. } else {
  918. //
  919. // mswsock.dll will reissue connect call for non-blocking sockets
  920. // in its async helper if the original requesting thread exits
  921. // causing the connect IRP to cancel. We only want to signal events
  922. // based upon the final resolution of the connect call (once only)!
  923. // However if the endpoint is now cleaning up, a followup call to
  924. // connect will fail without signalling the events.
  925. //
  926. if ((Irp->IoStatus.Status == STATUS_CANCELLED) &&
  927. !Endpoint->EndpointCleanedUp &&
  928. Endpoint->NonBlocking) {
  929. eventMask = 0;
  930. }
  931. } // if (NT_SUCCESS(Irp->IoStatus.Status))
  932. if (eventMask) {
  933. AfdIndicateEventSelectEvent(Endpoint, eventMask, Irp->IoStatus.Status);
  934. AfdReleaseSpinLock(&Endpoint->SpinLock, &lockHandle);
  935. AfdIndicatePollEvent(Endpoint, eventMask, Irp->IoStatus.Status);
  936. }
  937. else {
  938. AfdReleaseSpinLock(&Endpoint->SpinLock, &lockHandle);
  939. }
  940. AFD_END_STATE_CHANGE(Endpoint);
  941. ObDereferenceObject(fileObject);
  942. }
  943. NTSTATUS
  944. AfdRestartDgConnect (
  945. IN PDEVICE_OBJECT DeviceObject,
  946. IN PIRP Irp,
  947. IN PVOID Context
  948. )
  949. /*++
  950. Routine Description:
  951. Handles the IOCTL_AFD_CONNECT IOCTL.
  952. Arguments:
  953. Irp - Pointer to I/O request packet.
  954. IrpSp - pointer to the IO stack location to use for this request.
  955. Return Value:
  956. NTSTATUS -- Indicates whether the request was successfully queued.
  957. --*/
  958. {
  959. PAFD_ENDPOINT endpoint;
  960. PIO_STACK_LOCATION irpSp;
  961. PFILE_OBJECT fileObject;
  962. AFD_LOCK_QUEUE_HANDLE lockHandle;
  963. ULONG eventMask;
  964. UNREFERENCED_PARAMETER (DeviceObject);
  965. endpoint = Context;
  966. ASSERT( IS_DGRAM_ENDPOINT(endpoint) );
  967. irpSp = IoGetCurrentIrpStackLocation( Irp );
  968. fileObject = irpSp->FileObject;
  969. ASSERT (endpoint == fileObject->FsContext);
  970. IF_DEBUG(CONNECT) {
  971. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  972. "AfdRestartDgConnect: connect completed, status = %X, endpoint = %p\n",
  973. Irp->IoStatus.Status, endpoint ));
  974. }
  975. //
  976. // Indicate that the connect completed. Implicitly, the successful
  977. // completion of a connect also means that the caller can do a send
  978. // on the socket.
  979. //
  980. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  981. if ( NT_SUCCESS(Irp->IoStatus.Status) ) {
  982. endpoint->State = AfdEndpointStateConnected;
  983. endpoint->EnableSendEvent = TRUE;
  984. eventMask = AFD_POLL_CONNECT | AFD_POLL_SEND;
  985. } else {
  986. eventMask = AFD_POLL_CONNECT_FAIL;
  987. }
  988. AfdIndicateEventSelectEvent (endpoint, eventMask, Irp->IoStatus.Status);
  989. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  990. AfdIndicatePollEvent (endpoint, eventMask, Irp->IoStatus.Status);
  991. AFD_END_STATE_CHANGE (endpoint);
  992. ASSERT (Irp->AssociatedIrp.SystemBuffer!=NULL);
  993. AFD_FREE_POOL (Irp->AssociatedIrp.SystemBuffer, AFD_TDI_POOL_TAG);
  994. Irp->AssociatedIrp.SystemBuffer = NULL;
  995. //
  996. // If pending has be returned for this irp then mark the current
  997. // stack as pending.
  998. //
  999. if ( Irp->PendingReturned ) {
  1000. IoMarkIrpPending(Irp);
  1001. }
  1002. AfdCompleteOutstandingIrp( endpoint, Irp );
  1003. //
  1004. // Remove reference added in AfdConnect
  1005. //
  1006. ObDereferenceObject (fileObject);
  1007. return STATUS_SUCCESS;
  1008. } // AfdRestartDgConnect
  1009. VOID
  1010. AfdEnableFailedConnectEvent(
  1011. IN PAFD_ENDPOINT Endpoint
  1012. )
  1013. /*++
  1014. Routine Description:
  1015. Reenables the failed connect poll bit on the specified endpoint.
  1016. This is off in a separate (nonpageable) routine so that the bulk
  1017. of AfdConnect() can remain pageable.
  1018. Arguments:
  1019. Endpoint - The endpoint to enable.
  1020. Return Value:
  1021. None.
  1022. --*/
  1023. {
  1024. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1025. AfdAcquireSpinLock( &Endpoint->SpinLock, &lockHandle );
  1026. ASSERT( ( Endpoint->EventsActive & AFD_POLL_CONNECT ) == 0 );
  1027. Endpoint->EventsActive &= ~AFD_POLL_CONNECT_FAIL;
  1028. Endpoint->EventStatus[AFD_POLL_CONNECT_FAIL_BIT] = STATUS_SUCCESS;
  1029. IF_DEBUG(EVENT_SELECT) {
  1030. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1031. "AfdConnect: Endp %08lX, Active %08lX\n",
  1032. Endpoint,
  1033. Endpoint->EventsActive
  1034. ));
  1035. }
  1036. AfdReleaseSpinLock( &Endpoint->SpinLock, &lockHandle );
  1037. } // AfdEnableFailedConnectEvent
  1038. NTSTATUS
  1039. FASTCALL
  1040. AfdJoinLeaf (
  1041. IN PIRP Irp,
  1042. IN PIO_STACK_LOCATION IrpSp
  1043. )
  1044. /*++
  1045. Routine Description:
  1046. Handles the IOCTL_AFD_JOIN_LEAF IOCTL.
  1047. Arguments:
  1048. Irp - Pointer to I/O request packet.
  1049. IrpSp - pointer to the IO stack location to use for this request.
  1050. Return Value:
  1051. NTSTATUS -- Indicates whether the request was successfully queued.
  1052. --*/
  1053. {
  1054. NTSTATUS status;
  1055. PAFD_ENDPOINT leafEndpoint;
  1056. PAFD_CONNECTION connection;
  1057. PAFD_CONNECT_CONTEXT context;
  1058. HANDLE connectEndpointHandle;
  1059. HANDLE rootEndpointHandle;
  1060. PFILE_OBJECT fileObject;
  1061. PTRANSPORT_ADDRESS remoteAddress;
  1062. ULONG remoteAddressLength;
  1063. PTDI_CONNECTION_INFORMATION requestConnectionInfo, returnConnectionInfo;
  1064. PAGED_CODE( );
  1065. //
  1066. // Initialize for proper cleanup
  1067. //
  1068. fileObject = NULL;
  1069. connection = NULL;
  1070. context = NULL;
  1071. #ifdef _WIN64
  1072. if (IoIs32bitProcess (Irp)) {
  1073. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength<
  1074. (ULONG)FIELD_OFFSET(AFD_CONNECT_JOIN_INFO32, RemoteAddress.Address[0].Address) ||
  1075. (IrpSp->Parameters.DeviceIoControl.OutputBufferLength!=0 &&
  1076. IrpSp->Parameters.DeviceIoControl.OutputBufferLength<
  1077. sizeof (IO_STATUS_BLOCK32))){
  1078. status = STATUS_INVALID_PARAMETER;
  1079. goto complete;
  1080. }
  1081. AFD_W4_INIT status = STATUS_SUCCESS;
  1082. try {
  1083. if( Irp->RequestorMode != KernelMode ) {
  1084. ProbeForRead(
  1085. IrpSp->Parameters.DeviceIoControl.Type3InputBuffer,
  1086. IrpSp->Parameters.DeviceIoControl.InputBufferLength,
  1087. PROBE_ALIGNMENT32 (AFD_CONNECT_JOIN_INFO32)
  1088. );
  1089. }
  1090. connectEndpointHandle =
  1091. ((PAFD_CONNECT_JOIN_INFO32)IrpSp->Parameters.DeviceIoControl.Type3InputBuffer)->ConnectEndpoint;
  1092. rootEndpointHandle =
  1093. ((PAFD_CONNECT_JOIN_INFO32)IrpSp->Parameters.DeviceIoControl.Type3InputBuffer)->RootEndpoint;
  1094. remoteAddress = (PTRANSPORT_ADDRESS)&((PAFD_CONNECT_JOIN_INFO32)IrpSp->Parameters.DeviceIoControl.Type3InputBuffer)->RemoteAddress;
  1095. ASSERT (((ULONG_PTR)remoteAddress & (PROBE_ALIGNMENT(TRANSPORT_ADDRESS)-1))==0);
  1096. remoteAddressLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength
  1097. - FIELD_OFFSET (AFD_CONNECT_JOIN_INFO32, RemoteAddress);
  1098. }
  1099. except (AFD_EXCEPTION_FILTER (status)) {
  1100. ASSERT (NT_ERROR (status));
  1101. goto complete;
  1102. }
  1103. }
  1104. else
  1105. #endif //_WIN64
  1106. {
  1107. //
  1108. // Determine where in the system buffer the request and return
  1109. // connection information structures exist. Pass pointers to
  1110. // these locations instead of the user-mode pointers in the
  1111. // tdiRequest structure so that the memory will be nonpageable.
  1112. //
  1113. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength<
  1114. (ULONG)FIELD_OFFSET (AFD_CONNECT_JOIN_INFO, RemoteAddress.Address[0].Address) ||
  1115. (IrpSp->Parameters.DeviceIoControl.OutputBufferLength!=0 &&
  1116. IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1117. sizeof (IO_STATUS_BLOCK))) {
  1118. status = STATUS_INVALID_PARAMETER;
  1119. goto complete;
  1120. }
  1121. AFD_W4_INIT status = STATUS_SUCCESS;
  1122. try {
  1123. if( Irp->RequestorMode != KernelMode ) {
  1124. ProbeForRead(
  1125. IrpSp->Parameters.DeviceIoControl.Type3InputBuffer,
  1126. IrpSp->Parameters.DeviceIoControl.InputBufferLength,
  1127. PROBE_ALIGNMENT (AFD_CONNECT_JOIN_INFO)
  1128. );
  1129. }
  1130. connectEndpointHandle =
  1131. ((PAFD_CONNECT_JOIN_INFO)IrpSp->Parameters.DeviceIoControl.Type3InputBuffer)->ConnectEndpoint;
  1132. rootEndpointHandle =
  1133. ((PAFD_CONNECT_JOIN_INFO)IrpSp->Parameters.DeviceIoControl.Type3InputBuffer)->RootEndpoint;
  1134. remoteAddress = &((PAFD_CONNECT_JOIN_INFO)IrpSp->Parameters.DeviceIoControl.Type3InputBuffer)->RemoteAddress;
  1135. remoteAddressLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength
  1136. - FIELD_OFFSET (AFD_CONNECT_JOIN_INFO, RemoteAddress);
  1137. }
  1138. except (AFD_EXCEPTION_FILTER (status)) {
  1139. ASSERT (NT_ERROR (status));
  1140. goto complete;
  1141. }
  1142. }
  1143. //
  1144. // Do sanity check on remoteAddressLength to prevent addition overflow below
  1145. //
  1146. if ((LONG)remoteAddressLength < 0) {
  1147. //
  1148. // address length is unreasonably large
  1149. //
  1150. status = STATUS_INVALID_PARAMETER;
  1151. goto complete;
  1152. }
  1153. AFD_W4_INIT ASSERT (status == STATUS_SUCCESS);
  1154. try {
  1155. context = AFD_ALLOCATE_POOL_WITH_QUOTA (NonPagedPool,
  1156. FIELD_OFFSET (AFD_CONNECT_CONTEXT, RemoteAddress)
  1157. + remoteAddressLength,
  1158. AFD_TDI_POOL_TAG
  1159. );
  1160. // AFD_ALLOCATE_POOL_WITH_QUOTA macro sets POOL_RAISE_IF_ALLOCATION_FAILURE flag
  1161. ASSERT (context!=NULL);
  1162. Irp->AssociatedIrp.SystemBuffer = context;
  1163. RtlZeroMemory (context,
  1164. FIELD_OFFSET (AFD_CONNECT_CONTEXT, RemoteAddress));
  1165. RtlCopyMemory (&context->RemoteAddress,
  1166. remoteAddress,
  1167. remoteAddressLength);
  1168. //
  1169. // Validate internal consistency of the transport address structure.
  1170. // Note that we HAVE to do this after copying since the malicious
  1171. // application can change the content of the buffer on us any time
  1172. // and our check will be bypassed.
  1173. //
  1174. if ((context->RemoteAddress.TAAddressCount!=1) ||
  1175. (LONG)remoteAddressLength<
  1176. FIELD_OFFSET (TRANSPORT_ADDRESS,
  1177. Address[0].Address[context->RemoteAddress.Address[0].AddressLength])) {
  1178. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  1179. }
  1180. context->RequestConnectionInfo.RemoteAddress = &context->RemoteAddress;
  1181. context->RequestConnectionInfo.RemoteAddressLength = remoteAddressLength;
  1182. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength>0 &&
  1183. Irp->RequestorMode==UserMode) {
  1184. ProbeForWriteIoStatusEx (
  1185. ((PIO_STATUS_BLOCK)Irp->UserBuffer),
  1186. IoIs32bitProcess (Irp));
  1187. }
  1188. }
  1189. except (AFD_EXCEPTION_FILTER(status)) {
  1190. ASSERT (NT_ERROR (status));
  1191. goto complete;
  1192. }
  1193. fileObject = IrpSp->FileObject;
  1194. leafEndpoint = fileObject->FsContext;
  1195. if (leafEndpoint->Type==AfdBlockTypeHelper) {
  1196. //
  1197. // This is async join leaf which uses helper endpoint to
  1198. // communicate to AFD. Get the real endpoint.
  1199. //
  1200. status = ObReferenceObjectByHandle(
  1201. connectEndpointHandle,
  1202. (IrpSp->Parameters.DeviceIoControl.IoControlCode>>14) & 3,
  1203. // DesiredAccess
  1204. *IoFileObjectType, // ObjectType
  1205. Irp->RequestorMode,
  1206. (PVOID *)&fileObject,
  1207. NULL
  1208. );
  1209. if (!NT_SUCCESS (status)) {
  1210. goto complete;
  1211. }
  1212. if (fileObject->DeviceObject!=AfdDeviceObject) {
  1213. status = STATUS_INVALID_HANDLE;
  1214. goto complete_deref;
  1215. }
  1216. leafEndpoint = fileObject->FsContext;
  1217. IrpSp->FileObject = fileObject;
  1218. }
  1219. else
  1220. ObReferenceObject (fileObject);
  1221. if (rootEndpointHandle!=NULL) {
  1222. //
  1223. // Root inviting leaf
  1224. //
  1225. PFILE_OBJECT rootObject;
  1226. PAFD_ENDPOINT rootEndpoint;
  1227. status = ObReferenceObjectByHandle(
  1228. rootEndpointHandle,
  1229. (IrpSp->Parameters.DeviceIoControl.IoControlCode>>14) & 3,
  1230. // DesiredAccess
  1231. *IoFileObjectType, // ObjectType
  1232. Irp->RequestorMode,
  1233. (PVOID *)&rootObject,
  1234. NULL
  1235. );
  1236. if (!NT_SUCCESS (status)) {
  1237. goto complete_deref;
  1238. }
  1239. if (rootObject->DeviceObject!=AfdDeviceObject) {
  1240. ObDereferenceObject (rootObject);
  1241. status = STATUS_INVALID_HANDLE;
  1242. goto complete_deref;
  1243. }
  1244. //
  1245. // Get the endpoint structure of the file object
  1246. //
  1247. rootEndpoint = rootObject->FsContext;
  1248. if (!AFD_START_STATE_CHANGE (leafEndpoint, AfdEndpointStateConnected)) {
  1249. ObDereferenceObject (rootObject);
  1250. status = STATUS_INVALID_PARAMETER;
  1251. goto complete_deref;
  1252. }
  1253. //
  1254. // Verify root and leaf endpoint's type and states
  1255. //
  1256. if (IS_VC_ENDPOINT(rootEndpoint) &&
  1257. rootEndpoint->afdC_Root &&
  1258. rootEndpoint->State==AfdEndpointStateConnected &&
  1259. (leafEndpoint->Type == AfdBlockTypeEndpoint ||
  1260. leafEndpoint->Type == AfdBlockTypeVcConnecting) &&
  1261. leafEndpoint->TransportInfo==rootEndpoint->TransportInfo &&
  1262. leafEndpoint->State==AfdEndpointStateOpen) {
  1263. //
  1264. // Create a connection object to use for the connect operation.
  1265. //
  1266. status = AfdCreateConnection(
  1267. rootEndpoint->TransportInfo,
  1268. rootEndpoint->AddressHandle,
  1269. IS_TDI_BUFFERRING(rootEndpoint),
  1270. leafEndpoint->InLine,
  1271. leafEndpoint->OwningProcess,
  1272. &connection
  1273. );
  1274. //
  1275. // No more joins are allowed while this one is active
  1276. //
  1277. if (AFD_START_STATE_CHANGE (rootEndpoint, rootEndpoint->State)) {
  1278. AfdJoinInviteSetup (rootEndpoint, leafEndpoint);
  1279. }
  1280. else {
  1281. status = STATUS_INVALID_PARAMETER;
  1282. }
  1283. }
  1284. else {
  1285. status = STATUS_INVALID_PARAMETER;
  1286. }
  1287. //
  1288. // We referenced root endpoint in invite routine, so
  1289. // we no longer need reference to root file object
  1290. //
  1291. ObDereferenceObject (rootObject);
  1292. if (!NT_SUCCESS (status)) {
  1293. goto complete_state_change;
  1294. }
  1295. }
  1296. else {
  1297. //
  1298. // If this is a datagram endpoint, simply remember the specified
  1299. // address so that we can use it on sends, and writes.
  1300. //
  1301. if ( IS_DGRAM_ENDPOINT(leafEndpoint) ) {
  1302. if (leafEndpoint->State!=AfdEndpointStateConnected) {
  1303. return AfdDoDatagramConnect( fileObject, Irp, TRUE);
  1304. }
  1305. else {
  1306. //
  1307. // If endpoint is already connected, that connection takes
  1308. // precedence
  1309. //
  1310. status = STATUS_SUCCESS;
  1311. goto complete_deref;
  1312. }
  1313. }
  1314. else {
  1315. if (!AFD_START_STATE_CHANGE (leafEndpoint, AfdEndpointStateConnected)) {
  1316. status = STATUS_INVALID_PARAMETER;
  1317. goto complete_deref;
  1318. }
  1319. if ((leafEndpoint->Type != AfdBlockTypeEndpoint &&
  1320. leafEndpoint->Type != AfdBlockTypeVcConnecting) ||
  1321. leafEndpoint->State != AfdEndpointStateBound) {
  1322. status = STATUS_INVALID_PARAMETER;
  1323. goto complete_state_change;
  1324. }
  1325. //
  1326. // Create a connection object to use for the connect operation.
  1327. //
  1328. status = AfdCreateConnection(
  1329. leafEndpoint->TransportInfo,
  1330. leafEndpoint->AddressHandle,
  1331. IS_TDI_BUFFERRING(leafEndpoint),
  1332. leafEndpoint->InLine,
  1333. leafEndpoint->OwningProcess,
  1334. &connection
  1335. );
  1336. if ( !NT_SUCCESS(status) ) {
  1337. goto complete_state_change;
  1338. }
  1339. }
  1340. }
  1341. IF_DEBUG(CONNECT) {
  1342. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1343. "AfdJoinLeaf: starting join for endpoint %p\n",
  1344. leafEndpoint ));
  1345. }
  1346. //
  1347. // Set up a referenced pointer from the connection to the endpoint.
  1348. // Note that we set up the connection's pointer to the endpoint
  1349. // BEFORE the endpoint's pointer to the connection so that AfdPoll
  1350. // doesn't try to back reference the endpoint from the connection.
  1351. //
  1352. REFERENCE_ENDPOINT( leafEndpoint );
  1353. connection->Endpoint = leafEndpoint;
  1354. //
  1355. // Remember that this is now a connecting type of endpoint, and set
  1356. // up a pointer to the connection in the endpoint. This is
  1357. // implicitly a referenced pointer.
  1358. //
  1359. leafEndpoint->Common.VcConnecting.Connection = connection;
  1360. leafEndpoint->Type = AfdBlockTypeVcConnecting;
  1361. ASSERT( IS_TDI_BUFFERRING(leafEndpoint) == connection->TdiBufferring );
  1362. //
  1363. // Add an additional reference to the connection. This prevents the
  1364. // connection from being closed until the disconnect event handler
  1365. // is called.
  1366. //
  1367. AfdAddConnectedReference( connection );
  1368. //
  1369. // If there are connect data buffers, move them from the endpoint
  1370. // structure to the connection structure and set up the necessary
  1371. // pointers in the connection request we're going to give to the TDI
  1372. // provider. Do this in a subroutine so this routine can be pageable.
  1373. //
  1374. requestConnectionInfo = &context->RequestConnectionInfo;
  1375. returnConnectionInfo = &context->ReturnConnectionInfo;
  1376. if ( leafEndpoint->Common.VirtualCircuit.ConnectDataBuffers != NULL ) {
  1377. AfdSetupConnectDataBuffers(
  1378. leafEndpoint,
  1379. connection,
  1380. &requestConnectionInfo,
  1381. &returnConnectionInfo
  1382. );
  1383. }
  1384. //
  1385. // Since we may be reissuing a connect after a previous failed connect,
  1386. // reenable the failed connect event bit.
  1387. //
  1388. AfdEnableFailedConnectEvent( leafEndpoint );
  1389. REFERENCE_CONNECTION (connection);
  1390. //
  1391. // Build a TDI kernel-mode connect request in the next stack location
  1392. // of the IRP.
  1393. //
  1394. TdiBuildConnect(
  1395. Irp,
  1396. connection->DeviceObject,
  1397. connection->FileObject,
  1398. AfdRestartJoin,
  1399. connection,
  1400. &AfdInfiniteTimeout,
  1401. requestConnectionInfo,
  1402. returnConnectionInfo
  1403. );
  1404. AFD_VERIFY_ADDRESS (connection, &context->ReturnConnectionInfo->RemoteAddress);
  1405. //
  1406. // Call the transport to actually perform the connect operation.
  1407. //
  1408. return AfdIoCallDriver( leafEndpoint, connection->DeviceObject, Irp );
  1409. complete_state_change:
  1410. AFD_END_STATE_CHANGE (leafEndpoint);
  1411. complete_deref:
  1412. ObDereferenceObject (fileObject);
  1413. complete:
  1414. if (context!=NULL) {
  1415. AFD_FREE_POOL (context, AFD_TDI_POOL_TAG);
  1416. ASSERT (Irp->AssociatedIrp.SystemBuffer==context);
  1417. Irp->AssociatedIrp.SystemBuffer = NULL;
  1418. }
  1419. if (connection!=NULL) {
  1420. DEREFERENCE_CONNECTION (connection);
  1421. }
  1422. Irp->IoStatus.Information = 0;
  1423. Irp->IoStatus.Status = status;
  1424. IoCompleteRequest( Irp, AfdPriorityBoost );
  1425. return status;
  1426. } // AfdJoinLeaf
  1427. VOID
  1428. AfdJoinInviteSetup (
  1429. PAFD_ENDPOINT RootEndpoint,
  1430. PAFD_ENDPOINT LeafEndpoint
  1431. )
  1432. {
  1433. NTSTATUS status;
  1434. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1435. RootEndpoint->EventsActive &= ~AFD_POLL_CONNECT;
  1436. AfdAcquireSpinLock (&LeafEndpoint->SpinLock, &lockHandle);
  1437. LeafEndpoint->TdiServiceFlags = RootEndpoint->TdiServiceFlags;
  1438. //
  1439. // Set up a referenced pointer to the root endpoint. This is
  1440. // necessary so that the endpoint does not go away until all
  1441. // leaf endpoints have gone away. Without this, we can free
  1442. // several shared strucutures that are associated with root
  1443. // endpoint and then attempt to use them in leaf endpoints.
  1444. //
  1445. REFERENCE_ENDPOINT (RootEndpoint);
  1446. LeafEndpoint->Common.VcConnecting.ListenEndpoint = RootEndpoint;
  1447. //
  1448. // Set up a referenced pointer in the accepted endpoint to the
  1449. // TDI address object.
  1450. //
  1451. ObReferenceObject( RootEndpoint->AddressFileObject );
  1452. AfdRecordAddrRef();
  1453. LeafEndpoint->AddressFileObject = RootEndpoint->AddressFileObject;
  1454. LeafEndpoint->AddressDeviceObject = RootEndpoint->AddressDeviceObject;
  1455. //
  1456. // Copy the pointer to the local address. Because we keep listen
  1457. // endpoint alive for as long as any of its connection is
  1458. // active, we can rely on the fact that address structure won't go
  1459. // away as well.
  1460. //
  1461. LeafEndpoint->LocalAddress = RootEndpoint->LocalAddress;
  1462. LeafEndpoint->LocalAddressLength = RootEndpoint->LocalAddressLength;
  1463. status = STATUS_SUCCESS;
  1464. AfdReleaseSpinLock (&LeafEndpoint->SpinLock, &lockHandle);
  1465. } // AfdJoinInviteSetup
  1466. NTSTATUS
  1467. AfdRestartJoin (
  1468. IN PDEVICE_OBJECT DeviceObject,
  1469. IN PIRP Irp,
  1470. IN PVOID Context
  1471. )
  1472. /*++
  1473. Routine Description:
  1474. Handles the IOCTL_AFD_CONNECT IOCTL.
  1475. Arguments:
  1476. Irp - Pointer to I/O request packet.
  1477. IrpSp - pointer to the IO stack location to use for this request.
  1478. Return Value:
  1479. NTSTATUS -- Indicates whether the request was successfully queued.
  1480. --*/
  1481. {
  1482. PAFD_ENDPOINT endpoint, rootEndpoint;
  1483. PAFD_CONNECTION connection;
  1484. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1485. PIO_STACK_LOCATION irpSp;
  1486. PFILE_OBJECT fileObject;
  1487. PAFD_CONNECT_CONTEXT context;
  1488. UNREFERENCED_PARAMETER (DeviceObject);
  1489. connection = Context;
  1490. ASSERT( connection->Type == AfdBlockTypeConnection );
  1491. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1492. fileObject = irpSp->FileObject;
  1493. ASSERT( fileObject->DeviceObject == AfdDeviceObject );
  1494. endpoint = fileObject->FsContext;
  1495. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting );
  1496. context = Irp->AssociatedIrp.SystemBuffer;
  1497. ASSERT( context != NULL );
  1498. IF_DEBUG(CONNECT) {
  1499. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1500. "AfdRestartJoin: join completed, status = %X, "
  1501. "LeafEndpoint = %p, RootEndpoint = %p\n",
  1502. Irp->IoStatus.Status, endpoint,
  1503. endpoint->Common.VcConnecting.ListenEndpoint ));
  1504. }
  1505. //
  1506. // If this endpoint has root associated with it,
  1507. // we need to update it as well.
  1508. //
  1509. rootEndpoint = endpoint->Common.VcConnecting.ListenEndpoint;
  1510. ASSERT ( rootEndpoint==NULL ||
  1511. (rootEndpoint->afdC_Root &&
  1512. (rootEndpoint->Type == AfdBlockTypeVcConnecting ||
  1513. rootEndpoint->Type == AfdBlockTypeVcBoth) ) );
  1514. //
  1515. // If there are connect buffers on this endpoint, remember the
  1516. // size of the return connect data.
  1517. //
  1518. if ( connection->ConnectDataBuffers != NULL ) {
  1519. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  1520. //
  1521. // Double-check under the lock
  1522. //
  1523. if ( connection->ConnectDataBuffers != NULL ) {
  1524. NTSTATUS status;
  1525. status = AfdSaveReceivedConnectData(
  1526. &connection->ConnectDataBuffers,
  1527. IOCTL_AFD_SET_CONNECT_DATA,
  1528. connection->ConnectDataBuffers->ReturnConnectionInfo.UserData,
  1529. connection->ConnectDataBuffers->ReturnConnectionInfo.UserDataLength
  1530. );
  1531. ASSERT (NT_SUCCESS (status));
  1532. status = AfdSaveReceivedConnectData(
  1533. &connection->ConnectDataBuffers,
  1534. IOCTL_AFD_SET_CONNECT_OPTIONS,
  1535. connection->ConnectDataBuffers->ReturnConnectionInfo.Options,
  1536. connection->ConnectDataBuffers->ReturnConnectionInfo.OptionsLength
  1537. );
  1538. ASSERT (NT_SUCCESS (status));
  1539. }
  1540. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1541. }
  1542. //
  1543. // Indicate that the connect completed. Implicitly, the successful
  1544. // completion of a connect also means that the caller can do a send
  1545. // on the socket.
  1546. //
  1547. if ( NT_SUCCESS(Irp->IoStatus.Status) ) {
  1548. //
  1549. // If the request succeeded, set the endpoint to the connected
  1550. // state. The endpoint type has already been set to
  1551. // AfdBlockTypeVcConnecting.
  1552. //
  1553. endpoint->State = AfdEndpointStateConnected;
  1554. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting );
  1555. //
  1556. // Remember the time that the connection started.
  1557. //
  1558. connection->ConnectTime = KeQueryInterruptTime();
  1559. } else {
  1560. //
  1561. // The connect failed, so reset the type to open.
  1562. // If we don't reset, we won't be able to start
  1563. // another join
  1564. //
  1565. endpoint->Type = AfdBlockTypeEndpoint;
  1566. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  1567. //
  1568. // Remove references to listening endpoint and connection
  1569. // Actual dereferncing is below after we release the spinlock
  1570. if (rootEndpoint!=NULL) {
  1571. endpoint->Common.VcConnecting.ListenEndpoint = NULL;
  1572. //
  1573. // We used the local address from the listening endpoint,
  1574. // simply reset it, it will be freed when listening endpoint
  1575. // is freed.
  1576. //
  1577. ASSERT (endpoint->LocalAddress==rootEndpoint->LocalAddress);
  1578. endpoint->LocalAddress = NULL;
  1579. endpoint->LocalAddressLength = 0;
  1580. }
  1581. if (endpoint->Common.VcConnecting.Connection != NULL) {
  1582. endpoint->Common.VcConnecting.Connection = NULL;
  1583. //
  1584. // Manually delete the connected reference if somebody else
  1585. // hasn't already done so. We can't use
  1586. // AfdDeleteConnectedReference() because it refuses to delete
  1587. // the connected reference until the endpoint has been cleaned
  1588. // up.
  1589. //
  1590. if ( connection->ConnectedReferenceAdded ) {
  1591. connection->ConnectedReferenceAdded = FALSE;
  1592. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1593. DEREFERENCE_CONNECTION( connection );
  1594. } else {
  1595. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1596. }
  1597. //
  1598. // Dereference the connection block stored on the endpoint.
  1599. // This should cause the connection object reference count to go
  1600. // to zero to the connection object can be deleted.
  1601. //
  1602. DEREFERENCE_CONNECTION( connection );
  1603. }
  1604. else {
  1605. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1606. }
  1607. }
  1608. AFD_FREE_POOL (context, AFD_TDI_POOL_TAG);
  1609. Irp->AssociatedIrp.SystemBuffer = NULL;
  1610. //
  1611. // If pending has be returned for this irp then mark the current
  1612. // stack as pending.
  1613. //
  1614. if ( Irp->PendingReturned ) {
  1615. IoMarkIrpPending(Irp);
  1616. }
  1617. AfdCompleteOutstandingIrp( endpoint, Irp );
  1618. //
  1619. // Dereference connection to account for reference
  1620. // we added in AfdConnect
  1621. //
  1622. DEREFERENCE_CONNECTION( connection );
  1623. //
  1624. // Try to queue kernel APC to the user thread that
  1625. // started the connection operation, so we can
  1626. // communicate the status of the connect operation to
  1627. // msafd.dll before we inform the application through
  1628. // the select or EventSelect. Otherwise, we run into the
  1629. // race condition when application learns about connect first,
  1630. // calls msafd.dll that is not aware of the completion and
  1631. // returns WSAENOTCONN.
  1632. //
  1633. if ((Irp->RequestorMode==UserMode) && // Must be user mode calls
  1634. (Irp->UserBuffer!=NULL) && // Must be interested in status
  1635. // Thread should be able to
  1636. // run APCs.
  1637. (KeInitializeApc (&endpoint->Common.VcConnecting.Apc,
  1638. PsGetThreadTcb (Irp->Tail.Overlay.Thread),
  1639. Irp->ApcEnvironment,
  1640. AfdConnectApcKernelRoutine,
  1641. AfdConnectApcRundownRoutine,
  1642. (PKNORMAL_ROUTINE)NULL,
  1643. KernelMode,
  1644. NULL
  1645. ),
  1646. KeInsertQueueApc (&endpoint->Common.VcConnecting.Apc,
  1647. Irp,
  1648. rootEndpoint,
  1649. AfdPriorityBoost))) {
  1650. //
  1651. // We will complete the IRP in the APC.
  1652. //
  1653. return STATUS_MORE_PROCESSING_REQUIRED;
  1654. }
  1655. else {
  1656. //
  1657. // APC was not necessary or did not work.
  1658. // Complete it here.
  1659. //
  1660. AfdFinishConnect (endpoint, Irp, rootEndpoint);
  1661. return STATUS_SUCCESS;
  1662. }
  1663. } // AfdRestartJoin
  1664. NTSTATUS
  1665. FASTCALL
  1666. AfdSuperConnect (
  1667. IN PIRP Irp,
  1668. IN PIO_STACK_LOCATION IrpSp
  1669. )
  1670. /*++
  1671. Routine Description:
  1672. Handles the IOCTL_AFD_SUPER_CONNECT IOCTL.
  1673. Arguments:
  1674. Irp - Pointer to I/O request packet.
  1675. IrpSp - pointer to the IO stack location to use for this request.
  1676. Return Value:
  1677. NTSTATUS -- Indicates whether the request was successfully queued.
  1678. --*/
  1679. {
  1680. NTSTATUS status;
  1681. PAFD_ENDPOINT endpoint;
  1682. PAFD_CONNECTION connection;
  1683. PAFD_BUFFER afdBuffer;
  1684. PAFD_SUPER_CONNECT_INFO connectInfo;
  1685. PTRANSPORT_ADDRESS remoteAddress;
  1686. PVOID context;
  1687. PTDI_CONNECTION_INFORMATION requestConnectionInfo, returnConnectionInfo;
  1688. PAGED_CODE( );
  1689. //
  1690. // Initialize for proper cleanup
  1691. //
  1692. afdBuffer = NULL;
  1693. endpoint = IrpSp->FileObject->FsContext;
  1694. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength<
  1695. (ULONG)FIELD_OFFSET(AFD_SUPER_CONNECT_INFO, RemoteAddress.Address[0].Address)) {
  1696. status = STATUS_INVALID_PARAMETER;
  1697. goto complete;
  1698. }
  1699. AFD_W4_INIT status = STATUS_SUCCESS;
  1700. try {
  1701. if( Irp->RequestorMode != KernelMode ) {
  1702. ProbeForRead(
  1703. IrpSp->Parameters.DeviceIoControl.Type3InputBuffer,
  1704. IrpSp->Parameters.DeviceIoControl.InputBufferLength,
  1705. PROBE_ALIGNMENT (AFD_SUPER_CONNECT_INFO)
  1706. );
  1707. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength!=0) {
  1708. ProbeForRead (Irp->UserBuffer,
  1709. IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  1710. sizeof (UCHAR));
  1711. }
  1712. }
  1713. connectInfo = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  1714. //
  1715. // Check for if the caller is unaware of the SAN
  1716. // provider activation and report the error.
  1717. //
  1718. if (!connectInfo->SanActive && AfdSanServiceHelper!=NULL) {
  1719. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  1720. "AFD: Process %p is being told to enable SAN on connect\n",
  1721. PsGetCurrentProcessId ()));
  1722. status = STATUS_INVALID_PARAMETER_12;
  1723. goto complete;
  1724. }
  1725. afdBuffer = AfdGetBufferRaiseOnFailure (
  1726. endpoint,
  1727. IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  1728. IrpSp->Parameters.DeviceIoControl.InputBufferLength-
  1729. FIELD_OFFSET(AFD_SUPER_CONNECT_INFO, RemoteAddress),
  1730. endpoint->OwningProcess
  1731. );
  1732. remoteAddress = afdBuffer->TdiInfo.RemoteAddress;
  1733. afdBuffer->TdiInfo.RemoteAddressLength =
  1734. IrpSp->Parameters.DeviceIoControl.InputBufferLength-
  1735. FIELD_OFFSET(AFD_SUPER_CONNECT_INFO, RemoteAddress);
  1736. RtlCopyMemory (afdBuffer->TdiInfo.RemoteAddress,
  1737. &connectInfo->RemoteAddress,
  1738. afdBuffer->TdiInfo.RemoteAddressLength);
  1739. //
  1740. // Validate internal consistency of the transport address structure.
  1741. // Note that we HAVE to do this after copying since the malicious
  1742. // application can change the content of the buffer on us any time
  1743. // and our check will be bypassed.
  1744. //
  1745. if ((remoteAddress->TAAddressCount!=1) ||
  1746. (LONG)afdBuffer->TdiInfo.RemoteAddressLength<
  1747. FIELD_OFFSET (TRANSPORT_ADDRESS,
  1748. Address[0].Address[remoteAddress->Address[0].AddressLength])) {
  1749. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  1750. }
  1751. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength>0) {
  1752. RtlCopyMemory (afdBuffer->Buffer,
  1753. Irp->UserBuffer,
  1754. IrpSp->Parameters.DeviceIoControl.OutputBufferLength
  1755. );
  1756. afdBuffer->DataLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  1757. }
  1758. else {
  1759. afdBuffer->DataLength = 0;
  1760. }
  1761. }
  1762. except (AFD_EXCEPTION_FILTER(status)) {
  1763. ASSERT (NT_ERROR (status));
  1764. goto complete;
  1765. }
  1766. if (!AFD_START_STATE_CHANGE (endpoint, AfdEndpointStateConnected)) {
  1767. status = STATUS_INVALID_PARAMETER;
  1768. goto complete;
  1769. }
  1770. //
  1771. // If the endpoint is not bound, then this is an invalid request.
  1772. // Listening endpoints are not allowed as well.
  1773. // We do not support sending data with TDI buffering transports too.
  1774. //
  1775. if ( endpoint->Type != AfdBlockTypeEndpoint ||
  1776. endpoint->State != AfdEndpointStateBound ||
  1777. endpoint->Listening ||
  1778. (IS_TDI_BUFFERRING (endpoint) &&
  1779. IrpSp->Parameters.DeviceIoControl.OutputBufferLength!=0)) {
  1780. if (endpoint->State==AfdEndpointStateConnected) {
  1781. status = STATUS_CONNECTION_ACTIVE;
  1782. }
  1783. else {
  1784. status = STATUS_INVALID_PARAMETER;
  1785. }
  1786. goto complete_state_change;
  1787. }
  1788. IF_DEBUG(CONNECT) {
  1789. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1790. "AfdSuperConnect: starting connect on endpoint %p\n",
  1791. endpoint ));
  1792. }
  1793. //
  1794. // Create a connection object to use for the connect operation.
  1795. //
  1796. status = AfdCreateConnection(
  1797. endpoint->TransportInfo,
  1798. endpoint->AddressHandle,
  1799. IS_TDI_BUFFERRING(endpoint),
  1800. endpoint->InLine,
  1801. endpoint->OwningProcess,
  1802. &connection
  1803. );
  1804. if ( !NT_SUCCESS(status) ) {
  1805. goto complete_state_change;
  1806. }
  1807. //
  1808. // Set up a referenced pointer from the connection to the endpoint.
  1809. // Note that we set up the connection's pointer to the endpoint
  1810. // BEFORE the endpoint's pointer to the connection so that AfdPoll
  1811. // doesn't try to back reference the endpoint from the connection.
  1812. //
  1813. REFERENCE_ENDPOINT( endpoint );
  1814. connection->Endpoint = endpoint;
  1815. //
  1816. // Remember that this is now a connecting type of endpoint, and set
  1817. // up a pointer to the connection in the endpoint. This is
  1818. // implicitly a referenced pointer.
  1819. //
  1820. endpoint->Common.VcConnecting.Connection = connection;
  1821. endpoint->Type = AfdBlockTypeVcConnecting;
  1822. ASSERT( IS_TDI_BUFFERRING(endpoint) == connection->TdiBufferring );
  1823. //
  1824. // Add an additional reference to the connection. This prevents the
  1825. // connection from being closed until the disconnect event handler
  1826. // is called.
  1827. //
  1828. AfdAddConnectedReference( connection );
  1829. //
  1830. // Since we may be reissuing a connect after a previous failed connect,
  1831. // reenable the failed connect event bit.
  1832. //
  1833. AfdEnableFailedConnectEvent( endpoint );
  1834. //
  1835. // Copy remote address to the user mode context
  1836. //
  1837. context = AfdLockEndpointContext (endpoint);
  1838. if ( (((CLONG)(endpoint->Common.VcConnecting.RemoteSocketAddressOffset+
  1839. endpoint->Common.VcConnecting.RemoteSocketAddressLength)) <
  1840. endpoint->ContextLength) &&
  1841. (endpoint->Common.VcConnecting.RemoteSocketAddressLength >=
  1842. remoteAddress->Address[0].AddressLength +
  1843. sizeof(u_short))) {
  1844. RtlMoveMemory ((PUCHAR)context +
  1845. endpoint->Common.VcConnecting.RemoteSocketAddressOffset,
  1846. &remoteAddress->Address[0].AddressType,
  1847. remoteAddress->Address[0].AddressLength +
  1848. sizeof(u_short));
  1849. }
  1850. else {
  1851. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_WARNING_LEVEL,
  1852. "AfdSuperConnect: Could not copy remote address for AcceptEx on endpoint: %p, process: %p\n",
  1853. endpoint, endpoint->OwningProcess));
  1854. }
  1855. AfdUnlockEndpointContext (endpoint, context);
  1856. //
  1857. // Reference the connection block so it does not go away even if
  1858. // endpoint's reference to it is removed (in cleanup)
  1859. //
  1860. REFERENCE_CONNECTION (connection);
  1861. //
  1862. // If there are connect data buffers, move them from the endpoint
  1863. // structure to the connection structure and set up the necessary
  1864. // pointers in the connection request we're going to give to the TDI
  1865. // provider. Do this in a subroutine so this routine can be pageable.
  1866. //
  1867. requestConnectionInfo = &afdBuffer->TdiInfo;
  1868. afdBuffer->TdiInfo.UserDataLength = 0;
  1869. afdBuffer->TdiInfo.UserData = NULL;
  1870. afdBuffer->TdiInfo.OptionsLength = 0;
  1871. afdBuffer->TdiInfo.Options = NULL;
  1872. //
  1873. // Temporarily use IRP embedded in afd buffer
  1874. // for return connection information.
  1875. //
  1876. {
  1877. C_ASSERT (sizeof (TDI_CONNECTION_INFORMATION)<=
  1878. sizeof (IO_STACK_LOCATION));
  1879. }
  1880. returnConnectionInfo =
  1881. (PTDI_CONNECTION_INFORMATION)IoGetNextIrpStackLocation (afdBuffer->Irp);
  1882. RtlZeroMemory (returnConnectionInfo, sizeof (*returnConnectionInfo));
  1883. if ( endpoint->Common.VirtualCircuit.ConnectDataBuffers != NULL ) {
  1884. AfdSetupConnectDataBuffers(
  1885. endpoint,
  1886. connection,
  1887. &requestConnectionInfo,
  1888. &returnConnectionInfo
  1889. );
  1890. }
  1891. afdBuffer->Context = connection;
  1892. //
  1893. // Build a TDI kernel-mode connect request in the next stack location
  1894. // of the IRP.
  1895. //
  1896. TdiBuildConnect(
  1897. Irp,
  1898. connection->DeviceObject,
  1899. connection->FileObject,
  1900. AfdRestartSuperConnect,
  1901. afdBuffer,
  1902. &AfdInfiniteTimeout,
  1903. requestConnectionInfo,
  1904. returnConnectionInfo
  1905. );
  1906. AFD_VERIFY_ADDRESS (connection, afdBuffer->TdiInfo.RemoteAddress);
  1907. ObReferenceObject (IrpSp->FileObject);
  1908. //
  1909. // Call the transport to actually perform the connect operation.
  1910. //
  1911. return AfdIoCallDriver( endpoint, connection->DeviceObject, Irp );
  1912. complete_state_change:
  1913. AFD_END_STATE_CHANGE (endpoint);
  1914. complete:
  1915. if (afdBuffer!=NULL) {
  1916. AfdReturnBuffer (&afdBuffer->Header, endpoint->OwningProcess);
  1917. }
  1918. Irp->IoStatus.Information = 0;
  1919. Irp->IoStatus.Status = status;
  1920. IoCompleteRequest( Irp, AfdPriorityBoost );
  1921. return status;
  1922. } // AfdSuperConnect
  1923. NTSTATUS
  1924. AfdRestartSuperConnect (
  1925. IN PDEVICE_OBJECT DeviceObject,
  1926. IN PIRP Irp,
  1927. IN PVOID Context
  1928. )
  1929. /*++
  1930. Routine Description:
  1931. Handles the IOCTL_AFD_CONNECT IOCTL.
  1932. Arguments:
  1933. Irp - Pointer to I/O request packet.
  1934. IrpSp - pointer to the IO stack location to use for this request.
  1935. Return Value:
  1936. NTSTATUS -- Indicates whether the request was successfully queued.
  1937. --*/
  1938. {
  1939. PAFD_ENDPOINT endpoint;
  1940. PAFD_CONNECTION connection;
  1941. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1942. PIO_STACK_LOCATION irpSp;
  1943. PAFD_BUFFER afdBuffer;
  1944. UNREFERENCED_PARAMETER (DeviceObject);
  1945. afdBuffer = Context;
  1946. connection = afdBuffer->Context;
  1947. ASSERT( connection->Type == AfdBlockTypeConnection );
  1948. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1949. endpoint = irpSp->FileObject->FsContext;
  1950. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting );
  1951. ASSERT( endpoint==connection->Endpoint );
  1952. IF_DEBUG(CONNECT) {
  1953. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1954. "AfdRestartConnect: connect completed, status = %X, endpoint = %p\n",
  1955. Irp->IoStatus.Status, endpoint ));
  1956. }
  1957. if ( connection->ConnectDataBuffers != NULL ) {
  1958. //
  1959. // If there are connect buffers on this endpoint, remember the
  1960. // size of the return connect data.
  1961. //
  1962. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  1963. //
  1964. // Double-check under the lock
  1965. //
  1966. if ( connection->ConnectDataBuffers != NULL ) {
  1967. AfdSaveReceivedConnectData(
  1968. &connection->ConnectDataBuffers,
  1969. IOCTL_AFD_SET_CONNECT_DATA,
  1970. connection->ConnectDataBuffers->ReturnConnectionInfo.UserData,
  1971. connection->ConnectDataBuffers->ReturnConnectionInfo.UserDataLength
  1972. );
  1973. AfdSaveReceivedConnectData(
  1974. &connection->ConnectDataBuffers,
  1975. IOCTL_AFD_SET_CONNECT_OPTIONS,
  1976. connection->ConnectDataBuffers->ReturnConnectionInfo.Options,
  1977. connection->ConnectDataBuffers->ReturnConnectionInfo.OptionsLength
  1978. );
  1979. }
  1980. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1981. }
  1982. //
  1983. // Indicate that the connect completed. Implicitly, the successful
  1984. // completion of a connect also means that the caller can do a send
  1985. // on the socket.
  1986. //
  1987. if ( NT_SUCCESS(Irp->IoStatus.Status)) {
  1988. //
  1989. // If the request succeeded, set the endpoint to the connected
  1990. // state. The endpoint type has already been set to
  1991. // AfdBlockTypeVcConnecting.
  1992. //
  1993. endpoint->State = AfdEndpointStateConnected;
  1994. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting );
  1995. //
  1996. // Remember the time that the connection started.
  1997. //
  1998. connection->ConnectTime = KeQueryInterruptTime();
  1999. } else {
  2000. //
  2001. // The connect failed, so reset the type to open.
  2002. // Otherwise, we won't be able to start another connect
  2003. //
  2004. endpoint->Type = AfdBlockTypeEndpoint;
  2005. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  2006. if (endpoint->Common.VcConnecting.Connection!=NULL) {
  2007. ASSERT (connection==endpoint->Common.VcConnecting.Connection);
  2008. endpoint->Common.VcConnecting.Connection = NULL;
  2009. //
  2010. // Manually delete the connected reference if somebody else
  2011. // hasn't already done so. We can't use
  2012. // AfdDeleteConnectedReference() because it refuses to delete
  2013. // the connected reference until the endpoint has been cleaned
  2014. // up.
  2015. //
  2016. if ( connection->ConnectedReferenceAdded ) {
  2017. connection->ConnectedReferenceAdded = FALSE;
  2018. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  2019. DEREFERENCE_CONNECTION( connection );
  2020. } else {
  2021. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  2022. }
  2023. //
  2024. // Dereference the connection block stored on the endpoint.
  2025. // This should cause the connection object reference count to go
  2026. // to zero to the connection object can be deleted.
  2027. //
  2028. DEREFERENCE_CONNECTION( connection );
  2029. }
  2030. else {
  2031. //
  2032. // The endpoint's reference to connection was removed
  2033. // (perhaps in cleanup);
  2034. //
  2035. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  2036. }
  2037. }
  2038. //
  2039. // If pending has be returned for this irp then mark the current
  2040. // stack as pending.
  2041. //
  2042. if ( Irp->PendingReturned ) {
  2043. IoMarkIrpPending(Irp);
  2044. }
  2045. AfdCompleteOutstandingIrp( endpoint, Irp );
  2046. AfdFinishConnect (endpoint, Irp, NULL);
  2047. if (NT_SUCCESS (Irp->IoStatus.Status) && afdBuffer->DataLength>0) {
  2048. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  2049. if ( !connection->CleanupBegun && !connection->Aborted ) {
  2050. NTSTATUS status;
  2051. //
  2052. // Update count of send bytes pending on the connection.
  2053. //
  2054. connection->VcBufferredSendBytes += afdBuffer->DataLength;
  2055. connection->VcBufferredSendCount += 1;
  2056. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  2057. afdBuffer->Mdl->ByteCount = afdBuffer->DataLength;
  2058. ASSERT (afdBuffer->Context == connection );
  2059. TdiBuildSend(
  2060. afdBuffer->Irp,
  2061. connection->DeviceObject,
  2062. connection->FileObject,
  2063. AfdRestartBufferSend,
  2064. afdBuffer,
  2065. afdBuffer->Mdl,
  2066. 0,
  2067. afdBuffer->DataLength
  2068. );
  2069. Irp->IoStatus.Information = afdBuffer->DataLength;
  2070. //
  2071. // Call the transport to actually perform the send.
  2072. //
  2073. status = IoCallDriver (
  2074. connection->DeviceObject,
  2075. afdBuffer->Irp
  2076. );
  2077. if (!NT_SUCCESS (status)) {
  2078. Irp->IoStatus.Status = status;
  2079. Irp->IoStatus.Information = 0;
  2080. }
  2081. goto exit;
  2082. }
  2083. if (connection->CleanupBegun) {
  2084. Irp->IoStatus.Status = STATUS_LOCAL_DISCONNECT;
  2085. }
  2086. else {
  2087. ASSERT (connection->Aborted);
  2088. Irp->IoStatus.Status = STATUS_REMOTE_DISCONNECT;
  2089. }
  2090. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  2091. }
  2092. afdBuffer->DataOffset = 0;
  2093. AfdReturnBuffer (&afdBuffer->Header, endpoint->OwningProcess);
  2094. //
  2095. // Dereference connection to account for reference we added in AfdConnect
  2096. //
  2097. DEREFERENCE_CONNECTION (connection);
  2098. exit:
  2099. return STATUS_SUCCESS;
  2100. } // AfdRestartSuperConnect