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.

3444 lines
103 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. pnp.c
  5. Abstract:
  6. This module contains the PnP and PM routines
  7. Author:
  8. Vadim Eydelman (vadime) Apr-1997
  9. Revision History:
  10. --*/
  11. #include "afdp.h"
  12. NTSTATUS
  13. AfdPassQueryDeviceRelation (
  14. IN PFILE_OBJECT FileObject,
  15. IN PIRP Irp,
  16. IN PIO_STACK_LOCATION IrpSp
  17. );
  18. NTSTATUS
  19. AfdRestartQueryDeviceRelation (
  20. IN PDEVICE_OBJECT DeviceObject,
  21. IN PIRP Irp,
  22. IN PVOID Context
  23. );
  24. #ifdef ALLOC_PRAGMA
  25. #pragma alloc_text( PAGE, AfdPnpPower )
  26. #pragma alloc_text( PAGE, AfdPassQueryDeviceRelation )
  27. #pragma alloc_text( PAGEAFD, AfdRestartQueryDeviceRelation )
  28. #endif
  29. NTSTATUS
  30. FASTCALL
  31. AfdPnpPower (
  32. IN PIRP Irp,
  33. IN PIO_STACK_LOCATION IrpSp
  34. )
  35. /*++
  36. Routine Description:
  37. This is the dispatch routine for PNP_POWER irp
  38. Arguments:
  39. Irp - Pointer to I/O request packet.
  40. IrpSp - pointer to the stack location to use for this request.
  41. Return Value:
  42. NTSTATUS -- Indicates whether the request was successfully queued.
  43. --*/
  44. {
  45. PAGED_CODE( );
  46. switch (IrpSp->MinorFunction) {
  47. //
  48. // We only support target device relation query
  49. //
  50. case IRP_MN_QUERY_DEVICE_RELATIONS:
  51. if (IrpSp->Parameters.QueryDeviceRelations.Type==TargetDeviceRelation) {
  52. NTSTATUS status;
  53. PAFD_ENDPOINT endpoint;
  54. PAFD_CONNECTION connection;
  55. //
  56. // Set up local variables.
  57. //
  58. endpoint = IrpSp->FileObject->FsContext;
  59. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  60. //
  61. // Dispatch to correct TDI object of underlying transport
  62. // driver depedning on endpoint type
  63. //
  64. switch (endpoint->Type) {
  65. case AfdBlockTypeVcConnecting:
  66. case AfdBlockTypeVcBoth:
  67. connection = AfdGetConnectionReferenceFromEndpoint (endpoint);
  68. if (connection!=NULL) {
  69. status = AfdPassQueryDeviceRelation (connection->FileObject,
  70. Irp, IrpSp);
  71. DEREFERENCE_CONNECTION (connection);
  72. return status;
  73. }
  74. // fall through to try address handle if we have one.
  75. case AfdBlockTypeVcListening:
  76. case AfdBlockTypeDatagram:
  77. if (endpoint->State==AfdEndpointStateBound ||
  78. endpoint->State==AfdEndpointStateConnected) {
  79. return AfdPassQueryDeviceRelation (endpoint->AddressFileObject,
  80. Irp, IrpSp);
  81. }
  82. // fall through to fail
  83. case AfdBlockTypeHelper:
  84. case AfdBlockTypeEndpoint:
  85. case AfdBlockTypeSanHelper:
  86. case AfdBlockTypeSanEndpoint:
  87. break;
  88. default:
  89. ASSERT (!"Unknown endpoint type!");
  90. __assume (0);
  91. break;
  92. }
  93. }
  94. default:
  95. break;
  96. }
  97. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  98. IoCompleteRequest( Irp, AfdPriorityBoost );
  99. //
  100. // We do not support the rest
  101. //
  102. return STATUS_INVALID_DEVICE_REQUEST;
  103. }
  104. NTSTATUS
  105. AfdPassQueryDeviceRelation (
  106. IN PFILE_OBJECT FileObject,
  107. IN PIRP Irp,
  108. IN PIO_STACK_LOCATION IrpSp
  109. )
  110. /*++
  111. Routine Description:
  112. This is the dispatch routine for PNP_POWER irp
  113. Arguments:
  114. Irp - Pointer to I/O request packet.
  115. IrpSp - pointer to the stack location to use for this request.
  116. Return Value:
  117. NTSTATUS -- Indicates whether the request was successfully queued.
  118. --*/
  119. {
  120. PIO_STACK_LOCATION nextIrpSp;
  121. PAGED_CODE ();
  122. nextIrpSp = IoGetNextIrpStackLocation( Irp );
  123. *nextIrpSp = *IrpSp;
  124. //
  125. // Reference file object so it does not go away until this
  126. // IRP completes
  127. //
  128. ObReferenceObject (FileObject);
  129. nextIrpSp->FileObject = FileObject;
  130. IoSetCompletionRoutine(
  131. Irp,
  132. AfdRestartQueryDeviceRelation,
  133. FileObject,
  134. TRUE,
  135. TRUE,
  136. TRUE
  137. );
  138. return IoCallDriver( IoGetRelatedDeviceObject( FileObject ), Irp );
  139. }
  140. NTSTATUS
  141. AfdRestartQueryDeviceRelation (
  142. IN PDEVICE_OBJECT DeviceObject,
  143. IN PIRP Irp,
  144. IN PVOID Context
  145. )
  146. {
  147. PFILE_OBJECT fileObject = Context;
  148. //
  149. // Dereference file object that we referenced when calling the
  150. // lower driver
  151. //
  152. ObDereferenceObject (fileObject);
  153. //
  154. // Tell IO system to continue with IRP completion
  155. //
  156. return STATUS_SUCCESS;
  157. }
  158. #include <tdiinfo.h>
  159. #include <ntddip.h>
  160. #include <ntddip6.h>
  161. #include <ntddtcp.h>
  162. #include <ipinfo.h>
  163. typedef struct _AFD_PROTOCOL {
  164. USHORT AddressType;
  165. USHORT AddressLength;
  166. LPWSTR NetworkLayerDeviceName;
  167. LPWSTR TransportLayerDeviceName;
  168. ULONG RtChangeIoctl;
  169. ULONG RtChangeDataSize;
  170. LONG RoutingQueryRefCount;
  171. HANDLE DeviceHandle;
  172. PFILE_OBJECT FileObject;
  173. } AFD_PROTOCOL, *PAFD_PROTOCOL;
  174. NTSTATUS
  175. AfdOpenDevice (
  176. LPWSTR DeviceNameStr,
  177. HANDLE *Handle,
  178. PFILE_OBJECT *FileObject
  179. );
  180. NTSTATUS
  181. AfdGetRoutingQueryReference (
  182. IN PAFD_PROTOCOL Protocol
  183. );
  184. NTSTATUS
  185. AfdTcpQueueRoutingChangeRequest (
  186. IN PAFD_ENDPOINT Endpoint,
  187. IN PIRP Irp,
  188. IN BOOLEAN Overlapped
  189. );
  190. NTSTATUS
  191. AfdTcpRestartRoutingChange (
  192. IN PDEVICE_OBJECT DeviceObject,
  193. IN PIRP Irp,
  194. IN PVOID Context
  195. );
  196. NTSTATUS
  197. AfdTcpSignalRoutingChange (
  198. IN PDEVICE_OBJECT DeviceObject,
  199. IN PIRP Irp,
  200. IN PVOID Context
  201. );
  202. NTSTATUS
  203. AfdTcpRoutingQuery (
  204. PTA_ADDRESS Dest,
  205. PTA_ADDRESS Intf
  206. );
  207. NTSTATUS
  208. AfdTcp6RoutingQuery (
  209. PTA_ADDRESS Dest,
  210. PTA_ADDRESS Intf
  211. );
  212. VOID
  213. AfdDereferenceRoutingQueryEx (
  214. PAFD_PROTOCOL Protocol
  215. );
  216. #ifdef ALLOC_PRAGMA
  217. #pragma alloc_text( PAGE, AfdOpenDevice )
  218. #pragma alloc_text( PAGE, AfdRoutingInterfaceQuery )
  219. #pragma alloc_text( PAGE, AfdTcpRoutingQuery )
  220. #pragma alloc_text( PAGE, AfdTcp6RoutingQuery )
  221. #pragma alloc_text( PAGE, AfdGetRoutingQueryReference )
  222. #pragma alloc_text( PAGE, AfdDereferenceRoutingQuery )
  223. #pragma alloc_text( PAGE, AfdDereferenceRoutingQueryEx )
  224. #pragma alloc_text( PAGEAFD, AfdTcpQueueRoutingChangeRequest )
  225. #pragma alloc_text( PAGEAFD, AfdTcpRestartRoutingChange )
  226. #pragma alloc_text( PAGEAFD, AfdTcpSignalRoutingChange )
  227. #endif
  228. AFD_PROTOCOL Ip = { TDI_ADDRESS_TYPE_IP, TDI_ADDRESS_LENGTH_IP,
  229. DD_IP_DEVICE_NAME, DD_TCP_DEVICE_NAME,
  230. IOCTL_IP_RTCHANGE_NOTIFY_REQUEST,
  231. sizeof(IPNotifyData), 0, NULL, NULL };
  232. AFD_PROTOCOL Ip6= { TDI_ADDRESS_TYPE_IP6, TDI_ADDRESS_LENGTH_IP6,
  233. DD_IPV6_DEVICE_NAME, DD_TCPV6_DEVICE_NAME,
  234. IOCTL_IPV6_RTCHANGE_NOTIFY_REQUEST,
  235. sizeof(IPV6_RTCHANGE_NOTIFY_REQUEST), 0, NULL, NULL };
  236. const char ZeroString[16] = { 0 };
  237. #define TaAddressesEqual(a1,a2) \
  238. (RtlEqualMemory (a1,a2,FIELD_OFFSET (TA_ADDRESS,Address[(a1)->AddressLength])))
  239. NTSTATUS
  240. AfdRoutingInterfaceQuery (
  241. IN PFILE_OBJECT FileObject,
  242. IN ULONG IoctlCode,
  243. IN KPROCESSOR_MODE RequestorMode,
  244. IN PVOID InputBuffer,
  245. IN ULONG InputBufferLength,
  246. IN PVOID OutputBuffer,
  247. IN ULONG OutputBufferLength,
  248. OUT PUINT_PTR Information
  249. )
  250. /*++
  251. Routine Description:
  252. Processes routing query request. Protocol independent portion.
  253. Arguments:
  254. Irp - Pointer to I/O request packet.
  255. IrpSp - pointer to the stack location to use for this request.
  256. Return Value:
  257. NTSTATUS -- Indicates whether the request was successfully queued.
  258. --*/
  259. {
  260. CHAR addrBuffer[AFD_MAX_FAST_TRANSPORT_ADDRESS];
  261. PTRANSPORT_ADDRESS tempAddr;
  262. NTSTATUS status;
  263. PAGED_CODE ();
  264. //
  265. // Initialize locals for proper cleanup.
  266. //
  267. *Information = 0;
  268. tempAddr = (PTRANSPORT_ADDRESS)addrBuffer;
  269. //
  270. // Validate input parameters
  271. //
  272. if( InputBufferLength < sizeof(*tempAddr) ) {
  273. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  274. "AfdRoutingInterfaceQuery: Endp: %p - invalid input buffer (%p-%d).\n",
  275. FileObject->FsContext, InputBuffer, InputBufferLength));
  276. status = STATUS_INVALID_PARAMETER;
  277. goto Complete;
  278. }
  279. try {
  280. //
  281. // Copy input address into the local (or allocated from pool) buffer
  282. //
  283. if (InputBufferLength>sizeof (addrBuffer)) {
  284. tempAddr = AFD_ALLOCATE_POOL_WITH_QUOTA (PagedPool,
  285. InputBufferLength,
  286. AFD_ROUTING_QUERY_POOL_TAG);
  287. // AFD_ALLOCATE_POOL_WITH_QUOTA macro sets POOL_RAISE_IF_ALLOCATION_FAILURE
  288. }
  289. //
  290. // Validate user mode pointers
  291. //
  292. if (RequestorMode!=KernelMode) {
  293. ProbeForRead (InputBuffer,
  294. InputBufferLength,
  295. sizeof (CHAR));
  296. }
  297. RtlCopyMemory (tempAddr,
  298. InputBuffer,
  299. InputBufferLength);
  300. //
  301. // Validate the internal consistency of the transport address AFTER
  302. // copying it into the internal buffer to prevent malicious app from
  303. // changing it on the fly while we are checking.
  304. //
  305. if (tempAddr->TAAddressCount!=1 ||
  306. InputBufferLength <
  307. (ULONG)FIELD_OFFSET (TRANSPORT_ADDRESS,
  308. Address[0].Address[tempAddr->Address[0].AddressLength])) {
  309. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  310. }
  311. }
  312. except (EXCEPTION_EXECUTE_HANDLER) {
  313. status = GetExceptionCode ();
  314. goto Complete;
  315. }
  316. //
  317. // PROBLEM. We only support IP for now
  318. //
  319. switch (tempAddr->Address[0].AddressType) {
  320. case TDI_ADDRESS_TYPE_IP:
  321. status = AfdTcpRoutingQuery (&tempAddr->Address[0], &tempAddr->Address[0]);
  322. break;
  323. case TDI_ADDRESS_TYPE_IP6:
  324. status = AfdTcp6RoutingQuery (&tempAddr->Address[0], &tempAddr->Address[0]);
  325. break;
  326. default:
  327. status = STATUS_NOT_SUPPORTED;
  328. goto Complete;
  329. }
  330. //
  331. // Convert output to socket address if we succeeded.
  332. //
  333. if (NT_SUCCESS (status)) {
  334. //
  335. // Conversion to sockaddr requires extra bytes for address family
  336. // in addition to TDI_ADDRESS
  337. //
  338. if ((tempAddr->Address[0].AddressLength+sizeof(u_short)
  339. <= OutputBufferLength)) {
  340. try {
  341. //
  342. // Validate user mode pointers
  343. //
  344. if (RequestorMode!=KernelMode) {
  345. ProbeForWrite (OutputBuffer,
  346. OutputBufferLength,
  347. sizeof (CHAR));
  348. }
  349. //
  350. // Copy the data from the type on which corresponds
  351. // to the socket address.
  352. //
  353. RtlCopyMemory (
  354. OutputBuffer,
  355. &tempAddr->Address[0].AddressType,
  356. tempAddr->Address[0].AddressLength+sizeof(u_short));
  357. }
  358. except (EXCEPTION_EXECUTE_HANDLER) {
  359. status = GetExceptionCode ();
  360. goto Complete;
  361. }
  362. }
  363. else {
  364. //
  365. // Output buffer is not big enough, return warning
  366. // and the required buffer size.
  367. //
  368. status = STATUS_BUFFER_OVERFLOW;
  369. }
  370. *Information = tempAddr->Address[0].AddressLength+sizeof(u_short);
  371. }
  372. Complete:
  373. //
  374. // Free address buffer if we allocated one.
  375. //
  376. if (tempAddr!=(PTRANSPORT_ADDRESS)addrBuffer) {
  377. AFD_FREE_POOL (tempAddr, AFD_ROUTING_QUERY_POOL_TAG);
  378. }
  379. return status;
  380. } //AfdRoutingInterfaceQuery
  381. NTSTATUS
  382. FASTCALL
  383. AfdRoutingInterfaceChange (
  384. IN PIRP Irp,
  385. IN PIO_STACK_LOCATION IrpSp
  386. )
  387. /*++
  388. Routine Description:
  389. Processes routing change IRP
  390. Arguments:
  391. Irp - Pointer to I/O request packet.
  392. IrpSp - pointer to the stack location to use for this request.
  393. Return Value:
  394. NTSTATUS -- Indicates whether the request was successfully queued.
  395. --*/
  396. {
  397. PTRANSPORT_ADDRESS destAddr;
  398. NTSTATUS status;
  399. PAFD_ENDPOINT endpoint;
  400. BOOLEAN overlapped;
  401. AFD_TRANSPORT_IOCTL_INFO ioctlInfo;
  402. PAGED_CODE ();
  403. IF_DEBUG (ROUTING_QUERY) {
  404. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  405. "AfdRoutingInterfaceChange: Endp: %p, buf: %p, inlen: %ld, outlen: %ld.\n",
  406. IrpSp->FileObject->FsContext,
  407. Irp->AssociatedIrp.SystemBuffer,
  408. IrpSp->Parameters.DeviceIoControl.InputBufferLength,
  409. IrpSp->Parameters.DeviceIoControl.OutputBufferLength));
  410. }
  411. #ifdef _WIN64
  412. if (IoIs32bitProcess (Irp)) {
  413. PAFD_TRANSPORT_IOCTL_INFO32 ioctlInfo32;
  414. ioctlInfo32 = Irp->AssociatedIrp.SystemBuffer;
  415. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength<sizeof (*ioctlInfo32)) {
  416. status = STATUS_INVALID_PARAMETER;
  417. goto complete;
  418. }
  419. ioctlInfo.Handle = ioctlInfo32->Handle;
  420. ioctlInfo.InputBuffer = ioctlInfo32->InputBuffer;
  421. ioctlInfo.InputBufferLength = ioctlInfo32->InputBufferLength;
  422. ioctlInfo.IoControlCode = ioctlInfo32->IoControlCode;
  423. ioctlInfo.AfdFlags = ioctlInfo32->AfdFlags;
  424. ioctlInfo.PollEvent = ioctlInfo32->PollEvent;
  425. }
  426. else
  427. #endif // _WIN64
  428. {
  429. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength<sizeof (ioctlInfo)) {
  430. status = STATUS_INVALID_PARAMETER;
  431. goto complete;
  432. }
  433. ioctlInfo = *((PAFD_TRANSPORT_IOCTL_INFO)Irp->AssociatedIrp.SystemBuffer);
  434. }
  435. //
  436. // Setup locals
  437. //
  438. endpoint = IrpSp->FileObject->FsContext;
  439. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  440. //
  441. // Check if request is overlapped
  442. //
  443. overlapped = ((ioctlInfo.AfdFlags & AFD_OVERLAPPED)!=0);
  444. //
  445. // Validate input parameters
  446. //
  447. try {
  448. ULONG sysBufferLength;
  449. sysBufferLength = max (
  450. IrpSp->Parameters.DeviceIoControl.InputBufferLength,
  451. IrpSp->Parameters.DeviceIoControl.OutputBufferLength);
  452. if (Irp->RequestorMode != KernelMode) {
  453. ProbeForRead(
  454. ioctlInfo.InputBuffer,
  455. ioctlInfo.InputBufferLength,
  456. sizeof(UCHAR)
  457. );
  458. }
  459. if (ioctlInfo.InputBufferLength>sysBufferLength){
  460. PVOID newSystemBuffer;
  461. //
  462. // Don't use AFD tags on this as we are substituting
  463. // system buffer
  464. //
  465. newSystemBuffer = ExAllocatePoolWithQuota (
  466. NonPagedPoolCacheAligned,
  467. ioctlInfo.InputBufferLength
  468. );
  469. if (newSystemBuffer==NULL) {
  470. ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
  471. }
  472. ExFreePool (Irp->AssociatedIrp.SystemBuffer);
  473. Irp->AssociatedIrp.SystemBuffer = newSystemBuffer;
  474. }
  475. //
  476. // Copy application data to the system buffer
  477. //
  478. RtlCopyMemory (Irp->AssociatedIrp.SystemBuffer,
  479. ioctlInfo.InputBuffer,
  480. ioctlInfo.InputBufferLength);
  481. }
  482. except( AFD_EXCEPTION_FILTER(&status) ) {
  483. goto complete;
  484. }
  485. destAddr = Irp->AssociatedIrp.SystemBuffer;
  486. if(ioctlInfo.InputBufferLength <
  487. sizeof(*destAddr) ||
  488. ioctlInfo.InputBufferLength <
  489. (ULONG)FIELD_OFFSET (TRANSPORT_ADDRESS,
  490. Address[0].Address[destAddr->Address[0].AddressLength])
  491. ) {
  492. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  493. "AfdRoutingInterfaceChange: Endp: %p - invalid parameter.\n",
  494. IrpSp->FileObject->FsContext));
  495. status = STATUS_INVALID_PARAMETER;
  496. goto complete;
  497. }
  498. //
  499. // PROBLEM We only support IP for now
  500. //
  501. if (destAddr->Address[0].AddressType!=TDI_ADDRESS_TYPE_IP &&
  502. destAddr->Address[0].AddressType!=TDI_ADDRESS_TYPE_IP6) {
  503. status = STATUS_NOT_SUPPORTED;
  504. goto complete;
  505. }
  506. //
  507. // Reset the poll bit
  508. //
  509. endpoint->EventsActive &= ~AFD_POLL_ROUTING_IF_CHANGE;
  510. return AfdTcpQueueRoutingChangeRequest (endpoint, Irp, overlapped);
  511. complete:
  512. Irp->IoStatus.Status = status;
  513. Irp->IoStatus.Information = 0;
  514. IoCompleteRequest (Irp, AfdPriorityBoost);
  515. return status;
  516. } // AfdRoutingInterfaceChange
  517. NTSTATUS
  518. AfdOpenDevice (
  519. LPWSTR DeviceNameStr,
  520. HANDLE *Handle,
  521. PFILE_OBJECT *FileObject
  522. )
  523. /*++
  524. Routine Description:
  525. Opens specified device driver (control channel) and returns handle and
  526. file object
  527. Arguments:
  528. DeviceNameStr - device to open.
  529. Handle - returned handle.
  530. FileObject - returned file object.
  531. Return Value:
  532. NTSTATUS -- Indicates whether the device was opened OK
  533. --*/
  534. {
  535. NTSTATUS status;
  536. UNICODE_STRING DeviceName;
  537. OBJECT_ATTRIBUTES objectAttributes;
  538. IO_STATUS_BLOCK iosb;
  539. PAGED_CODE( );
  540. RtlInitUnicodeString(&DeviceName, DeviceNameStr);
  541. //
  542. // We ask to create a kernel handle which is
  543. // the handle in the context of the system process
  544. // so that application cannot close it on us while
  545. // we are creating and referencing it.
  546. //
  547. InitializeObjectAttributes(
  548. &objectAttributes,
  549. &DeviceName,
  550. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, // attributes
  551. NULL,
  552. NULL
  553. );
  554. status = IoCreateFile(
  555. Handle,
  556. MAXIMUM_ALLOWED,
  557. &objectAttributes,
  558. &iosb, // returned status information.
  559. 0, // block size (unused).
  560. 0, // file attributes.
  561. FILE_SHARE_READ | FILE_SHARE_WRITE,
  562. FILE_CREATE, // create disposition.
  563. 0, // create options.
  564. NULL, // eaInfo
  565. 0, // eaLength
  566. CreateFileTypeNone, // CreateFileType
  567. NULL, // ExtraCreateParameters
  568. IO_NO_PARAMETER_CHECKING // Options
  569. | IO_FORCE_ACCESS_CHECK
  570. );
  571. if (NT_SUCCESS (status)) {
  572. status = ObReferenceObjectByHandle (
  573. *Handle,
  574. 0L,
  575. *IoFileObjectType,
  576. KernelMode,
  577. (PVOID *)FileObject,
  578. NULL
  579. );
  580. if (!NT_SUCCESS (status)) {
  581. ZwClose (*Handle);
  582. *Handle = NULL;
  583. }
  584. }
  585. IF_DEBUG (ROUTING_QUERY) {
  586. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  587. "AfdOpenDevice: Opened %ls, handle: %p, file: %p, status: %lx.\n",
  588. DeviceNameStr, *Handle, *FileObject, status));
  589. }
  590. return status;
  591. } //AfdOpenDevice
  592. VOID
  593. AfdDereferenceRoutingQueryEx (
  594. PAFD_PROTOCOL Protocol
  595. )
  596. {
  597. //
  598. // Make sure the thread in which we execute cannot get
  599. // suspeneded in APC while we own the global resource.
  600. //
  601. KeEnterCriticalRegion ();
  602. ExAcquireResourceExclusiveLite( AfdResource, TRUE );
  603. ASSERT (Protocol->RoutingQueryRefCount>0);
  604. ASSERT (Protocol->DeviceHandle!=NULL);
  605. if (InterlockedDecrement (&Protocol->RoutingQueryRefCount)==0) {
  606. HANDLE DeviceHandle = Protocol->DeviceHandle;
  607. PFILE_OBJECT FileObject = Protocol->FileObject;
  608. Protocol->DeviceHandle = NULL;
  609. Protocol->FileObject = NULL;
  610. ExReleaseResourceLite( AfdResource );
  611. KeLeaveCriticalRegion ();
  612. ObDereferenceObject (FileObject);
  613. //
  614. // Do this in the context of system process so that it does not
  615. // get closed when applications exit
  616. //
  617. ZwClose (DeviceHandle);
  618. }
  619. else {
  620. ExReleaseResourceLite( AfdResource );
  621. KeLeaveCriticalRegion ();
  622. }
  623. }
  624. PAFD_PROTOCOL
  625. AfdGetProtocolInfo(
  626. IN USHORT AddressType
  627. )
  628. {
  629. switch (AddressType) {
  630. case TDI_ADDRESS_TYPE_IP: return &Ip;
  631. case TDI_ADDRESS_TYPE_IP6: return &Ip6;
  632. default: return NULL;
  633. }
  634. }
  635. VOID
  636. AfdDereferenceRoutingQuery (
  637. USHORT AddressType
  638. )
  639. {
  640. PAFD_PROTOCOL Protocol;
  641. Protocol = AfdGetProtocolInfo(AddressType);
  642. ASSERT (Protocol!=NULL);
  643. AfdDereferenceRoutingQueryEx(Protocol);
  644. }
  645. NTSTATUS
  646. AfdTcp6RoutingQuery (
  647. PTA_ADDRESS Dest,
  648. PTA_ADDRESS Intf
  649. )
  650. /*++
  651. Routine Description:
  652. Submits routing query request to TCP6
  653. Arguments:
  654. Dest - destination to query
  655. Intf - interface through which destination can be reached.
  656. Return Value:
  657. NTSTATUS -- Indicates whether operation succeded
  658. --*/
  659. {
  660. NTSTATUS status;
  661. TDIObjectID *lpObject;
  662. CHAR byBuffer[FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX,
  663. Context) + sizeof(TDI_ADDRESS_IP6)];
  664. TCP_REQUEST_QUERY_INFORMATION_EX *ptrqiBuffer = (TCP_REQUEST_QUERY_INFORMATION_EX *) byBuffer;
  665. IP6RouteEntry routeEntry;
  666. IO_STATUS_BLOCK iosb;
  667. KEVENT event;
  668. PIRP irp;
  669. PIO_STACK_LOCATION irpSp;
  670. HANDLE tcpDeviceHandle;
  671. PFILE_OBJECT tcpFileObject;
  672. PDEVICE_OBJECT tcpDeviceObject;
  673. PAGED_CODE ();
  674. //
  675. // Initialize for cleanup.
  676. //
  677. tcpDeviceHandle = NULL;
  678. if (Dest->AddressLength<TDI_ADDRESS_LENGTH_IP6) {
  679. KdPrintEx ((DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  680. "AfdTcp6RoutingQuery: Destination address buffer too small.\n"));
  681. status = STATUS_BUFFER_TOO_SMALL;
  682. goto complete;
  683. }
  684. //
  685. // Open TCP6 driver.
  686. //
  687. status = AfdOpenDevice (DD_TCPV6_DEVICE_NAME, &tcpDeviceHandle, &tcpFileObject);
  688. if (!NT_SUCCESS (status)) {
  689. goto complete;
  690. }
  691. tcpDeviceObject = IoGetRelatedDeviceObject ( tcpFileObject );
  692. //
  693. // Setup the query
  694. //
  695. RtlCopyMemory( (PVOID)ptrqiBuffer->Context, Dest->Address,
  696. TDI_ADDRESS_LENGTH_IP6);
  697. lpObject = &ptrqiBuffer->ID;
  698. lpObject->toi_id = IP6_GET_BEST_ROUTE_ID;
  699. lpObject->toi_class = INFO_CLASS_PROTOCOL;
  700. lpObject->toi_type = INFO_TYPE_PROVIDER;
  701. lpObject->toi_entity.tei_entity = CL_NL_ENTITY;
  702. lpObject->toi_entity.tei_instance = 0;
  703. KeInitializeEvent (&event, NotificationEvent, FALSE);
  704. //
  705. // Build and setup the IRP and call the driver
  706. //
  707. irp = IoBuildDeviceIoControlRequest (
  708. IOCTL_TCP_QUERY_INFORMATION_EX, //Control
  709. tcpDeviceObject, // Device
  710. ptrqiBuffer, // Input buffer
  711. sizeof(byBuffer), // Input buffer size
  712. &routeEntry, // Output buffer
  713. sizeof(routeEntry), // Output buffer size
  714. FALSE, // Internal ?
  715. &event, // Event
  716. &iosb // Status block
  717. );
  718. if (irp==NULL) {
  719. IF_DEBUG(ROUTING_QUERY) {
  720. KdPrintEx ((DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  721. "AfdTcp6RoutingQuery: Could not allocate IRP.\n"));
  722. }
  723. status = STATUS_INSUFFICIENT_RESOURCES;
  724. goto complete;
  725. }
  726. irpSp = IoGetNextIrpStackLocation (irp);
  727. irpSp->FileObject = tcpFileObject;
  728. status = IoCallDriver (tcpDeviceObject, irp);
  729. if (status==STATUS_PENDING) {
  730. status = KeWaitForSingleObject(
  731. &event,
  732. Executive,
  733. KernelMode,
  734. FALSE, // Alertable
  735. NULL); // Timeout
  736. }
  737. IF_DEBUG (ROUTING_QUERY) {
  738. KdPrintEx ((DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  739. "AfdTcp6RoutingQuery: IP6_GET_BEST_ROUTE_ID - status: %lx.\n",
  740. status));
  741. }
  742. if (!NT_SUCCESS (status)) {
  743. goto complete;
  744. }
  745. if (!NT_SUCCESS (iosb.Status)) {
  746. status = iosb.Status;
  747. goto complete;
  748. }
  749. // Fill in IPv6 address
  750. Intf->AddressType = TDI_ADDRESS_TYPE_IP6;
  751. Intf->AddressLength = TDI_ADDRESS_LENGTH_IP6;
  752. RtlCopyMemory( ((PTDI_ADDRESS_IP6)Intf->Address)->sin6_addr,
  753. &routeEntry.ire_Source,
  754. sizeof(routeEntry.ire_Source) );
  755. ((PTDI_ADDRESS_IP6)Intf->Address)->sin6_flowinfo = 0;
  756. ((PTDI_ADDRESS_IP6)Intf->Address)->sin6_port = 0;
  757. ((PTDI_ADDRESS_IP6)Intf->Address)->sin6_scope_id = routeEntry.ire_ScopeId;
  758. status = STATUS_SUCCESS;
  759. complete:
  760. if (tcpDeviceHandle!=NULL) {
  761. ObDereferenceObject (tcpFileObject);
  762. ZwClose (tcpDeviceHandle);
  763. tcpDeviceHandle = NULL;
  764. }
  765. return status;
  766. }
  767. #define AFD_IP_ADDRESS_QUERY_SIZE PAGE_SIZE
  768. NTSTATUS
  769. AfdTcpRoutingQuery (
  770. PTA_ADDRESS Dest,
  771. PTA_ADDRESS Intf
  772. )
  773. /*++
  774. Routine Description:
  775. Submits routing query request to TCP
  776. Arguments:
  777. Dest - destination to query
  778. Intf - interface through which destination can be reached.
  779. Return Value:
  780. NTSTATUS -- Indicates whether operation succeded
  781. --*/
  782. {
  783. NTSTATUS status;
  784. TDIObjectID *lpObject;
  785. IPRouteLookupData *pRtLookupData;
  786. TCP_REQUEST_QUERY_INFORMATION_EX trqiBuffer;
  787. IPRouteEntry routeEntry;
  788. IPAddrEntry *pAddrEntry;
  789. USHORT *pNTEContext;
  790. PVOID addrEntryBuf;
  791. IO_STATUS_BLOCK iosb;
  792. KEVENT event;
  793. PIRP irp;
  794. PIO_STACK_LOCATION irpSp;
  795. HANDLE tcpDeviceHandle;
  796. PFILE_OBJECT tcpFileObject;
  797. PDEVICE_OBJECT tcpDeviceObject;
  798. PAGED_CODE ();
  799. //
  800. // Initialize for cleanup.
  801. //
  802. tcpDeviceHandle = NULL;
  803. if (Dest->AddressLength<TDI_ADDRESS_LENGTH_IP) {
  804. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  805. "AfdTcpRoutingQuery: Destination address buffer too small.\n"));
  806. status = STATUS_BUFFER_TOO_SMALL;
  807. goto complete;
  808. }
  809. //
  810. // Open TCP driver.
  811. //
  812. status = AfdOpenDevice (DD_TCP_DEVICE_NAME, &tcpDeviceHandle, &tcpFileObject);
  813. if (!NT_SUCCESS (status)) {
  814. goto complete;
  815. }
  816. tcpDeviceObject = IoGetRelatedDeviceObject ( tcpFileObject );
  817. //
  818. // Setup the query
  819. //
  820. RtlZeroMemory (&trqiBuffer, sizeof (trqiBuffer));
  821. pRtLookupData = (IPRouteLookupData *)trqiBuffer.Context;
  822. pRtLookupData->DestAdd = ((PTDI_ADDRESS_IP)Dest->Address)->in_addr;
  823. pRtLookupData->SrcAdd = 0;
  824. lpObject = &trqiBuffer.ID;
  825. lpObject->toi_id = IP_MIB_SINGLE_RT_ENTRY_ID;
  826. lpObject->toi_class = INFO_CLASS_PROTOCOL;
  827. lpObject->toi_type = INFO_TYPE_PROVIDER;
  828. lpObject->toi_entity.tei_entity = CL_NL_ENTITY;
  829. lpObject->toi_entity.tei_instance = 0;
  830. KeInitializeEvent (&event, NotificationEvent, FALSE);
  831. //
  832. // Build and setup the IRP and call the driver
  833. //
  834. irp = IoBuildDeviceIoControlRequest (
  835. IOCTL_TCP_QUERY_INFORMATION_EX, //Control
  836. tcpDeviceObject, // Device
  837. &trqiBuffer, // Input buffer
  838. sizeof(trqiBuffer), // Input buffer size
  839. &routeEntry, // Output buffer
  840. sizeof(routeEntry), // Output buffer size
  841. FALSE, // Internal ?
  842. &event, // Event
  843. &iosb // Status block
  844. );
  845. if (irp==NULL) {
  846. IF_DEBUG (ROUTING_QUERY) {
  847. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  848. "AfdTcpRoutingQuery: Could not allocate IRP.\n"));
  849. }
  850. status = STATUS_INSUFFICIENT_RESOURCES;
  851. goto complete;
  852. }
  853. irpSp = IoGetNextIrpStackLocation (irp);
  854. irpSp->FileObject = tcpFileObject;
  855. IF_DEBUG (ROUTING_QUERY) {
  856. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  857. "AfdTcpRoutingQuery: Quering for route to %lx.\n",
  858. ((PTDI_ADDRESS_IP)Dest->Address)->in_addr));
  859. }
  860. status = IoCallDriver (tcpDeviceObject, irp);
  861. if (status==STATUS_PENDING) {
  862. status = KeWaitForSingleObject(
  863. &event,
  864. Executive,
  865. KernelMode,
  866. FALSE, // Alertable
  867. NULL); // Timeout
  868. }
  869. IF_DEBUG (ROUTING_QUERY) {
  870. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  871. "AfdTcpRoutingQuery: IP_MIB_SINGLE_RT_ENTRY_ID - status: %lx.\n",
  872. status));
  873. }
  874. if (!NT_SUCCESS (status)) {
  875. goto complete;
  876. }
  877. if (!NT_SUCCESS (iosb.Status)) {
  878. status = iosb.Status;
  879. goto complete;
  880. }
  881. //
  882. // Allocate buffer for address table
  883. //
  884. try {
  885. addrEntryBuf = AFD_ALLOCATE_POOL_WITH_QUOTA (NonPagedPool,
  886. AFD_IP_ADDRESS_QUERY_SIZE, AFD_ROUTING_QUERY_POOL_TAG);
  887. // AFD_ALLOCATE_POOL_WITH_QUOTA macro sets POOL_RAISE_IF_ALLOCATION_FAILURE
  888. }
  889. except (EXCEPTION_EXECUTE_HANDLER) {
  890. status = GetExceptionCode ();
  891. addrEntryBuf = NULL;
  892. IF_DEBUG (ROUTING_QUERY) {
  893. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  894. "AfdTcpRoutingQuery: Could not allocate address buffer.\n"));
  895. }
  896. goto complete;
  897. }
  898. //
  899. // Setup the query
  900. //
  901. RtlZeroMemory (&trqiBuffer, sizeof (trqiBuffer));
  902. //
  903. // Initialize the context to 0, TCP should update it
  904. // if we don't have enough space to get all the interfaces.
  905. //
  906. pNTEContext = (USHORT *)trqiBuffer.Context;
  907. *pNTEContext = 0;
  908. lpObject->toi_id = IP_MIB_ADDRTABLE_ENTRY_ID;
  909. lpObject->toi_class = INFO_CLASS_PROTOCOL;
  910. lpObject->toi_type = INFO_TYPE_PROVIDER;
  911. lpObject->toi_entity.tei_entity = CL_NL_ENTITY;
  912. lpObject->toi_entity.tei_instance = 0;
  913. //
  914. // Keep quering until we find an entry or TCP returns
  915. // STATUS_BUFFER_OVERFLOW.
  916. //
  917. do {
  918. KeInitializeEvent (&event, NotificationEvent, FALSE);
  919. //
  920. // Build, setup and submit the request.
  921. //
  922. irp = IoBuildDeviceIoControlRequest (
  923. IOCTL_TCP_QUERY_INFORMATION_EX, //Control
  924. tcpDeviceObject, // Device
  925. &trqiBuffer, // Input buffer
  926. sizeof(trqiBuffer), // Input buffer size
  927. addrEntryBuf, // Output buffer
  928. AFD_IP_ADDRESS_QUERY_SIZE, // Output buffer size
  929. FALSE, // Internal ?
  930. &event, // Event
  931. &iosb // Status block
  932. );
  933. if (irp==NULL) {
  934. IF_DEBUG (ROUTING_QUERY) {
  935. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  936. "AfdTcpRoutingQuery: Could not allocate IRP.\n"));
  937. }
  938. status = STATUS_INSUFFICIENT_RESOURCES;
  939. goto complete_free_pool;
  940. }
  941. irpSp = IoGetNextIrpStackLocation (irp);
  942. irpSp->FileObject = tcpFileObject;
  943. status = IoCallDriver (tcpDeviceObject, irp);
  944. if (status==STATUS_PENDING) {
  945. status = KeWaitForSingleObject(
  946. &event,
  947. Executive,
  948. KernelMode,
  949. FALSE, // Alertable
  950. NULL); // Timeout
  951. }
  952. IF_DEBUG (ROUTING_QUERY) {
  953. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  954. "AfdTcpRoutingQuery: IP_MIB_ADDRTABLE_ENTRY_ID - status: %lx.\n",
  955. status));
  956. }
  957. if (!NT_SUCCESS (status) && status!=STATUS_BUFFER_OVERFLOW) {
  958. goto complete_free_pool;
  959. }
  960. status = iosb.Status;
  961. if (!NT_SUCCESS (status) && status!=STATUS_BUFFER_OVERFLOW) {
  962. goto complete_free_pool;
  963. }
  964. //
  965. // Look for matching interface index in the address table
  966. //
  967. IF_DEBUG (ROUTING_QUERY) {
  968. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  969. "AfdTcpRoutingQuery: Looking for interface %ld.\n",
  970. routeEntry.ire_index));
  971. }
  972. for (pAddrEntry = addrEntryBuf;
  973. pAddrEntry<(IPAddrEntry *)((PUCHAR)addrEntryBuf+iosb.Information);
  974. pAddrEntry++) {
  975. if (pAddrEntry->iae_index==routeEntry.ire_index) {
  976. Intf->AddressType = TDI_ADDRESS_TYPE_IP;
  977. Intf->AddressLength = TDI_ADDRESS_LENGTH_IP;
  978. ((PTDI_ADDRESS_IP)Intf->Address)->in_addr = pAddrEntry->iae_addr;
  979. ((PTDI_ADDRESS_IP)Intf->Address)->sin_port = 0;
  980. RtlFillMemory (((PTDI_ADDRESS_IP)Intf->Address)->sin_zero,
  981. sizeof (((PTDI_ADDRESS_IP)Intf->Address)->sin_zero), 0);
  982. IF_DEBUG (ROUTING_QUERY) {
  983. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  984. "AfdTcpRoutingQuery: Found interface %lx.\n",
  985. ((PTDI_ADDRESS_IP)Intf->Address)->in_addr));
  986. }
  987. status = STATUS_SUCCESS;
  988. goto complete_free_pool;
  989. }
  990. }
  991. }
  992. while (status==STATUS_BUFFER_OVERFLOW);
  993. //
  994. // We should always be able to find a match or TCP lied to us
  995. // when it returned the interface index
  996. //
  997. ASSERT (!"TCP must have failed routing query or return valid interface index!!!");
  998. status = STATUS_HOST_UNREACHABLE;
  999. complete_free_pool:
  1000. AFD_FREE_POOL (addrEntryBuf, AFD_ROUTING_QUERY_POOL_TAG);
  1001. complete:
  1002. if (tcpDeviceHandle!=NULL) {
  1003. ObDereferenceObject (tcpFileObject);
  1004. ZwClose (tcpDeviceHandle);
  1005. tcpDeviceHandle = NULL;
  1006. }
  1007. return status;
  1008. } // AfdTcpRoutingQuery
  1009. NTSTATUS
  1010. AfdGetRoutingQueryReference (
  1011. PAFD_PROTOCOL Protocol
  1012. )
  1013. /*++
  1014. Routine Description:
  1015. Initializes routing query if necessary and references it
  1016. Arguments:
  1017. None
  1018. Return Value:
  1019. NTSTATUS -- Indicates whether operation succeded
  1020. --*/
  1021. {
  1022. // KAPC_STATE apcState;
  1023. HANDLE DeviceHandle;
  1024. PFILE_OBJECT FileObject;
  1025. NTSTATUS status;
  1026. status = AfdOpenDevice (Protocol->NetworkLayerDeviceName, &DeviceHandle, &FileObject);
  1027. if (NT_SUCCESS (status)) {
  1028. //
  1029. // Make sure the thread in which we execute cannot get
  1030. // suspeneded in APC while we own the global resource.
  1031. //
  1032. KeEnterCriticalRegion ();
  1033. ExAcquireResourceExclusiveLite ( AfdResource, TRUE);
  1034. if (Protocol->DeviceHandle==NULL) {
  1035. Protocol->DeviceHandle = DeviceHandle;
  1036. Protocol->FileObject = FileObject;
  1037. ASSERT (Protocol->RoutingQueryRefCount==0);
  1038. Protocol->RoutingQueryRefCount = 1;
  1039. ExReleaseResourceLite( AfdResource );
  1040. KeLeaveCriticalRegion ();
  1041. }
  1042. else {
  1043. ASSERT (Protocol->RoutingQueryRefCount>0);
  1044. InterlockedIncrement (&Protocol->RoutingQueryRefCount);
  1045. ExReleaseResourceLite( AfdResource );
  1046. KeLeaveCriticalRegion ();
  1047. ObDereferenceObject (FileObject);
  1048. status = ZwClose (DeviceHandle);
  1049. ASSERT (status==STATUS_SUCCESS);
  1050. }
  1051. }
  1052. else {
  1053. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  1054. "AfdGetRoutingQueryReference: Network layer device open failed, status: %lx.\n",
  1055. status));
  1056. }
  1057. return status;
  1058. } // AfdGetRoutingQueryReference
  1059. NTSTATUS
  1060. AfdTcpQueueRoutingChangeRequest (
  1061. IN PAFD_ENDPOINT Endpoint,
  1062. IN PIRP Irp,
  1063. BOOLEAN Overlapped
  1064. )
  1065. /*++
  1066. Routine Description:
  1067. Submits routing change request to TCP
  1068. Arguments:
  1069. Endpoint - endpoint on which request is issued
  1070. Irp - the request
  1071. Overlapped - whether request is overlapped (and thus should be
  1072. pended event on non-blocking socket)
  1073. Return Value:
  1074. NTSTATUS -- Indicates whether operation succeded
  1075. --*/
  1076. {
  1077. PTRANSPORT_ADDRESS destAddr;
  1078. NTSTATUS status;
  1079. PFILE_OBJECT fileObject;
  1080. PDEVICE_OBJECT deviceObject;
  1081. PIO_STACK_LOCATION irpSp;
  1082. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1083. struct Notify {
  1084. ROUTING_NOTIFY Ctx;
  1085. char Data[0];
  1086. } * notify;
  1087. PIRP irp;
  1088. PIO_COMPLETION_ROUTINE compRoutine;
  1089. PAFD_PROTOCOL Protocol;
  1090. //
  1091. // Set locals for easy cleanup.
  1092. //
  1093. notify = NULL;
  1094. irp = NULL;
  1095. destAddr = Irp->AssociatedIrp.SystemBuffer;
  1096. Protocol = AfdGetProtocolInfo(destAddr->Address[0].AddressType);
  1097. if (Protocol == NULL) {
  1098. status = STATUS_INVALID_PARAMETER;
  1099. goto complete;
  1100. }
  1101. if (destAddr->Address[0].AddressLength < Protocol->AddressLength) {
  1102. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  1103. "AfdTcpQueueRoutingChangeRequest: Destination buffer too small.\n"));
  1104. status = STATUS_INVALID_PARAMETER;
  1105. goto complete;
  1106. }
  1107. //
  1108. // Allocate context structures to keep IRP in the endpoint list in
  1109. // case the latter gets closed and we need to cancel the IRP.
  1110. // Also allocate buffer for passing data to IP
  1111. //
  1112. try {
  1113. notify = AFD_ALLOCATE_POOL_WITH_QUOTA (NonPagedPool,
  1114. FIELD_OFFSET(struct Notify, Data[Protocol->RtChangeDataSize]),
  1115. AFD_ROUTING_QUERY_POOL_TAG);
  1116. // AFD_ALLOCATE_POOL_WITH_QUOTA macro sets POOL_RAISE_IF_ALLOCATION_FAILURE
  1117. }
  1118. except (EXCEPTION_EXECUTE_HANDLER) {
  1119. status = GetExceptionCode ();
  1120. notify = NULL;
  1121. goto complete;
  1122. }
  1123. //
  1124. // Open IP driver if necessary
  1125. //
  1126. AfdAcquireSpinLock (&Endpoint->SpinLock, &lockHandle);
  1127. //
  1128. // Check if endpoint was cleaned-up and cancel the request.
  1129. //
  1130. if (Endpoint->EndpointCleanedUp) {
  1131. AfdReleaseSpinLock (&Endpoint->SpinLock, &lockHandle);
  1132. status = STATUS_CANCELLED;
  1133. goto complete;
  1134. }
  1135. if (Endpoint->RoutingQueryReferenced) {
  1136. ASSERT (Protocol->DeviceHandle != NULL);
  1137. ASSERT (Protocol->FileObject != NULL);
  1138. ASSERT (Protocol->RoutingQueryRefCount>0);
  1139. InterlockedIncrement (&Protocol->RoutingQueryRefCount);
  1140. }
  1141. else {
  1142. if (Protocol->DeviceHandle!=NULL) {
  1143. Endpoint->RoutingQueryReferenced = TRUE;
  1144. InterlockedIncrement (&Protocol->RoutingQueryRefCount);
  1145. if (Protocol->AddressType == TDI_ADDRESS_TYPE_IP6) {
  1146. Endpoint->RoutingQueryIPv6 = TRUE;
  1147. }
  1148. }
  1149. else {
  1150. AfdReleaseSpinLock (&Endpoint->SpinLock, &lockHandle);
  1151. status = AfdGetRoutingQueryReference (Protocol);
  1152. if (!NT_SUCCESS (status)) {
  1153. goto complete;
  1154. }
  1155. ASSERT (Protocol->DeviceHandle!=NULL);
  1156. AfdAcquireSpinLock (&Endpoint->SpinLock, &lockHandle);
  1157. if (Endpoint->EndpointCleanedUp) {
  1158. //
  1159. // Endpoint was cleaned-up while we were
  1160. // referencing routing query. Release the reference.
  1161. //
  1162. AfdReleaseSpinLock (&Endpoint->SpinLock, &lockHandle);
  1163. AfdDereferenceRoutingQueryEx (Protocol);
  1164. status = STATUS_CANCELLED;
  1165. goto complete;
  1166. }
  1167. if (Endpoint->RoutingQueryReferenced) {
  1168. LONG result;
  1169. //
  1170. // Another thread referenced routing query for this endpoint.
  1171. // Since we know that that other's thread reference cannot
  1172. // go away while we are holding spinlock, we can simply
  1173. // decrement the reference count and be sure that it
  1174. // won't go all the way to 0.
  1175. //
  1176. result = InterlockedDecrement (&Protocol->RoutingQueryRefCount);
  1177. ASSERT (result>0);
  1178. }
  1179. else {
  1180. Endpoint->RoutingQueryReferenced = TRUE;
  1181. if (Protocol->AddressType == TDI_ADDRESS_TYPE_IP6) {
  1182. Endpoint->RoutingQueryIPv6 = TRUE;
  1183. }
  1184. }
  1185. }
  1186. }
  1187. fileObject = Protocol->FileObject;
  1188. deviceObject = IoGetRelatedDeviceObject ( fileObject );
  1189. if (Endpoint->NonBlocking && !Overlapped) {
  1190. //
  1191. // For non-blocking socket and non-overlapped requests
  1192. // we shall post the query using new IRP,
  1193. // so even if thread in which rhe request
  1194. // is originated by user exits, our request to IP does not get
  1195. // cancelled and we will still signal the event.
  1196. //
  1197. irp = IoAllocateIrp (deviceObject->StackSize, TRUE);
  1198. if (irp==NULL) {
  1199. AfdReleaseSpinLock (&Endpoint->SpinLock, &lockHandle);
  1200. status = STATUS_INSUFFICIENT_RESOURCES;
  1201. goto complete;
  1202. }
  1203. //
  1204. // Save the endpoint reference in notify context.
  1205. //
  1206. REFERENCE_ENDPOINT (Endpoint);
  1207. notify->Ctx.NotifyContext = Endpoint;
  1208. //
  1209. // Setup completion routine so we can remove the IRP
  1210. // from the endpoint list and free it.
  1211. //
  1212. compRoutine = AfdTcpSignalRoutingChange;
  1213. }
  1214. else {
  1215. //
  1216. // Blocking endpoint: just pass the original request on to the IP
  1217. //
  1218. irp = Irp;
  1219. //
  1220. // Save the original system buffer of the IRP, so we can restore
  1221. // it when TCP completes it
  1222. //
  1223. notify->Ctx.NotifyContext = Irp->AssociatedIrp.SystemBuffer;
  1224. //
  1225. // Setup completion routine so we can restore the IRP and remove it
  1226. // from the endpoint list
  1227. //
  1228. compRoutine = AfdTcpRestartRoutingChange;
  1229. }
  1230. //
  1231. // Insert notification into the endpoint list
  1232. //
  1233. InsertTailList (&Endpoint->RoutingNotifications,
  1234. &notify->Ctx.NotifyListLink);
  1235. AfdReleaseSpinLock (&Endpoint->SpinLock, &lockHandle);
  1236. //
  1237. // Save pointer to IRP in notify structure
  1238. //
  1239. notify->Ctx.NotifyIrp = irp;
  1240. //
  1241. // Setup IP notification request
  1242. //
  1243. switch(Protocol->AddressType) {
  1244. case TDI_ADDRESS_TYPE_IP:
  1245. {
  1246. IPNotifyData *data = (IPNotifyData *)notify->Data;
  1247. data->Version = 0;
  1248. data->Add = ((PTDI_ADDRESS_IP)destAddr->Address[0].Address)->in_addr;
  1249. break;
  1250. }
  1251. case TDI_ADDRESS_TYPE_IP6:
  1252. {
  1253. IPV6_RTCHANGE_NOTIFY_REQUEST *data = (IPV6_RTCHANGE_NOTIFY_REQUEST *)notify->Data;
  1254. data->Flags = 0;
  1255. data->ScopeId = ((PTDI_ADDRESS_IP6)destAddr->Address[0].Address)->sin6_scope_id;
  1256. if (RtlEqualMemory(((PTDI_ADDRESS_IP6)destAddr->Address[0].Address)->sin6_addr, ZeroString, 16)) {
  1257. data->PrefixLength = 0;
  1258. }
  1259. else {
  1260. data->PrefixLength = 128;
  1261. }
  1262. RtlCopyMemory(
  1263. &data->Prefix,
  1264. ((PTDI_ADDRESS_IP6)destAddr->Address[0].Address)->sin6_addr,
  1265. 16);
  1266. break;
  1267. }
  1268. }
  1269. //
  1270. // Setup IRP stack location to forward IRP to IP
  1271. // Must be METHOD_BUFFERED or we are not setting it up correctly
  1272. //
  1273. ASSERT ( (Protocol->RtChangeIoctl & 0x03)==METHOD_BUFFERED );
  1274. irp->AssociatedIrp.SystemBuffer = notify->Data;
  1275. irpSp = IoGetNextIrpStackLocation (irp);
  1276. irpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1277. irpSp->MinorFunction = 0;
  1278. irpSp->Flags = 0;
  1279. irpSp->Control = 0;
  1280. irpSp->FileObject = fileObject;
  1281. irpSp->Parameters.DeviceIoControl.InputBufferLength = Protocol->RtChangeDataSize;
  1282. irpSp->Parameters.DeviceIoControl.OutputBufferLength = 0;
  1283. irpSp->Parameters.DeviceIoControl.IoControlCode = Protocol->RtChangeIoctl;
  1284. irpSp->Parameters.DeviceIoControl.Type3InputBuffer = NULL;
  1285. IoSetCompletionRoutine( irp, compRoutine, notify, TRUE, TRUE, TRUE );
  1286. IF_DEBUG (ROUTING_QUERY) {
  1287. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1288. "AfdTcpQueueRoutingChangeRequest: Passing Irp %p to IP\n",
  1289. irp));
  1290. }
  1291. if (irp==Irp) {
  1292. //
  1293. // Just pass the request through to the driver and return what it
  1294. // returns
  1295. //
  1296. return AfdIoCallDriver (Endpoint, deviceObject, irp);
  1297. }
  1298. IoCallDriver (deviceObject, irp);
  1299. status = STATUS_DEVICE_NOT_READY; // To be converted to WSAEWOULDBLOCK
  1300. //
  1301. // Error cases
  1302. //
  1303. complete:
  1304. IF_DEBUG (ROUTING_QUERY) {
  1305. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1306. "AfdTcpQueueRoutingChangeRequest: completing with status: %lx\n",
  1307. status));
  1308. }
  1309. Irp->IoStatus.Status = status;
  1310. Irp->IoStatus.Information = 0;
  1311. IoCompleteRequest( Irp, AfdPriorityBoost );
  1312. return status;
  1313. } //AfdTcpQueueRoutingChangeRequest
  1314. NTSTATUS
  1315. AfdTcpRestartRoutingChange (
  1316. IN PDEVICE_OBJECT DeviceObject,
  1317. IN PIRP Irp,
  1318. IN PVOID Context
  1319. )
  1320. /*++
  1321. Routine Description:
  1322. Completion routing for routing change IRP forwarded to IP
  1323. Arguments:
  1324. DeviceObject - must be our device object
  1325. Irp - the request to be completed
  1326. Context - completion context
  1327. Return Value:
  1328. NTSTATUS -- Indicates to the system what to do next with the IRP
  1329. --*/
  1330. {
  1331. PROUTING_NOTIFY notifyCtx = Context;
  1332. PAFD_ENDPOINT endpoint = IoGetCurrentIrpStackLocation (Irp)->FileObject->FsContext;
  1333. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  1334. IF_DEBUG (ROUTING_QUERY) {
  1335. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1336. "AfdTcpRestartRoutingChange: Irp: %p, status: %lx, info: %ld.\n",
  1337. Irp, Irp->IoStatus.Status, Irp->IoStatus.Information));
  1338. }
  1339. //
  1340. // Check if IRP is still on the endpoint's list and remove if it is
  1341. //
  1342. if (InterlockedExchangePointer ((PVOID *)&notifyCtx->NotifyIrp, NULL)!=NULL) {
  1343. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1344. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  1345. RemoveEntryList (&notifyCtx->NotifyListLink);
  1346. AfdIndicateEventSelectEvent (endpoint,
  1347. AFD_POLL_ROUTING_IF_CHANGE,
  1348. Irp->IoStatus.Status);
  1349. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1350. //
  1351. // Indicate event as the endpoint is still active
  1352. //
  1353. AfdIndicatePollEvent (endpoint,
  1354. AFD_POLL_ROUTING_IF_CHANGE,
  1355. Irp->IoStatus.Status);
  1356. }
  1357. //
  1358. // If pending has be returned for this IRP then mark the current
  1359. // stack as pending.
  1360. //
  1361. if ( Irp->PendingReturned ) {
  1362. IoMarkIrpPending( Irp );
  1363. }
  1364. //
  1365. // Restore the IRP to its previous glory and free allocated context structure
  1366. //
  1367. Irp->AssociatedIrp.SystemBuffer = notifyCtx->NotifyContext;
  1368. AfdCompleteOutstandingIrp (endpoint, Irp);
  1369. AFD_FREE_POOL (notifyCtx, AFD_ROUTING_QUERY_POOL_TAG);
  1370. return STATUS_SUCCESS;
  1371. }
  1372. NTSTATUS
  1373. AfdTcpSignalRoutingChange (
  1374. IN PDEVICE_OBJECT DeviceObject,
  1375. IN PIRP Irp,
  1376. IN PVOID Context
  1377. )
  1378. /*++
  1379. Routine Description:
  1380. Completion routing for routing change IRP submitted to IP
  1381. Arguments:
  1382. DeviceObject - must be our device object
  1383. Irp - the request to be completed
  1384. Context - completion context
  1385. Return Value:
  1386. NTSTATUS -- Indicates to the system what to do next with the IRP
  1387. --*/
  1388. {
  1389. PROUTING_NOTIFY notifyCtx = Context;
  1390. PAFD_ENDPOINT endpoint = notifyCtx->NotifyContext;
  1391. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  1392. IF_DEBUG (ROUTING_QUERY) {
  1393. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1394. "AfdTcpSignalRoutingChange: Irp: %p, status: %lx, info: %ld.\n",
  1395. Irp, Irp->IoStatus.Status, Irp->IoStatus.Information));
  1396. }
  1397. //
  1398. // Check if IRP is still on the endpoint's list and remove if it is
  1399. //
  1400. if (InterlockedExchangePointer ((PVOID *)&notifyCtx->NotifyIrp, NULL)!=NULL) {
  1401. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1402. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  1403. RemoveEntryList (&notifyCtx->NotifyListLink);
  1404. AfdIndicateEventSelectEvent (endpoint,
  1405. AFD_POLL_ROUTING_IF_CHANGE,
  1406. Irp->IoStatus.Status);
  1407. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1408. //
  1409. // Indicate event as the endpoint is still active
  1410. //
  1411. AfdIndicatePollEvent (endpoint,
  1412. AFD_POLL_ROUTING_IF_CHANGE,
  1413. Irp->IoStatus.Status);
  1414. }
  1415. //
  1416. // Release previously acquired endpoint reference
  1417. //
  1418. DEREFERENCE_ENDPOINT (endpoint);
  1419. //
  1420. // Free allocated irp and context structure
  1421. //
  1422. IoFreeIrp (Irp);
  1423. AFD_FREE_POOL (notifyCtx, AFD_ROUTING_QUERY_POOL_TAG);
  1424. return STATUS_MORE_PROCESSING_REQUIRED;
  1425. }
  1426. VOID
  1427. AfdCancelAddressListChange (
  1428. IN PDEVICE_OBJECT DeviceObject,
  1429. IN PIRP Irp
  1430. );
  1431. BOOLEAN
  1432. AfdCleanupAddressListChange (
  1433. PAFD_ENDPOINT Endpoint,
  1434. PAFD_REQUEST_CONTEXT RequestCtx
  1435. );
  1436. NTSTATUS
  1437. AfdInitializeAddressList (VOID);
  1438. VOID
  1439. AfdAddAddressHandler (
  1440. IN PTA_ADDRESS NetworkAddress,
  1441. IN PUNICODE_STRING DeviceName,
  1442. IN PTDI_PNP_CONTEXT Context
  1443. );
  1444. VOID
  1445. AfdDelAddressHandler (
  1446. IN PTA_ADDRESS NetworkAddress,
  1447. IN PUNICODE_STRING DeviceName,
  1448. IN PTDI_PNP_CONTEXT Context
  1449. );
  1450. VOID
  1451. AfdProcessAddressChangeList (
  1452. USHORT AddressType,
  1453. PUNICODE_STRING DeviceName
  1454. );
  1455. NTSTATUS
  1456. AfdPnPPowerChange(
  1457. IN PUNICODE_STRING DeviceName,
  1458. IN PNET_PNP_EVENT PowerEvent,
  1459. IN PTDI_PNP_CONTEXT Context1,
  1460. IN PTDI_PNP_CONTEXT Context2
  1461. );
  1462. VOID
  1463. AfdReturnNicsPackets (
  1464. PVOID Pdo
  1465. );
  1466. BOOLEAN
  1467. AfdHasHeldPacketsFromNic (
  1468. PAFD_CONNECTION Connection,
  1469. PVOID Pdo
  1470. );
  1471. #ifdef ALLOC_PRAGMA
  1472. #pragma alloc_text( PAGE, AfdAddressListQuery )
  1473. #pragma alloc_text( PAGEAFD, AfdAddressListChange )
  1474. #pragma alloc_text( PAGEAFD, AfdCancelAddressListChange )
  1475. #pragma alloc_text( PAGE, AfdInitializeAddressList )
  1476. #pragma alloc_text( PAGE, AfdDeregisterPnPHandlers )
  1477. #pragma alloc_text( PAGE, AfdAddAddressHandler )
  1478. #pragma alloc_text( PAGE, AfdDelAddressHandler )
  1479. #pragma alloc_text( PAGEAFD, AfdProcessAddressChangeList )
  1480. #pragma alloc_text( PAGE, AfdPnPPowerChange )
  1481. #pragma alloc_text( PAGEAFD, AfdReturnNicsPackets )
  1482. #pragma alloc_text( PAGEAFD, AfdHasHeldPacketsFromNic )
  1483. #endif
  1484. //
  1485. // Cache the device being brought down as a result of
  1486. // removal or power down event, so we do not scan our endpoints
  1487. // unnecessarily when more than one transport propagates device down
  1488. // event for the same device to us.
  1489. //
  1490. PVOID AfdLastRemovedPdo = NULL;
  1491. ULONGLONG AfdLastRemoveTime = 0i64;
  1492. NTSTATUS
  1493. AfdAddressListQuery (
  1494. IN PFILE_OBJECT FileObject,
  1495. IN ULONG IoctlCode,
  1496. IN KPROCESSOR_MODE RequestorMode,
  1497. IN PVOID InputBuffer,
  1498. IN ULONG InputBufferLength,
  1499. IN PVOID OutputBuffer,
  1500. IN ULONG OutputBufferLength,
  1501. OUT PUINT_PTR Information
  1502. )
  1503. /*++
  1504. Routine Description:
  1505. Processes address list query IRP
  1506. Arguments:
  1507. Irp - Pointer to I/O request packet.
  1508. IrpSp - pointer to the stack location to use for this request.
  1509. Return Value:
  1510. NTSTATUS -- Indicates whether the request was successfully queued.
  1511. --*/
  1512. {
  1513. NTSTATUS status;
  1514. PLIST_ENTRY listEntry;
  1515. PTRANSPORT_ADDRESS addressList;
  1516. PAFD_ENDPOINT endpoint;
  1517. PUCHAR addressBuf;
  1518. ULONG dataLen;
  1519. PAFD_ADDRESS_ENTRY addressEntry;
  1520. USHORT addressType;
  1521. PAGED_CODE ();
  1522. *Information = 0;
  1523. status = STATUS_SUCCESS;
  1524. IF_DEBUG (ADDRESS_LIST) {
  1525. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1526. "AfdAddressListQuery: Endp: %p, buf: %p, inlen: %ld, outlen: %ld.\n",
  1527. FileObject->FsContext,
  1528. OutputBuffer,
  1529. InputBufferLength,
  1530. OutputBufferLength));
  1531. }
  1532. //
  1533. // Validate input parameters
  1534. //
  1535. if( InputBufferLength < sizeof(USHORT) ||
  1536. OutputBufferLength < FIELD_OFFSET (TRANSPORT_ADDRESS, Address)
  1537. ) {
  1538. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  1539. "AfdAddressListQuery: Endp: %p - invalid parameter.\n",
  1540. FileObject->FsContext));
  1541. return STATUS_INVALID_PARAMETER;
  1542. }
  1543. endpoint = FileObject->FsContext;
  1544. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  1545. try {
  1546. if (RequestorMode!=KernelMode) {
  1547. ProbeForRead (InputBuffer,
  1548. sizeof (addressType),
  1549. sizeof (USHORT));
  1550. ProbeForWrite (OutputBuffer,
  1551. OutputBufferLength,
  1552. sizeof (ULONG));
  1553. }
  1554. addressType = *((PUSHORT)InputBuffer);
  1555. addressList = OutputBuffer;
  1556. addressBuf = (PUCHAR)OutputBuffer;
  1557. dataLen = FIELD_OFFSET (TRANSPORT_ADDRESS, Address);
  1558. addressList->TAAddressCount = 0;
  1559. }
  1560. except (AFD_EXCEPTION_FILTER (&status)) {
  1561. return status;
  1562. }
  1563. //
  1564. // Make sure the thread in which we execute cannot get
  1565. // suspeneded in APC while we own the global resource.
  1566. //
  1567. KeEnterCriticalRegion ();
  1568. ExAcquireResourceSharedLite( AfdResource, TRUE );
  1569. //
  1570. // Setup address handlers with TDI if not already done
  1571. //
  1572. if (AfdBindingHandle==NULL) {
  1573. ExReleaseResourceLite( AfdResource );
  1574. ExAcquireResourceExclusiveLite( AfdResource, TRUE );
  1575. if (AfdBindingHandle==NULL) {
  1576. status = AfdInitializeAddressList ();
  1577. if (!NT_SUCCESS (status)) {
  1578. ExReleaseResourceLite (AfdResource);
  1579. KeLeaveCriticalRegion ();
  1580. return status;
  1581. }
  1582. }
  1583. else
  1584. status = STATUS_SUCCESS;
  1585. ASSERT (AfdBindingHandle!=NULL);
  1586. }
  1587. ExAcquireResourceSharedLite( AfdAddressListLock, TRUE );
  1588. ExReleaseResourceLite( AfdResource );
  1589. //
  1590. // Walk the address list and pick up the addresses of matching protocol
  1591. // family
  1592. //
  1593. listEntry = AfdAddressEntryList.Flink;
  1594. while (listEntry!=&AfdAddressEntryList) {
  1595. addressEntry = CONTAINING_RECORD (listEntry, AFD_ADDRESS_ENTRY, AddressListLink);
  1596. listEntry = listEntry->Flink;
  1597. //
  1598. // Found a match ?
  1599. //
  1600. if ((addressEntry->Address.AddressType==addressType)
  1601. //
  1602. // Special check for Netbios addresses because
  1603. // we have separate protocols for each lana/device
  1604. //
  1605. && ((addressType!=TDI_ADDRESS_TYPE_NETBIOS)
  1606. || endpoint->TransportInfo==NULL
  1607. || RtlEqualUnicodeString (
  1608. &addressEntry->DeviceName,
  1609. &endpoint->TransportInfo->TransportDeviceName,
  1610. TRUE))) {
  1611. ULONG addressLength = FIELD_OFFSET (TA_ADDRESS,
  1612. Address[addressEntry->Address.AddressLength]);
  1613. try {
  1614. //
  1615. // Copy address to the output buffer if it is not full
  1616. //
  1617. if (status==STATUS_SUCCESS) {
  1618. if (dataLen+addressLength<OutputBufferLength) {
  1619. RtlCopyMemory (&addressBuf[dataLen],
  1620. &addressEntry->Address,
  1621. addressLength);
  1622. IF_DEBUG (ADDRESS_LIST) {
  1623. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1624. "AfdAddressListQuery: Adding address of type: %d, length: %d.\n",
  1625. addressEntry->Address.AddressType,
  1626. addressEntry->Address.AddressLength));
  1627. }
  1628. }
  1629. else {
  1630. //
  1631. // End of buffer reached. Set error code so we do not
  1632. // attempt to copy more data
  1633. //
  1634. IF_DEBUG (ADDRESS_LIST) {
  1635. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1636. "AfdAddressListQuery: Buffer is full.\n"));
  1637. }
  1638. status = STATUS_BUFFER_OVERFLOW;
  1639. }
  1640. }
  1641. //
  1642. // Count the addresses and total buffer length whether we copied
  1643. // them or not to the output buffer
  1644. //
  1645. addressList->TAAddressCount += 1;
  1646. dataLen += addressLength;
  1647. }
  1648. except (AFD_EXCEPTION_FILTER (&status)) {
  1649. dataLen = 0;
  1650. break;
  1651. }
  1652. }
  1653. }
  1654. ExReleaseResourceLite (AfdAddressListLock);
  1655. KeLeaveCriticalRegion ();
  1656. //
  1657. // Return total number of copied/required bytes in the buffer and status
  1658. //
  1659. IF_DEBUG (ADDRESS_LIST) {
  1660. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1661. "AfdAddressListQuery: Address count: %ld, total buffer size: %ld.\n",
  1662. addressList->TAAddressCount, dataLen));
  1663. }
  1664. *Information = dataLen;
  1665. return status;
  1666. } //AfdAddressListQuery
  1667. //
  1668. // Context structure allocated for non-blocking address list change IOCTLs
  1669. //
  1670. typedef struct _AFD_NBCHANGE_CONTEXT {
  1671. AFD_REQUEST_CONTEXT Context; // Context to keep track of request
  1672. AFD_ADDRESS_CHANGE Change; // Address change parameters
  1673. } AFD_NBCHANGE_CONTEXT, *PAFD_NBCHANGE_CONTEXT;
  1674. NTSTATUS
  1675. FASTCALL
  1676. AfdAddressListChange (
  1677. IN PIRP Irp,
  1678. IN PIO_STACK_LOCATION IrpSp
  1679. )
  1680. /*++
  1681. Routine Description:
  1682. Processes address list change IRP
  1683. Arguments:
  1684. Irp - Pointer to I/O request packet.
  1685. IrpSp - pointer to the stack location to use for this request.
  1686. Return Value:
  1687. NTSTATUS -- Indicates whether the request was successfully queued.
  1688. --*/
  1689. {
  1690. NTSTATUS status = STATUS_PENDING;
  1691. USHORT addressType;
  1692. PAFD_ADDRESS_CHANGE change;
  1693. PAFD_REQUEST_CONTEXT requestCtx;
  1694. PAFD_ENDPOINT endpoint;
  1695. AFD_LOCK_QUEUE_HANDLE addressLockHandle, endpointLockHandle;
  1696. KIRQL oldIrql;
  1697. BOOLEAN overlapped;
  1698. AFD_TRANSPORT_IOCTL_INFO ioctlInfo;
  1699. IF_DEBUG (ADDRESS_LIST) {
  1700. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1701. "AfdAddressListChange: Endp: %p, buf: %p, inlen: %ld, outlen: %ld.\n",
  1702. IrpSp->FileObject->FsContext,
  1703. Irp->AssociatedIrp.SystemBuffer,
  1704. IrpSp->Parameters.DeviceIoControl.InputBufferLength,
  1705. IrpSp->Parameters.DeviceIoControl.OutputBufferLength));
  1706. }
  1707. endpoint = IrpSp->FileObject->FsContext;
  1708. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  1709. //
  1710. // Validate input parameters
  1711. //
  1712. #ifdef _WIN64
  1713. if (IoIs32bitProcess (Irp)) {
  1714. PAFD_TRANSPORT_IOCTL_INFO32 ioctlInfo32;
  1715. ioctlInfo32 = Irp->AssociatedIrp.SystemBuffer;
  1716. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength<sizeof (*ioctlInfo32)) {
  1717. status = STATUS_INVALID_PARAMETER;
  1718. goto complete;
  1719. }
  1720. ioctlInfo.Handle = ioctlInfo32->Handle;
  1721. ioctlInfo.InputBuffer = ioctlInfo32->InputBuffer;
  1722. ioctlInfo.InputBufferLength = ioctlInfo32->InputBufferLength;
  1723. ioctlInfo.IoControlCode = ioctlInfo32->IoControlCode;
  1724. ioctlInfo.AfdFlags = ioctlInfo32->AfdFlags;
  1725. ioctlInfo.PollEvent = ioctlInfo32->PollEvent;
  1726. }
  1727. else
  1728. #endif // _WIN64
  1729. {
  1730. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength<sizeof (ioctlInfo)) {
  1731. status = STATUS_INVALID_PARAMETER;
  1732. goto complete;
  1733. }
  1734. //
  1735. // Just copy the buffer verified by the IO system
  1736. //
  1737. ioctlInfo = *((PAFD_TRANSPORT_IOCTL_INFO)
  1738. Irp->AssociatedIrp.SystemBuffer);
  1739. }
  1740. if( ioctlInfo.InputBufferLength < sizeof(USHORT)) {
  1741. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  1742. "AfdAddressListChange: Endp: %p - invalid parameter.\n",
  1743. IrpSp->FileObject->FsContext));
  1744. status = STATUS_INVALID_PARAMETER;
  1745. goto complete;
  1746. }
  1747. try {
  1748. if (Irp->RequestorMode != KernelMode) {
  1749. ProbeForRead(
  1750. ioctlInfo.InputBuffer,
  1751. ioctlInfo.InputBufferLength,
  1752. sizeof (USHORT)
  1753. );
  1754. }
  1755. addressType = *((PUSHORT)ioctlInfo.InputBuffer);
  1756. }
  1757. except( AFD_EXCEPTION_FILTER(&status) ) {
  1758. goto complete;
  1759. }
  1760. //
  1761. // Check if request is overlapped
  1762. //
  1763. overlapped = ((ioctlInfo.AfdFlags & AFD_OVERLAPPED)!=0);
  1764. //
  1765. // Reset the poll bit
  1766. //
  1767. endpoint->EventsActive &= ~AFD_POLL_ADDRESS_LIST_CHANGE;
  1768. //
  1769. // Setup address handlers with TDI if not already done
  1770. //
  1771. if (AfdBindingHandle==NULL) {
  1772. //
  1773. // Make sure the thread in which we execute cannot get
  1774. // suspeneded in APC while we own the global resource.
  1775. //
  1776. KeEnterCriticalRegion ();
  1777. ExAcquireResourceExclusiveLite( AfdResource, TRUE );
  1778. if (AfdBindingHandle==NULL)
  1779. status = AfdInitializeAddressList ();
  1780. else
  1781. status = STATUS_SUCCESS;
  1782. ExReleaseResourceLite (AfdResource);
  1783. KeLeaveCriticalRegion ();
  1784. if (!NT_SUCCESS (status)) {
  1785. goto complete;
  1786. }
  1787. }
  1788. //
  1789. // Setup locals
  1790. //
  1791. if (endpoint->NonBlocking && !overlapped) {
  1792. PAFD_NBCHANGE_CONTEXT nbCtx;
  1793. //
  1794. // If endpoint is non-blocking and request is not overlapped,
  1795. // we'll have to complete it right away and remeber that we
  1796. // need to set event when address list changes
  1797. //
  1798. //
  1799. // Allocate context to keep track of this request
  1800. //
  1801. try {
  1802. nbCtx = AFD_ALLOCATE_POOL_WITH_QUOTA (NonPagedPool,
  1803. sizeof(AFD_NBCHANGE_CONTEXT),
  1804. AFD_ADDRESS_CHANGE_POOL_TAG);
  1805. // AFD_ALLOCATE_POOL_WITH_QUOTA macro sets POOL_RAISE_IF_ALLOCATION_FAILURE
  1806. }
  1807. except (AFD_EXCEPTION_FILTER (&status)) {
  1808. nbCtx = NULL;
  1809. IF_DEBUG(ROUTING_QUERY) {
  1810. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1811. "AfdAddressListChange: Endp: %p - can't allocate change strucure.\n",
  1812. IrpSp->FileObject->FsContext));
  1813. }
  1814. goto complete;
  1815. }
  1816. requestCtx = &nbCtx->Context;
  1817. change = &nbCtx->Change;
  1818. change->Endpoint = endpoint;
  1819. change->NonBlocking = TRUE;
  1820. status = STATUS_DEVICE_NOT_READY;
  1821. }
  1822. else {
  1823. C_ASSERT (sizeof (IrpSp->Parameters.Others)>=sizeof (*requestCtx));
  1824. C_ASSERT (sizeof (Irp->Tail.Overlay.DriverContext)>=sizeof (*change));
  1825. requestCtx = (PAFD_REQUEST_CONTEXT)&IrpSp->Parameters.Others;
  1826. change = (PAFD_ADDRESS_CHANGE)Irp->Tail.Overlay.DriverContext;
  1827. change->NonBlocking = FALSE;
  1828. change->Irp = Irp;
  1829. }
  1830. //
  1831. // Remeber the endpoint and address type for the request
  1832. //
  1833. change->AddressType = addressType;
  1834. requestCtx->CleanupRoutine = AfdCleanupAddressListChange;
  1835. requestCtx->Context = change;
  1836. //
  1837. // Insert change notification into the list
  1838. //
  1839. KeRaiseIrql (DISPATCH_LEVEL, &oldIrql);
  1840. AfdAcquireSpinLockAtDpcLevel (&AfdAddressChangeLock, &addressLockHandle);
  1841. //
  1842. // While holding the address change spinlock acquire endpoint
  1843. // spinlock so if notification occurs, neither structure can
  1844. // be deallocated or IRP completed while we are queuing
  1845. // it to endpoint list
  1846. //
  1847. AfdAcquireSpinLockAtDpcLevel (&endpoint->SpinLock, &endpointLockHandle);
  1848. //
  1849. // If request is non-blocking, check if we have another non-blocking
  1850. // request on the same endpoint. If so, we do not need to have
  1851. // two request structures in the list waiting to signal.
  1852. //
  1853. if (change->NonBlocking) {
  1854. PLIST_ENTRY listEntry = endpoint->RequestList.Flink;
  1855. while (listEntry!=&endpoint->RequestList) {
  1856. PAFD_REQUEST_CONTEXT req = CONTAINING_RECORD (
  1857. listEntry,
  1858. AFD_REQUEST_CONTEXT,
  1859. EndpointListLink);
  1860. listEntry = listEntry->Flink;
  1861. if (req->CleanupRoutine==AfdCleanupAddressListChange) {
  1862. PAFD_ADDRESS_CHANGE chg = req->Context;
  1863. if (chg->NonBlocking) {
  1864. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &endpointLockHandle);
  1865. AfdReleaseSpinLockFromDpcLevel (&AfdAddressChangeLock, &addressLockHandle);
  1866. KeLowerIrql (oldIrql);
  1867. AFD_FREE_POOL (CONTAINING_RECORD (
  1868. requestCtx,
  1869. AFD_NBCHANGE_CONTEXT,
  1870. Context),
  1871. AFD_ADDRESS_CHANGE_POOL_TAG);
  1872. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  1873. "AfdAddressListChange: Endp: %p - non-blocking request already pending.\n",
  1874. IrpSp->FileObject->FsContext));
  1875. ASSERT (status == STATUS_DEVICE_NOT_READY);
  1876. goto complete;
  1877. }
  1878. }
  1879. }
  1880. }
  1881. InsertTailList (&AfdAddressChangeList, &change->ChangeListLink);
  1882. AfdReleaseSpinLockFromDpcLevel (&AfdAddressChangeLock, &addressLockHandle);
  1883. InsertTailList (&endpoint->RequestList, &requestCtx->EndpointListLink);
  1884. if (!change->NonBlocking) {
  1885. //
  1886. // Set cancel routine
  1887. //
  1888. IoSetCancelRoutine( Irp, AfdCancelAddressListChange );
  1889. if ( !Irp->Cancel || IoSetCancelRoutine( Irp, NULL ) == NULL) {
  1890. IoMarkIrpPending (Irp);
  1891. //
  1892. // Either there was no cancel or cancel routine has
  1893. // been invoked already
  1894. //
  1895. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &endpointLockHandle);
  1896. KeLowerIrql (oldIrql);
  1897. IF_DEBUG (ADDRESS_LIST) {
  1898. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1899. "AfdAddressListChange: Queued change IRP: %p on endp: %p .\n",
  1900. Irp, endpoint));
  1901. }
  1902. return STATUS_PENDING;
  1903. }
  1904. else {
  1905. RemoveEntryList (&requestCtx->EndpointListLink);
  1906. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &endpointLockHandle);
  1907. KeLowerIrql (oldIrql);
  1908. goto complete;
  1909. }
  1910. }
  1911. else {
  1912. ASSERT (status==STATUS_DEVICE_NOT_READY);
  1913. }
  1914. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &endpointLockHandle);
  1915. KeLowerIrql (oldIrql);
  1916. complete:
  1917. Irp->IoStatus.Status = status;
  1918. Irp->IoStatus.Information = 0;
  1919. IF_DEBUG (ADDRESS_LIST) {
  1920. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1921. "AfdAddressListChange: Completing IRP: %ld on endp: %p with status: %lx .\n",
  1922. Irp, IrpSp->FileObject->FsContext, status));
  1923. }
  1924. IoCompleteRequest( Irp, 0 );
  1925. return status;
  1926. }
  1927. VOID
  1928. AfdCancelAddressListChange (
  1929. IN PDEVICE_OBJECT DeviceObject,
  1930. IN PIRP Irp
  1931. )
  1932. /*++
  1933. Routine Description:
  1934. Cancel routine for pending address list change IRP
  1935. Arguments:
  1936. DeviceObject - must be our device object
  1937. Irp - the request to be cancelled
  1938. Return Value:
  1939. None
  1940. --*/
  1941. {
  1942. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1943. PAFD_ADDRESS_CHANGE change;
  1944. PAFD_REQUEST_CONTEXT requestCtx;
  1945. PAFD_ENDPOINT endpoint;
  1946. PIO_STACK_LOCATION irpSp;
  1947. //
  1948. // We do not use cancel spinlock to manage address list queue, so
  1949. // we can release it right away
  1950. //
  1951. IoReleaseCancelSpinLock( Irp->CancelIrql );
  1952. //
  1953. // Get the request context and remove it from the queue if not
  1954. // already removed.
  1955. //
  1956. irpSp = IoGetCurrentIrpStackLocation (Irp);
  1957. endpoint = irpSp->FileObject->FsContext;
  1958. ASSERT (IS_AFD_ENDPOINT_TYPE (endpoint));
  1959. requestCtx = (PAFD_REQUEST_CONTEXT)&irpSp->Parameters.DeviceIoControl;
  1960. change = requestCtx->Context;
  1961. ASSERT (change==(PAFD_ADDRESS_CHANGE)Irp->Tail.Overlay.DriverContext);
  1962. ASSERT (change->NonBlocking==FALSE);
  1963. AfdAcquireSpinLock (&AfdAddressChangeLock, &lockHandle);
  1964. if (change->ChangeListLink.Flink!=NULL) {
  1965. RemoveEntryList (&change->ChangeListLink);
  1966. change->ChangeListLink.Flink = NULL;
  1967. }
  1968. AfdReleaseSpinLock (&AfdAddressChangeLock, &lockHandle);
  1969. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  1970. if (AfdIsRequestInQueue (requestCtx)) {
  1971. //
  1972. // Context is still in the list, just remove it so
  1973. // noone can see it anymore and complete the IRP
  1974. //
  1975. RemoveEntryList (&requestCtx->EndpointListLink);
  1976. }
  1977. else if (!AfdIsRequestCompleted (requestCtx)) {
  1978. //
  1979. // During endpoint cleanup, this context was removed from the
  1980. // list and cleanup routine is about to be called, don't
  1981. // free this IRP until cleanup routine is called
  1982. // Also, indicate to the cleanup routine that we are done
  1983. // with this IRP and it can free it.
  1984. //
  1985. AfdMarkRequestCompleted (requestCtx);
  1986. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  1987. return;
  1988. }
  1989. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  1990. Irp->IoStatus.Status = STATUS_CANCELLED;
  1991. Irp->IoStatus.Information = 0;
  1992. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  1993. IF_DEBUG (ADDRESS_LIST) {
  1994. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1995. "AfdCancelAddressListChange: Cancelled IRP: %p on endp: %p .\n",
  1996. Irp, endpoint));
  1997. }
  1998. }
  1999. BOOLEAN
  2000. AfdCleanupAddressListChange (
  2001. PAFD_ENDPOINT Endpoint,
  2002. PAFD_REQUEST_CONTEXT RequestCtx
  2003. )
  2004. {
  2005. AFD_LOCK_QUEUE_HANDLE lockHandle;
  2006. PAFD_ADDRESS_CHANGE change;
  2007. change = RequestCtx->Context;
  2008. //
  2009. // In no case IRP and request structure
  2010. // could have been freed until we mark it as completed as
  2011. // the caller of this routine should have marked the request
  2012. // as being cancelled
  2013. //
  2014. ASSERT (RequestCtx->EndpointListLink.Flink==NULL);
  2015. AfdAcquireSpinLock (&AfdAddressChangeLock, &lockHandle);
  2016. if (change->ChangeListLink.Flink!=NULL) {
  2017. RemoveEntryList (&change->ChangeListLink);
  2018. change->ChangeListLink.Flink = NULL;
  2019. }
  2020. AfdReleaseSpinLock (&AfdAddressChangeLock, &lockHandle);
  2021. AfdAcquireSpinLock (&Endpoint->SpinLock, &lockHandle);
  2022. //
  2023. // The processing routine has either already initiated completion
  2024. // of this request and marked it as completed what it saw that the request is
  2025. // no longer on the endpoint queue, or the processing routine will
  2026. // never see the request since we removed it from the processing list.
  2027. // However, it is possible that blocking request is being cancelled in another
  2028. // thread as we cleaning up, so we need to sync with the cancel routine.
  2029. //
  2030. if (AfdIsRequestCompleted (RequestCtx) ||
  2031. change->NonBlocking ||
  2032. IoSetCancelRoutine (change->Irp, NULL)!=NULL) {
  2033. AfdReleaseSpinLock (&Endpoint->SpinLock, &lockHandle);
  2034. if (change->NonBlocking) {
  2035. ASSERT (CONTAINING_RECORD (RequestCtx,
  2036. AFD_NBCHANGE_CONTEXT,
  2037. Context)
  2038. ==CONTAINING_RECORD (change,
  2039. AFD_NBCHANGE_CONTEXT,
  2040. Change));
  2041. ASSERT (Endpoint == change->Endpoint);
  2042. AFD_FREE_POOL (CONTAINING_RECORD (RequestCtx,
  2043. AFD_NBCHANGE_CONTEXT,
  2044. Context),
  2045. AFD_ADDRESS_CHANGE_POOL_TAG);
  2046. }
  2047. else {
  2048. PIRP irp = change->Irp;
  2049. ASSERT (change==(PAFD_ADDRESS_CHANGE)irp->Tail.Overlay.DriverContext);
  2050. ASSERT (Endpoint == IoGetCurrentIrpStackLocation (irp)->FileObject->FsContext);
  2051. ASSERT (RequestCtx == (PAFD_REQUEST_CONTEXT)
  2052. &IoGetCurrentIrpStackLocation (irp)->Parameters.DeviceIoControl);
  2053. irp->IoStatus.Status = STATUS_CANCELLED;
  2054. irp->IoStatus.Information = 0;
  2055. IoCompleteRequest (irp, IO_NO_INCREMENT);
  2056. }
  2057. return TRUE;
  2058. }
  2059. else {
  2060. //
  2061. // AFD has not completed the request before returning
  2062. // from cancel routine, mark the request to indicate
  2063. // that we are done with it and cancel routine
  2064. // can free it
  2065. //
  2066. AfdMarkRequestCompleted (RequestCtx);
  2067. AfdReleaseSpinLock (&Endpoint->SpinLock, &lockHandle);
  2068. return FALSE;
  2069. }
  2070. }
  2071. NTSTATUS
  2072. AfdInitializeAddressList (VOID)
  2073. /*++
  2074. Routine Description:
  2075. Register address handler routinges with TDI
  2076. Arguments:
  2077. None
  2078. Return Value:
  2079. NTSTATUS -- Indicates whether registration succeded
  2080. --*/
  2081. {
  2082. NTSTATUS status;
  2083. TDI_CLIENT_INTERFACE_INFO info;
  2084. UNICODE_STRING afdName;
  2085. PAGED_CODE ();
  2086. //
  2087. // Do basic initialization if we haven't done this before.
  2088. //
  2089. if (AfdAddressListLock==NULL) {
  2090. //
  2091. // Initialize spinlock that protects address change list.
  2092. //
  2093. AfdInitializeSpinLock (&AfdAddressChangeLock);
  2094. //
  2095. // Allocate and initialize resource that protects address list
  2096. //
  2097. AfdAddressListLock = AFD_ALLOCATE_POOL_PRIORITY(
  2098. NonPagedPool,
  2099. sizeof(*AfdAddressListLock),
  2100. AFD_RESOURCE_POOL_TAG,
  2101. HighPoolPriority
  2102. );
  2103. if ( AfdAddressListLock == NULL ) {
  2104. return STATUS_INSUFFICIENT_RESOURCES;
  2105. }
  2106. ExInitializeResourceLite( AfdAddressListLock );
  2107. //
  2108. // Initialize our lists
  2109. //
  2110. InitializeListHead (&AfdAddressEntryList);
  2111. InitializeListHead (&AfdAddressChangeList);
  2112. }
  2113. //
  2114. // Setup the TDI request structure
  2115. //
  2116. RtlZeroMemory (&info, sizeof (info));
  2117. RtlInitUnicodeString(&afdName, L"AFD");
  2118. #ifdef TDI_CURRENT_VERSION
  2119. info.TdiVersion = TDI_CURRENT_VERSION;
  2120. #else
  2121. info.MajorTdiVersion = 2;
  2122. info.MinorTdiVersion = 0;
  2123. #endif
  2124. info.Unused = 0;
  2125. info.ClientName = &afdName;
  2126. info.BindingHandler = NULL;
  2127. info.AddAddressHandlerV2 = AfdAddAddressHandler;
  2128. info.DelAddressHandlerV2 = AfdDelAddressHandler;
  2129. info.PnPPowerHandler = AfdPnPPowerChange;
  2130. //
  2131. // Register handlers with TDI
  2132. //
  2133. status = TdiRegisterPnPHandlers (&info, sizeof (info), &AfdBindingHandle);
  2134. if (!NT_SUCCESS (status)) {
  2135. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
  2136. "AfdInitializeAddressList: Failed to register PnP handlers: %lx .\n",
  2137. status));
  2138. return status;
  2139. }
  2140. return STATUS_SUCCESS;
  2141. }
  2142. VOID
  2143. AfdDeregisterPnPHandlers (
  2144. PVOID Param
  2145. )
  2146. {
  2147. ASSERT ( ExIsResourceAcquiredSharedLite ( AfdAddressListLock )==0
  2148. || ExIsResourceAcquiredExclusiveLite( AfdAddressListLock ));
  2149. KeEnterCriticalRegion ();
  2150. ExAcquireResourceExclusiveLite (AfdResource, TRUE);
  2151. //
  2152. // Free address list and associated structures
  2153. //
  2154. if (AfdBindingHandle) {
  2155. ExAcquireResourceExclusiveLite( AfdAddressListLock, TRUE );
  2156. TdiDeregisterPnPHandlers (AfdBindingHandle);
  2157. AfdBindingHandle = NULL;
  2158. ASSERT (AfdAddressListLock!=NULL);
  2159. while( !IsListEmpty( &AfdAddressEntryList ) ) {
  2160. PAFD_ADDRESS_ENTRY addressEntry;
  2161. PLIST_ENTRY listEntry;
  2162. listEntry = RemoveHeadList( &AfdAddressEntryList );
  2163. addressEntry = CONTAINING_RECORD(
  2164. listEntry,
  2165. AFD_ADDRESS_ENTRY,
  2166. AddressListLink
  2167. );
  2168. AFD_FREE_POOL(
  2169. addressEntry,
  2170. AFD_TRANSPORT_ADDRESS_POOL_TAG
  2171. );
  2172. }
  2173. if (!IsListEmpty (&AfdEndpointListHead)) {
  2174. //
  2175. // Call routine to notify all the clietns
  2176. //
  2177. ASSERT (!IsListEmpty (&AfdTransportInfoListHead));
  2178. ASSERT (AfdLoaded);
  2179. AfdProcessAddressChangeList (TDI_ADDRESS_TYPE_UNSPEC, NULL);
  2180. }
  2181. ExReleaseResourceLite (AfdAddressListLock);
  2182. }
  2183. ExReleaseResourceLite (AfdResource);
  2184. KeLeaveCriticalRegion ();
  2185. }
  2186. VOID
  2187. AfdAddAddressHandler (
  2188. IN PTA_ADDRESS NetworkAddress,
  2189. IN PUNICODE_STRING DeviceName,
  2190. IN PTDI_PNP_CONTEXT Context
  2191. )
  2192. /*++
  2193. Routine Description:
  2194. TDI add address handler
  2195. Arguments:
  2196. NetworkAddress - new network address available on the system
  2197. Context1 - name of the device to which address belongs
  2198. Context2 - PDO to which address belongs
  2199. Return Value:
  2200. None
  2201. --*/
  2202. {
  2203. PAFD_ADDRESS_ENTRY addrEntry;
  2204. PAGED_CODE ();
  2205. //
  2206. // Clear the cached last removed PDO when we get address add notification
  2207. // since PDO can now be reused for something else.
  2208. //
  2209. AfdLastRemovedPdo = NULL;
  2210. if (DeviceName==NULL) {
  2211. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
  2212. "AfdAddAddressHandler: "
  2213. "NO DEVICE NAME SUPPLIED when adding address of type %d., IGNORING IT!!!\n",
  2214. NetworkAddress->AddressType));
  2215. return;
  2216. }
  2217. //
  2218. // Allocate memory to keep address in our list
  2219. // Note since the address information usually gets
  2220. // populated during boot and not used right away, we
  2221. // make it a "cold" allocation. The flag has no effect
  2222. // after system is booted.
  2223. //
  2224. addrEntry = AFD_ALLOCATE_POOL_PRIORITY (PagedPool|POOL_COLD_ALLOCATION,
  2225. ALIGN_UP(FIELD_OFFSET (AFD_ADDRESS_ENTRY,
  2226. Address.Address[NetworkAddress->AddressLength]),
  2227. WCHAR)
  2228. +DeviceName->MaximumLength,
  2229. AFD_TRANSPORT_ADDRESS_POOL_TAG,
  2230. HighPoolPriority);
  2231. if (addrEntry!=NULL) {
  2232. //
  2233. // Insert new address in the list
  2234. //
  2235. RtlCopyMemory (&addrEntry->Address, NetworkAddress,
  2236. FIELD_OFFSET (TA_ADDRESS,
  2237. Address[NetworkAddress->AddressLength]));
  2238. addrEntry->DeviceName.MaximumLength = DeviceName->MaximumLength;
  2239. addrEntry->DeviceName.Buffer =
  2240. ALIGN_UP_POINTER(&addrEntry->Address.Address[NetworkAddress->AddressLength],
  2241. WCHAR);
  2242. RtlCopyUnicodeString (&addrEntry->DeviceName, DeviceName);
  2243. //
  2244. // We shouldn't be calling into TDI while having resource
  2245. // acquired in shared mode because it can cause a deadloclk
  2246. // rigth here as TDI reenters us and we need to acquire the
  2247. // resource exclusive
  2248. //
  2249. ASSERT ( ExIsResourceAcquiredSharedLite ( AfdAddressListLock )==0
  2250. || ExIsResourceAcquiredExclusiveLite( AfdAddressListLock ));
  2251. //
  2252. // Make sure the thread in which we execute cannot get
  2253. // suspeneded in APC while we own the global resource.
  2254. //
  2255. KeEnterCriticalRegion ();
  2256. //
  2257. // Acquire AfdResource since we will be checking if there are endpoints in
  2258. // the list to decide whether to call non-pageable routine.
  2259. //
  2260. ExAcquireResourceSharedLite (AfdResource, TRUE);
  2261. ExAcquireResourceExclusiveLite( AfdAddressListLock, TRUE );
  2262. InsertTailList (&AfdAddressEntryList, &addrEntry->AddressListLink);
  2263. //
  2264. // Don't call if endpoint list is empty, since the driver
  2265. // may be paged out. There should be no-one to notify anyway
  2266. // if there are no sockets there.
  2267. //
  2268. if (!IsListEmpty (&AfdEndpointListHead)) {
  2269. //
  2270. // Call routine to notify all the clietns
  2271. //
  2272. ASSERT (!IsListEmpty (&AfdTransportInfoListHead));
  2273. ASSERT (AfdLoaded);
  2274. AfdProcessAddressChangeList (NetworkAddress->AddressType, DeviceName);
  2275. }
  2276. ExReleaseResourceLite (AfdAddressListLock);
  2277. ExReleaseResourceLite (AfdResource);
  2278. KeLeaveCriticalRegion ();
  2279. }
  2280. else {
  2281. //
  2282. // Failed allocation - queue work item to deregister PnP
  2283. // handlers and notify all apps.
  2284. // When apps come back will re-register and our list will
  2285. // get re-populated, or we'll fail the app's call(s);
  2286. //
  2287. AfdQueueWorkItem (&AfdDeregisterPnPHandlers, &AfdPnPDeregisterWorker);
  2288. }
  2289. IF_DEBUG (ADDRESS_LIST) {
  2290. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  2291. "AfdAddAddressHandler: Type: %d, length: %d, device: %*ls .\n",
  2292. NetworkAddress->AddressType,
  2293. NetworkAddress->AddressLength,
  2294. DeviceName->Length/2,
  2295. DeviceName->Buffer));
  2296. }
  2297. }
  2298. VOID
  2299. AfdDelAddressHandler (
  2300. IN PTA_ADDRESS NetworkAddress,
  2301. IN PUNICODE_STRING DeviceName,
  2302. IN PTDI_PNP_CONTEXT Context
  2303. )
  2304. /*++
  2305. Routine Description:
  2306. TDI delete address handler
  2307. Arguments:
  2308. NetworkAddress - network address that is no longer available on the system
  2309. Context1 - name of the device to which address belongs
  2310. Context2 - PDO to which address belongs
  2311. Return Value:
  2312. None
  2313. --*/
  2314. {
  2315. PAFD_ADDRESS_ENTRY addrEntry;
  2316. PLIST_ENTRY listEntry;
  2317. PAGED_CODE ();
  2318. if (DeviceName==NULL) {
  2319. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
  2320. "AfdDelAddressHandler: "
  2321. "NO DEVICE NAME SUPPLIED when deleting address of type %d.\n",
  2322. NetworkAddress->AddressType));
  2323. return;
  2324. }
  2325. //
  2326. // We shouldn't be calling into TDI while having resource
  2327. // acquired in shared mode because it can cause a deadloclk
  2328. // rigth here as TDI reenters us and we need to acquire the
  2329. // resource exclusive
  2330. //
  2331. ASSERT ( ExIsResourceAcquiredSharedLite ( AfdAddressListLock )==0
  2332. || ExIsResourceAcquiredExclusiveLite( AfdAddressListLock ));
  2333. //
  2334. // Find address in our list
  2335. //
  2336. //
  2337. // Make sure the thread in which we execute cannot get
  2338. // suspeneded in APC while we own the global resource.
  2339. //
  2340. KeEnterCriticalRegion ();
  2341. //
  2342. // Acquire AfdResource since we will be checking if there are endpoints in
  2343. // the list to decide whether to call non-pageable routine.
  2344. //
  2345. ExAcquireResourceSharedLite (AfdResource, TRUE);
  2346. ExAcquireResourceExclusiveLite( AfdAddressListLock, TRUE );
  2347. listEntry = AfdAddressEntryList.Flink;
  2348. while (listEntry!=&AfdAddressEntryList) {
  2349. addrEntry = CONTAINING_RECORD (listEntry, AFD_ADDRESS_ENTRY, AddressListLink);
  2350. listEntry = listEntry->Flink;
  2351. if (RtlEqualMemory (&addrEntry->Address, NetworkAddress,
  2352. FIELD_OFFSET (TA_ADDRESS,
  2353. Address[NetworkAddress->AddressLength]))
  2354. && RtlEqualUnicodeString (&addrEntry->DeviceName,
  2355. DeviceName,
  2356. TRUE)) {
  2357. //
  2358. // Remove it and notify the clients
  2359. //
  2360. RemoveEntryList (&addrEntry->AddressListLink);
  2361. //
  2362. // Don't call if endpoint list is empty, since the driver
  2363. // may be paged out. There should be no-one to notify anyway
  2364. // if there are no sockets there.
  2365. //
  2366. if (!IsListEmpty (&AfdEndpointListHead)) {
  2367. ASSERT (!IsListEmpty (&AfdTransportInfoListHead));
  2368. ASSERT (AfdLoaded);
  2369. AfdProcessAddressChangeList (NetworkAddress->AddressType, DeviceName);
  2370. }
  2371. ExReleaseResourceLite (AfdAddressListLock);
  2372. ExReleaseResourceLite (AfdResource);
  2373. KeLeaveCriticalRegion ();
  2374. AFD_FREE_POOL (addrEntry, AFD_TRANSPORT_ADDRESS_POOL_TAG);
  2375. IF_DEBUG (ADDRESS_LIST) {
  2376. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  2377. "AfdDelAddressHandler: Type: %d, length: %d, device: %*ls .\n",
  2378. NetworkAddress->AddressType,
  2379. NetworkAddress->AddressLength,
  2380. DeviceName->Length/2,
  2381. DeviceName->Buffer));
  2382. }
  2383. return;
  2384. }
  2385. }
  2386. ExReleaseResourceLite (AfdAddressListLock);
  2387. ExReleaseResourceLite (AfdResource);
  2388. KeLeaveCriticalRegion ();
  2389. ASSERT (!"AfdDelAddressHandler: Could not find matching entry");
  2390. }
  2391. VOID
  2392. AfdProcessAddressChangeList (
  2393. USHORT AddressType,
  2394. PUNICODE_STRING DeviceName
  2395. )
  2396. /*++
  2397. Routine Description:
  2398. Notifuis all interested clients of address arrival/deletion
  2399. Arguments:
  2400. AddressType - type of the address that arrived/ was deleted
  2401. DeviceName - name of the device to which address belongs
  2402. Return Value:
  2403. None
  2404. --*/
  2405. {
  2406. AFD_LOCK_QUEUE_HANDLE lockHandle;
  2407. PLIST_ENTRY listEntry;
  2408. LIST_ENTRY completedChangeList;
  2409. PAFD_ADDRESS_CHANGE change;
  2410. PAFD_REQUEST_CONTEXT requestCtx;
  2411. PIRP irp;
  2412. PIO_STACK_LOCATION irpSp;
  2413. PAFD_ENDPOINT endpoint;
  2414. PAFD_TRANSPORT_INFO transportInfo;
  2415. // ASSERT ((AddressType!=TDI_ADDRESS_TYPE_NETBIOS) || (DeviceName!=NULL));
  2416. //
  2417. // Special check for Netbios addresses because
  2418. // we have separate protocols for each lana/device
  2419. //
  2420. transportInfo = NULL;
  2421. if ((AddressType==TDI_ADDRESS_TYPE_NETBIOS) && (DeviceName!=NULL)) {
  2422. BOOLEAN found = FALSE;
  2423. for ( listEntry = AfdTransportInfoListHead.Flink;
  2424. listEntry != &AfdTransportInfoListHead;
  2425. listEntry = listEntry->Flink ) {
  2426. transportInfo = CONTAINING_RECORD(
  2427. listEntry,
  2428. AFD_TRANSPORT_INFO,
  2429. TransportInfoListEntry
  2430. );
  2431. if (RtlEqualUnicodeString (
  2432. DeviceName,
  2433. &transportInfo->TransportDeviceName,
  2434. TRUE)) {
  2435. found = TRUE;
  2436. break;
  2437. }
  2438. }
  2439. if (!found)
  2440. return;
  2441. }
  2442. //
  2443. // Create local list to process notifications after spinlock is released
  2444. //
  2445. InitializeListHead (&completedChangeList);
  2446. //
  2447. // Walk the list and move matching notifications to the local list
  2448. //
  2449. AfdAcquireSpinLock (&AfdAddressChangeLock, &lockHandle);
  2450. listEntry = AfdAddressChangeList.Flink;
  2451. while (listEntry!=&AfdAddressChangeList) {
  2452. change = CONTAINING_RECORD (listEntry,
  2453. AFD_ADDRESS_CHANGE,
  2454. ChangeListLink);
  2455. if (change->NonBlocking) {
  2456. endpoint = change->Endpoint;
  2457. requestCtx = &CONTAINING_RECORD (change,
  2458. AFD_NBCHANGE_CONTEXT,
  2459. Change)->Context;
  2460. ASSERT (requestCtx->Context==change);
  2461. }
  2462. else {
  2463. irp = change->Irp;
  2464. irpSp = IoGetCurrentIrpStackLocation (irp);
  2465. requestCtx = (PAFD_REQUEST_CONTEXT)&irpSp->Parameters.DeviceIoControl;
  2466. endpoint = irpSp->FileObject->FsContext;
  2467. ASSERT (change==(PAFD_ADDRESS_CHANGE)irp->Tail.Overlay.DriverContext);
  2468. }
  2469. listEntry = listEntry->Flink;
  2470. if (((change->AddressType==AddressType) || (AddressType==TDI_ADDRESS_TYPE_UNSPEC))
  2471. //
  2472. // Special check for Netbios addresses because
  2473. // we have separate protocols for each lana/device
  2474. //
  2475. && ((transportInfo==NULL)
  2476. || (transportInfo==endpoint->TransportInfo)) ) {
  2477. AFD_LOCK_QUEUE_HANDLE lockHandle2;
  2478. RemoveEntryList (&change->ChangeListLink);
  2479. change->ChangeListLink.Flink = NULL;
  2480. //
  2481. // If request is already canceled, let cancel routine complete it
  2482. //
  2483. if (!change->NonBlocking && IoSetCancelRoutine (irp, NULL)==NULL) {
  2484. continue;
  2485. }
  2486. AfdAcquireSpinLockAtDpcLevel (&endpoint->SpinLock, &lockHandle2);
  2487. if (AfdIsRequestInQueue (requestCtx)) {
  2488. //
  2489. // Context is still in the list, just remove it so
  2490. // no-one can see it anymore and complete
  2491. //
  2492. RemoveEntryList (&requestCtx->EndpointListLink);
  2493. InsertTailList (&completedChangeList,
  2494. &change->ChangeListLink);
  2495. if (change->NonBlocking) {
  2496. AfdIndicateEventSelectEvent (change->Endpoint,
  2497. AFD_POLL_ADDRESS_LIST_CHANGE,
  2498. STATUS_SUCCESS);
  2499. }
  2500. }
  2501. else if (!AfdIsRequestCompleted (requestCtx)) {
  2502. //
  2503. // During endpoint cleanup, this context was removed from the
  2504. // list and cleanup routine is about to be called, don't
  2505. // free this IRP until cleanup routine is called
  2506. // Also, indicate to the cleanup routine that we are done
  2507. // with this IRP and it can free it.
  2508. //
  2509. AfdMarkRequestCompleted (requestCtx);
  2510. }
  2511. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &lockHandle2);
  2512. }
  2513. }
  2514. AfdReleaseSpinLock (&AfdAddressChangeLock, &lockHandle);
  2515. //
  2516. // Signal interested clients and complete IRPs as necessary
  2517. //
  2518. while (!IsListEmpty (&completedChangeList)) {
  2519. listEntry = RemoveHeadList (&completedChangeList);
  2520. change = CONTAINING_RECORD (listEntry,
  2521. AFD_ADDRESS_CHANGE,
  2522. ChangeListLink);
  2523. if (change->NonBlocking) {
  2524. IF_DEBUG (ADDRESS_LIST) {
  2525. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  2526. "AfdProcessAddressChangeList: Signalling address list change on endpoint %p .\n",
  2527. change->Endpoint));
  2528. }
  2529. AfdIndicatePollEvent (change->Endpoint,
  2530. AFD_POLL_ADDRESS_LIST_CHANGE,
  2531. STATUS_SUCCESS);
  2532. AFD_FREE_POOL (CONTAINING_RECORD (change,
  2533. AFD_NBCHANGE_CONTEXT,
  2534. Change),
  2535. AFD_ADDRESS_CHANGE_POOL_TAG);
  2536. }
  2537. else {
  2538. irp = change->Irp;
  2539. irp->IoStatus.Status = STATUS_SUCCESS;
  2540. irp->IoStatus.Information = 0;
  2541. IF_DEBUG (ADDRESS_LIST) {
  2542. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  2543. "AfdProcessAddressChangeList: Completing change IRP: %p with status: 0 .\n",
  2544. irp));
  2545. }
  2546. IoCompleteRequest (irp, AfdPriorityBoost);
  2547. }
  2548. }
  2549. }
  2550. BOOLEAN
  2551. AfdHasHeldPacketsFromNic (
  2552. PAFD_CONNECTION Connection,
  2553. PVOID Pdo
  2554. )
  2555. {
  2556. PLIST_ENTRY le;
  2557. //
  2558. // Scan the list of buffers and check with TDI/NDIS
  2559. // if packet belongs to a given card
  2560. //
  2561. if (!IsListEmpty( &Connection->VcReceiveBufferListHead ) ) {
  2562. le = Connection->VcReceiveBufferListHead.Flink;
  2563. while ( le!=&Connection->VcReceiveBufferListHead ) {
  2564. PAFD_BUFFER afdBuffer;
  2565. afdBuffer = CONTAINING_RECORD( le, AFD_BUFFER, BufferListEntry );
  2566. if ((afdBuffer->BufferLength==AfdBufferTagSize) &&
  2567. TdiMatchPdoWithChainedReceiveContext (afdBuffer->Context, Pdo)) {
  2568. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_WARNING_LEVEL,
  2569. "AFD: Aborting connection %p due to held packet %p at power down on nic %p\n",
  2570. Connection,
  2571. afdBuffer->Context,
  2572. Pdo));
  2573. return TRUE;
  2574. }
  2575. le = le->Flink;
  2576. }
  2577. }
  2578. return FALSE;
  2579. }
  2580. VOID
  2581. AfdReturnNicsPackets (
  2582. PVOID Pdo
  2583. )
  2584. {
  2585. KIRQL oldIrql;
  2586. AFD_LOCK_QUEUE_HANDLE lockHandle;
  2587. PLIST_ENTRY listEntry, le;
  2588. LIST_ENTRY connList;
  2589. //
  2590. // Don't scan twice for the same PDO if this event
  2591. // is less than 3 sec apart from previous.
  2592. // Several transports bound to the same NIC may indicate
  2593. // the set power event to us
  2594. //
  2595. if ((AfdLastRemovedPdo!=Pdo) ||
  2596. ((KeQueryInterruptTime()-AfdLastRemoveTime)>30000000i64)) {
  2597. //
  2598. // Scan the list of endpoints and find packets
  2599. // that belong to the NIC.
  2600. //
  2601. KeEnterCriticalRegion ();
  2602. ExAcquireResourceExclusiveLite (AfdResource, TRUE);
  2603. if (!IsListEmpty (&AfdEndpointListHead)) {
  2604. KeRaiseIrql (DISPATCH_LEVEL, &oldIrql);
  2605. listEntry = AfdEndpointListHead.Flink;
  2606. while (listEntry!=&AfdEndpointListHead) {
  2607. PAFD_CONNECTION connection;
  2608. PAFD_ENDPOINT endpoint = CONTAINING_RECORD (
  2609. listEntry,
  2610. AFD_ENDPOINT,
  2611. GlobalEndpointListEntry);
  2612. listEntry = listEntry->Flink;
  2613. switch (endpoint->Type) {
  2614. case AfdBlockTypeDatagram:
  2615. //
  2616. // Afd currently does not support buffer
  2617. // ownership on datagram sockets.
  2618. //
  2619. // If such support is added, we will need to
  2620. // add code here to return all the buffers
  2621. // owned by the netcards.
  2622. //
  2623. break;
  2624. case AfdBlockTypeVcConnecting:
  2625. //
  2626. // Drop all of the connections that have unreturned packets.
  2627. //
  2628. AfdAcquireSpinLockAtDpcLevel (&endpoint->SpinLock, &lockHandle);
  2629. connection = endpoint->Common.VcConnecting.Connection;
  2630. if (endpoint->State==AfdEndpointStateConnected &&
  2631. !IS_TDI_BUFFERRING(endpoint) &&
  2632. connection!=NULL &&
  2633. AfdHasHeldPacketsFromNic (connection, Pdo)) {
  2634. REFERENCE_CONNECTION (connection);
  2635. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &lockHandle);
  2636. AfdBeginAbort (connection);
  2637. AfdAcquireSpinLockAtDpcLevel (&endpoint->SpinLock, &lockHandle);
  2638. //
  2639. // Make sure we do not have any buffered data
  2640. // (could have just checked for netcard owned
  2641. // buffers, but connection is going down anyway
  2642. // - save memory).
  2643. //
  2644. connection->VcBufferredReceiveBytes = 0;
  2645. connection->VcBufferredReceiveCount = 0;
  2646. connection->VcBufferredExpeditedBytes = 0;
  2647. connection->VcBufferredExpeditedCount = 0;
  2648. connection->VcReceiveBytesInTransport = 0;
  2649. while ( !IsListEmpty( &connection->VcReceiveBufferListHead ) ) {
  2650. PAFD_BUFFER_HEADER afdBuffer;
  2651. le = RemoveHeadList( &connection->VcReceiveBufferListHead );
  2652. afdBuffer = CONTAINING_RECORD( le, AFD_BUFFER_HEADER, BufferListEntry );
  2653. DEBUG afdBuffer->BufferListEntry.Flink = NULL;
  2654. if (afdBuffer->RefCount==1 || // Can't change once off the list
  2655. InterlockedDecrement (&afdBuffer->RefCount)==0) {
  2656. afdBuffer->ExpeditedData = FALSE;
  2657. AfdReturnBuffer( afdBuffer, connection->OwningProcess );
  2658. }
  2659. }
  2660. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &lockHandle);
  2661. DEREFERENCE_CONNECTION (connection);
  2662. }
  2663. else {
  2664. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &lockHandle);
  2665. }
  2666. break;
  2667. case AfdBlockTypeVcBoth:
  2668. case AfdBlockTypeVcListening:
  2669. if (IS_TDI_BUFFERRING (endpoint))
  2670. break;
  2671. //
  2672. // Drop all unaccepted and/or returned connections that have
  2673. // unreturned packets.
  2674. //
  2675. InitializeListHead (&connList);
  2676. AfdAcquireSpinLockAtDpcLevel (&endpoint->SpinLock, &lockHandle);
  2677. le = endpoint->Common.VcListening.UnacceptedConnectionListHead.Flink;
  2678. while ( le!=&endpoint->Common.VcListening.UnacceptedConnectionListHead ) {
  2679. connection = CONTAINING_RECORD (le, AFD_CONNECTION, ListEntry);
  2680. ASSERT( connection->Endpoint == endpoint );
  2681. le = le->Flink;
  2682. if (AfdHasHeldPacketsFromNic (connection, Pdo)) {
  2683. RemoveEntryList (&connection->ListEntry);
  2684. InsertTailList (&connList, &connection->ListEntry);
  2685. InterlockedIncrement (&endpoint->Common.VcListening.FailedConnectionAdds);
  2686. }
  2687. }
  2688. le = endpoint->Common.VcListening.ReturnedConnectionListHead.Flink;
  2689. while ( le!=&endpoint->Common.VcListening.ReturnedConnectionListHead ) {
  2690. connection = CONTAINING_RECORD (le, AFD_CONNECTION, ListEntry);
  2691. ASSERT( connection->Endpoint == endpoint );
  2692. le = le->Flink;
  2693. if (AfdHasHeldPacketsFromNic (connection, Pdo)) {
  2694. RemoveEntryList (&connection->ListEntry);
  2695. InsertTailList (&connList, &connection->ListEntry);
  2696. InterlockedIncrement (&endpoint->Common.VcListening.FailedConnectionAdds);
  2697. }
  2698. }
  2699. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &lockHandle);
  2700. while (!IsListEmpty (&connList)) {
  2701. le = RemoveHeadList (&connList);
  2702. connection = CONTAINING_RECORD (le, AFD_CONNECTION, ListEntry);
  2703. AfdAbortConnection( connection );
  2704. }
  2705. if ( endpoint->Common.VcListening.FailedConnectionAdds > 0 ) {
  2706. AfdInitiateListenBacklogReplenish( endpoint );
  2707. }
  2708. break;
  2709. }
  2710. }
  2711. KeLowerIrql (oldIrql);
  2712. }
  2713. ExReleaseResourceLite (AfdResource);
  2714. KeLeaveCriticalRegion ();
  2715. }
  2716. AfdLastRemovedPdo = Pdo;
  2717. AfdLastRemoveTime = KeQueryInterruptTime ();
  2718. }
  2719. NTSTATUS
  2720. AfdPnPPowerChange(
  2721. IN PUNICODE_STRING DeviceName,
  2722. IN PNET_PNP_EVENT PowerEvent,
  2723. IN PTDI_PNP_CONTEXT Context1,
  2724. IN PTDI_PNP_CONTEXT Context2
  2725. )
  2726. {
  2727. PAGED_CODE ();
  2728. switch (PowerEvent->NetEvent) {
  2729. case NetEventSetPower: {
  2730. NET_DEVICE_POWER_STATE powerState =
  2731. *((PNET_DEVICE_POWER_STATE)PowerEvent->Buffer);
  2732. ASSERT (PowerEvent->BufferLength>=sizeof (NET_DEVICE_POWER_STATE));
  2733. switch (powerState) {
  2734. case NetDeviceStateD0:
  2735. //
  2736. // Clear the cached last removed PDO when we get Power UP notification
  2737. // since PDO can now be reused for something else.
  2738. //
  2739. AfdLastRemovedPdo = NULL;
  2740. goto DoNothing;
  2741. default:
  2742. ASSERTMSG ("NIC enters unknown power state", FALSE);
  2743. case NetDeviceStateD1:
  2744. case NetDeviceStateD2:
  2745. case NetDeviceStateD3:
  2746. case NetDeviceStateUnspecified:
  2747. //
  2748. // Break to execute PDO matching code
  2749. //
  2750. break;
  2751. }
  2752. break;
  2753. }
  2754. case NetEventQueryRemoveDevice:
  2755. //
  2756. // Break to execute PDO matching code
  2757. //
  2758. break;
  2759. case NetEventCancelRemoveDevice:
  2760. //
  2761. // Clear the cached last removed PDO when we get Power UP notification
  2762. // since PDO can now be removed again.
  2763. //
  2764. AfdLastRemovedPdo = NULL;
  2765. goto DoNothing;
  2766. default:
  2767. goto DoNothing;
  2768. }
  2769. //
  2770. // When power is removed or device is disabled, we need to release all
  2771. // packets that we may own.
  2772. // We can only do this for transports that give us
  2773. // PDO, so NDIS can match the packet to the device.
  2774. // Note that PDO is usually the second context argument (first one is
  2775. // usually the device name), but we check the first one too since
  2776. // the TDI spec isn't crystal clear on this (it just says: for example TCP
  2777. // usually <does the above>).
  2778. //
  2779. if ((Context2!=NULL) &&
  2780. (Context2->ContextType==TDI_PNP_CONTEXT_TYPE_PDO) &&
  2781. (Context2->ContextSize==sizeof (PVOID)) ){
  2782. AfdReturnNicsPackets (*((PVOID UNALIGNED *)&Context2->ContextData));
  2783. }
  2784. else if ((Context1!=NULL) &&
  2785. (Context1->ContextType==TDI_PNP_CONTEXT_TYPE_PDO) &&
  2786. (Context1->ContextSize==sizeof (PVOID)) ) {
  2787. AfdReturnNicsPackets (*((PVOID UNALIGNED *)&Context1->ContextData));
  2788. }
  2789. DoNothing:
  2790. return STATUS_SUCCESS;
  2791. }