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

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