1 2 /*++ 3 4 Copyright (c) Microsoft. All rights reserved. 5 6 Module Name: 7 8 FxIoQueue.h 9 10 Abstract: 11 12 This module implements the I/O package queue object 13 14 Author: 15 16 17 18 19 Environment: 20 21 Both kernel and user mode 22 23 Revision History: 24 25 26 --*/ 27 28 #ifndef _FXIOQUEUE_H_ 29 #define _FXIOQUEUE_H_ 30 31 #include "fxioqueuecallbacks.hpp" 32 33 extern "C" { 34 #if defined(EVENT_TRACING) 35 #include "FxIoQueue.hpp.tmh" 36 #endif 37 } 38 39 40 // 41 // These FxIoQueue public Enum and Struct are used to tie the queue 42 // with FxPkgIo. 43 // 44 enum FxIoQueueNodeType { 45 FxIoQueueNodeTypeInvalid = 0, 46 FxIoQueueNodeTypeQueue, 47 FxIoQueueNodeTypeBookmark, 48 FxIoQueueNodeTypeLast, 49 }; 50 51 struct FxIoQueueNode { 52 public: 53 // 54 // Data members. 55 // 56 LIST_ENTRY m_ListEntry; 57 FxIoQueueNodeType m_Type; 58 59 public: 60 // 61 // Manager functions. 62 // FxIoQueueNodeFxIoQueueNode63 FxIoQueueNode( 64 FxIoQueueNodeType NodeType 65 ) : 66 m_Type(NodeType) 67 { 68 ASSERT(_IsValidNodeType(m_Type)); 69 InitializeListHead(&m_ListEntry); 70 } 71 ~FxIoQueueNodeFxIoQueueNode72 ~FxIoQueueNode() 73 { 74 ASSERT(IsListEmpty(&m_ListEntry) == TRUE); 75 } 76 77 private: 78 // 79 // Turn off unsupported manager functions. 80 // 81 FxIoQueueNode(); 82 83 // 84 // Block default behavior to shallow copy the object because it contains 85 // a double-link entry; shallow copying the object produces an invalid 86 // copy because the double-link entry is not properly re-initialized. 87 // 88 FxIoQueueNode(const FxIoQueueNode&); 89 90 FxIoQueueNode& operator=(const FxIoQueueNode&); 91 92 public: 93 // 94 // Helper functions. 95 // 96 static 97 FxIoQueueNode* _FromListEntryFxIoQueueNode98 _FromListEntry( 99 __in PLIST_ENTRY Entry 100 ) 101 { 102 return CONTAINING_RECORD(Entry, FxIoQueueNode, m_ListEntry); 103 } 104 105 static 106 BOOLEAN _IsValidNodeTypeFxIoQueueNode107 _IsValidNodeType( 108 __in FxIoQueueNodeType NodeType 109 ) 110 { 111 return ((NodeType > FxIoQueueNodeTypeInvalid) && 112 (NodeType < FxIoQueueNodeTypeLast)) ? TRUE : FALSE; 113 } 114 115 __inline 116 BOOLEAN IsNodeTypeFxIoQueueNode117 IsNodeType( 118 __in FxIoQueueNodeType NodeType 119 ) 120 { 121 return (NodeType == m_Type) ? TRUE : FALSE; 122 } 123 }; 124 125 // 126 // These FxIoQueue private Enum's control the internal state machine 127 // 128 129 // begin_wpp enum 130 typedef enum FxIoQueuePowerState { 131 FxIoQueuePowerInvalid = 0, 132 FxIoQueuePowerOn, 133 FxIoQueuePowerOff, 134 FxIoQueuePowerStartingTransition, 135 FxIoQueuePowerStopping, 136 FxIoQueuePowerStoppingNotifyingDriver, 137 FxIoQueuePowerStoppingDriverNotified, 138 FxIoQueuePowerPurge, 139 FxIoQueuePowerPurgeNotifyingDriver, 140 FxIoQueuePowerPurgeDriverNotified, 141 FxIoQueuePowerRestarting, 142 FxIoQueuePowerRestartingNotifyingDriver, 143 FxIoQueuePowerRestartingDriverNotified, 144 FxIoQueuePowerLast, 145 } FXIOQUEUE_POWER_STATE; 146 // end_wpp 147 148 typedef struct _FXIO_FORWARD_PROGRESS_CONTEXT { 149 // 150 // Total Number of Reserved requests 151 // 152 ULONG m_NumberOfReservedRequests; 153 // 154 // Callback invoked to allocate resources for reserved requests at init time 155 // 156 FxIoQueueForwardProgressAllocateResourcesReserved m_IoReservedResourcesAllocate; 157 // 158 // Callback invoked to allocate resources for non-reserved requests at run time 159 // 160 FxIoQueueForwardProgressAllocateResources m_IoResourcesAllocate; 161 // 162 // Callback invoked to Examine the IRP and decide whether to fail it or not 163 // 164 FxIoQueueForwardProgressExamineIrp m_IoExamineIrp; 165 // 166 // Policy configured for forward progress 167 // 168 WDF_IO_FORWARD_PROGRESS_RESERVED_POLICY m_Policy; 169 // 170 // List of available reserved requests 171 // 172 LIST_ENTRY m_ReservedRequestList; 173 174 // 175 // List of in use reserved requests 176 // 177 LIST_ENTRY m_ReservedRequestInUseList; 178 179 // 180 // List of all pended IRPs 181 // 182 LIST_ENTRY m_PendedIrpList; 183 // 184 // This lock is used to add new entreies to the pended IRP list 185 // or the add the request back to the Reserved List 186 // 187 MxLockNoDynam m_PendedReserveLock; 188 189 } FXIO_FORWARD_PROGRESS_CONTEXT, *PFXIO_FORWARD_PROGRESS_CONTEXT; 190 191 // 192 // This defines the valid arguments to the 193 // SetStatus call. 194 // 195 typedef enum _FX_IO_QUEUE_SET_STATE { 196 FxIoQueueSetAcceptRequests = 0x80000001, 197 FxIoQueueClearAcceptRequests = 0x80000002, 198 FxIoQueueSetDispatchRequests = 0x80000004, 199 FxIoQueueClearDispatchRequests = 0x80000008, 200 FxIoQueueSetShutdown = 0x80010000, 201 FxIoQueueClearShutdown = 0x80020000, 202 } FX_IO_QUEUE_SET_STATE; 203 204 205 // 206 // This defines the internal queue state. 207 // 208 typedef enum _FX_IO_QUEUE_STATE { 209 // 210 // private == public values (low word). 211 // 212 FxIoQueueAcceptRequests = WdfIoQueueAcceptRequests, // 0x00000001 213 FxIoQueueDispatchRequests = WdfIoQueueDispatchRequests, // 0x00000002 214 FxIoQueueNoRequests = WdfIoQueueNoRequests, // 0x00000004 215 FxIoQueueDriverNoRequests = WdfIoQueueDriverNoRequests, // 0x00000008 216 FxIoQueuePnpHeld = WdfIoQueuePnpHeld, // 0x00000010 217 // 218 // private values only (high word). 219 // 220 // Queue is being shut down. Flag on means do not queue any request 221 // even if the accept request state is set. This flag prevents the 222 // following scenarios: 223 // (1) a race condition where a dispatch queue handler changes the 224 // state of the queue to accept_requests while we are in the 225 // middle of a power stopping (purge) operation (Win7 719587). 226 // (2) another thread calling Stop or Start on a queue that is in the 227 // middle of a power stopping (purge) operation. 228 // 229 FxIoQueueShutdown = 0x00010000 230 } FX_IO_QUEUE_STATE; 231 232 class FxIoQueue : public FxNonPagedObject, IFxHasCallbacks { 233 234 friend VOID GetTriageInfo(VOID); 235 236 private: 237 238 // 239 // forward progress fields 240 // 241 PFXIO_FORWARD_PROGRESS_CONTEXT m_FwdProgContext; 242 243 // 244 // This is a true indicator whether the Queue is ready for forward progress 245 // 246 BOOLEAN m_SupportForwardProgress; 247 248 // 249 // Specifies that the queue has been configured 250 // with driver callbacks and presentation serialization 251 // 252 BOOLEAN m_Configured; 253 254 // 255 // TRUE if this is a power managed queue. If TRUE, it is reported 256 // as a power managed queue, and will automatically start/resume 257 // based on power management requests. 258 // 259 // If false, the device driver has manual control on start/resume. 260 // 261 BOOLEAN m_PowerManaged; 262 263 // 264 // This is TRUE if we have an outstanding reference to the 265 // Pnp package about having I/O in our queue. 266 // 267 volatile BOOLEAN m_PowerReferenced; 268 269 // 270 // If TRUE, zero length read/writes are allowed to the driver. 271 // Otherwise, they are completed automatically with STATUS_SUCCESS. 272 // 273 BOOLEAN m_AllowZeroLengthRequests; 274 275 // 276 // True if callback operations to the driver occur at 277 // PASSIVE_LEVEL. Also marked in FxObject, but this cache 278 // avoids acquiring FxObject state lock. 279 // 280 BOOLEAN m_PassiveLevel; 281 282 // 283 // This is set before m_FinishDisposing is signalled to 284 // allow the Dispose thread to continue deletion of 285 // queue resources. Once this is set, no thread is 286 // allowed to run thru DispatchEvents. 287 // 288 volatile BOOLEAN m_Deleted; 289 290 // 291 // This is set when the I/O package marks the queue 292 // for deleting, but the I/O queue deferrs its final 293 // dereference until all outstanding I/O's to the 294 // device driver are completed. 295 // 296 volatile BOOLEAN m_Disposing; 297 MxEvent m_FinishDisposing; 298 299 // 300 // Power State of the Queue 301 // 302 FXIOQUEUE_POWER_STATE m_PowerState; 303 304 // 305 // This is the type of queue, and is configured by the 306 // user at initial queue creation time. 307 // 308 WDF_IO_QUEUE_DISPATCH_TYPE m_Type; 309 310 // 311 // Maximum number of driver presented Requests on a parallel Queue 312 // 313 ULONG m_MaxParallelQueuePresentedRequests; 314 315 // 316 // This is the current processing status of the queue. 317 // 318 FX_IO_QUEUE_STATE m_QueueState; 319 320 // 321 // The FxIoQueue tracks a request from the time it arrives by being 322 // enqueued, until it leaves by being completed, or forwarded. 323 // 324 // At any given time, a request may be in one the following five states: 325 // 326 // 1) Request is queued and cancelable 327 // 328 // It is on the FxIrpQueue m_Queue using the LIST_ENTRY 329 // FxRequest::m_Irp->Tail.Overlay.ListEntry 330 // 331 // 2) Request has been passed to the driver, and is not cancelable 332 // 333 // It is on the LIST_ENTRY m_DriverNonCancelable using the LIST_ENTRY 334 // FxRequest::m_OwnerListEntry 335 // 336 // It is also on the LIST_ENTRY m_DriverInFlight using the LIST_ENTRY 337 // FxRequest::m_InFlightListEntry 338 // 339 // 3) Request has been passed to the driver, and is cancelable 340 // 341 // It is on the FxIrpQueue m_DriverCancelable using the LIST_ENTRY 342 // FxRequest::m_Irp->Tail.Overlay.ListEntry 343 // 344 // It is also on the LIST_ENTRY m_DriverInFlight using the LIST_ENTRY 345 // FxRequest::m_InFlightListEntry 346 // 347 // 4) Request has been cancelled, but the driver has not been notified 348 // 349 // It is on the LIST_ENTRY m_Cancelled using the LIST_ENTRY 350 // FxRequest::m_OwnerListEntry 351 // 352 // 5) Request has been cancelled, driver has been notified, but has 353 // not completed it yet 354 // 355 // It is on the LIST_ENTRY m_DriverNonCancelable using the LIST_ENTRY 356 // FxRequest::m_OwnerListEntry 357 // 358 // It is also on the LIST_ENTRY m_DriverInFlight using the LIST_ENTRY 359 // FxRequest::m_InFlightListEntry 360 // 361 362 // 363 // This is the Queue of current requests that have not 364 // been presented to the driver 365 // 366 FxIrpQueue m_Queue; 367 368 // 369 // This is the list of requests that driver has accepted 370 // and is working on, but wants to be cancelable. 371 // 372 FxIrpQueue m_DriverCancelable; 373 374 // 375 // This is a list of cancelled requests to be notified to the driver. 376 // 377 // FxListEntryQueueOwned of FxRequest is used for linkage 378 // 379 LIST_ENTRY m_Cancelled; 380 381 // 382 // This is a list of request cancelled on queue waiting 383 // to be notified to the driver. 384 // 385 // FxListEntryQueueOwned of FxRequest is used for linkage 386 // 387 LIST_ENTRY m_CanceledOnQueueList; 388 389 // 390 // This is a list of requests that the driver has accepted 391 // and is working on, but has not been completed. 392 // 393 // They may, or may not be cancelable. 394 // 395 // FxListEntryDriverOwned of FxRequest is used for linkage 396 // 397 LIST_ENTRY m_DriverOwned; 398 399 // 400 // This is the list of power stop/start requests to be notified to 401 // the driver. 402 // 403 // FxListEntryDriverOwned of FxRequest is used for linkage 404 // 405 LIST_ENTRY m_PowerNotify; 406 407 // 408 // This is the list of power stop requests in which the driver 409 // has been notified, and must be zero before power code can 410 // resume the power thread. 411 // 412 // FxListEntryDriverOwned of FxRequest is used for linkage 413 // 414 LIST_ENTRY m_PowerDriverNotified; 415 416 // 417 // Pointer to FxPkgIo object that contains this queue. 418 // (No additional reference count) 419 // 420 FxPkgIo* m_PkgIo; 421 422 // 423 // Weak pointer to the associated FxCxDeviceInfo struct. 424 // 425 FxCxDeviceInfo* m_CxDeviceInfo; 426 427 // 428 // This is the count of currently executing callback 429 // handlers into the device driver. 430 // 431 // It is used to control the dispatch state to prevent stack 432 // recursions, as well as to handle notification when a queue 433 // is idle and has no callbacks outstanding. 434 // 435 volatile ULONG m_Dispatching; 436 437 // 438 // This is set when a queue goes from empty to 439 // having requests and allows a callback to the driver 440 // when a queue is ready. 441 // 442 volatile BOOLEAN m_TransitionFromEmpty; 443 444 // 445 // This flag is set when the we return no_more_requests from 446 // WdfRequesdtGetNextRequest but the queue actually holds one or 447 // more requests in cancellation state (their cancellation routine 448 // are already running). 449 // This flag insures that we call the ReadyNotify callback when a new 450 // request is inserted in the queue. 451 // 452 volatile BOOLEAN m_ForceTransitionFromEmptyWhenAddingNewRequest; 453 454 // 455 // This is set when the driver starts a WdfIoQueueStopAndPurge operation. 456 // This is cleared in the following conditions: 457 // (a) there are no more driver owned requests. 458 // (b) driver re-enables the dispatch gate. 459 // When set any requeued requests will be automatically deleted. 460 // 461 volatile BOOLEAN m_CancelDispatchedRequests; 462 463 BOOLEAN m_IsDevicePowerPolicyOwner; 464 465 // 466 // This is the number of requests the driver 467 // currently is processing both cancellable and noncancellable. 468 // 469 // For serial queue dispatch mode, this is used 470 // to control when a request can be presented to the driver. 471 // This is also used to implement counted Queues to make 472 // sure the count doesn't exceed max. allowed on the 473 // parallel Queue. 474 // 475 volatile LONG m_DriverIoCount; 476 477 // 478 // This is the number of requests that are about to be completed using two 479 // phase completion technique (to support queued-by-driver requests). 480 // 481 volatile LONG m_TwoPhaseCompletions; 482 483 // 484 // These are the driver configured callbacks to send 485 // I/O events to the driver 486 // 487 FxIoQueueIoDefault m_IoDefault; 488 FxIoQueueIoStop m_IoStop; 489 FxIoQueueIoResume m_IoResume; 490 FxIoQueueIoRead m_IoRead; 491 FxIoQueueIoWrite m_IoWrite; 492 FxIoQueueIoDeviceControl m_IoDeviceControl; 493 FxIoQueueIoInternalDeviceControl m_IoInternalDeviceControl; 494 FxIoQueueIoCanceledOnQueue m_IoCanceledOnQueue; 495 496 FxCallbackLock* m_IoCancelCallbackLockPtr; 497 498 // 499 // These are status events registered by the device driver 500 // 501 FxIoQueueIoState m_IdleComplete; 502 WDFCONTEXT m_IdleCompleteContext; 503 504 FxIoQueueIoState m_PurgeComplete; 505 WDFCONTEXT m_PurgeCompleteContext; 506 507 FxIoQueueIoState m_ReadyNotify; 508 WDFCONTEXT m_ReadyNotifyContext; 509 510 // 511 // The following items support the callback constraints 512 // and handle locking and deferral 513 // 514 WDF_EXECUTION_LEVEL m_ExecutionLevel; 515 WDF_SYNCHRONIZATION_SCOPE m_SynchronizationScope; 516 517 // 518 // These are the passive and dispatch level presentation locks 519 // 520 FxCallbackSpinLock m_CallbackSpinLock; 521 FxCallbackMutexLock m_CallbackMutexLock; 522 523 // 524 // This pointer allows the proper lock to be acquired 525 // based on the configuration with a minimal of runtime 526 // checks. This is configured by ConfigureLocking() 527 // 528 FxCallbackLock* m_CallbackLockPtr; 529 FxObject* m_CallbackLockObjectPtr; 530 531 // 532 // The IoQueue must sometimes defer event delivery to the 533 // device driver due to interactions with current locks held, 534 // and the device driver configured callback constraints. 535 // 536 // When a deferral occurs, a DPC or FxSystemWorkItem is used 537 // to post an event to later deliver the event(s) to the device 538 // driver. Whether a DPC or WorkItem is used depends 539 // on the drivers configured execution level constraints. 540 // 541 // The IoQueue is designed to be robust in that multiple events 542 // may occur while the queued DPC or WorkItem is outstanding, 543 // and they will be properly processed without having to enqueue 544 // one for each event. Basically, they are just a signal that 545 // an IoQueue needs some attention that could result in device 546 // driver notification. 547 // 548 // KDPC is only needed in kernel mode 549 // 550 551 552 553 #if (FX_CORE_MODE==FX_CORE_KERNEL_MODE) 554 KDPC m_Dpc; 555 #endif 556 557 FxSystemWorkItem* m_SystemWorkItem; 558 559 // 560 // These are true if the associated Dpc or Work Item is queued 561 // 562 BOOLEAN m_DpcQueued; 563 BOOLEAN m_WorkItemQueued; 564 565 // 566 // Track whether the above DPC and WorkItem needs to be requeued. 567 // 568 BOOLEAN m_RequeueDeferredDispatcher; 569 570 // This is set when the Queue is power idle 571 MxEvent m_PowerIdle; 572 573 574 575 576 577 #if (FX_CORE_MODE==FX_CORE_USER_MODE) 578 MxEvent m_RequestWaitEventUm; 579 #endif 580 581 public: 582 583 // 584 // List node to tie the queue with FxPkgIo. 585 // 586 FxIoQueueNode m_IoPkgListNode; 587 // 588 // List entry is used by FxPkgIo to iterate list all the queues without 589 // holding a lock. 590 // 591 SINGLE_LIST_ENTRY m_PowerSListEntry; 592 593 public: 594 // Factory function 595 _Must_inspect_result_ 596 static 597 NTSTATUS 598 _Create( 599 __in PFX_DRIVER_GLOBALS DriverGlobals, 600 __in_opt PWDF_OBJECT_ATTRIBUTES Attributes, 601 __in PWDF_IO_QUEUE_CONFIG Config, 602 __in_opt FxDriver* Caller, 603 __in FxPkgIo* PkgIo, 604 __in BOOLEAN InitialPowerStateOn, 605 __deref_out FxIoQueue** Object 606 ); 607 608 FxIoQueue( 609 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 610 __in FxPkgIo* PkgIo 611 ); 612 613 virtual 614 ~FxIoQueue( 615 ); 616 617 _Must_inspect_result_ 618 NTSTATUS 619 Initialize( 620 __in PWDF_IO_QUEUE_CONFIG pConfig, 621 __in_opt PWDF_OBJECT_ATTRIBUTES QueueAttributes, 622 __in_opt FxDriver* Caller, 623 __in BOOLEAN InitialPowerStateOn 624 ); 625 626 _Releases_lock_(this->m_SpinLock.m_Lock) 627 VOID 628 CancelForQueue( 629 __in FxRequest* pRequest, 630 __in __drv_restoresIRQL KIRQL PreviousIrql 631 ); 632 633 // Do not specify argument names 634 FX_DECLARE_VF_FUNCTION_P1( 635 VOID, 636 VerifyCancelForDriver, 637 _In_ FxRequest* 638 ); 639 640 VOID 641 CancelForDriver( 642 __in FxRequest* pRequest 643 ); 644 645 // Do not specify argument names 646 FX_DECLARE_VF_FUNCTION_P1( 647 VOID, 648 VerifyValidateCompletedRequest, 649 _In_ FxRequest* 650 ); 651 652 __inline 653 VOID RequestCompletedCallback(__in FxRequest * Request)654 RequestCompletedCallback( 655 __in FxRequest* Request 656 ) 657 { 658 // 659 // This is called when a FxRequest object completes based 660 // on the callback event registered by the I/O queue support 661 // routines. 662 // 663 664 KIRQL irql; 665 666 #if FX_VERBOSE_TRACE 667 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGIO, 668 "Enter: WDFQUEUE 0x%p, WDFREQUEST 0x%p", 669 GetObjectHandle(),Request->GetHandle()); 670 #endif 671 VerifyValidateCompletedRequest(GetDriverGlobals(), Request); 672 673 Lock(&irql); 674 675 // 676 // I/O has been completed by the driver 677 // 678 RemoveFromDriverOwnedList(Request); 679 680 // 681 // Don't run the event dispatcher if we come from a Request 682 // complete callback in order to prevent stack recursion. 683 // 684 // Since some other thread (possibly this thread higher on 685 // the stack) is running the dispatcher, no events will get lost. 686 // 687 DispatchInternalEvents(irql); 688 } 689 690 __inline 691 VOID PreRequestCompletedCallback(__in FxRequest * Request)692 PreRequestCompletedCallback( 693 __in FxRequest* Request 694 ) 695 { 696 // 697 // This is called when a driver created request is about to be completed. 698 // This callback removes the FxRequest object from the internal queue linked 699 // lists. A call to PostRequestCompletedCallback must be made after irp is 700 // completed. 701 // 702 703 KIRQL irql; 704 705 #if FX_VERBOSE_TRACE 706 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGIO, 707 "Enter: WDFQUEUE 0x%p, WDFREQUEST 0x%p", 708 GetObjectHandle(),Request->GetHandle()); 709 #endif 710 711 VerifyValidateCompletedRequest(GetDriverGlobals(), Request); 712 713 Lock(&irql); 714 715 // 716 // I/O has been completed by the driver 717 // 718 PreRemoveFromDriverOwnedList(Request); 719 720 Unlock(irql); 721 } 722 723 __inline 724 VOID PostRequestCompletedCallback(__in FxRequest * Request)725 PostRequestCompletedCallback( 726 __in FxRequest* Request 727 ) 728 { 729 // Do not acccess Request, at this point the object may have already been 730 // deleted or reused. 731 732 // 733 // This is called when a queued-by-driver request (driver created) is 734 // completed or sent to a lower driver with 'send-and-forget' option. 735 // This callback allows the queue to schedule another request for delivery. 736 // 737 738 KIRQL irql; 739 740 #if FX_VERBOSE_TRACE 741 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGIO, 742 "Enter: WDFQUEUE 0x%p, WDFREQUEST 0x%p", 743 GetObjectHandle(), FxRequest::_ToHandle(Request)); 744 #else 745 UNREFERENCED_PARAMETER(Request); 746 #endif 747 748 Lock(&irql); 749 750 // 751 // I/O has been completed by the driver 752 // 753 PostRemoveFromDriverOwnedList(); 754 755 // 756 // Don't run the event dispatcher if we come from a Request 757 // complete callback in order to prevent stack recursion. 758 // 759 // Since some other thread (possibly this thread higher on 760 // the stack) is running the dispatcher, no events will get lost. 761 // 762 DispatchInternalEvents(irql); 763 } 764 765 __inline 766 FxDriver* GetDriver(VOID)767 GetDriver(VOID) { 768 return m_PkgIo->GetDriver(); 769 } 770 771 __inline 772 CfxDevice* GetDevice(VOID)773 GetDevice(VOID) 774 { 775 return m_Device; 776 } 777 778 __inline 779 FxPkgIo* GetPackage(VOID)780 GetPackage(VOID) { 781 return m_PkgIo; 782 } 783 784 WDFQUEUE 785 __inline GetHandle(VOID)786 GetHandle( 787 VOID 788 ) 789 { 790 return (WDFQUEUE) GetObjectHandle(); 791 } 792 793 __inline 794 BOOLEAN IsPowerManaged()795 IsPowerManaged() { 796 return m_PowerManaged; 797 } 798 799 VOID 800 StartPowerTransitionOn( 801 VOID 802 ); 803 804 VOID 805 StartPowerTransitionOff( 806 VOID 807 ); 808 809 VOID 810 StopProcessingForPower( 811 __in FxIoStopProcessingForPowerAction Action 812 ); 813 814 VOID 815 ResumeProcessingForPower( 816 VOID 817 ); 818 819 VOID 820 SetStateForShutdown( 821 VOID 822 ); 823 824 VOID 825 ResetStateForRestart( 826 VOID 827 ); 828 829 WDF_IO_QUEUE_STATE 830 GetState( 831 __out_opt PULONG pQueueCount, 832 __out_opt PULONG pDriverCount 833 ); 834 835 VOID 836 SetState( 837 __in FX_IO_QUEUE_SET_STATE NewStatus 838 ); 839 840 841 __inline 842 BOOLEAN IsState(__in WDF_IO_QUEUE_STATE State)843 IsState( 844 __in WDF_IO_QUEUE_STATE State 845 ) 846 { 847 ASSERT(!(State & 0x80000000)); // Don't allow FX_IO_QUEUE_SET states 848 return (((int)m_QueueState & (int) (State)) != 0); 849 } 850 851 __inline 852 BOOLEAN IsState(__in FX_IO_QUEUE_STATE State)853 IsState( 854 __in FX_IO_QUEUE_STATE State 855 ) 856 { 857 ASSERT(!(State & 0x80000000)); // Don't allow FX_IO_QUEUE_SET states 858 return (((int)m_QueueState & (int) (State)) != 0); 859 } 860 861 // GetRequest Verifiers 862 // Do not specify argument names 863 FX_DECLARE_VF_FUNCTION_P1( 864 NTSTATUS, 865 VerifyGetRequestUpdateFlags, 866 _In_ FxRequest* 867 ); 868 869 // Do not specify argument names 870 FX_DECLARE_VF_FUNCTION_P1( 871 VOID, 872 VerifyGetRequestRestoreFlags, 873 _In_ FxRequest* 874 ); 875 876 _Must_inspect_result_ 877 NTSTATUS 878 GetRequest( 879 __in_opt MdFileObject FileObject, 880 __in_opt FxRequest* TagRequest, 881 __deref_out FxRequest** pOutRequest 882 ); 883 884 // PeekRequest Verifiers 885 // Do not specify argument names 886 FX_DECLARE_VF_FUNCTION_P1( 887 NTSTATUS, 888 VerifyPeekRequest, 889 _In_ FxRequest* 890 ); 891 892 _Must_inspect_result_ 893 NTSTATUS 894 PeekRequest( 895 __in_opt FxRequest* TagRequest, 896 __in_opt MdFileObject FileObject, 897 __out_opt PWDF_REQUEST_PARAMETERS Parameters, 898 __deref_out FxRequest** pOutRequest 899 ); 900 901 // ForwardRequest Verifiers 902 // Do not specify argument names 903 FX_DECLARE_VF_FUNCTION_P2( 904 NTSTATUS, 905 VerifyForwardRequest, 906 _In_ FxIoQueue*, 907 _In_ FxRequest* 908 ); 909 910 _Must_inspect_result_ 911 NTSTATUS 912 ForwardRequest( 913 __in FxIoQueue* pDestQueue, 914 __in FxRequest* pRequest 915 ); 916 917 // QueueDriverCreatedRequest 918 // Do not specify argument names 919 FX_DECLARE_VF_FUNCTION_P2( 920 NTSTATUS, 921 VerifyQueueDriverCreatedRequest, 922 _In_ FxRequest*, 923 _Inout_ SHORT* 924 ); 925 926 _Must_inspect_result_ 927 NTSTATUS 928 QueueDriverCreatedRequest( 929 __in FxRequest* Request, 930 __in BOOLEAN ParentQueue 931 ); 932 933 __drv_requiresIRQL(DISPATCH_LEVEL) 934 VOID 935 ProcessAcknowledgedRequests( 936 __in FxRequest* Request, 937 __out PKIRQL PreviousIrql 938 ); 939 940 // Do not specify argument names 941 FX_DECLARE_VF_FUNCTION_P1( 942 NTSTATUS, 943 VerifyRequeue, 944 _In_ FxRequest* 945 ); 946 947 _Must_inspect_result_ 948 NTSTATUS 949 Requeue( 950 __in FxRequest* pRequest 951 ); 952 953 // Do not specify argument names 954 FX_DECLARE_VF_FUNCTION_P2( 955 NTSTATUS, 956 VerifyRequestCancelable, 957 _In_ FxRequest*, 958 _In_ BOOLEAN 959 ); 960 961 _Must_inspect_result_ 962 NTSTATUS 963 RequestCancelable( 964 __in FxRequest* pRequest, 965 __in BOOLEAN Cancelable, 966 __in_opt PFN_WDF_REQUEST_CANCEL EvtRequestCancel, 967 __in BOOLEAN FailIfIrpIsCancelled 968 ); 969 970 _Must_inspect_result_ 971 NTSTATUS 972 RequestCompleteEvent( 973 __in FxRequest* Request 974 ); 975 976 977 _Must_inspect_result_ 978 NTSTATUS 979 QueueRequest( 980 __in FxRequest* pRequest 981 ); 982 983 _Must_inspect_result_ 984 NTSTATUS 985 QueueRequestFromForward( 986 __in FxRequest* pRequest 987 ); 988 989 _Must_inspect_result_ 990 BOOLEAN 991 CanThreadDispatchEventsLocked( 992 __in KIRQL PreviousIrql 993 ); 994 995 _Releases_lock_(this->m_SpinLock.m_Lock) 996 __drv_requiresIRQL(DISPATCH_LEVEL) 997 BOOLEAN 998 DispatchEvents( 999 __in __drv_restoresIRQL KIRQL PreviousIrql, 1000 __in_opt FxRequest* NewRequest = NULL 1001 ); 1002 1003 _Releases_lock_(this->m_SpinLock.m_Lock) __drv_requiresIRQL(DISPATCH_LEVEL)1004 __drv_requiresIRQL(DISPATCH_LEVEL) 1005 __inline 1006 VOID 1007 DispatchInternalEvents( 1008 __in __drv_restoresIRQL KIRQL PreviousIrql 1009 ) 1010 /*++ 1011 1012 Routine Description: 1013 1014 Dispatch events and requests from the queue to the driver. 1015 1016 The IoQueue object lock must be held on entry, but this 1017 routine returns to the caller with the lock released. 1018 1019 To avoid recursion, this routine checks to see if this or another 1020 thread is already in the dispatch-event loop. If so, it 1021 doesn't re-enter the dispatch-even loop. 1022 1023 --*/ 1024 { 1025 if(m_Dispatching == 0) { 1026 // 1027 // Nobody is dispatching events so we must 1028 // call the main DispatchEvents function because 1029 // the caller of this function might have affected the 1030 // state of the queue. 1031 // 1032 (VOID) DispatchEvents(PreviousIrql); 1033 1034 } else { 1035 1036 Unlock(PreviousIrql); 1037 } 1038 } 1039 1040 1041 VOID 1042 DispatchRequestToDriver( 1043 __in FxRequest* pRequest 1044 ); 1045 1046 virtual 1047 VOID GetConstraints(__out WDF_EXECUTION_LEVEL * ExecutionLevel,__out WDF_SYNCHRONIZATION_SCOPE * SynchronizationScope)1048 GetConstraints( 1049 __out WDF_EXECUTION_LEVEL* ExecutionLevel, 1050 __out WDF_SYNCHRONIZATION_SCOPE* SynchronizationScope 1051 ) { 1052 1053 if (ExecutionLevel != NULL) { 1054 *ExecutionLevel = m_ExecutionLevel; 1055 } 1056 1057 if (SynchronizationScope != NULL) { 1058 *SynchronizationScope = m_SynchronizationScope; 1059 } 1060 } 1061 1062 virtual 1063 FxCallbackLock* GetCallbackLockPtr(__deref_out FxObject ** LockObject)1064 GetCallbackLockPtr( 1065 __deref_out FxObject** LockObject 1066 ) 1067 { 1068 if (LockObject != NULL) { 1069 *LockObject = m_CallbackLockObjectPtr; 1070 } 1071 1072 return m_CallbackLockPtr; 1073 } 1074 1075 _Must_inspect_result_ 1076 virtual 1077 NTSTATUS QueryInterface(__in FxQueryInterfaceParams * Params)1078 QueryInterface( 1079 __in FxQueryInterfaceParams* Params 1080 ) 1081 { 1082 switch (Params->Type) { 1083 case FX_TYPE_QUEUE: 1084 *Params->Object = (FxIoQueue*) this; 1085 break; 1086 1087 case FX_TYPE_IHASCALLBACKS: 1088 *Params->Object = (IFxHasCallbacks*) this; 1089 break; 1090 1091 default: 1092 return FxNonPagedObject::QueryInterface(Params); // __super call 1093 } 1094 1095 return STATUS_SUCCESS; 1096 } 1097 1098 virtual 1099 BOOLEAN 1100 Dispose( 1101 VOID 1102 ); 1103 1104 // 1105 // Start the Queue 1106 // 1107 VOID 1108 QueueStart( 1109 VOID 1110 ); 1111 1112 // 1113 // Idle/Stop the Queue 1114 // 1115 _Must_inspect_result_ 1116 NTSTATUS 1117 QueueIdle( 1118 __in BOOLEAN CancelQueueRequests, 1119 __in_opt PFN_WDF_IO_QUEUE_STATE IdleComplete, 1120 __in_opt WDFCONTEXT Context 1121 ); 1122 1123 // 1124 // Idle the Queue 1125 // 1126 _Must_inspect_result_ 1127 NTSTATUS 1128 QueueIdleSynchronously( 1129 __in BOOLEAN CancelRequests 1130 ); 1131 1132 // 1133 // Purge the Queue 1134 // 1135 _Must_inspect_result_ 1136 NTSTATUS 1137 QueuePurge( 1138 __in BOOLEAN CancelQueueRequests, 1139 __in BOOLEAN CancelDriverRequests, 1140 __in_opt PFN_WDF_IO_QUEUE_STATE PurgeComplete, 1141 __in_opt WDFCONTEXT Context 1142 ); 1143 1144 _Must_inspect_result_ 1145 NTSTATUS 1146 QueuePurgeSynchronously( 1147 VOID 1148 ); 1149 1150 // 1151 // Idle the Queue 1152 // 1153 _Must_inspect_result_ 1154 NTSTATUS 1155 QueueDrain( 1156 __in_opt PFN_WDF_IO_QUEUE_STATE DrainComplete, 1157 __in_opt WDFCONTEXT Context 1158 ); 1159 1160 // 1161 // Idle the Queue 1162 // 1163 _Must_inspect_result_ 1164 NTSTATUS 1165 QueueDrainSynchronously( 1166 VOID 1167 ); 1168 1169 // 1170 // Notify the driver through a callback when the queue transitions 1171 // from no requests to having a request. 1172 // 1173 _Must_inspect_result_ 1174 NTSTATUS 1175 ReadyNotify( 1176 __in PFN_WDF_IO_QUEUE_STATE QueueReady, 1177 __in_opt WDFCONTEXT Context 1178 ); 1179 1180 1181 VOID 1182 FlushByFileObject( 1183 __in MdFileObject FileObject 1184 ); 1185 1186 // 1187 // Return count of queued and driver pending requests. 1188 // 1189 VOID 1190 GetRequestCount( 1191 __out_opt PULONG pQueuedRequests, 1192 __out_opt PULONG pDriverPendingRequests 1193 ); 1194 1195 1196 _Must_inspect_result_ 1197 NTSTATUS 1198 ConfigureConstraints( 1199 __in_opt PWDF_OBJECT_ATTRIBUTES ObjectAttributes, 1200 __in_opt FxDriver* Caller 1201 ); 1202 1203 VOID 1204 DeferredDispatchRequestsFromDpc( 1205 VOID 1206 ); 1207 1208 VOID 1209 DeferredDispatchRequestsFromWorkerThread( 1210 VOID 1211 ); 1212 1213 __inline 1214 static 1215 FxIoQueue* _FromIoPkgListEntry(__in PLIST_ENTRY Entry)1216 _FromIoPkgListEntry( 1217 __in PLIST_ENTRY Entry 1218 ) 1219 { 1220 return CONTAINING_RECORD(Entry, FxIoQueue, m_IoPkgListNode.m_ListEntry); 1221 } 1222 1223 __inline 1224 static 1225 FxIoQueue* _FromPowerSListEntry(__in PSINGLE_LIST_ENTRY Entry)1226 _FromPowerSListEntry( 1227 __in PSINGLE_LIST_ENTRY Entry 1228 ) 1229 { 1230 return CONTAINING_RECORD(Entry, FxIoQueue, m_PowerSListEntry); 1231 } 1232 1233 DECLSPEC_NORETURN 1234 VOID 1235 FatalError( 1236 __in NTSTATUS Status 1237 ); 1238 1239 BOOLEAN 1240 IsIoEventHandlerRegistered( 1241 __in WDF_REQUEST_TYPE RequestType 1242 ); 1243 1244 __inline 1245 VOID SetPowerState(__in FXIOQUEUE_POWER_STATE PowerState)1246 SetPowerState( 1247 __in FXIOQUEUE_POWER_STATE PowerState 1248 ) 1249 { 1250 if (m_PowerManaged) { 1251 m_PowerState = PowerState; 1252 } 1253 } 1254 1255 _Must_inspect_result_ 1256 NTSTATUS 1257 GetReservedRequest( 1258 __in MdIrp Irp, 1259 __deref_out_opt FxRequest **ReservedRequest 1260 ); 1261 1262 __inline 1263 BOOLEAN IsForwardProgressQueue(VOID)1264 IsForwardProgressQueue( 1265 VOID 1266 ) 1267 { 1268 return m_SupportForwardProgress; 1269 } 1270 1271 __inline 1272 NTSTATUS InvokeAllocateResourcesCallback(__in FxRequest * Request)1273 InvokeAllocateResourcesCallback( 1274 __in FxRequest *Request 1275 ) 1276 /*++ 1277 1278 Routine Description: 1279 Give callback to allocate resources at runtime for a general request 1280 (not a reserved request). 1281 1282 --*/ 1283 { 1284 NTSTATUS status; 1285 1286 ASSERT(Request->IsReserved() == FALSE); 1287 1288 status = STATUS_SUCCESS; 1289 if (m_FwdProgContext->m_IoResourcesAllocate.Method != NULL) { 1290 Request->SetPresented(); 1291 status = m_FwdProgContext->m_IoResourcesAllocate.Invoke( 1292 GetHandle(), Request->GetHandle()); 1293 } 1294 1295 return status; 1296 } 1297 1298 VOID 1299 ReturnReservedRequest( 1300 __in FxRequest *ReservedRequest 1301 ); 1302 1303 _Must_inspect_result_ 1304 NTSTATUS 1305 AllocateReservedRequest( 1306 __deref_out FxRequest** Request 1307 ); 1308 1309 _Must_inspect_result_ 1310 NTSTATUS 1311 AssignForwardProgressPolicy( 1312 __in PWDF_IO_QUEUE_FORWARD_PROGRESS_POLICY Policy 1313 ); 1314 1315 // ForwardRequestWorker verifiers 1316 // Do not specify argument names 1317 FX_DECLARE_VF_FUNCTION_P1_EX( 1318 , 1319 SHORT, 1320 0, 1321 VerifyForwardRequestUpdateFlags, 1322 _In_ FxRequest* 1323 ); 1324 1325 _Must_inspect_result_ 1326 NTSTATUS 1327 ForwardRequestWorker( 1328 __in FxRequest* Request, 1329 __in FxIoQueue* DestQueue 1330 ); 1331 1332 // ForwardRequestToParent Verifiers 1333 // Do not specify argument names 1334 FX_DECLARE_VF_FUNCTION_P2( 1335 NTSTATUS, 1336 VerifyForwardRequestToParent, 1337 _In_ FxIoQueue*, 1338 _In_ FxRequest* 1339 ); 1340 1341 _Must_inspect_result_ 1342 NTSTATUS 1343 ForwardRequestToParent( 1344 __in FxIoQueue* DestQueue, 1345 __in FxRequest* Request, 1346 __in PWDF_REQUEST_FORWARD_OPTIONS ForwardOptions 1347 ); 1348 1349 __inline 1350 VOID SetCxDeviceInfo(__in FxCxDeviceInfo * CxDeviceInfo)1351 SetCxDeviceInfo( 1352 __in FxCxDeviceInfo* CxDeviceInfo 1353 ) 1354 { 1355 m_CxDeviceInfo = CxDeviceInfo; 1356 } 1357 1358 __inline 1359 FxCxDeviceInfo* GetCxDeviceInfo(VOID)1360 GetCxDeviceInfo( 1361 VOID 1362 ) 1363 { 1364 return m_CxDeviceInfo; 1365 } 1366 1367 __inline 1368 VOID SetInterruptQueue(VOID)1369 SetInterruptQueue( 1370 VOID 1371 ) 1372 { 1373 MarkNoDeleteDDI(ObjectLock); 1374 } 1375 1376 VOID 1377 FlushQueuedDpcs( 1378 VOID 1379 ); 1380 1381 VOID 1382 InsertQueueDpc( 1383 VOID 1384 ); 1385 1386 private: 1387 1388 // 1389 // Helper functions for event processing loop DispatchEvents() 1390 // 1391 __drv_requiresIRQL(DISPATCH_LEVEL) 1392 VOID 1393 ProcessIdleComplete( 1394 __out PKIRQL PreviousIrql 1395 ); 1396 1397 __drv_requiresIRQL(DISPATCH_LEVEL) 1398 VOID 1399 ProcessPurgeComplete( 1400 __out PKIRQL PreviousIrql 1401 ); 1402 1403 __drv_requiresIRQL(DISPATCH_LEVEL) 1404 VOID 1405 ProcessReadyNotify( 1406 __out PKIRQL PreviousIrql 1407 ); 1408 1409 __drv_requiresIRQL(DISPATCH_LEVEL) 1410 BOOLEAN 1411 ProcessCancelledRequests( 1412 __out PKIRQL PreviousIrql 1413 ); 1414 1415 __drv_requiresIRQL(DISPATCH_LEVEL) 1416 BOOLEAN 1417 ProcessCancelledRequestsOnQueue( 1418 __out PKIRQL PreviousIrql 1419 ); 1420 1421 __drv_requiresIRQL(DISPATCH_LEVEL) 1422 BOOLEAN 1423 ProcessPowerEvents( 1424 __out PKIRQL PreviousIrql 1425 ); 1426 1427 __inline 1428 BOOLEAN IsPowerStateNotifyingDriver(VOID)1429 IsPowerStateNotifyingDriver( 1430 VOID 1431 ) 1432 { 1433 if (m_PowerState == FxIoQueuePowerStoppingNotifyingDriver || 1434 m_PowerState == FxIoQueuePowerPurgeNotifyingDriver || 1435 m_PowerState == FxIoQueuePowerRestartingNotifyingDriver) { 1436 return TRUE; 1437 } 1438 else { 1439 return FALSE; 1440 } 1441 } 1442 1443 // 1444 // Insert in the list of requests that the driver is operating 1445 // on. 1446 // 1447 // Must be called with the FxIoQueue lock held. 1448 // 1449 __inline 1450 VOID InsertInDriverOwnedList(__in FxRequest * Request)1451 InsertInDriverOwnedList( 1452 __in FxRequest* Request 1453 ) 1454 { 1455 m_DriverIoCount++; 1456 1457 InsertTailList(&m_DriverOwned, Request->GetListEntry(FxListEntryDriverOwned)); 1458 return; 1459 } 1460 1461 // 1462 // Remove the request from the list that the driver is operating 1463 // on. 1464 // 1465 // Must be called with the FxIoQueue lock held. 1466 // 1467 // Note: ForwardRequest and two phase completions (queued-by-driver) cases breaks 1468 // this up and manipulates the list entry and m_DriverIoCount separately. 1469 // 1470 __inline 1471 VOID RemoveFromDriverOwnedList(__in FxRequest * Request)1472 RemoveFromDriverOwnedList( 1473 __in FxRequest* Request 1474 ) 1475 { 1476 PLIST_ENTRY listEntry; 1477 1478 listEntry = Request->GetListEntry(FxListEntryDriverOwned); 1479 1480 RemoveEntryList(listEntry); 1481 InitializeListHead(listEntry); 1482 1483 m_DriverIoCount--; 1484 ASSERT(m_DriverIoCount >= 0); 1485 1486 return; 1487 } 1488 1489 // 1490 // Pre-Remove the request from the list that the driver is operating on 1491 // (the first of two phase completion). 1492 // 1493 // Must be called with the FxIoQueue lock held. 1494 // 1495 __inline 1496 VOID PreRemoveFromDriverOwnedList(__in FxRequest * Request)1497 PreRemoveFromDriverOwnedList( 1498 __in FxRequest* Request 1499 ) 1500 { 1501 PLIST_ENTRY listEntry; 1502 1503 listEntry = Request->GetListEntry(FxListEntryDriverOwned); 1504 1505 RemoveEntryList(listEntry); 1506 InitializeListHead(listEntry); 1507 1508 m_TwoPhaseCompletions++; 1509 ASSERT(m_TwoPhaseCompletions > 0); 1510 1511 return; 1512 } 1513 1514 // 1515 // Post-Remove the request from the list that the driver is operating on 1516 // (the second of two phase completion). 1517 // 1518 // Must be called with the FxIoQueue lock held. 1519 // 1520 __inline 1521 VOID PostRemoveFromDriverOwnedList(VOID)1522 PostRemoveFromDriverOwnedList( 1523 VOID 1524 ) 1525 { 1526 m_TwoPhaseCompletions--; 1527 ASSERT(m_TwoPhaseCompletions >= 0); 1528 1529 m_DriverIoCount--; 1530 ASSERT(m_DriverIoCount >= 0); 1531 return; 1532 } 1533 1534 // 1535 // This is called after inserting a new request in the IRP queue. 1536 // 1537 // Must be called with the FxIoQueue lock held. 1538 // 1539 __inline 1540 VOID CheckTransitionFromEmpty(VOID)1541 CheckTransitionFromEmpty( 1542 VOID 1543 ) 1544 { 1545 if (m_Queue.GetRequestCount() == 1L || 1546 m_ForceTransitionFromEmptyWhenAddingNewRequest) { 1547 1548 SetTransitionFromEmpty(); 1549 } 1550 } 1551 1552 // 1553 // Indicate that the queue went from empty to having one or more requests. 1554 // 1555 // Must be called with the FxIoQueue lock held. 1556 // 1557 __inline 1558 VOID SetTransitionFromEmpty(VOID)1559 SetTransitionFromEmpty( 1560 VOID 1561 ) 1562 { 1563 m_TransitionFromEmpty = TRUE; 1564 m_ForceTransitionFromEmptyWhenAddingNewRequest = FALSE; 1565 1566 if(m_IsDevicePowerPolicyOwner && 1567 m_PowerManaged && 1568 m_PowerReferenced == FALSE) { 1569 1570 if (NT_SUCCESS(m_Device->m_PkgPnp->PowerReference(FALSE))) { 1571 m_PowerReferenced = TRUE; 1572 } 1573 } 1574 } 1575 1576 NTSTATUS 1577 InsertNewRequestLocked( 1578 __deref_in FxRequest** Request, 1579 __in KIRQL PreviousIrql 1580 ); 1581 1582 __inline 1583 NTSTATUS InsertNewRequest(__in FxRequest ** Request,__in KIRQL PreviousIrql)1584 InsertNewRequest( 1585 __in FxRequest** Request, 1586 __in KIRQL PreviousIrql 1587 ) 1588 { 1589 NTSTATUS status; 1590 1591 if (*Request != NULL) { 1592 status = InsertNewRequestLocked(Request, PreviousIrql); 1593 } 1594 else { 1595 status = STATUS_SUCCESS; // nothing to do. 1596 } 1597 1598 return status; 1599 } 1600 1601 VOID 1602 FreeAllReservedRequests( 1603 __in BOOLEAN Verify 1604 ); 1605 1606 _Must_inspect_result_ 1607 NTSTATUS 1608 QueueForwardProgressIrpLocked( 1609 __in MdIrp Irp 1610 ); 1611 1612 _Must_inspect_result_ 1613 MdIrp 1614 GetForwardProgressIrpLocked( 1615 __in_opt PFILE_OBJECT FileObject 1616 ); 1617 1618 BOOLEAN 1619 IsPagingIo( 1620 __in MdIrp Irp 1621 ); 1622 1623 VOID PutBackReservedRequest(__in FxRequest * ReservedRequest)1624 PutBackReservedRequest( 1625 __in FxRequest *ReservedRequest 1626 ) 1627 { 1628 KIRQL oldIrql; 1629 PLIST_ENTRY listEntry; 1630 1631 ASSERT(m_Deleted == FALSE); 1632 1633 listEntry = ReservedRequest->GetListEntry(FxListEntryForwardProgress); 1634 1635 m_FwdProgContext->m_PendedReserveLock.Acquire(&oldIrql); 1636 1637 RemoveEntryList(listEntry); 1638 InitializeListHead(listEntry); 1639 1640 InsertTailList(&m_FwdProgContext->m_ReservedRequestList, listEntry); 1641 1642 if (GetDriverGlobals()->FxVerifierIO) { 1643 VerifierVerifyFwdProgListsLocked(); 1644 } 1645 1646 m_FwdProgContext->m_PendedReserveLock.Release(oldIrql); 1647 } 1648 1649 1650 VOID 1651 GetForwardProgressIrps( 1652 __in PLIST_ENTRY IrpListHead, 1653 __in_opt MdFileObject FileObject 1654 ); 1655 1656 VOID 1657 CancelIrps( 1658 __in PLIST_ENTRY IrpListHead 1659 ); 1660 1661 VOID 1662 PurgeForwardProgressIrps( 1663 __in_opt MdFileObject FileObject 1664 ); 1665 1666 VOID 1667 VerifierVerifyFwdProgListsLocked( 1668 VOID 1669 ); 1670 1671 protected: 1672 static 1673 EVT_IRP_QUEUE_CANCEL 1674 _IrpCancelForQueue; 1675 1676 // 1677 // This is our Cancel Safe Queue Callback from 1678 // FxIrpQueue notifying us of an I/O cancellation 1679 // on a driver owned request (driver queue) 1680 // 1681 static 1682 EVT_IRP_QUEUE_CANCEL 1683 _IrpCancelForDriver; 1684 1685 static 1686 EVT_SYSTEMWORKITEM 1687 _DeferredDispatchThreadThunk; 1688 1689 static 1690 MdDeferredRoutineType 1691 _DeferredDispatchDpcThunk; 1692 1693 static 1694 EVT_WDF_IO_QUEUE_STATE 1695 _PurgeComplete; 1696 1697 static 1698 EVT_WDF_IO_QUEUE_STATE 1699 _IdleComplete; 1700 1701 static 1702 MdCancelRoutineType 1703 _WdmCancelRoutineForReservedIrp; 1704 1705 }; 1706 1707 #if (FX_CORE_MODE==FX_CORE_KERNEL_MODE) 1708 #include "fxioqueuekm.hpp" 1709 #else 1710 #include "fxioqueueum.hpp" 1711 #endif 1712 1713 1714 #endif // _FXIOQUEUE_H_ 1715