1 /*++ 2 3 Copyright (c) Microsoft Corporation. All rights reserved. 4 5 Module Name: 6 7 FxIoTarget.hpp 8 9 Abstract: 10 11 Encapsulation of the target to which FxRequest are sent to. For example, 12 an FxTarget could represent the next device object in the pnp stack. 13 Derivations from this class could include bus specific formatters or device 14 objects outside of the pnp stack of the device. 15 16 Author: 17 18 19 20 Environment: 21 22 Both kernel and user mode 23 24 Revision History: 25 26 --*/ 27 28 #ifndef _FXIOTARGET_H_ 29 #define _FXIOTARGET_H_ 30 31 32 struct FxIoContext : public FxRequestContext { 33 34 FxIoContext( 35 VOID 36 ); 37 38 virtual 39 ~FxIoContext( 40 VOID 41 ); 42 43 VOID StoreAndReferenceOtherMemoryFxIoContext44 StoreAndReferenceOtherMemory( 45 __in FxRequestBuffer* Buffer 46 ) 47 { 48 _StoreAndReferenceMemoryWorker(this, &m_OtherMemory, Buffer); 49 } 50 51 virtual 52 VOID 53 ReleaseAndRestore( 54 __in FxRequestBase* Request 55 ); 56 57 VOID 58 ClearBuffer( 59 VOID 60 ); 61 62 VOID 63 SetBufferAndLength( 64 __in PVOID Buffer, 65 __in size_t BufferLength, 66 __in BOOLEAN CopyBackToBuffer 67 ); 68 69 VOID 70 CopyParameters( 71 __in FxRequestBase* Request 72 ); 73 74 VOID 75 CaptureState( 76 __in FxIrp* Irp 77 ); 78 79 VOID 80 SwapIrpBuffer( 81 _In_ FxRequestBase* Request, 82 _In_ ULONG NewInputBufferCb, 83 _In_reads_bytes_opt_(NewInputBufferCb) PVOID NewInputBuffer, 84 _In_ ULONG NewOutputBufferCb, 85 _In_reads_bytes_opt_(NewOutputBufferCb) PVOID NewOutputBuffer 86 ); 87 88 public: 89 90 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 91 PVOID m_BufferToFree; 92 PVOID m_OriginalSystemBuffer; 93 PVOID m_OriginalUserBuffer; 94 PMDL m_MdlToFree; 95 union { 96 PMDL m_OriginalMdl; 97 PFX_DRIVER_GLOBALS m_DriverGlobals; 98 }; 99 100 ULONG m_OriginalFlags; 101 102 size_t m_BufferToFreeLength; 103 size_t m_MdlToFreeSize; 104 BOOLEAN m_CopyBackToBuffer; 105 BOOLEAN m_UnlockPages; 106 #else 107 // 108 // Captured state of the IRP before buffers are modified by Format 109 // 110 WUDFX_IRP_BUFFER_INFO m_OriginalBufferInfo; 111 #endif 112 113 BOOLEAN m_RestoreState; 114 UCHAR m_MajorFunction; 115 IFxMemory* m_OtherMemory; 116 }; 117 118 struct FxInternalIoctlOthersContext : public FxRequestContext { 119 FxInternalIoctlOthersContextFxInternalIoctlOthersContext120 FxInternalIoctlOthersContext( 121 VOID 122 ) : 123 FxRequestContext(FX_RCT_INTERNAL_IOCTL_OTHERS) 124 { 125 RtlZeroMemory(&m_MemoryObjects[0], sizeof(m_MemoryObjects)); 126 } 127 128 VOID StoreAndReferenceOtherMemoriesFxInternalIoctlOthersContext129 StoreAndReferenceOtherMemories( 130 __in FxRequestBuffer* Buffer1, 131 __in FxRequestBuffer* Buffer2, 132 __in FxRequestBuffer* Buffer4 133 ) 134 { 135 StoreAndReferenceMemory(Buffer1); 136 _StoreAndReferenceMemoryWorker(this, &m_MemoryObjects[0], Buffer2); 137 _StoreAndReferenceMemoryWorker(this, &m_MemoryObjects[1], Buffer4); 138 } 139 140 virtual 141 VOID ReleaseAndRestoreFxInternalIoctlOthersContext142 ReleaseAndRestore( 143 __in FxRequestBase* Request 144 ) 145 { 146 ULONG i; 147 148 for (i = 0; 149 i < sizeof(m_MemoryObjects)/sizeof(m_MemoryObjects[0]); 150 i++) { 151 152 if (m_MemoryObjects[i] != NULL) { 153 m_MemoryObjects[i]->RELEASE(this); 154 m_MemoryObjects[i] = NULL; 155 } 156 } 157 158 FxRequestContext::ReleaseAndRestore(Request); // __super call 159 } 160 161 private: 162 virtual 163 VOID StoreAndReferenceMemoryFxInternalIoctlOthersContext164 StoreAndReferenceMemory( 165 __in FxRequestBuffer* Buffer 166 ) 167 { 168 FxRequestContext::StoreAndReferenceMemory(Buffer); // __super call 169 } 170 171 public: 172 // 173 // __super has a field for one IFxMemory, so we don't need to store all 174 // 3 in the derivative, reuse the __super's field for one of them. 175 // 176 IFxMemory* m_MemoryObjects[FX_REQUEST_NUM_OTHER_PARAMS-1]; 177 }; 178 179 struct FxTargetSubmitSyncParams { 180 // 181 // Event to set if the request is synchronous after the request has completed 182 // 183 FxCREvent SynchEvent; 184 185 // 186 // Status of the request if it was synchronous 187 // 188 NTSTATUS Status; 189 190 // 191 // Original completion routine to be called in the synchronous case 192 // 193 PFN_WDF_REQUEST_COMPLETION_ROUTINE OrigTargetCompletionRoutine; 194 195 // 196 // Original completion context to be passed in the synchronous case 197 // 198 WDFCONTEXT OrigTargetCompletionContext; 199 }; 200 201 enum SubmitActionFlags { 202 SubmitSend = 0x00000001, 203 SubmitQueued = 0x00000002, 204 SubmitSent = 0x00000004, 205 SubmitWait = 0x00000008, 206 SubmitTimeout = 0x00000010, 207 SubmitSyncCallCompletion = 0x00000020, 208 }; 209 210 class FxIoTarget : public FxNonPagedObject { 211 212 friend FxRequestBase; 213 214 public: 215 216 FxIoTarget( 217 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 218 __in USHORT ObjectSize 219 ); 220 221 FxIoTarget( 222 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 223 __in USHORT ObjectSize, 224 __in WDFTYPE WdfType 225 ); 226 227 virtual 228 _Must_inspect_result_ 229 NTSTATUS 230 Start( 231 VOID 232 ); 233 234 virtual 235 VOID 236 Stop( 237 __in WDF_IO_TARGET_SENT_IO_ACTION Action 238 ); 239 240 virtual 241 VOID 242 Purge( 243 __in WDF_IO_TARGET_PURGE_IO_ACTION Action 244 ); 245 246 virtual 247 VOID 248 Remove( 249 VOID 250 ); 251 252 // 253 // IFxObject override 254 // 255 NTSTATUS 256 _Must_inspect_result_ 257 QueryInterface( 258 __inout FxQueryInterfaceParams* Params 259 ); 260 261 __inline 262 WDF_IO_TARGET_STATE GetState(VOID)263 GetState( 264 VOID 265 ) 266 { 267 return m_State; 268 } 269 270 __inline 271 MdDeviceObject GetTargetDevice(VOID)272 GetTargetDevice( 273 VOID 274 ) 275 { 276 return m_TargetDevice; 277 } 278 279 __inline 280 MdDeviceObject GetTargetPDO(VOID)281 GetTargetPDO( 282 VOID 283 ) 284 { 285 return m_TargetPdo; 286 } 287 288 __inline 289 MdFileObject GetTargetFileObject(VOID)290 GetTargetFileObject( 291 VOID 292 ) 293 { 294 return m_TargetFileObject; 295 } 296 297 __inline 298 WDFDEVICE GetDeviceHandle(VOID)299 GetDeviceHandle( 300 VOID 301 ) 302 { 303 return m_Device->GetHandle(); 304 } 305 306 WDFIOTARGET GetHandle(VOID)307 GetHandle( 308 VOID 309 ) 310 { 311 return (WDFIOTARGET) GetObjectHandle(); 312 } 313 314 __inline 315 FxDriver* GetDriver(VOID)316 GetDriver( 317 VOID 318 ) 319 { 320 return m_Driver; 321 } 322 323 virtual 324 _Must_inspect_result_ 325 MdDeviceObject GetTargetDeviceObject(_In_ CfxDeviceBase * Device)326 GetTargetDeviceObject( 327 _In_ CfxDeviceBase* Device 328 ) 329 { 330 return Device->GetAttachedDevice(); 331 } 332 333 _Must_inspect_result_ 334 NTSTATUS 335 Init( 336 __in CfxDeviceBase* Device 337 ); 338 339 ULONG 340 Submit( 341 __in FxRequestBase* Request, 342 __in_opt PWDF_REQUEST_SEND_OPTIONS Options, 343 __in_opt ULONG Flags 344 ); 345 346 // Do not specify argument names 347 FX_DECLARE_VF_FUNCTION_P1( 348 NTSTATUS, 349 VerifySubmitLocked, 350 _In_ FxRequestBase* 351 ); 352 353 ULONG 354 SubmitLocked( 355 __in FxRequestBase* Request, 356 __in_opt PWDF_REQUEST_SEND_OPTIONS Options, 357 __in ULONG Flags 358 ); 359 360 _Must_inspect_result_ 361 NTSTATUS 362 SubmitSync( 363 __in FxRequestBase* Request, 364 __in_opt PWDF_REQUEST_SEND_OPTIONS Options = NULL, 365 __out_opt PULONG Action = NULL 366 ); 367 368 VOID 369 TimerCallback( 370 __in FxRequestBase* Request 371 ); 372 373 VOID 374 CompleteCanceledRequest( 375 __in FxRequestBase* Request 376 ); 377 378 VOID 379 SubmitPendedRequest( 380 __in FxRequestBase* Request 381 ); 382 383 VOID 384 CompletePendedRequest( 385 __in FxRequestBase* Request 386 ); 387 388 static 389 VOID 390 _CancelSentRequest( 391 __in FxRequestBase* Request 392 ); 393 394 BOOLEAN 395 __inline HasEnoughStackLocations(__in FxIrp * Irp)396 HasEnoughStackLocations( 397 __in FxIrp* Irp 398 ) 399 { 400 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 401 // 402 // Check to make sure there are enough current stack locations available. 403 // When a IRP is initially created, Irp->CurrentLocation is set to 404 // StackSize + 1. When comparing against the target device, subtract 405 // off the extra space to see how many locations are left. 406 // 407 // Say Target->m_TargetStackSize == 1, then: 408 // irp = IoAllocateIrp(Target->m_TargetStackSize, FALSE); 409 // ASSERT(irp->CurrentLocation == 2); 410 // 411 return (Irp->GetCurrentIrpStackLocationIndex() - 1 >= m_TargetStackSize) ? TRUE : FALSE; 412 #else // FX_CORE_USER_MODE 413 // 414 // For UMDF, host does the necessary checks to ensure there are enough 415 // stack locations. In addition, UMDF drivers can't create WDM IRPs 416 // so they don't get to dictate the number of stack locations in the irp 417 // so this kind of check in framework for UMDF is redundant. Return TRUE 418 // always. 419 // 420 return TRUE; 421 #endif 422 } 423 424 _Must_inspect_result_ 425 NTSTATUS 426 FormatIoRequest( 427 __inout FxRequestBase* Request, 428 __in UCHAR MajorCode, 429 __in FxRequestBuffer* IoBuffer, 430 __in_opt PLONGLONG StartingOffset, 431 __in_opt FxFileObject* FileObject = NULL 432 ); 433 434 _Must_inspect_result_ 435 NTSTATUS 436 FormatIoctlRequest( 437 __in FxRequestBase* Request, 438 __in ULONG Ioctl, 439 __in BOOLEAN Internal, 440 __in FxRequestBuffer* InputBuffer, 441 __in FxRequestBuffer* OutputBuffer, 442 __in_opt FxFileObject* FileObject = NULL 443 ); 444 445 _Must_inspect_result_ 446 NTSTATUS 447 FormatInternalIoctlOthersRequest( 448 __in FxRequestBase* Request, 449 __in ULONG Ioctl, 450 __in FxRequestBuffer* Buffers 451 ); 452 453 static 454 FxIoTarget* _FromEntry(__in FxTransactionedEntry * Entry)455 _FromEntry( 456 __in FxTransactionedEntry* Entry 457 ) 458 { 459 return CONTAINING_RECORD(Entry, FxIoTarget, m_TransactionedEntry); 460 } 461 462 VOID 463 CancelSentIo( 464 VOID 465 ); 466 467 _Must_inspect_result_ 468 NTSTATUS 469 SubmitSyncRequestIgnoreTargetState( 470 __in FxRequestBase* Request, 471 __in_opt PWDF_REQUEST_SEND_OPTIONS RequestOptions 472 ); 473 474 VOID 475 UpdateTargetIoType( 476 VOID 477 ); 478 479 BOOLEAN 480 HasValidStackSize( 481 VOID 482 ); 483 484 virtual 485 VOID 486 Send( 487 _In_ MdIrp Irp 488 ); 489 490 protected: 491 // 492 // Hide destructor since we are reference counted object 493 // 494 ~FxIoTarget(); 495 496 _Must_inspect_result_ 497 NTSTATUS 498 InitModeSpecific( 499 __in CfxDeviceBase* Device 500 ); 501 502 // FxObject overrides 503 virtual 504 BOOLEAN 505 Dispose( 506 VOID 507 ); 508 // FxObject overrides 509 510 VOID 511 FailPendedRequest( 512 __in FxRequestBase* Request, 513 __in NTSTATUS Status 514 ); 515 516 VOID 517 DrainPendedRequestsLocked( 518 __in PLIST_ENTRY RequestListHead, 519 __in BOOLEAN RequestWillBeResent 520 ); 521 522 VOID 523 CompletePendedRequestList( 524 __in PLIST_ENTRY RequestListHead 525 ); 526 527 VOID 528 SubmitPendedRequests( 529 __in PLIST_ENTRY RequestListHeadHead 530 ); 531 532 VOID 533 GetSentRequestsListLocked( 534 __in PSINGLE_LIST_ENTRY RequestListHead, 535 __in PLIST_ENTRY SendList, 536 __out PBOOLEAN AddedToList 537 ); 538 539 static 540 VOID 541 _CancelSentRequests( 542 __in PSINGLE_LIST_ENTRY RequestListHead 543 ); 544 545 virtual 546 _Must_inspect_result_ 547 NTSTATUS 548 GotoStartState( 549 __in PLIST_ENTRY RequestListHead, 550 __in BOOLEAN Lock = TRUE 551 ); 552 553 virtual 554 VOID 555 GotoStopState( 556 __in WDF_IO_TARGET_SENT_IO_ACTION Action, 557 __in PSINGLE_LIST_ENTRY SentRequestListHead, 558 __out PBOOLEAN Wait, 559 __in BOOLEAN LockSelf 560 ); 561 562 virtual 563 VOID 564 GotoPurgeState( 565 __in WDF_IO_TARGET_PURGE_IO_ACTION Action, 566 __in PLIST_ENTRY PendedRequestListHead, 567 __in PSINGLE_LIST_ENTRY SentRequestListHead, 568 __out PBOOLEAN Wait, 569 __in BOOLEAN LockSelf 570 ); 571 572 _Must_inspect_result_ 573 NTSTATUS 574 PendRequestLocked( 575 __in FxRequestBase* Request 576 ); 577 578 __inline 579 VOID CompleteRequest(__in FxRequestBase * Request)580 CompleteRequest( 581 __in FxRequestBase* Request 582 ) 583 { 584 // 585 // This will remove the reference taken by this object on the request 586 // 587 Request->CompleteSubmitted(); 588 } 589 590 // 591 // Completion routine to handle the case when re-submitting a pended 592 // request fails. 593 // 594 VOID 595 HandleFailedResubmit( 596 __in FxRequestBase* Request 597 ); 598 599 // 600 // Generic I/O completion routine and its static caller. 601 // 602 VOID 603 RequestCompletionRoutine( 604 __in FxRequestBase* Request 605 ); 606 607 static 608 MdCompletionRoutineType 609 _RequestCompletionRoutine; 610 611 BOOLEAN 612 RemoveCompletedRequestLocked( 613 __in FxRequestBase* Request 614 ); 615 616 virtual 617 VOID ClearTargetPointers(VOID)618 ClearTargetPointers( 619 VOID 620 ) 621 { 622 m_TargetDevice = NULL; 623 m_TargetPdo = NULL; 624 m_TargetFileObject = NULL; 625 626 m_TargetStackSize = 0; 627 m_TargetIoType = WdfDeviceIoUndefined; 628 } 629 630 UCHAR GetTargetIoType(VOID)631 GetTargetIoType( 632 VOID 633 ) 634 { 635 ULONG flags; 636 MxDeviceObject deviceObject(m_TargetDevice); 637 638 flags = deviceObject.GetFlags(); 639 640 if (flags & DO_BUFFERED_IO) { 641 return WdfDeviceIoBuffered; 642 } 643 else if (flags & DO_DIRECT_IO) { 644 return WdfDeviceIoDirect; 645 } 646 else { 647 return WdfDeviceIoNeither; 648 } 649 } 650 651 static 652 VOID 653 _RequestCancelled( 654 __in FxIrpQueue* Queue, 655 __in MdIrp Irp, 656 __in PMdIoCsqIrpContext pCsqContext, 657 __in KIRQL CallerIrql 658 ); 659 660 static 661 EVT_WDF_REQUEST_COMPLETION_ROUTINE 662 _SyncCompletionRoutine; 663 664 virtual 665 VOID 666 GotoRemoveState( 667 __in WDF_IO_TARGET_STATE NewState, 668 __in PLIST_ENTRY PendedRequestListHead, 669 __in PSINGLE_LIST_ENTRY SentRequestListHead, 670 __in BOOLEAN Lock, 671 __out PBOOLEAN Wait 672 ); 673 674 virtual 675 VOID WaitForSentIoToComplete(VOID)676 WaitForSentIoToComplete( 677 VOID 678 ) 679 { 680 ASSERT(Mx::MxGetCurrentIrql() == PASSIVE_LEVEL); 681 682 m_SentIoEvent.EnterCRAndWaitAndLeave(); 683 } 684 685 virtual 686 VOID 687 WaitForDisposeEvent( 688 VOID 689 ); 690 691 #if (FX_CORE_MODE == FX_CORE_USER_MODE) 692 // 693 //Making it a virtual function so that derived classes can override it 694 //For example, CWdfIoTargetLocal overrides it to set the file object 695 //before forwarding the request 696 // 697 virtual 698 VOID Forward(__in MdIrp Irp)699 Forward( 700 __in MdIrp Irp 701 ) 702 { 703 // 704 // Ignore the return value because once we have sent the request, we 705 // want all processing to be done in the completion routine. 706 // 707 (void) Irp->Forward(); 708 } 709 #endif 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 __inline 742 VOID CopyFileObjectAndFlags(__in FxRequestBase * Request)743 CopyFileObjectAndFlags( 744 __in FxRequestBase* Request 745 ) 746 { 747 FxIrp* irp = Request->GetSubmitFxIrp(); 748 749 if (Request->IsAllocatedFromIo()) { 750 irp->SetNextStackFlags(irp->GetCurrentStackFlags()); 751 irp->SetNextStackFileObject(irp->GetCurrentStackFileObject()); 752 } 753 754 // 755 // Use the target's fileobject if present, otherwise use the current 756 // stack location's fileobject (if there is a current stack location). 757 // 758 if (m_InStack == FALSE) { 759 irp->SetNextStackFileObject(m_TargetFileObject); 760 } 761 } 762 763 764 765 __inline 766 VOID IncrementIoCount(VOID)767 IncrementIoCount( 768 VOID 769 ) 770 { 771 LONG ret; 772 773 ret = InterlockedIncrement(&m_IoCount); 774 775 #if DBG 776 ASSERT(ret > 1); 777 #else 778 UNREFERENCED_PARAMETER(ret); 779 #endif 780 } 781 782 783 __inline 784 VOID DecrementIoCount(VOID)785 DecrementIoCount( 786 VOID 787 ) 788 { 789 LONG ret; 790 791 ret = InterlockedDecrement(&m_IoCount); 792 ASSERT(ret >= 0); 793 794 if (ret == 0) { 795 PrintDisposeMessage(); 796 ASSERT(m_DisposeEvent != NULL); 797 m_DisposeEvent->Set(); 798 } 799 } 800 801 VOID 802 PrintDisposeMessage( 803 VOID 804 ); 805 806 private: 807 808 VOID 809 Construct( 810 VOID 811 ); 812 813 VOID ClearCompletedRequestVerifierFlags(__in FxRequestBase * Request)814 ClearCompletedRequestVerifierFlags( 815 __in FxRequestBase* Request 816 ) 817 { 818 if (GetDriverGlobals()->FxVerifierOn && 819 GetDriverGlobals()->FxVerifierIO) { 820 KIRQL irql; 821 822 Request->Lock(&irql); 823 // 824 // IF we are completing a request that was pended in the target, 825 // this flag was not set. 826 // 827 // ASSERT(Request->GetVerifierFlagsLocked() & FXREQUEST_FLAG_SENT_TO_TARGET); 828 Request->ClearVerifierFlagsLocked(FXREQUEST_FLAG_SENT_TO_TARGET); 829 Request->Unlock(irql); 830 } 831 } 832 833 VOID SetCompletionRoutine(__in FxRequestBase * Request)834 SetCompletionRoutine( 835 __in FxRequestBase* Request 836 ) 837 { 838 FxIrp* irp = Request->GetSubmitFxIrp(); 839 840 irp->SetCompletionRoutineEx( 841 m_InStackDevice, 842 _RequestCompletionRoutine, 843 Request, 844 TRUE, 845 TRUE, 846 TRUE); 847 } 848 849 public: 850 // 851 // Transaction entry for FxDevice to queue this target on 852 // 853 FxTransactionedEntry m_TransactionedEntry; 854 855 BOOLEAN m_InStack; 856 857 // 858 // TRUE when FxDevice::AddIoTarget has been called 859 // 860 BOOLEAN m_AddedToDeviceList; 861 862 static const PVOID m_SentRequestTag; 863 864 protected: 865 // 866 // List of requests that have been sent to the target 867 // 868 LIST_ENTRY m_SentIoListHead; 869 870 // 871 // List of requests which were sent ignoring the state of the target 872 // 873 LIST_ENTRY m_IgnoredIoListHead; 874 875 // 876 // Event used to wait for sent I/O to complete 877 // 878 FxCREvent m_SentIoEvent; 879 880 // 881 // Event used to wait by Dispose to make sure all I/O's are completed. 882 // This is required to make sure that all the I/O are completed before 883 // disposing the target. This acts like remlock. 884 // 885 FxCREvent *m_DisposeEvent; 886 887 #if (FX_CORE_MODE == FX_CORE_USER_MODE) 888 // 889 // Eventy initialization can fail in user-mode so we define one as 890 // part of object. 891 // 892 FxCREvent m_DisposeEventUm; 893 #endif 894 895 FxIrpQueue m_PendedQueue; 896 897 // 898 // Back link to the object that represents our devobj 899 // 900 FxDriver* m_Driver; 901 902 // 903 // The PDEVICE_OBJECT that is owned by m_Device 904 // 905 MdDeviceObject m_InStackDevice; 906 907 // 908 // The device object which is our "target" 909 // 910 MdDeviceObject m_TargetDevice; 911 912 // 913 // The PDO for m_TargetDevice. For this class, it would be the same PDO 914 // as the owning WDFDEVICE. In a derived class (like FxIoTargetRemote), 915 // this would not be the PDO of the owning WDFDEVICE, rather the PDO for 916 // the other stack. 917 // 918 MdDeviceObject m_TargetPdo; 919 920 // 921 // File object that is attached to all I/O sent to m_TargetDevice 922 // 923 MdFileObject m_TargetFileObject; 924 925 // 926 // Current state 927 // 928 WDF_IO_TARGET_STATE m_State; 929 930 // 931 // This is used to track the I/O's sent to the lower driver 932 // and is used to make sure all I/Os are completed before disposing the 933 // Iotarget. 934 // 935 LONG m_IoCount; 936 937 // 938 // Cached value of m_TargetDevice->StackSize. The value is cached so that 939 // we can still format to the target during query remove transitions. 940 // 941 CCHAR m_TargetStackSize; 942 943 // 944 // Cached value of m_TargetDevice->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO) 945 // which uses WDF_DEVICE_IO_TYPE to indicate state. 946 // 947 UCHAR m_TargetIoType; 948 949 // 950 // TRUE if we are in the processing of stopping/purging and there are 951 // requests that have been sent and must be waited upon for completion. 952 // 953 BOOLEAN m_WaitingForSentIo; 954 955 BOOLEAN m_Removing; 956 957 }; 958 959 960 #if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE)) 961 #include "fxiotargetkm.hpp" 962 #elif ((FX_CORE_MODE)==(FX_CORE_USER_MODE)) 963 #include "fxiotargetum.hpp" 964 #endif 965 966 #endif //_FXIOTARGET_H_ 967