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.

802 lines
20 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. queue.c
  5. Abstract:
  6. This module implements IRP queue processing routines for ws2ifsl.sys driver.
  7. Author:
  8. Vadim Eydelman (VadimE) Dec-1996
  9. Revision History:
  10. Vadim Eydelman (VadimE) Oct-1997, rewrite to properly handle IRP
  11. cancellation
  12. --*/
  13. #include "precomp.h"
  14. //
  15. // Private prototypes
  16. //
  17. VOID
  18. QueueKernelRoutine (
  19. IN struct _KAPC *Apc,
  20. IN OUT PKNORMAL_ROUTINE *NormalRoutine,
  21. IN OUT PVOID *NormalContext,
  22. IN OUT PVOID *SystemArgument1,
  23. IN OUT PVOID *SystemArgument2
  24. );
  25. VOID
  26. SignalRequest (
  27. IN PIFSL_PROCESS_CTX ProcessCtx
  28. );
  29. VOID
  30. RequestRundownRoutine (
  31. IN struct _KAPC *Apc
  32. );
  33. VOID
  34. FlushRequestQueue (
  35. PIFSL_QUEUE Queue
  36. );
  37. VOID
  38. QueuedCancelRoutine (
  39. IN PDEVICE_OBJECT DeviceObject,
  40. IN PIRP Irp
  41. );
  42. VOID
  43. SignalCancel (
  44. IN PIFSL_PROCESS_CTX ProcessCtx
  45. );
  46. VOID
  47. CancelRundownRoutine (
  48. IN struct _KAPC *Apc
  49. );
  50. VOID
  51. FlushCancelQueue (
  52. PIFSL_QUEUE Queue
  53. );
  54. #pragma alloc_text(PAGE, InitializeRequestQueue)
  55. #pragma alloc_text(PAGE, InitializeCancelQueue)
  56. VOID
  57. InitializeRequestQueue (
  58. IN PIFSL_PROCESS_CTX ProcessCtx,
  59. IN PKTHREAD ApcThread,
  60. IN KPROCESSOR_MODE ApcMode,
  61. IN PKNORMAL_ROUTINE ApcRoutine,
  62. IN PVOID ApcContext
  63. )
  64. /*++
  65. Routine Description:
  66. Initializes request queue object
  67. Arguments:
  68. ProcessCtx - process context to which queue belongs
  69. ApcThread - thread to which to queue APC requests for processing
  70. ApcMode - mode of the caller (should be user)
  71. ApcRoutine - routine that processes requests
  72. ApcContext - context to pass to the routine in addition to request
  73. parameters
  74. Return Value:
  75. None
  76. --*/
  77. {
  78. PAGED_CODE ();
  79. InitializeListHead (&ProcessCtx->RequestQueue.ListHead);
  80. ProcessCtx->RequestQueue.Busy = FALSE;
  81. KeInitializeSpinLock (&ProcessCtx->RequestQueue.Lock);
  82. KeInitializeApc (&ProcessCtx->RequestQueue.Apc,
  83. ApcThread,
  84. OriginalApcEnvironment,
  85. QueueKernelRoutine,
  86. RequestRundownRoutine,
  87. ApcRoutine,
  88. ApcMode,
  89. ApcContext);
  90. }
  91. BOOLEAN
  92. QueueRequest (
  93. IN PIFSL_PROCESS_CTX ProcessCtx,
  94. IN PIRP Irp
  95. )
  96. /*++
  97. Routine Description:
  98. Queues IRP to IFSL request queue and signals to user mode DLL
  99. to start processing if it is not busy already.
  100. Arguments:
  101. ProcessCtx - process context in which to queue
  102. Irp - request to be queued
  103. Return Value:
  104. TRUE - IRP was queued
  105. FALSE - IRP was already cancelled
  106. --*/
  107. {
  108. BOOLEAN res;
  109. KIRQL oldIRQL;
  110. PIFSL_QUEUE queue = &ProcessCtx->RequestQueue;
  111. IoSetCancelRoutine (Irp, QueuedCancelRoutine);
  112. KeAcquireSpinLock (&queue->Lock, &oldIRQL);
  113. if (!Irp->Cancel) {
  114. //
  115. // Request is not cancelled, insert it into the queue
  116. //
  117. InsertTailList (&queue->ListHead, &Irp->Tail.Overlay.ListEntry);
  118. Irp->Tail.Overlay.IfslRequestQueue = queue;
  119. //
  120. // If queue wasn't busy, signal to user mode DLL to pick up new request
  121. //
  122. if (!queue->Busy) {
  123. ASSERT (queue->ListHead.Flink==&Irp->Tail.Overlay.ListEntry);
  124. SignalRequest (ProcessCtx);
  125. ASSERT (queue->Busy);
  126. }
  127. res = TRUE;
  128. }
  129. else {
  130. res = FALSE;
  131. }
  132. KeReleaseSpinLock (&queue->Lock, oldIRQL);
  133. return res;
  134. } // QueueRequest
  135. PIRP
  136. DequeueRequest (
  137. PIFSL_PROCESS_CTX ProcessCtx,
  138. ULONG UniqueId,
  139. BOOLEAN *more
  140. )
  141. /*++
  142. Routine Description:
  143. Removes IRP from IFSL request queue.
  144. Arguments:
  145. ProcessCtx - process context from which to remove
  146. UniqueId - unique request id
  147. more - set to TRUE if there are more requests in the queue
  148. Return Value:
  149. IRP - pointer to the IRP
  150. NULL - the request was not in the queue
  151. --*/
  152. {
  153. KIRQL oldIRQL;
  154. PIRP irp;
  155. PIFSL_QUEUE queue = &ProcessCtx->RequestQueue;
  156. KeAcquireSpinLock (&queue->Lock, &oldIRQL);
  157. irp = CONTAINING_RECORD (queue->ListHead.Flink, IRP, Tail.Overlay.ListEntry);
  158. if (!IsListEmpty (&queue->ListHead)
  159. && (irp->Tail.Overlay.IfslRequestId==UlongToPtr(UniqueId))) {
  160. //
  161. // Queue is not empty and first request matches passed in parameters,
  162. // dequeue and return it
  163. //
  164. ASSERT (queue->Busy);
  165. RemoveEntryList (&irp->Tail.Overlay.ListEntry);
  166. irp->Tail.Overlay.IfslRequestQueue = NULL;
  167. }
  168. else {
  169. irp = NULL;
  170. }
  171. if (IsListEmpty (&queue->ListHead)) {
  172. //
  173. // Queue is now empty, change its state, so that new request knows to
  174. // signal to user mode DLL
  175. //
  176. queue->Busy = FALSE;
  177. }
  178. else {
  179. //
  180. // There is another request pending, signal it now
  181. //
  182. SignalRequest (ProcessCtx);
  183. ASSERT (queue->Busy);
  184. }
  185. //
  186. // Hint the caller that we just signalled, so it does not have to wait on event
  187. //
  188. *more = queue->Busy;
  189. KeReleaseSpinLock (&queue->Lock, oldIRQL);
  190. return irp;
  191. }
  192. VOID
  193. SignalRequest (
  194. IN PIFSL_PROCESS_CTX ProcessCtx
  195. )
  196. /*++
  197. Routine Description:
  198. Fills request parameters & signals user mode DLL to process the request
  199. Arguments:
  200. ProcessCtx - our context for the process which IRP belongs to
  201. Return Value:
  202. None
  203. Note:
  204. SHOULD ONLY BE CALLED WITH QUEUE SPINLOCK HELD
  205. --*/
  206. {
  207. PIRP irp;
  208. PIO_STACK_LOCATION irpSp;
  209. ULONG bufferLen;
  210. ASSERT (!IsListEmpty (&ProcessCtx->RequestQueue.ListHead));
  211. irp = CONTAINING_RECORD (
  212. ProcessCtx->RequestQueue.ListHead.Flink,
  213. IRP,
  214. Tail.Overlay.ListEntry
  215. );
  216. irpSp = IoGetCurrentIrpStackLocation (irp);
  217. switch (irpSp->MajorFunction) {
  218. case IRP_MJ_READ:
  219. bufferLen = irpSp->Parameters.Read.Length;;
  220. break;
  221. case IRP_MJ_WRITE:
  222. bufferLen = irpSp->Parameters.Write.Length;
  223. break;
  224. case IRP_MJ_DEVICE_CONTROL:
  225. switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
  226. case IOCTL_AFD_RECEIVE_DATAGRAM:
  227. bufferLen = ADDR_ALIGN(irpSp->Parameters.DeviceIoControl.OutputBufferLength)
  228. + irpSp->Parameters.DeviceIoControl.InputBufferLength;
  229. break;
  230. case IOCTL_AFD_RECEIVE:
  231. bufferLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
  232. break;
  233. case IOCTL_AFD_SEND_DATAGRAM:
  234. bufferLen = ADDR_ALIGN(irpSp->Parameters.DeviceIoControl.OutputBufferLength)
  235. + irpSp->Parameters.DeviceIoControl.InputBufferLength;
  236. break;
  237. }
  238. break;
  239. case IRP_MJ_PNP:
  240. bufferLen = sizeof (HANDLE);
  241. break;
  242. default:
  243. ASSERT (FALSE);
  244. break;
  245. }
  246. if (KeInsertQueueApc (&ProcessCtx->RequestQueue.Apc,
  247. irp->Tail.Overlay.IfslRequestId,
  248. UlongToPtr(bufferLen),
  249. IO_NETWORK_INCREMENT)) {
  250. WsProcessPrint (ProcessCtx, DBG_QUEUE,
  251. ("WS2IFSL-%04lx SignalRequest: Irp %p (id %ld) on socket %p.\n",
  252. ProcessCtx->UniqueId,
  253. irp, irp->Tail.Overlay.IfslRequestId,
  254. irpSp->FileObject));
  255. ProcessCtx->RequestQueue.Busy = TRUE;
  256. }
  257. else {
  258. WsProcessPrint (ProcessCtx, DBG_QUEUE|DBG_FAILURES,
  259. ("WS2IFSL-%04lx KeInsertQueueApc failed: Irp %p (id %ld) on socket %p.\n",
  260. ProcessCtx->UniqueId,
  261. irp, irp->Tail.Overlay.IfslRequestId,
  262. irpSp->FileObject));
  263. //
  264. // APC queing failed, cancel all outstanding requests.
  265. //
  266. FlushRequestQueue (&ProcessCtx->RequestQueue);
  267. }
  268. } // SignalRequest
  269. VOID
  270. QueueKernelRoutine (
  271. IN struct _KAPC *Apc,
  272. IN OUT PKNORMAL_ROUTINE *NormalRoutine,
  273. IN OUT PVOID *NormalContext,
  274. IN OUT PVOID *SystemArgument1,
  275. IN OUT PVOID *SystemArgument2
  276. )
  277. {
  278. NOTHING;
  279. }
  280. VOID
  281. RequestRundownRoutine (
  282. IN struct _KAPC *Apc
  283. )
  284. /*++
  285. Routine Description:
  286. APC rundown routine for request queue APC
  287. Flushes the queue and marks it as not busy so new
  288. request fail immediately as well.
  289. Arguments:
  290. APC - cancel queue APC structure
  291. Return Value:
  292. None
  293. --*/
  294. {
  295. PIFSL_QUEUE Queue;
  296. KIRQL oldIrql;
  297. Queue = CONTAINING_RECORD (Apc, IFSL_QUEUE, Apc);
  298. KeAcquireSpinLock (&Queue->Lock, &oldIrql);
  299. Queue->Busy = FALSE;
  300. FlushRequestQueue (Queue);
  301. KeReleaseSpinLock (&Queue->Lock, oldIrql);
  302. }
  303. VOID
  304. FlushRequestQueue (
  305. PIFSL_QUEUE Queue
  306. )
  307. /*++
  308. Routine Description:
  309. Flushes and completes IRPs in the request queue
  310. Arguments:
  311. Queue - request queue to flush
  312. Return Value:
  313. None
  314. Note:
  315. SHOULD ONLY BE CALLED WITH QUEUE SPINLOCK HELD
  316. --*/
  317. {
  318. while (!IsListEmpty (&Queue->ListHead)) {
  319. PIRP irp = CONTAINING_RECORD (Queue->ListHead.Flink,
  320. IRP,
  321. Tail.Overlay.ListEntry);
  322. RemoveEntryList (&irp->Tail.Overlay.ListEntry);
  323. irp->Tail.Overlay.IfslRequestQueue = NULL;
  324. KeReleaseSpinLockFromDpcLevel (&Queue->Lock);
  325. irp->IoStatus.Information = 0;
  326. irp->IoStatus.Status = STATUS_CANCELLED;
  327. CompleteSocketIrp (irp);
  328. KeAcquireSpinLockAtDpcLevel (&Queue->Lock);
  329. }
  330. }
  331. VOID
  332. CleanupQueuedRequests (
  333. IN PIFSL_PROCESS_CTX ProcessCtx,
  334. IN PFILE_OBJECT SocketFile,
  335. OUT PLIST_ENTRY IrpList
  336. )
  337. /*++
  338. Routine Description:
  339. Cleans up all IRPs associated with a socket file object from the request
  340. queue
  341. Arguments:
  342. ProcessCtx - process context to which queue belongs
  343. SocketFile - socket file object for which to remove requests
  344. IrpList - list head to hold the IRPs removed from the queue
  345. Return Value:
  346. None
  347. --*/
  348. {
  349. KIRQL oldIRQL;
  350. PLIST_ENTRY entry;
  351. PIFSL_QUEUE queue = &ProcessCtx->RequestQueue;
  352. KeAcquireSpinLock (&queue->Lock, &oldIRQL);
  353. entry = queue->ListHead.Flink;
  354. while (entry!=&queue->ListHead) {
  355. PIRP irp = CONTAINING_RECORD (entry, IRP, Tail.Overlay.ListEntry);
  356. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp);
  357. entry = entry->Flink;
  358. if (irpSp->FileObject==SocketFile) {
  359. RemoveEntryList (&irp->Tail.Overlay.ListEntry);
  360. irp->Tail.Overlay.IfslRequestQueue = NULL;
  361. InsertTailList (IrpList, &irp->Tail.Overlay.ListEntry);
  362. }
  363. }
  364. KeReleaseSpinLock (&queue->Lock, oldIRQL);
  365. }
  366. VOID
  367. QueuedCancelRoutine (
  368. IN PDEVICE_OBJECT DeviceObject,
  369. IN PIRP Irp
  370. )
  371. /*++
  372. Routine Description:
  373. Driver cancel routine for socket request waiting in the queue
  374. to be reported to user mode DLL.
  375. Arguments:
  376. DeviceObject - WS2IFSL device object
  377. Irp - Irp to be cancelled
  378. Return Value:
  379. None
  380. --*/
  381. {
  382. PIO_STACK_LOCATION irpSp;
  383. PIFSL_SOCKET_CTX SocketCtx;
  384. PIFSL_PROCESS_CTX ProcessCtx;
  385. irpSp = IoGetCurrentIrpStackLocation (Irp);
  386. SocketCtx = irpSp->FileObject->FsContext;
  387. ProcessCtx = SocketCtx->ProcessRef->FsContext;
  388. WsProcessPrint (ProcessCtx, DBG_QUEUE,
  389. ("WS2IFSL-%04lx CancelQueuedRequest: Socket %p , Irp %p\n",
  390. ProcessCtx->UniqueId,
  391. irpSp->FileObject, Irp));
  392. KeAcquireSpinLockAtDpcLevel (&ProcessCtx->RequestQueue.Lock);
  393. if (Irp->Tail.Overlay.IfslRequestQueue!=NULL) {
  394. ASSERT (Irp->Tail.Overlay.IfslRequestQueue==&ProcessCtx->RequestQueue);
  395. //
  396. // Request was in the queue, remove and cancel it here
  397. //
  398. RemoveEntryList (&Irp->Tail.Overlay.ListEntry);
  399. Irp->Tail.Overlay.IfslRequestQueue = NULL;
  400. KeReleaseSpinLockFromDpcLevel (&ProcessCtx->RequestQueue.Lock);
  401. IoReleaseCancelSpinLock (Irp->CancelIrql);
  402. Irp->IoStatus.Information = 0;
  403. Irp->IoStatus.Status = STATUS_CANCELLED;
  404. CompleteSocketIrp (Irp);
  405. }
  406. else {
  407. //
  408. // Request was not in the queue, whoever removed should note the
  409. // cancel flag and properly deal with it
  410. //
  411. KeReleaseSpinLockFromDpcLevel (&ProcessCtx->RequestQueue.Lock);
  412. IoReleaseCancelSpinLock (Irp->CancelIrql);
  413. //
  414. // Don't touch IRP after this as we do not own it anymore
  415. //
  416. }
  417. }
  418. VOID
  419. InitializeCancelQueue (
  420. IN PIFSL_PROCESS_CTX ProcessCtx,
  421. IN PKTHREAD ApcThread,
  422. IN KPROCESSOR_MODE ApcMode,
  423. IN PKNORMAL_ROUTINE ApcRoutine,
  424. IN PVOID ApcContext
  425. )
  426. /*++
  427. Routine Description:
  428. Initializes cancel queue object
  429. Arguments:
  430. ProcessCtx - process context to which queue belongs
  431. ApcThread - thread to which to queue APC requests for processing
  432. ApcMode - mode of the caller (should be user)
  433. ApcRoutine - routine that processes requests
  434. ApcContext - context to pass to the routine in addition to request
  435. parameters
  436. Return Value:
  437. None
  438. --*/
  439. {
  440. PAGED_CODE ();
  441. InitializeListHead (&ProcessCtx->CancelQueue.ListHead);
  442. ProcessCtx->CancelQueue.Busy = FALSE;
  443. KeInitializeSpinLock (&ProcessCtx->CancelQueue.Lock);
  444. KeInitializeApc (&ProcessCtx->CancelQueue.Apc,
  445. ApcThread,
  446. OriginalApcEnvironment,
  447. QueueKernelRoutine,
  448. CancelRundownRoutine,
  449. ApcRoutine,
  450. ApcMode,
  451. ApcContext);
  452. }
  453. VOID
  454. QueueCancel (
  455. IN PIFSL_PROCESS_CTX ProcessCtx,
  456. IN PIFSL_CANCEL_CTX CancelCtx
  457. )
  458. /*++
  459. Routine Description:
  460. Queues cancel request to IFSL cancel queue and signals to user mode DLL
  461. to start processing if it is not busy already.
  462. Arguments:
  463. ProcessCtx - process context in which to queue
  464. CancelCtx - request to be queued
  465. Return Value:
  466. None
  467. --*/
  468. {
  469. KIRQL oldIRQL;
  470. PIFSL_QUEUE queue = &ProcessCtx->CancelQueue;
  471. KeAcquireSpinLock (&queue->Lock, &oldIRQL);
  472. InsertTailList (&queue->ListHead, &CancelCtx->ListEntry);
  473. ASSERT (CancelCtx->ListEntry.Flink != NULL);
  474. if (!queue->Busy) {
  475. ASSERT (queue->ListHead.Flink==&CancelCtx->ListEntry);
  476. SignalCancel (ProcessCtx);
  477. ASSERT (ProcessCtx->CancelQueue.Busy);
  478. }
  479. KeReleaseSpinLock (&queue->Lock, oldIRQL);
  480. } // QueueCancel
  481. PIFSL_CANCEL_CTX
  482. DequeueCancel (
  483. PIFSL_PROCESS_CTX ProcessCtx,
  484. ULONG UniqueId,
  485. BOOLEAN *more
  486. )
  487. /*++
  488. Routine Description:
  489. Removes cancel request from IFSL cancel queue.
  490. Arguments:
  491. ProcessCtx - process context from which to remove
  492. UniqueId - unique cancel request id
  493. more - set to TRUE if there are more requests in the queue
  494. Return Value:
  495. CTX - pointer to cancel request context
  496. NULL - the request was not in the queue
  497. --*/
  498. {
  499. KIRQL oldIRQL;
  500. PIFSL_CANCEL_CTX cancelCtx;
  501. PIFSL_QUEUE queue = &ProcessCtx->CancelQueue;
  502. KeAcquireSpinLock (&queue->Lock, &oldIRQL);
  503. cancelCtx = CONTAINING_RECORD (
  504. queue->ListHead.Flink,
  505. IFSL_CANCEL_CTX,
  506. ListEntry
  507. );
  508. if (!IsListEmpty (&queue->ListHead)
  509. && (cancelCtx->UniqueId==UniqueId)) {
  510. //
  511. // Queue is not empty and first request matches passed in parameters,
  512. // dequeue and return it
  513. //
  514. ASSERT (queue->Busy);
  515. RemoveEntryList (&cancelCtx->ListEntry);
  516. cancelCtx->ListEntry.Flink = NULL;
  517. }
  518. else
  519. cancelCtx = NULL;
  520. if (IsListEmpty (&queue->ListHead)) {
  521. //
  522. // Queue is now empty, change its state, so that new request knows to
  523. // signal to user mode DLL
  524. //
  525. queue->Busy = FALSE;
  526. }
  527. else {
  528. //
  529. // There is another request pending, signal it now
  530. //
  531. SignalCancel (ProcessCtx);
  532. ASSERT (queue->Busy);
  533. }
  534. //
  535. // Hint the caller that we just signalled, so it does not have to wait on event
  536. //
  537. *more = queue->Busy;
  538. KeReleaseSpinLock (&queue->Lock, oldIRQL);
  539. return cancelCtx;
  540. }
  541. VOID
  542. SignalCancel (
  543. IN PIFSL_PROCESS_CTX ProcessCtx
  544. )
  545. /*++
  546. Routine Description:
  547. Fills request parameters & signals user mode DLL to process the request
  548. Arguments:
  549. ProcessCtx - our context for the process which cancel request belongs to
  550. Return Value:
  551. None
  552. Note:
  553. SHOULD ONLY BE CALLED WITH QUEUE SPINLOCK HELD
  554. --*/
  555. {
  556. PIFSL_CANCEL_CTX cancelCtx;
  557. PIFSL_SOCKET_CTX SocketCtx;
  558. ASSERT (!IsListEmpty (&ProcessCtx->CancelQueue.ListHead));
  559. ProcessCtx->CancelQueue.Busy = TRUE;
  560. cancelCtx = CONTAINING_RECORD (
  561. ProcessCtx->CancelQueue.ListHead.Flink,
  562. IFSL_CANCEL_CTX,
  563. ListEntry
  564. );
  565. SocketCtx = cancelCtx->SocketFile->FsContext;
  566. if (KeInsertQueueApc (&ProcessCtx->CancelQueue.Apc,
  567. UlongToPtr(cancelCtx->UniqueId),
  568. SocketCtx->DllContext,
  569. IO_NETWORK_INCREMENT)) {
  570. WsProcessPrint (ProcessCtx, DBG_QUEUE,
  571. ("WS2IFSL-%04lx SignalCancel: Context %p on socket %p (h %p).\n",
  572. ProcessCtx->UniqueId,
  573. cancelCtx, cancelCtx->SocketFile, SocketCtx->DllContext));
  574. }
  575. else {
  576. //
  577. // APC queing failed, cancel all outstanding requests.
  578. //
  579. FlushCancelQueue (&ProcessCtx->CancelQueue);
  580. }
  581. } // SignalCancel
  582. VOID
  583. FlushCancelQueue (
  584. PIFSL_QUEUE Queue
  585. )
  586. /*++
  587. Routine Description:
  588. Flushes and frees entries in the cancel queue
  589. Arguments:
  590. Queue - request queue to flush
  591. Return Value:
  592. None
  593. Note:
  594. SHOULD ONLY BE CALLED WITH QUEUE SPINLOCK HELD
  595. --*/
  596. {
  597. while (!IsListEmpty (&Queue->ListHead)) {
  598. PIFSL_CANCEL_CTX cancelCtx = CONTAINING_RECORD (
  599. Queue->ListHead.Flink,
  600. IFSL_CANCEL_CTX,
  601. ListEntry
  602. );
  603. RemoveEntryList (&cancelCtx->ListEntry);
  604. cancelCtx->ListEntry.Flink = NULL;
  605. FreeSocketCancel (cancelCtx);
  606. }
  607. }
  608. VOID
  609. CancelRundownRoutine (
  610. IN struct _KAPC *Apc
  611. )
  612. /*++
  613. Routine Description:
  614. APC rundown routine for cancel queue APC
  615. Flushes the queue and marks it as not busy so new
  616. request fail immediately as well.
  617. Arguments:
  618. APC - cancel queue APC structure
  619. Return Value:
  620. None
  621. --*/
  622. {
  623. PIFSL_QUEUE Queue;
  624. KIRQL oldIrql;
  625. Queue = CONTAINING_RECORD (Apc, IFSL_QUEUE, Apc);
  626. KeAcquireSpinLock (&Queue->Lock, &oldIrql);
  627. Queue->Busy = FALSE;
  628. FlushCancelQueue (Queue);
  629. KeReleaseSpinLock (&Queue->Lock, oldIrql);
  630. }
  631. BOOLEAN
  632. RemoveQueuedCancel (
  633. PIFSL_PROCESS_CTX ProcessCtx,
  634. PIFSL_CANCEL_CTX CancelCtx
  635. )
  636. /*++
  637. Routine Description:
  638. Remove cancel request from the cancel queue if it is there
  639. Arguments:
  640. ProcessCtx - process context to which queue belongs
  641. CancelCtx - request to remove
  642. Return Value:
  643. None
  644. --*/
  645. {
  646. KIRQL oldIRQL;
  647. BOOLEAN res;
  648. // Acquire queue lock
  649. KeAcquireSpinLock (&ProcessCtx->CancelQueue.Lock, &oldIRQL);
  650. res = (CancelCtx->ListEntry.Flink!=NULL);
  651. if (res) {
  652. RemoveEntryList (&CancelCtx->ListEntry);
  653. CancelCtx->ListEntry.Flink = NULL;
  654. }
  655. KeReleaseSpinLock (&ProcessCtx->CancelQueue.Lock, oldIRQL);
  656. return res;
  657. }