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.

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