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.

2140 lines
68 KiB

  1. /*++
  2. Copyright (c) 1989 - 1999 Microsoft Corporation
  3. Module Name:
  4. poll.c
  5. Abstract:
  6. Contains AfdPoll to handle IOCTL_AFD_POLL and code to process
  7. and signal poll events.
  8. Author:
  9. David Treadwell (davidtr) 4-Apr-1992
  10. Revision History:
  11. Vadim Eydelman (vadime)
  12. 1998-1999 NT5.0 Optimizations and 32/64 support
  13. --*/
  14. #include "afdp.h"
  15. VOID
  16. AfdCancelPoll (
  17. IN PDEVICE_OBJECT DeviceObject,
  18. IN PIRP Irp
  19. );
  20. VOID
  21. AfdFreePollInfo (
  22. IN PAFD_POLL_INFO_INTERNAL PollInfoInternal
  23. );
  24. VOID
  25. AfdTimeoutPoll (
  26. IN struct _KDPC *Dpc,
  27. IN PVOID DeferredContext,
  28. IN PVOID SystemArgument1,
  29. IN PVOID SystemArgument2
  30. );
  31. #ifdef _WIN64
  32. NTSTATUS
  33. AfdPoll32 (
  34. IN PIRP Irp,
  35. IN PIO_STACK_LOCATION IrpSp
  36. );
  37. #endif
  38. VOID
  39. AfdSanPollApcKernelRoutine (
  40. IN struct _KAPC *Apc,
  41. IN OUT PKNORMAL_ROUTINE *NormalRoutine,
  42. IN OUT PVOID *NormalContext,
  43. IN OUT PVOID *SystemArgument1,
  44. IN OUT PVOID *SystemArgument2
  45. );
  46. VOID
  47. AfdSanPollApcRundownRoutine (
  48. IN struct _KAPC *Apc
  49. );
  50. VOID
  51. AfdCompleteOldPollIrp (
  52. IN PIRP Irp,
  53. IN PAFD_POLL_INFO_INTERNAL PollInfo
  54. );
  55. ULONG
  56. AfdCheckPollEvents (
  57. IN PAFD_ENDPOINT Endpoint,
  58. IN ULONG PollEventMask,
  59. OUT NTSTATUS *Status
  60. );
  61. #ifdef ALLOC_PRAGMA
  62. #pragma alloc_text( PAGEAFD, AfdPoll )
  63. #ifdef _WIN64
  64. #pragma alloc_text( PAGEAFD, AfdPoll32 )
  65. #endif
  66. #pragma alloc_text( PAGEAFD, AfdCancelPoll )
  67. #pragma alloc_text( PAGEAFD, AfdFreePollInfo )
  68. #pragma alloc_text( PAGEAFD, AfdTimeoutPoll )
  69. #pragma alloc_text( PAGEAFD, AfdCheckPollEvents )
  70. #pragma alloc_text( PAGEAFD, AfdCompleteOldPollIrp )
  71. #pragma alloc_text( PAGEAFD, AfdIndicatePollEventReal )
  72. #pragma alloc_text( PAGE, AfdSanPollApcKernelRoutine )
  73. #pragma alloc_text( PAGE, AfdSanPollApcRundownRoutine )
  74. #endif
  75. NTSTATUS
  76. FASTCALL
  77. AfdPoll (
  78. IN PIRP Irp,
  79. IN PIO_STACK_LOCATION IrpSp
  80. )
  81. {
  82. NTSTATUS status;
  83. PAFD_POLL_INFO pollInfo;
  84. PAFD_POLL_HANDLE_INFO pollHandleInfo;
  85. PAFD_POLL_INFO_INTERNAL pollInfoInternal;
  86. PAFD_POLL_INFO_INTERNAL freePollInfo = NULL;
  87. PAFD_POLL_ENDPOINT_INFO pollEndpointInfo;
  88. ULONG i;
  89. AFD_LOCK_QUEUE_HANDLE pollLockHandle, endpointLockHandle;
  90. PIRP oldIrp = NULL;
  91. #ifdef _WIN64
  92. if (IoIs32bitProcess (Irp)) {
  93. return AfdPoll32 (Irp, IrpSp);
  94. }
  95. #endif
  96. //
  97. // Set up locals.
  98. //
  99. pollInfo = Irp->AssociatedIrp.SystemBuffer;
  100. if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength<
  101. (ULONG)FIELD_OFFSET (AFD_POLL_INFO, Handles[0])) ||
  102. (pollInfo->NumberOfHandles < 1) ||
  103. ((IrpSp->Parameters.DeviceIoControl.InputBufferLength -
  104. FIELD_OFFSET (AFD_POLL_INFO, Handles[0]))/
  105. sizeof(pollInfo->Handles[0]) < pollInfo->NumberOfHandles) ||
  106. (IrpSp->Parameters.DeviceIoControl.OutputBufferLength<
  107. IrpSp->Parameters.DeviceIoControl.InputBufferLength)) {
  108. status = STATUS_INVALID_PARAMETER;
  109. goto complete;
  110. }
  111. //
  112. // A Unique poll must specify infinite timeout
  113. //
  114. if (pollInfo->Unique &&
  115. pollInfo->Timeout.HighPart != 0x7FFFFFFF) {
  116. status = STATUS_INVALID_PARAMETER;
  117. goto complete;
  118. }
  119. IF_DEBUG(POLL) {
  120. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  121. "AfdPoll: poll IRP %p, IrpSp %p, handles %ld, "
  122. "TO %lx,%lx\n",
  123. Irp, IrpSp,
  124. pollInfo->NumberOfHandles,
  125. pollInfo->Timeout.HighPart, pollInfo->Timeout.LowPart ));
  126. }
  127. Irp->IoStatus.Information = 0;
  128. //
  129. // Determine how large the internal poll information structure will
  130. // be and allocate space for it from nonpaged pool. It must be
  131. // nonpaged since this will be accesses in event handlers.
  132. //
  133. try {
  134. pollInfoInternal = AFD_ALLOCATE_POOL_WITH_QUOTA (
  135. NonPagedPool,
  136. FIELD_OFFSET (AFD_POLL_INFO_INTERNAL,
  137. EndpointInfo[pollInfo->NumberOfHandles]),
  138. AFD_POLL_POOL_TAG
  139. );
  140. // AFD_ALLOCATE_POOL_WITH_QUOTA macro sets POOL_RAISE_IF_ALLOCATION_FAILURE
  141. }
  142. except (EXCEPTION_EXECUTE_HANDLER) {
  143. status = GetExceptionCode ();
  144. pollInfoInternal = NULL;
  145. goto complete;
  146. }
  147. //
  148. // Initialize the internal information buffer.
  149. //
  150. pollInfoInternal->Irp = Irp;
  151. pollInfoInternal->NumberOfEndpoints = 0;
  152. pollInfoInternal->Unique = pollInfo->Unique;
  153. pollInfoInternal->SanPoll = FALSE;
  154. pollHandleInfo = pollInfo->Handles;
  155. pollEndpointInfo = pollInfoInternal->EndpointInfo;
  156. for ( i = 0; i < pollInfo->NumberOfHandles; i++ ) {
  157. status = ObReferenceObjectByHandle(
  158. pollHandleInfo->Handle,
  159. (IrpSp->Parameters.DeviceIoControl.IoControlCode>>14) & 3,
  160. // DesiredAccess
  161. *IoFileObjectType,
  162. Irp->RequestorMode,
  163. (PVOID *)&pollEndpointInfo->FileObject,
  164. NULL
  165. );
  166. if ( !NT_SUCCESS(status) ) {
  167. AfdFreePollInfo( pollInfoInternal );
  168. goto complete;
  169. }
  170. //
  171. // Make sure that this is an AFD endpoint and not some other
  172. // random file handle.
  173. //
  174. if ( pollEndpointInfo->FileObject->DeviceObject != AfdDeviceObject ) {
  175. //
  176. // Dereference last referenced object
  177. // The rest will be dereferenced in AfdFreePollInfo
  178. // as determined by NumberOfEndpoints counter which
  179. // is incremented below.
  180. //
  181. ObDereferenceObject( pollEndpointInfo->FileObject );
  182. status = STATUS_INVALID_HANDLE;
  183. AfdFreePollInfo( pollInfoInternal );
  184. goto complete;
  185. }
  186. pollEndpointInfo->PollEvents = pollHandleInfo->PollEvents;
  187. pollEndpointInfo->Handle = pollHandleInfo->Handle;
  188. pollEndpointInfo->Endpoint = pollEndpointInfo->FileObject->FsContext;
  189. if (IS_SAN_ENDPOINT (pollEndpointInfo->Endpoint)) {
  190. ASSERT (pollEndpointInfo->Endpoint->State==AfdEndpointStateConnected);
  191. status = AfdSanPollBegin (pollEndpointInfo->Endpoint,
  192. pollEndpointInfo->PollEvents);
  193. if (!NT_SUCCESS (status)) {
  194. //
  195. // Dereference last referenced object
  196. // The rest will be dereferenced in AfdFreePollInfo
  197. // as determined by NumberOfEndpoints counter which
  198. // is incremented below.
  199. // Don't call AfdSanPollEnd() as we're not sure what
  200. // AfdSanPollBegin() managed to update before failing.
  201. // At worst, switch will start calling us with all events.
  202. //
  203. ObDereferenceObject( pollEndpointInfo->FileObject );
  204. AfdFreePollInfo (pollInfoInternal);
  205. goto complete;
  206. }
  207. pollEndpointInfo->PollEvents |= AFD_POLL_SANCOUNTS_UPDATED;
  208. pollInfoInternal->SanPoll = TRUE;
  209. }
  210. ASSERT( InterlockedIncrement( &pollEndpointInfo->Endpoint->ObReferenceBias ) > 0 );
  211. IF_DEBUG(POLL) {
  212. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  213. "AfdPoll: event %lx, endp %p, conn %p, handle %p, "
  214. "info %p\n",
  215. pollEndpointInfo->PollEvents,
  216. pollEndpointInfo->Endpoint,
  217. AFD_CONNECTION_FROM_ENDPOINT( pollEndpointInfo->Endpoint ),
  218. pollEndpointInfo->Handle,
  219. pollEndpointInfo ));
  220. }
  221. REFERENCE_ENDPOINT2( pollEndpointInfo->Endpoint, "Poll for 0x%x", pollEndpointInfo->PollEvents );
  222. //
  223. // Increment pointers in the poll info structures.
  224. //
  225. pollHandleInfo++;
  226. pollEndpointInfo++;
  227. pollInfoInternal->NumberOfEndpoints++;
  228. }
  229. restart_poll:
  230. //
  231. // Hold the AFD spin lock while we check for endpoints that already
  232. // satisfy a condition to synchronize between this operation and
  233. // a call to AfdIndicatePollEvent. We release the spin lock
  234. // after all the endpoints have been checked and the internal
  235. // poll info structure is on the global list so AfdIndicatePollEvent
  236. // can find it if necessary.
  237. //
  238. AfdAcquireSpinLock( &AfdPollListLock, &pollLockHandle );
  239. //
  240. // We're done with the input structure provided by the caller. Now
  241. // walk through the internal structure and determine whether any of
  242. // the specified endpoints are ready for the specified condition.
  243. //
  244. pollInfo->NumberOfHandles = 0;
  245. pollHandleInfo = pollInfo->Handles;
  246. pollEndpointInfo = pollInfoInternal->EndpointInfo;
  247. for ( i = 0; i < pollInfoInternal->NumberOfEndpoints; i++ ) {
  248. PAFD_ENDPOINT endpoint;
  249. endpoint = pollEndpointInfo->Endpoint;
  250. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  251. AfdAcquireSpinLockAtDpcLevel (&endpoint->SpinLock, &endpointLockHandle);
  252. //
  253. // Remember that there has been a poll on this endpoint. This flag
  254. // allows us to optimize AfdIndicatePollEvent() for endpoints that have
  255. // never been polled, which is a common case.
  256. //
  257. endpoint->PollCalled = TRUE;
  258. pollHandleInfo->PollEvents = AfdCheckPollEvents (
  259. endpoint,
  260. pollEndpointInfo->PollEvents,
  261. &pollHandleInfo->Status
  262. );
  263. if (pollHandleInfo->PollEvents) {
  264. //
  265. // If the handle had a current event that was requested, update
  266. // the count of handles in the output buffer and increment the
  267. // pointer to the output buffer.
  268. //
  269. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &endpointLockHandle);
  270. UPDATE_ENDPOINT2 (endpoint, "Poll events satisfied inline: 0x%lX",
  271. pollHandleInfo->PollEvents);
  272. pollHandleInfo->Handle = pollEndpointInfo->Handle;
  273. pollInfo->NumberOfHandles++;
  274. pollHandleInfo++;
  275. }
  276. else if (IS_SAN_ENDPOINT (endpoint) &&
  277. (pollEndpointInfo->PollEvents & AFD_POLL_SANCOUNTS_UPDATED)==0 &&
  278. pollInfo->NumberOfHandles==0) {
  279. //
  280. // OOPS, endpoint has been converted too SAN while we were looping,
  281. // need to release the spinlock, update switch counts, and restart
  282. // the loop. We don't do this is we are about to return anyway.
  283. //
  284. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &endpointLockHandle);
  285. AfdReleaseSpinLock (&AfdPollListLock, &pollLockHandle);
  286. ASSERT (endpoint->State==AfdEndpointStateConnected);
  287. status = AfdSanPollBegin (endpoint,
  288. pollEndpointInfo->PollEvents);
  289. if (!NT_SUCCESS (status)) {
  290. AfdFreePollInfo (pollInfoInternal);
  291. goto complete;
  292. }
  293. pollEndpointInfo->PollEvents |= AFD_POLL_SANCOUNTS_UPDATED;
  294. pollInfoInternal->SanPoll = TRUE;
  295. goto restart_poll;
  296. }
  297. else {
  298. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &endpointLockHandle);
  299. }
  300. pollEndpointInfo++;
  301. }
  302. //
  303. // If this is a unique poll, determine whether there is another
  304. // unique poll on this endpoint. If there is an existing unique
  305. // poll, cancel it. This request will supercede the existing
  306. // request.
  307. //
  308. if ( pollInfo->Unique ) {
  309. PLIST_ENTRY listEntry;
  310. for ( listEntry = AfdPollListHead.Flink;
  311. listEntry != &AfdPollListHead;
  312. listEntry = listEntry->Flink ) {
  313. PAFD_POLL_INFO_INTERNAL testInfo;
  314. testInfo = CONTAINING_RECORD(
  315. listEntry,
  316. AFD_POLL_INFO_INTERNAL,
  317. PollListEntry
  318. );
  319. if ( testInfo->Unique &&
  320. testInfo->EndpointInfo[0].FileObject ==
  321. pollInfoInternal->EndpointInfo[0].FileObject ) {
  322. IF_DEBUG(POLL) {
  323. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  324. "AfdPoll: found existing unique poll IRP %p "
  325. "for file object %p, context %p, cancelling.\n",
  326. testInfo->Irp,
  327. testInfo->EndpointInfo[0].FileObject,
  328. testInfo ));
  329. }
  330. //
  331. // Cancel the IRP manually rather than calling
  332. // AfdCancelPoll because we already hold the
  333. // AfdSpinLock, we can't acquire it recursively, and we
  334. // don't want to release it. Remove the poll structure
  335. // from the global list.
  336. //
  337. RemoveEntryList( &testInfo->PollListEntry );
  338. //
  339. // No timer to cancel for Unique poll
  340. //
  341. ASSERT ( testInfo->TimerStarted == FALSE );
  342. //
  343. // Complete the IRP with STATUS_CANCELLED as the status.
  344. //
  345. testInfo->Irp->IoStatus.Information = 0;
  346. testInfo->Irp->IoStatus.Status = STATUS_CANCELLED;
  347. oldIrp = testInfo->Irp;
  348. //
  349. // Remember the poll info structure so that we'll free
  350. // before we exit. We cannot free it now because we're
  351. // holding the AfdSpinLock.
  352. //
  353. freePollInfo = testInfo;
  354. //
  355. // There should be only one outstanding unique poll IRP
  356. // on any given file object, so quit looking for another
  357. // now that we've found one.
  358. //
  359. break;
  360. }
  361. }
  362. }
  363. //
  364. // If we found any endpoints that are ready, free the poll information
  365. // structure and complete the request.
  366. //
  367. if ( pollInfo->NumberOfHandles > 0 ) {
  368. AfdReleaseSpinLock( &AfdPollListLock, &pollLockHandle );
  369. AfdFreePollInfo( pollInfoInternal );
  370. Irp->IoStatus.Information = (PUCHAR)pollHandleInfo - (PUCHAR)pollInfo;
  371. status = STATUS_SUCCESS;
  372. goto complete;
  373. }
  374. if ( pollInfo->Timeout.QuadPart == 0 ) {
  375. //
  376. // A timeout equal to 0 was specified; free the internal
  377. // structure and complete the request with no endpoints in the
  378. // output buffer.
  379. //
  380. IF_DEBUG(POLL) {
  381. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  382. "AfdPoll: zero timeout on poll IRP %p and no "
  383. "current events--completing.\n", Irp ));
  384. }
  385. AfdReleaseSpinLock( &AfdPollListLock, &pollLockHandle );
  386. AfdFreePollInfo( pollInfoInternal );
  387. Irp->IoStatus.Information = (PUCHAR)pollHandleInfo - (PUCHAR)pollInfo;
  388. status = STATUS_SUCCESS;
  389. goto complete;
  390. }
  391. //
  392. // Set up a cancel routine in the IRP so that the IRP will be
  393. // completed correctly if it gets canceled. Also check whether the
  394. // IRP has already been canceled.
  395. //
  396. IoSetCancelRoutine( Irp, AfdCancelPoll );
  397. if ( Irp->Cancel ) {
  398. //
  399. // The IRP has already been canceled. Free the internal
  400. // poll information structure and complete the IRP.
  401. //
  402. AfdReleaseSpinLock( &AfdPollListLock, &pollLockHandle );
  403. if (IoSetCancelRoutine( Irp, NULL ) == NULL) {
  404. KIRQL cancelIrql;
  405. //
  406. // If the cancel routine was NULL then cancel routine
  407. // may be running. Wait on the cancel spinlock until
  408. // the cancel routine is done.
  409. //
  410. // Note: The cancel routine will not find the IRP
  411. // since it is not in the list.
  412. //
  413. IoAcquireCancelSpinLock( &cancelIrql );
  414. IoReleaseCancelSpinLock( cancelIrql );
  415. }
  416. AfdFreePollInfo( pollInfoInternal );
  417. status = STATUS_CANCELLED;
  418. goto complete;
  419. }
  420. IF_DEBUG(POLL) {
  421. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  422. "AfdPoll: no current events for poll IRP %p, "
  423. "info %p\n", Irp, pollInfoInternal ));
  424. }
  425. //
  426. // Set up the information field of the IO status block to indicate
  427. // that an output buffer with no handles should be returned.
  428. // AfdIndicatePollEvent will modify this if necessary.
  429. //
  430. Irp->IoStatus.Information = (PUCHAR)pollHandleInfo - (PUCHAR)pollInfo;
  431. //
  432. // Put a pointer to the internal poll info struct into the IRP
  433. // so that the cancel routine can find it.
  434. //
  435. IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = pollInfoInternal;
  436. //
  437. // Place the internal poll info struct on the global list.
  438. //
  439. InsertTailList( &AfdPollListHead, &pollInfoInternal->PollListEntry );
  440. //
  441. // If the timeout is infinite, then don't set up a timer and
  442. // DPC. Otherwise, set up a timer so we can timeout the poll
  443. // request if appropriate.
  444. //
  445. if ( pollInfo->Timeout.HighPart != 0x7FFFFFFF ) {
  446. pollInfoInternal->TimerStarted = TRUE;
  447. KeInitializeDpc(
  448. &pollInfoInternal->Dpc,
  449. AfdTimeoutPoll,
  450. pollInfoInternal
  451. );
  452. KeInitializeTimer( &pollInfoInternal->Timer );
  453. KeSetTimer(
  454. &pollInfoInternal->Timer,
  455. pollInfo->Timeout,
  456. &pollInfoInternal->Dpc
  457. );
  458. } else {
  459. pollInfoInternal->TimerStarted = FALSE;
  460. }
  461. //
  462. // Mark the IRP pending and release the spin locks. At this
  463. // point the IRP may get completed or cancelled.
  464. //
  465. IoMarkIrpPending( Irp );
  466. AfdReleaseSpinLock( &AfdPollListLock, &pollLockHandle );
  467. //
  468. // Complete any old poll irps.
  469. //
  470. if ( oldIrp != NULL ) {
  471. AfdCompleteOldPollIrp (oldIrp, freePollInfo);
  472. }
  473. //
  474. // Return pending. The IRP will be completed when an appropriate
  475. // event is indicated by the TDI provider, when the timeout is hit,
  476. // or when the IRP is cancelled.
  477. //
  478. return STATUS_PENDING;
  479. complete:
  480. //
  481. // Complete any old poll irps.
  482. //
  483. if ( oldIrp != NULL ) {
  484. AfdCompleteOldPollIrp (oldIrp, freePollInfo);
  485. }
  486. Irp->IoStatus.Status = status;
  487. IoCompleteRequest( Irp, AfdPriorityBoost );
  488. return status;
  489. } // AfdPoll
  490. #ifdef _WIN64
  491. NTSTATUS
  492. AfdPoll32 (
  493. IN PIRP Irp,
  494. IN PIO_STACK_LOCATION IrpSp
  495. )
  496. {
  497. NTSTATUS status;
  498. PAFD_POLL_INFO32 pollInfo;
  499. PAFD_POLL_HANDLE_INFO32 pollHandleInfo;
  500. PAFD_POLL_INFO_INTERNAL pollInfoInternal;
  501. PAFD_POLL_INFO_INTERNAL freePollInfo = NULL;
  502. PAFD_POLL_ENDPOINT_INFO pollEndpointInfo;
  503. ULONG i;
  504. AFD_LOCK_QUEUE_HANDLE pollLockHandle, endpointLockHandle;
  505. PIRP oldIrp = NULL;
  506. //
  507. // Set up locals.
  508. //
  509. pollInfo = Irp->AssociatedIrp.SystemBuffer;
  510. if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength<
  511. (ULONG)FIELD_OFFSET (AFD_POLL_INFO32, Handles[0])) ||
  512. ((IrpSp->Parameters.DeviceIoControl.InputBufferLength -
  513. FIELD_OFFSET (AFD_POLL_INFO32, Handles[0]))/
  514. sizeof(pollInfo->Handles[0]) < pollInfo->NumberOfHandles) ||
  515. (IrpSp->Parameters.DeviceIoControl.OutputBufferLength<
  516. IrpSp->Parameters.DeviceIoControl.InputBufferLength)) {
  517. status = STATUS_INVALID_PARAMETER;
  518. goto complete;
  519. }
  520. //
  521. // A Unique poll must specify infinite timeout
  522. //
  523. if (pollInfo->Unique &&
  524. pollInfo->Timeout.HighPart != 0x7FFFFFFF) {
  525. status = STATUS_INVALID_PARAMETER;
  526. goto complete;
  527. }
  528. IF_DEBUG(POLL) {
  529. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  530. "AfdPoll32: poll IRP %p, IrpSp %p, handles %ld, "
  531. "TO %lx,%lx\n",
  532. Irp, IrpSp,
  533. pollInfo->NumberOfHandles,
  534. pollInfo->Timeout.HighPart, pollInfo->Timeout.LowPart ));
  535. }
  536. Irp->IoStatus.Information = 0;
  537. //
  538. // Determine how large the internal poll information structure will
  539. // be and allocate space for it from nonpaged pool. It must be
  540. // nonpaged since this will be accesses in event handlers.
  541. //
  542. try {
  543. pollInfoInternal = AFD_ALLOCATE_POOL_WITH_QUOTA(
  544. NonPagedPool,
  545. FIELD_OFFSET (AFD_POLL_INFO_INTERNAL,
  546. EndpointInfo[pollInfo->NumberOfHandles]),
  547. AFD_POLL_POOL_TAG
  548. );
  549. // AFD_ALLOCATE_POOL_WITH_QUOTA macro sets POOL_RAISE_IF_ALLOCATION_FAILURE
  550. }
  551. except (EXCEPTION_EXECUTE_HANDLER) {
  552. status = GetExceptionCode ();
  553. pollInfoInternal = NULL;
  554. goto complete;
  555. }
  556. //
  557. // Initialize the internal information buffer.
  558. //
  559. pollInfoInternal->Irp = Irp;
  560. pollInfoInternal->NumberOfEndpoints = 0;
  561. pollInfoInternal->Unique = pollInfo->Unique;
  562. pollInfoInternal->SanPoll = FALSE;
  563. pollHandleInfo = pollInfo->Handles;
  564. pollEndpointInfo = pollInfoInternal->EndpointInfo;
  565. for ( i = 0; i < pollInfo->NumberOfHandles; i++ ) {
  566. status = ObReferenceObjectByHandle(
  567. pollHandleInfo->Handle,
  568. (IrpSp->Parameters.DeviceIoControl.IoControlCode>>14) & 3,
  569. // DesiredAccess
  570. *IoFileObjectType,
  571. Irp->RequestorMode,
  572. (PVOID *)&pollEndpointInfo->FileObject,
  573. NULL
  574. );
  575. if ( !NT_SUCCESS(status) ) {
  576. AfdFreePollInfo( pollInfoInternal );
  577. goto complete;
  578. }
  579. //
  580. // Make sure that this is an AFD endpoint and not some other
  581. // random file handle.
  582. //
  583. if ( pollEndpointInfo->FileObject->DeviceObject != AfdDeviceObject ) {
  584. //
  585. // Dereference last referenced object
  586. // The rest will be dereferenced in AfdFreePollInfo
  587. // as determined by NumberOfEndpoints counter which
  588. // is incremented below.
  589. //
  590. ObDereferenceObject( pollEndpointInfo->FileObject );
  591. status = STATUS_INVALID_HANDLE;
  592. AfdFreePollInfo( pollInfoInternal );
  593. goto complete;
  594. }
  595. pollEndpointInfo->PollEvents = pollHandleInfo->PollEvents;
  596. pollEndpointInfo->Handle = pollHandleInfo->Handle;
  597. pollEndpointInfo->Endpoint = pollEndpointInfo->FileObject->FsContext;
  598. ASSERT( InterlockedIncrement( &pollEndpointInfo->Endpoint->ObReferenceBias ) > 0 );
  599. IF_DEBUG(POLL) {
  600. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  601. "AfdPoll32: event %lx, endp %p, conn %p, handle %p, "
  602. "info %p\n",
  603. pollEndpointInfo->PollEvents,
  604. pollEndpointInfo->Endpoint,
  605. AFD_CONNECTION_FROM_ENDPOINT( pollEndpointInfo->Endpoint ),
  606. pollEndpointInfo->Handle,
  607. pollEndpointInfo ));
  608. }
  609. REFERENCE_ENDPOINT2( pollEndpointInfo->Endpoint, "Poll for 0x%x", pollEndpointInfo->PollEvents );
  610. //
  611. // Increment pointers in the poll info structures.
  612. //
  613. pollHandleInfo++;
  614. pollEndpointInfo++;
  615. pollInfoInternal->NumberOfEndpoints++;
  616. }
  617. restart_poll:
  618. //
  619. // Hold the AFD spin lock while we check for endpoints that already
  620. // satisfy a condition to synchronize between this operation and
  621. // a call to AfdIndicatePollEvent. We release the spin lock
  622. // after all the endpoints have been checked and the internal
  623. // poll info structure is on the global list so AfdIndicatePollEvent
  624. // can find it if necessary.
  625. //
  626. AfdAcquireSpinLock( &AfdPollListLock, &pollLockHandle );
  627. //
  628. // We're done with the input structure provided by the caller. Now
  629. // walk through the internal structure and determine whether any of
  630. // the specified endpoints are ready for the specified condition.
  631. //
  632. pollInfo->NumberOfHandles = 0;
  633. pollHandleInfo = pollInfo->Handles;
  634. pollEndpointInfo = pollInfoInternal->EndpointInfo;
  635. for ( i = 0; i < pollInfoInternal->NumberOfEndpoints; i++ ) {
  636. PAFD_ENDPOINT endpoint;
  637. endpoint = pollEndpointInfo->Endpoint;
  638. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  639. AfdAcquireSpinLockAtDpcLevel (&endpoint->SpinLock, &endpointLockHandle);
  640. //
  641. // Remember that there has been a poll on this endpoint. This flag
  642. // allows us to optimize AfdIndicatePollEvent() for endpoints that have
  643. // never been polled, which is a common case.
  644. //
  645. endpoint->PollCalled = TRUE;
  646. pollHandleInfo->PollEvents = AfdCheckPollEvents (
  647. endpoint,
  648. pollEndpointInfo->PollEvents,
  649. &status
  650. );
  651. if (pollHandleInfo->PollEvents) {
  652. //
  653. // If the handle had a current event that was requested, update
  654. // the count of handles in the output buffer and increment the
  655. // pointer to the output buffer.
  656. //
  657. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &endpointLockHandle);
  658. UPDATE_ENDPOINT2 (endpoint, "Poll events satisfied inline:0x%lX",
  659. pollHandleInfo->PollEvents);
  660. pollHandleInfo->Handle = (VOID * POINTER_32)pollEndpointInfo->Handle;
  661. pollHandleInfo->Status = status;
  662. pollInfo->NumberOfHandles++;
  663. pollHandleInfo++;
  664. }
  665. else if (IS_SAN_ENDPOINT (endpoint) &&
  666. (pollEndpointInfo->PollEvents & AFD_POLL_SANCOUNTS_UPDATED)==0 &&
  667. pollInfo->NumberOfHandles==0) {
  668. //
  669. // OOPS, endpoint has been converted too SAN while we were looping,
  670. // need to release the spinlock, update switch counts, and restart
  671. // the loop. We don't do this is we are about to return anyway.
  672. //
  673. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &endpointLockHandle);
  674. AfdReleaseSpinLock (&AfdPollListLock, &pollLockHandle);
  675. ASSERT (endpoint->State==AfdEndpointStateConnected);
  676. status = AfdSanPollBegin (endpoint,
  677. pollEndpointInfo->PollEvents);
  678. if (!NT_SUCCESS (status)) {
  679. AfdFreePollInfo (pollInfoInternal);
  680. goto complete;
  681. }
  682. pollEndpointInfo->PollEvents |= AFD_POLL_SANCOUNTS_UPDATED;
  683. pollInfoInternal->SanPoll = TRUE;
  684. goto restart_poll;
  685. }
  686. else {
  687. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &endpointLockHandle);
  688. }
  689. pollEndpointInfo++;
  690. }
  691. //
  692. // If this is a unique poll, determine whether there is another
  693. // unique poll on this endpoint. If there is an existing unique
  694. // poll, cancel it. This request will supercede the existing
  695. // request.
  696. //
  697. if ( pollInfo->Unique ) {
  698. PLIST_ENTRY listEntry;
  699. for ( listEntry = AfdPollListHead.Flink;
  700. listEntry != &AfdPollListHead;
  701. listEntry = listEntry->Flink ) {
  702. PAFD_POLL_INFO_INTERNAL testInfo;
  703. testInfo = CONTAINING_RECORD(
  704. listEntry,
  705. AFD_POLL_INFO_INTERNAL,
  706. PollListEntry
  707. );
  708. if ( testInfo->Unique &&
  709. testInfo->EndpointInfo[0].FileObject ==
  710. pollInfoInternal->EndpointInfo[0].FileObject ) {
  711. IF_DEBUG(POLL) {
  712. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  713. "AfdPoll32: found existing unique poll IRP %p "
  714. "for file object %p, context %p, cancelling.\n",
  715. testInfo->Irp,
  716. testInfo->EndpointInfo[0].FileObject,
  717. testInfo ));
  718. }
  719. //
  720. // Cancel the IRP manually rather than calling
  721. // AfdCancelPoll because we already hold the
  722. // AfdSpinLock, we can't acquire it recursively, and we
  723. // don't want to release it. Remove the poll structure
  724. // from the global list.
  725. //
  726. RemoveEntryList( &testInfo->PollListEntry );
  727. //
  728. // No timer to cancel for Unique poll
  729. //
  730. ASSERT ( testInfo->TimerStarted == FALSE );
  731. //
  732. // Complete the IRP with STATUS_CANCELLED as the status.
  733. //
  734. testInfo->Irp->IoStatus.Information = 0;
  735. testInfo->Irp->IoStatus.Status = STATUS_CANCELLED;
  736. oldIrp = testInfo->Irp;
  737. //
  738. // Remember the poll info structure so that we'll free
  739. // before we exit. We cannot free it now because we're
  740. // holding the AfdSpinLock.
  741. //
  742. freePollInfo = testInfo;
  743. //
  744. // There should be only one outstanding unique poll IRP
  745. // on any given file object, so quit looking for another
  746. // now that we've found one.
  747. //
  748. break;
  749. }
  750. }
  751. }
  752. //
  753. // If we found any endpoints that are ready, free the poll information
  754. // structure and complete the request.
  755. //
  756. if ( pollInfo->NumberOfHandles > 0 ) {
  757. AfdReleaseSpinLock( &AfdPollListLock, &pollLockHandle );
  758. AfdFreePollInfo( pollInfoInternal );
  759. Irp->IoStatus.Information = (PUCHAR)pollHandleInfo - (PUCHAR)pollInfo;
  760. status = STATUS_SUCCESS;
  761. goto complete;
  762. }
  763. if ( pollInfo->Timeout.QuadPart == 0 ) {
  764. //
  765. // A timeout equal to 0 was specified; free the internal
  766. // structure and complete the request with no endpoints in the
  767. // output buffer.
  768. //
  769. IF_DEBUG(POLL) {
  770. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  771. "AfdPoll32: zero timeout on poll IRP %p and no "
  772. "current events--completing.\n", Irp ));
  773. }
  774. AfdReleaseSpinLock( &AfdPollListLock, &pollLockHandle );
  775. AfdFreePollInfo( pollInfoInternal );
  776. Irp->IoStatus.Information = (PUCHAR)pollHandleInfo - (PUCHAR)pollInfo;
  777. status = STATUS_SUCCESS;
  778. goto complete;
  779. }
  780. //
  781. // Set up a cancel routine in the IRP so that the IRP will be
  782. // completed correctly if it gets canceled. Also check whether the
  783. // IRP has already been canceled.
  784. //
  785. IoSetCancelRoutine( Irp, AfdCancelPoll );
  786. if ( Irp->Cancel ) {
  787. //
  788. // The IRP has already been canceled. Free the internal
  789. // poll information structure and complete the IRP.
  790. //
  791. AfdReleaseSpinLock( &AfdPollListLock, &pollLockHandle );
  792. if (IoSetCancelRoutine( Irp, NULL ) == NULL) {
  793. KIRQL cancelIrql;
  794. //
  795. // If the cancel routine was NULL then cancel routine
  796. // may be running. Wait on the cancel spinlock until
  797. // the cancel routine is done.
  798. //
  799. // Note: The cancel routine will not find the IRP
  800. // since it is not in the list.
  801. //
  802. IoAcquireCancelSpinLock( &cancelIrql );
  803. IoReleaseCancelSpinLock( cancelIrql );
  804. }
  805. AfdFreePollInfo( pollInfoInternal );
  806. status = STATUS_CANCELLED;
  807. goto complete;
  808. }
  809. IF_DEBUG(POLL) {
  810. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  811. "AfdPoll32: no current events for poll IRP %p, "
  812. "info %p\n", Irp, pollInfoInternal ));
  813. }
  814. //
  815. // Set up the information field of the IO status block to indicate
  816. // that an output buffer with no handles should be returned.
  817. // AfdIndicatePollEvent will modify this if necessary.
  818. //
  819. Irp->IoStatus.Information = (PUCHAR)pollHandleInfo - (PUCHAR)pollInfo;
  820. //
  821. // Put a pointer to the internal poll info struct into the IRP
  822. // so that the cancel routine can find it.
  823. //
  824. IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = pollInfoInternal;
  825. //
  826. // Place the internal poll info struct on the global list.
  827. //
  828. InsertTailList( &AfdPollListHead, &pollInfoInternal->PollListEntry );
  829. //
  830. // If the timeout is infinite, then don't set up a timer and
  831. // DPC. Otherwise, set up a timer so we can timeout the poll
  832. // request if appropriate.
  833. //
  834. if ( pollInfo->Timeout.HighPart != 0x7FFFFFFF ) {
  835. pollInfoInternal->TimerStarted = TRUE;
  836. KeInitializeDpc(
  837. &pollInfoInternal->Dpc,
  838. AfdTimeoutPoll,
  839. pollInfoInternal
  840. );
  841. KeInitializeTimer( &pollInfoInternal->Timer );
  842. KeSetTimer(
  843. &pollInfoInternal->Timer,
  844. pollInfo->Timeout,
  845. &pollInfoInternal->Dpc
  846. );
  847. } else {
  848. pollInfoInternal->TimerStarted = FALSE;
  849. }
  850. //
  851. // Mark the IRP pending and release the spin locks. At this
  852. // point the IRP may get completed or cancelled.
  853. //
  854. IoMarkIrpPending( Irp );
  855. AfdReleaseSpinLock( &AfdPollListLock, &pollLockHandle );
  856. //
  857. // Complete any old poll irps.
  858. //
  859. if ( oldIrp != NULL ) {
  860. AfdCompleteOldPollIrp (oldIrp, freePollInfo);
  861. }
  862. //
  863. // Return pending. The IRP will be completed when an appropriate
  864. // event is indicated by the TDI provider, when the timeout is hit,
  865. // or when the IRP is cancelled.
  866. //
  867. return STATUS_PENDING;
  868. complete:
  869. //
  870. // Complete any old poll irps.
  871. //
  872. if ( oldIrp != NULL ) {
  873. AfdCompleteOldPollIrp (oldIrp, freePollInfo);
  874. }
  875. Irp->IoStatus.Status = status;
  876. IoCompleteRequest( Irp, AfdPriorityBoost );
  877. return status;
  878. } // AfdPoll32
  879. #endif //_WIN64
  880. VOID
  881. AfdCancelPoll (
  882. IN PDEVICE_OBJECT DeviceObject,
  883. IN PIRP Irp
  884. )
  885. {
  886. PAFD_POLL_INFO_INTERNAL pollInfoInternal;
  887. PLIST_ENTRY listEntry;
  888. BOOLEAN found = FALSE;
  889. BOOLEAN timerCancelSucceeded;
  890. PIO_STACK_LOCATION irpSp;
  891. AFD_LOCK_QUEUE_HANDLE lockHandle;
  892. UNREFERENCED_PARAMETER (DeviceObject);
  893. irpSp = IoGetCurrentIrpStackLocation( Irp );
  894. pollInfoInternal =
  895. (PAFD_POLL_INFO_INTERNAL)irpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  896. IF_DEBUG(POLL) {
  897. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  898. "AfdCancelPoll called for IRP %p\n", Irp ));
  899. }
  900. //
  901. // Get the AFD spin lock and attempt to find the poll structure on
  902. // the list of outstanding polls.
  903. // Note the afdspinlock must be acquired befor the cancel spinlock
  904. // is released so that the pollInfoInternal does not get reused
  905. // before we have had a chance to look at the queue.
  906. //
  907. AfdAcquireSpinLockAtDpcLevel( &AfdPollListLock, &lockHandle);
  908. for ( listEntry = AfdPollListHead.Flink;
  909. listEntry != &AfdPollListHead;
  910. listEntry = listEntry->Flink ) {
  911. PAFD_POLL_INFO_INTERNAL testInfo;
  912. testInfo = CONTAINING_RECORD(
  913. listEntry,
  914. AFD_POLL_INFO_INTERNAL,
  915. PollListEntry
  916. );
  917. if ( testInfo == pollInfoInternal ) {
  918. found = TRUE;
  919. break;
  920. }
  921. }
  922. //
  923. // If we didn't find the poll structure on the list, then the
  924. // indication handler got called prior to the spinlock acquisition
  925. // above and it is already off the list. Just return and do
  926. // nothing, as the indication handler completed the IRP.
  927. //
  928. if ( !found ) {
  929. AfdReleaseSpinLockFromDpcLevel( &AfdPollListLock, &lockHandle);
  930. IoReleaseCancelSpinLock( Irp->CancelIrql );
  931. IF_DEBUG(POLL) {
  932. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  933. "AfdCancelPoll: poll info %p not found on list.\n",
  934. pollInfoInternal ));
  935. }
  936. return;
  937. }
  938. //
  939. // Remove the poll structure from the global list.
  940. //
  941. IF_DEBUG(POLL) {
  942. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  943. "AfdCancelPoll: poll info %p found on list, completing.\n",
  944. pollInfoInternal ));
  945. }
  946. RemoveEntryList( &pollInfoInternal->PollListEntry );
  947. //
  948. // Cancel the timer and reset the IRP pointer in the internal
  949. // poll information structure. NULLing the IRP field
  950. // prevents the timer routine from completing the IRP.
  951. //
  952. if ( pollInfoInternal->TimerStarted ) {
  953. timerCancelSucceeded = KeCancelTimer( &pollInfoInternal->Timer );
  954. } else {
  955. timerCancelSucceeded = TRUE;
  956. }
  957. //
  958. // Complete the IRP with STATUS_CANCELLED as the status.
  959. //
  960. Irp->IoStatus.Information = 0;
  961. Irp->IoStatus.Status = STATUS_CANCELLED;
  962. AfdReleaseSpinLockFromDpcLevel( &AfdPollListLock, &lockHandle);
  963. IoReleaseCancelSpinLock( Irp->CancelIrql );
  964. if (timerCancelSucceeded) {
  965. if (pollInfoInternal->SanPoll &&
  966. (Irp->CancelIrql>APC_LEVEL ||
  967. (Irp->Tail.Overlay.Thread!=PsGetCurrentThread ()))) {
  968. KeInitializeApc (&pollInfoInternal->Apc,
  969. PsGetThreadTcb (Irp->Tail.Overlay.Thread),
  970. Irp->ApcEnvironment,
  971. AfdSanPollApcKernelRoutine,
  972. AfdSanPollApcRundownRoutine,
  973. (PKNORMAL_ROUTINE)-1,
  974. KernelMode,
  975. NULL);
  976. if (KeInsertQueueApc (&pollInfoInternal->Apc,
  977. pollInfoInternal,
  978. Irp,
  979. AfdPriorityBoost)) {
  980. return ;
  981. }
  982. else {
  983. pollInfoInternal->SanPoll = FALSE;
  984. }
  985. }
  986. //
  987. // Free the poll information structure if the cancel succeeded. If
  988. // the cancel of the timer did not succeed, then the timer is
  989. // already running and the timer DPC will free the internal
  990. // poll info.
  991. //
  992. AfdFreePollInfo( pollInfoInternal );
  993. IoCompleteRequest( Irp, AfdPriorityBoost );
  994. }
  995. return;
  996. } // AfdCancelPoll
  997. VOID
  998. AfdFreePollInfo (
  999. IN PAFD_POLL_INFO_INTERNAL PollInfoInternal
  1000. )
  1001. {
  1002. ULONG i;
  1003. PAFD_POLL_ENDPOINT_INFO pollEndpointInfo;
  1004. IF_DEBUG(POLL) {
  1005. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1006. "AfdFreePollInfo: freeing info struct at %p\n",
  1007. PollInfoInternal ));
  1008. }
  1009. // *** Note that this routine does not remove the poll information
  1010. // structure from the global list--that is the responsibility
  1011. // of the caller!
  1012. //
  1013. // Walk the list of endpoints in the poll information structure and
  1014. // dereference each one.
  1015. //
  1016. pollEndpointInfo = PollInfoInternal->EndpointInfo;
  1017. for ( i = 0; i < PollInfoInternal->NumberOfEndpoints; i++ ) {
  1018. ASSERT( InterlockedDecrement( &pollEndpointInfo->Endpoint->ObReferenceBias ) >= 0 );
  1019. if (PollInfoInternal->SanPoll) {
  1020. ASSERT (PollInfoInternal->Irp!=NULL);
  1021. ASSERT (PsGetCurrentThread ()==PollInfoInternal->Irp->Tail.Overlay.Thread);
  1022. if (pollEndpointInfo->PollEvents & AFD_POLL_SANCOUNTS_UPDATED) {
  1023. ASSERT (IS_SAN_ENDPOINT (pollEndpointInfo->Endpoint));
  1024. AfdSanPollEnd (pollEndpointInfo->Endpoint,
  1025. pollEndpointInfo->PollEvents);
  1026. }
  1027. }
  1028. DEREFERENCE_ENDPOINT( pollEndpointInfo->Endpoint );
  1029. ObDereferenceObject( pollEndpointInfo->FileObject );
  1030. pollEndpointInfo++;
  1031. }
  1032. //
  1033. // Free the structure itself and return.
  1034. //
  1035. AFD_FREE_POOL(
  1036. PollInfoInternal,
  1037. AFD_POLL_POOL_TAG
  1038. );
  1039. return;
  1040. } // AfdFreePollInfo
  1041. VOID
  1042. AfdCompleteOldPollIrp (
  1043. IN PIRP Irp,
  1044. IN PAFD_POLL_INFO_INTERNAL PollInfo
  1045. )
  1046. {
  1047. if (IoSetCancelRoutine( Irp, NULL ) == NULL) {
  1048. KIRQL cancelIrql;
  1049. //
  1050. // If the cancel routine was NULL then cancel routine
  1051. // may be running. Wait on the cancel spinlock until
  1052. // the cancel routine is done.
  1053. //
  1054. // Note: The cancel routine will not find the IRP
  1055. // since it is not in the list.
  1056. //
  1057. IoAcquireCancelSpinLock( &cancelIrql );
  1058. ASSERT( Irp->Cancel );
  1059. IoReleaseCancelSpinLock( cancelIrql );
  1060. }
  1061. if (PollInfo!=NULL) {
  1062. if (PollInfo->SanPoll &&
  1063. (Irp->Tail.Overlay.Thread!=PsGetCurrentThread ())) {
  1064. KeInitializeApc (&PollInfo->Apc,
  1065. PsGetThreadTcb (Irp->Tail.Overlay.Thread),
  1066. Irp->ApcEnvironment,
  1067. AfdSanPollApcKernelRoutine,
  1068. AfdSanPollApcRundownRoutine,
  1069. (PKNORMAL_ROUTINE)-1,
  1070. KernelMode,
  1071. NULL);
  1072. if (KeInsertQueueApc (&PollInfo->Apc,
  1073. PollInfo,
  1074. Irp,
  1075. AfdPriorityBoost)) {
  1076. //
  1077. // IRP will be completed in APC
  1078. //
  1079. return ;
  1080. }
  1081. else {
  1082. PollInfo->SanPoll = FALSE;
  1083. }
  1084. }
  1085. AfdFreePollInfo( PollInfo );
  1086. }
  1087. IoCompleteRequest( Irp, AfdPriorityBoost );
  1088. }
  1089. VOID
  1090. AfdIndicatePollEventReal (
  1091. IN PAFD_ENDPOINT Endpoint,
  1092. IN ULONG PollEventMask,
  1093. IN NTSTATUS Status
  1094. )
  1095. /*++
  1096. Routine Description:
  1097. Called to complete polls with a specific event or events.
  1098. Arguments:
  1099. Endpoint - the endpoint on which the action occurred.
  1100. PollEventMask - the mask of the events which occurred.
  1101. Status - the status of the event, if any.
  1102. Return Value:
  1103. None.
  1104. --*/
  1105. {
  1106. LIST_ENTRY completePollListHead;
  1107. PLIST_ENTRY listEntry;
  1108. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1109. PAFD_POLL_INFO_INTERNAL pollInfoInternal;
  1110. union {
  1111. PAFD_POLL_INFO PollInfo;
  1112. PAFD_POLL_INFO32 PollInfo32;
  1113. } u;
  1114. #define pollInfo u.PollInfo
  1115. #define pollInfo32 u.PollInfo32
  1116. PIRP irp;
  1117. PIO_STACK_LOCATION irpSp;
  1118. ASSERT (PollEventMask!=0);
  1119. ASSERT (((~((1<<AFD_NUM_POLL_EVENTS)-1)) & PollEventMask)==0);
  1120. //
  1121. // Note that AFD_POLL_ABORT implies AFD_POLL_SEND.
  1122. //
  1123. if( PollEventMask & AFD_POLL_ABORT ) {
  1124. PollEventMask |= AFD_POLL_SEND;
  1125. }
  1126. //
  1127. // Initialize the list of poll info structures that we'll be
  1128. // completing for this event.
  1129. //
  1130. InitializeListHead( &completePollListHead );
  1131. //
  1132. // Walk the global list of polls, searching for any the are waiting
  1133. // for the specified event on the specified endpoint.
  1134. //
  1135. AfdAcquireSpinLock( &AfdPollListLock, &lockHandle );
  1136. for ( listEntry = AfdPollListHead.Flink;
  1137. listEntry != &AfdPollListHead;
  1138. listEntry = listEntry->Flink ) {
  1139. PAFD_POLL_ENDPOINT_INFO pollEndpointInfo;
  1140. ULONG i;
  1141. ULONG foundCount = 0;
  1142. pollInfoInternal = CONTAINING_RECORD(
  1143. listEntry,
  1144. AFD_POLL_INFO_INTERNAL,
  1145. PollListEntry
  1146. );
  1147. pollInfo = pollInfoInternal->Irp->AssociatedIrp.SystemBuffer;
  1148. irp = pollInfoInternal->Irp;
  1149. irpSp = IoGetCurrentIrpStackLocation( irp );
  1150. IF_DEBUG(POLL) {
  1151. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1152. "AfdIndicatePollEvent: pollInfoInt %p "
  1153. "IRP %p pollInfo %p event mask %lx status %lx\n",
  1154. pollInfoInternal, irp, pollInfo,
  1155. PollEventMask, Status ));
  1156. }
  1157. //
  1158. // Walk the poll structure looking for matching endpoints.
  1159. //
  1160. pollEndpointInfo = pollInfoInternal->EndpointInfo;
  1161. for ( i = 0; i < pollInfoInternal->NumberOfEndpoints; i++ ) {
  1162. IF_DEBUG(POLL) {
  1163. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1164. "AfdIndicatePollEvent: pollEndpointInfo = %p, "
  1165. "comparing %p, %p\n",
  1166. pollEndpointInfo, pollEndpointInfo->Endpoint,
  1167. Endpoint ));
  1168. }
  1169. //
  1170. // Update the counts for the polls that were issued before
  1171. // the endpoint was converted to SAN.
  1172. //
  1173. if (Endpoint==pollEndpointInfo->Endpoint &&
  1174. IS_SAN_ENDPOINT (Endpoint) &&
  1175. !(pollEndpointInfo->PollEvents & AFD_POLL_SANCOUNTS_UPDATED) &&
  1176. Endpoint->Common.SanEndp.LocalContext!=NULL) {
  1177. AfdSanPollUpdate (Endpoint, pollEndpointInfo->PollEvents);
  1178. pollEndpointInfo->PollEvents |= AFD_POLL_SANCOUNTS_UPDATED;
  1179. }
  1180. //
  1181. // Regardless of whether the caller requested to be told about
  1182. // local closes, we'll complete the IRP if an endpoint
  1183. // is being closed. When they close an endpoint, all IO on
  1184. // the endpoint must be completed.
  1185. //
  1186. if ( Endpoint == pollEndpointInfo->Endpoint &&
  1187. ( (PollEventMask & pollEndpointInfo->PollEvents) != 0
  1188. ||
  1189. (PollEventMask & AFD_POLL_LOCAL_CLOSE) ) ) {
  1190. //
  1191. // Revalidate under the lock that event is still present
  1192. // (except for AFD_POLL_ADDRESS_LIST_CHANGE which never gets
  1193. // OR'd into Endpoint->EventsActive)
  1194. // It is possible that once we released endpoint lock to
  1195. // acquire poll list lock, application made a call that
  1196. // reset the event (e.g. consumed the data and receive event
  1197. // is no longer valid). If after invalidating the event
  1198. // application also managed to submit another select, we
  1199. // can produce a false signal.
  1200. //
  1201. AFD_LOCK_QUEUE_HANDLE endpointLockHandle;
  1202. ULONG events;
  1203. AfdAcquireSpinLockAtDpcLevel (&Endpoint->SpinLock, &endpointLockHandle);
  1204. events = AfdCheckPollEvents (
  1205. Endpoint,
  1206. pollEndpointInfo->PollEvents,
  1207. &Status) | (PollEventMask & AFD_POLL_LOCAL_CLOSE)
  1208. | (PollEventMask & AFD_POLL_ADDRESS_LIST_CHANGE);
  1209. AfdReleaseSpinLockFromDpcLevel (&Endpoint->SpinLock, &endpointLockHandle);
  1210. if (events) {
  1211. UPDATE_ENDPOINT2 (Endpoint, "Poll events satisfied in indication: 0x%lX", events);
  1212. #ifdef _WIN64
  1213. if (IoIs32bitProcess (irp)) {
  1214. ASSERT( pollInfo32->NumberOfHandles == foundCount );
  1215. IF_DEBUG(POLL) {
  1216. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1217. "AfdIndicatePollEvent32: endpoint %p found "
  1218. " for event %lx\n",
  1219. pollEndpointInfo->Endpoint, PollEventMask ));
  1220. }
  1221. pollInfo32->NumberOfHandles++;
  1222. pollInfo32->Handles[foundCount].Handle = (VOID * POINTER_32)pollEndpointInfo->Handle;
  1223. pollInfo32->Handles[foundCount].PollEvents = events;
  1224. pollInfo32->Handles[foundCount].Status = Status;
  1225. }
  1226. else
  1227. #endif // _WIN64
  1228. {
  1229. ASSERT( pollInfo->NumberOfHandles == foundCount );
  1230. IF_DEBUG(POLL) {
  1231. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1232. "AfdIndicatePollEvent: endpoint %p found "
  1233. " for event %lx\n",
  1234. pollEndpointInfo->Endpoint, PollEventMask ));
  1235. }
  1236. pollInfo->NumberOfHandles++;
  1237. pollInfo->Handles[foundCount].Handle = pollEndpointInfo->Handle;
  1238. pollInfo->Handles[foundCount].PollEvents = events;
  1239. pollInfo->Handles[foundCount].Status = Status;
  1240. }
  1241. foundCount++;
  1242. }
  1243. }
  1244. pollEndpointInfo++;
  1245. }
  1246. //
  1247. // If we found any matching endpoints, remove the poll information
  1248. // structure from the global list, complete the IRP, and free the
  1249. // poll information structure.
  1250. //
  1251. if ( foundCount != 0 ) {
  1252. BOOLEAN timerCancelSucceeded;
  1253. //
  1254. // We need to release the spin lock to call AfdFreePollInfo,
  1255. // since it calls AfdDereferenceEndpoint which in turn needs
  1256. // to acquire the spin lock, and recursive spin lock
  1257. // acquisitions result in deadlock. However, we can't
  1258. // release the lock of else the state of the poll list could
  1259. // change, e.g. the next entry could get freed. Remove
  1260. // this entry from the global list and place it on a local
  1261. // list. We'll complete all the poll IRPs after walking
  1262. // the entire list.
  1263. //
  1264. RemoveEntryList( &pollInfoInternal->PollListEntry );
  1265. //
  1266. // Set up the IRP for completion now, since we have all needed
  1267. // information here.
  1268. //
  1269. #ifdef _WIN64
  1270. if (IoIs32bitProcess (irp)) {
  1271. irp->IoStatus.Information =
  1272. (PUCHAR)&pollInfo32->Handles[foundCount] - (PUCHAR)pollInfo32;
  1273. }
  1274. else
  1275. #endif
  1276. {
  1277. irp->IoStatus.Information =
  1278. (PUCHAR)&pollInfo->Handles[foundCount] - (PUCHAR)pollInfo;
  1279. }
  1280. irp->IoStatus.Status = STATUS_SUCCESS;
  1281. //
  1282. // Cancel the timer on the poll so that it does not fire.
  1283. //
  1284. if ( pollInfoInternal->TimerStarted ) {
  1285. timerCancelSucceeded = KeCancelTimer( &pollInfoInternal->Timer );
  1286. } else {
  1287. timerCancelSucceeded = TRUE;
  1288. }
  1289. //
  1290. // If the cancel of the timer failed, then we don't want to
  1291. // free this structure since the timer routine is running.
  1292. // Let the timer routine free the structure.
  1293. //
  1294. if ( timerCancelSucceeded ) {
  1295. InsertTailList(
  1296. &completePollListHead,
  1297. &irp->Tail.Overlay.ListEntry
  1298. );
  1299. }
  1300. }
  1301. }
  1302. AfdReleaseSpinLock( &AfdPollListLock, &lockHandle );
  1303. //
  1304. // Now walk the list of polls we need to actually complete. Free
  1305. // the poll info structures as we go.
  1306. //
  1307. while ( !IsListEmpty( &completePollListHead ) ) {
  1308. listEntry = RemoveHeadList( &completePollListHead );
  1309. ASSERT( listEntry != &completePollListHead );
  1310. irp = CONTAINING_RECORD(
  1311. listEntry,
  1312. IRP,
  1313. Tail.Overlay.ListEntry
  1314. );
  1315. irpSp = IoGetCurrentIrpStackLocation( irp );
  1316. pollInfoInternal =
  1317. irpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  1318. if (IoSetCancelRoutine( irp, NULL ) == NULL) {
  1319. KIRQL cancelIrql;
  1320. //
  1321. // If the cancel routine was NULL then cancel routine
  1322. // may be running. Wait on the cancel spinlock until
  1323. // the cancel routine is done.
  1324. //
  1325. // Note: The cancel routine will not find the IRP
  1326. // since it is not in the list.
  1327. //
  1328. IoAcquireCancelSpinLock( &cancelIrql );
  1329. ASSERT( irp->Cancel );
  1330. IoReleaseCancelSpinLock( cancelIrql );
  1331. }
  1332. if (pollInfoInternal->SanPoll &&
  1333. ((irp->Tail.Overlay.Thread!=PsGetCurrentThread ()) ||
  1334. (KeGetCurrentIrql() > APC_LEVEL)) ) {
  1335. KeInitializeApc (&pollInfoInternal->Apc,
  1336. PsGetThreadTcb (irp->Tail.Overlay.Thread),
  1337. irp->ApcEnvironment,
  1338. AfdSanPollApcKernelRoutine,
  1339. AfdSanPollApcRundownRoutine,
  1340. (PKNORMAL_ROUTINE)-1,
  1341. KernelMode,
  1342. NULL);
  1343. if (KeInsertQueueApc (&pollInfoInternal->Apc,
  1344. pollInfoInternal,
  1345. irp,
  1346. AfdPriorityBoost)) {
  1347. continue ;
  1348. }
  1349. else {
  1350. pollInfoInternal->SanPoll = FALSE;
  1351. }
  1352. }
  1353. //
  1354. // Free the poll info structure.
  1355. //
  1356. AfdFreePollInfo( pollInfoInternal );
  1357. IoCompleteRequest( irp, AfdPriorityBoost );
  1358. }
  1359. return;
  1360. } // AfdIndicatePollEvent
  1361. ULONG
  1362. AfdCheckPollEvents (
  1363. IN PAFD_ENDPOINT Endpoint,
  1364. IN ULONG PollEventMask,
  1365. OUT NTSTATUS *Status
  1366. )
  1367. /*++
  1368. Routine Description:
  1369. Checks the state of the endpoint to see if given events can be satisfied
  1370. Arguments:
  1371. Endpoint - the endpoint to check
  1372. PollEventMask - the mask of the events to check for
  1373. Status - the status for the events being signalled.
  1374. Return Value:
  1375. Mask of the events being signalled.
  1376. --*/
  1377. {
  1378. ULONG events;
  1379. PAFD_CONNECTION connection = AFD_CONNECTION_FROM_ENDPOINT (Endpoint);
  1380. ASSERT( connection == NULL || connection->Type == AfdBlockTypeConnection );
  1381. events = 0;
  1382. *Status = STATUS_SUCCESS;
  1383. if (IS_SAN_ENDPOINT (Endpoint)) {
  1384. if (Endpoint->Common.SanEndp.SelectEventsActive & PollEventMask) {
  1385. events = PollEventMask & Endpoint->Common.SanEndp.SelectEventsActive;
  1386. }
  1387. }
  1388. else {
  1389. //
  1390. // Check each possible event and, if it is being polled, whether
  1391. // the endpoint is ready for that event. If the endpoint is
  1392. // ready, write information about the endpoint into the output
  1393. // buffer.
  1394. //
  1395. if ( (PollEventMask & AFD_POLL_RECEIVE) != 0 ) {
  1396. //
  1397. // For most endpoints, a receive poll is completed when
  1398. // data arrived that does not have a posted receive.
  1399. //
  1400. // If the endpoint is set up for inline reception of
  1401. // expedited data, then any expedited data should
  1402. // be indicated as normal data.
  1403. //
  1404. if ( (IS_DGRAM_ENDPOINT(Endpoint) &&
  1405. ARE_DATAGRAMS_ON_ENDPOINT( Endpoint )) ||
  1406. (connection != NULL &&
  1407. ( IS_DATA_ON_CONNECTION( connection ) ||
  1408. (Endpoint->InLine &&
  1409. IS_EXPEDITED_DATA_ON_CONNECTION( connection )) ) ) ) {
  1410. events |= AFD_POLL_RECEIVE;
  1411. }
  1412. }
  1413. if ( (PollEventMask & AFD_POLL_RECEIVE_EXPEDITED) != 0 ) {
  1414. //
  1415. // If the endpoint is set up for inline reception of
  1416. // expedited data, do not indicate as expedited data.
  1417. //
  1418. if ( connection != NULL && !Endpoint->InLine &&
  1419. IS_EXPEDITED_DATA_ON_CONNECTION( connection ) ) {
  1420. events |= AFD_POLL_RECEIVE_EXPEDITED;
  1421. }
  1422. }
  1423. if ( (PollEventMask & AFD_POLL_SEND) != 0 ) {
  1424. //
  1425. // For unconnected non-datagram endpoints, a send poll
  1426. // should complete when a connect operation completes.
  1427. // Therefore, if this is an non-datagram endpoint which is
  1428. // not connected, do not complete the poll until the connect
  1429. // completes.
  1430. //
  1431. //
  1432. // For nonbufferring VC
  1433. // endpoints, check whether a blocking error has
  1434. // occurred. If so, it will not be possible to do a
  1435. // nonblocking send until a send possible indication
  1436. // arrives.
  1437. //
  1438. // For bufferring endpoints (TDI provider does not
  1439. // buffer), check whether we have too much send data
  1440. // outstanding.
  1441. //
  1442. if ( (IS_DGRAM_ENDPOINT(Endpoint) &&
  1443. (Endpoint->DgBufferredSendBytes <
  1444. Endpoint->Common.Datagram.MaxBufferredSendBytes ||
  1445. Endpoint->DgBufferredSendBytes == 0)) ||
  1446. ( (connection!=NULL) &&
  1447. (Endpoint->State == AfdEndpointStateConnected) &&
  1448. (
  1449. (IS_TDI_BUFFERRING(Endpoint) &&
  1450. connection->VcNonBlockingSendPossible ) ||
  1451. ( !IS_TDI_BUFFERRING(Endpoint) &&
  1452. (connection->VcBufferredSendBytes <
  1453. connection->MaxBufferredSendBytes ||
  1454. connection->VcBufferredSendBytes == 0)) ||
  1455. connection->Aborted ) ) ) {
  1456. events |= AFD_POLL_SEND;
  1457. }
  1458. }
  1459. if ( (PollEventMask & AFD_POLL_ACCEPT) != 0 ) {
  1460. if ( (Endpoint->Type & AfdBlockTypeVcListening) == AfdBlockTypeVcListening &&
  1461. !IsListEmpty( &Endpoint->Common.VcListening.UnacceptedConnectionListHead ) ) {
  1462. events |= AFD_POLL_ACCEPT;
  1463. }
  1464. }
  1465. if ( (PollEventMask & AFD_POLL_CONNECT) != 0 ) {
  1466. //
  1467. // If the endpoint is now connected, complete this event.
  1468. //
  1469. if ( Endpoint->State == AfdEndpointStateConnected ) {
  1470. ASSERT( NT_SUCCESS(Endpoint->EventStatus[AFD_POLL_CONNECT_FAIL_BIT]) );
  1471. events |= AFD_POLL_CONNECT;
  1472. }
  1473. }
  1474. if ( (PollEventMask & AFD_POLL_CONNECT_FAIL) != 0 ) {
  1475. //
  1476. // This is a poll to see whether a connect has failed
  1477. // recently. The connect status must indicate an error.
  1478. //
  1479. if ( Endpoint->State == AfdEndpointStateBound &&
  1480. !NT_SUCCESS(Endpoint->EventStatus[AFD_POLL_CONNECT_FAIL_BIT]) ) {
  1481. events |= AFD_POLL_CONNECT_FAIL;
  1482. *Status = Endpoint->EventStatus[AFD_POLL_CONNECT_FAIL_BIT];
  1483. }
  1484. }
  1485. if ( (PollEventMask & AFD_POLL_DISCONNECT) != 0 ) {
  1486. if ( connection != NULL && connection->DisconnectIndicated ) {
  1487. events |= AFD_POLL_DISCONNECT;
  1488. }
  1489. }
  1490. if ( (PollEventMask & AFD_POLL_ABORT) != 0 ) {
  1491. if ( connection != NULL && connection->Aborted ) {
  1492. events |= AFD_POLL_ABORT;
  1493. }
  1494. }
  1495. }
  1496. return events;
  1497. }
  1498. VOID
  1499. AfdTimeoutPoll (
  1500. IN PKDPC Dpc,
  1501. IN PVOID DeferredContext,
  1502. IN PVOID SystemArgument1,
  1503. IN PVOID SystemArgument2
  1504. )
  1505. {
  1506. PAFD_POLL_INFO_INTERNAL pollInfoInternal = DeferredContext;
  1507. PIRP irp;
  1508. PLIST_ENTRY listEntry;
  1509. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1510. UNREFERENCED_PARAMETER (Dpc);
  1511. UNREFERENCED_PARAMETER (SystemArgument1);
  1512. UNREFERENCED_PARAMETER (SystemArgument2);
  1513. //
  1514. // Get the AFD spin lock and attempt to find the poll structure on
  1515. // the list of outstanding polls.
  1516. //
  1517. AfdAcquireSpinLock( &AfdPollListLock, &lockHandle );
  1518. for ( listEntry = AfdPollListHead.Flink;
  1519. listEntry != &AfdPollListHead;
  1520. listEntry = listEntry->Flink ) {
  1521. PAFD_POLL_INFO_INTERNAL testInfo;
  1522. testInfo = CONTAINING_RECORD(
  1523. listEntry,
  1524. AFD_POLL_INFO_INTERNAL,
  1525. PollListEntry
  1526. );
  1527. if ( testInfo == pollInfoInternal ) {
  1528. //
  1529. // Remove the poll structure from the global list.
  1530. //
  1531. IF_DEBUG(POLL) {
  1532. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL, "AfdTimeoutPoll: poll info %p found on list, completing.\n",
  1533. pollInfoInternal ));
  1534. }
  1535. RemoveEntryList( &pollInfoInternal->PollListEntry );
  1536. break;
  1537. }
  1538. }
  1539. ASSERT( pollInfoInternal->TimerStarted );
  1540. //
  1541. // If we didn't find the poll structure on the list, then the
  1542. // indication handler got called prior to the spinlock acquisition
  1543. // above and it is already off the list. It must have setup
  1544. // the IRP completion code already.
  1545. //
  1546. // We must free the internal information structure in this case,
  1547. // since the indication handler will not free it. The indication
  1548. // handler cannot free the structure because the structure contains
  1549. // the timer object, which must remain intact until this routine
  1550. // is entered.
  1551. //
  1552. //
  1553. // The IRP should not have been completed at this point.
  1554. //
  1555. ASSERT( pollInfoInternal->Irp != NULL );
  1556. irp = pollInfoInternal->Irp;
  1557. //
  1558. // Remove the poll structure from the global list.
  1559. //
  1560. IF_DEBUG(POLL) {
  1561. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1562. "AfdTimeoutPoll: poll info %p found on list, completing.\n",
  1563. pollInfoInternal ));
  1564. }
  1565. AfdReleaseSpinLock( &AfdPollListLock, &lockHandle );
  1566. //
  1567. // Complete the IRP pointed to in the poll structure. The
  1568. // Information field has already been set up by AfdPoll, as well as
  1569. // the output buffer.
  1570. //
  1571. if (IoSetCancelRoutine( irp, NULL ) == NULL) {
  1572. KIRQL cancelIrql;
  1573. //
  1574. // If the cancel routine was NULL then cancel routine
  1575. // may be running. Wait on the cancel spinlock until
  1576. // the cancel routine is done.
  1577. //
  1578. // Note: The cancel routine will not find the IRP
  1579. // since it is not in the list.
  1580. //
  1581. IoAcquireCancelSpinLock( &cancelIrql );
  1582. ASSERT( irp->Cancel );
  1583. IoReleaseCancelSpinLock( cancelIrql );
  1584. }
  1585. if (pollInfoInternal->SanPoll) {
  1586. KeInitializeApc (&pollInfoInternal->Apc,
  1587. PsGetThreadTcb (irp->Tail.Overlay.Thread),
  1588. irp->ApcEnvironment,
  1589. AfdSanPollApcKernelRoutine,
  1590. AfdSanPollApcRundownRoutine,
  1591. (PKNORMAL_ROUTINE)-1,
  1592. KernelMode,
  1593. NULL);
  1594. if (KeInsertQueueApc (&pollInfoInternal->Apc,
  1595. pollInfoInternal,
  1596. irp,
  1597. AfdPriorityBoost)) {
  1598. return;
  1599. }
  1600. else {
  1601. pollInfoInternal->SanPoll = FALSE;
  1602. }
  1603. }
  1604. IoCompleteRequest( irp, AfdPriorityBoost );
  1605. //
  1606. // Free the poll information structure.
  1607. //
  1608. AfdFreePollInfo( pollInfoInternal );
  1609. return;
  1610. } // AfdTimeoutPoll
  1611. VOID
  1612. AfdSanPollApcKernelRoutine (
  1613. IN struct _KAPC *Apc,
  1614. IN OUT PKNORMAL_ROUTINE *NormalRoutine,
  1615. IN OUT PVOID *NormalContext,
  1616. IN OUT PVOID *SystemArgument1,
  1617. IN OUT PVOID *SystemArgument2
  1618. )
  1619. /*++
  1620. Routine Description:
  1621. Special kernel apc routine. Executed in the context of
  1622. the target thread at APC_LEVEL
  1623. Arguments:
  1624. NormalRoutine - pointer containing address of normal routine (it will
  1625. be NULL for special kernel APC and not NULL for normal
  1626. kernel APC)
  1627. SystemArgument1 - pointer to the address of worker routine to execute
  1628. SyetemArgument2 - pointer to the argument to pass to worker routine
  1629. Return Value:
  1630. None.
  1631. --*/
  1632. {
  1633. PAFD_POLL_INFO_INTERNAL pollInfoInternal;
  1634. PIRP irp;
  1635. UNREFERENCED_PARAMETER (Apc);
  1636. UNREFERENCED_PARAMETER (NormalContext);
  1637. PAGED_CODE ();
  1638. pollInfoInternal = *SystemArgument1;
  1639. irp = *SystemArgument2;
  1640. ASSERT (pollInfoInternal->Irp==irp);
  1641. //
  1642. // Normal APC, but we are requested to run in its special
  1643. // routine which avoids raising and lowering IRQL
  1644. //
  1645. ASSERT (*NormalRoutine==(PKNORMAL_ROUTINE)-1);
  1646. *NormalRoutine = NULL;
  1647. AfdFreePollInfo (pollInfoInternal);
  1648. IoCompleteRequest (irp, IO_NO_INCREMENT);
  1649. }
  1650. VOID
  1651. AfdSanPollApcRundownRoutine (
  1652. IN struct _KAPC *Apc
  1653. )
  1654. /*++
  1655. Routine Description:
  1656. APC rundown routine. Executed if APC cannot be delivered for
  1657. some reason (thread exiting).
  1658. Arguments:
  1659. Apc - APC structure
  1660. Return Value:
  1661. None.
  1662. --*/
  1663. {
  1664. PAFD_POLL_INFO_INTERNAL pollInfoInternal;
  1665. PIRP irp;
  1666. PAGED_CODE ();
  1667. pollInfoInternal = Apc->SystemArgument1;
  1668. irp = Apc->SystemArgument2;
  1669. ASSERT (pollInfoInternal->Irp==irp);
  1670. AfdFreePollInfo (pollInfoInternal);
  1671. IoCompleteRequest (irp, IO_NO_INCREMENT);
  1672. }