1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxRequest.hpp 8 9 Abstract: 10 11 This is the request object for the driver frameworks. 12 13 The request object wraps the IRP, containing persistent 14 information required by the driver frameworks. 15 16 Author: 17 18 19 20 21 22 Environment: 23 24 Both kernel and user mode 25 26 Revision History: 27 28 --*/ 29 30 #ifndef _FXREQUEST_H_ 31 #define _FXREQUEST_H_ 32 33 // 34 // Magic number to differentiate between default value and caller provided one 35 // 36 #define USE_DEFAULT_PRIORITY_BOOST ((CHAR) 0x7F) 37 38 // 39 // This tag is used to set and clear the completion callback state as the 40 // ownership of the request transfers from I/O pkg-to-queue or queue-to-queue. 41 // 42 #define FXREQUEST_STATE_TAG (PVOID) 'tatS' 43 44 // 45 // This tag is used when the request is added and removed from FxIrpQueue. 46 // 47 #define FXREQUEST_QUEUE_TAG (PVOID) 'ueuQ' 48 49 // 50 // This tag is used to take a reference in the completion path. 51 // 52 #define FXREQUEST_COMPLETE_TAG (PVOID) 'pmoC' 53 54 // 55 // Use this tag when you want to temporarily hold the object from 56 // disappearing between unlock and lock operation. 57 // 58 #define FXREQUEST_HOLD_TAG (PVOID) 'dloH' 59 60 // 61 // This tag is used to take a reference in the completion path. 62 // 63 #define FXREQUEST_FWDPRG_TAG (PVOID) 'PdwF' 64 65 // 66 // This tag is used to take a reference in the completion path for driver created 67 // requests that support completion operations. 68 // 69 #define FXREQUEST_DCRC_TAG (PVOID) 'CRCD' 70 71 extern "C" { 72 #if defined(EVENT_TRACING) 73 #include "FxRequest.hpp.tmh" 74 #endif 75 } 76 77 #if (FX_CORE_MODE == FX_CORE_USER_MODE) 78 #define WDF_REQUEST_SEND_OPTION_IMPERSONATION_FLAGS \ 79 (WDF_REQUEST_SEND_OPTION_IMPERSONATE_CLIENT | \ 80 WDF_REQUEST_SEND_OPTION_IMPERSONATION_IGNORE_FAILURE) 81 82 #define FxIrpStackFlagsFromSendFlags(sendFlags) \ 83 ((WUDFX_IRP_STACK_FLAGS) \ 84 ((sendFlags) & WDF_REQUEST_SEND_OPTION_IMPERSONATION_FLAGS)) 85 #endif 86 87 typedef 88 NTSTATUS 89 (*PFN_FX_QUEUE_REQUEST_COMPLETE) ( 90 __in FxRequest* Request, 91 __in FxIoQueue* Queue, 92 __in_opt WDFCONTEXT Context 93 ); 94 95 struct FxRequestSystemBuffer : public IFxMemory { 96 friend FxRequest; 97 98 public: FxRequestSystemBufferFxRequestSystemBuffer99 FxRequestSystemBuffer( 100 VOID 101 ) 102 { 103 m_Buffer = NULL; 104 } 105 106 _Must_inspect_result_ 107 virtual 108 PVOID 109 GetBuffer( 110 VOID 111 ); 112 113 virtual 114 size_t 115 GetBufferSize( 116 VOID 117 ); 118 119 _Must_inspect_result_ 120 virtual 121 PMDL 122 GetMdl( 123 VOID 124 ); 125 126 virtual 127 WDFMEMORY 128 GetHandle( 129 VOID 130 ); 131 132 virtual 133 USHORT 134 GetFlags( 135 VOID 136 ); 137 138 virtual 139 PFX_DRIVER_GLOBALS 140 GetDriverGlobals( 141 VOID 142 ); 143 144 virtual 145 ULONG 146 AddRef( 147 __in PVOID Tag, 148 __in LONG Line, 149 __in_opt PSTR File 150 ); 151 152 virtual 153 ULONG 154 Release( 155 __in PVOID Tag, 156 __in LONG Line, 157 __in_opt PSTR File 158 ); 159 160 virtual 161 VOID 162 Delete( 163 VOID 164 ); 165 166 __inline 167 BOOLEAN IsBufferSetFxRequestSystemBuffer168 IsBufferSet( 169 VOID 170 ) 171 { 172 return m_Buffer != NULL ? TRUE : FALSE; 173 } 174 175 __inline 176 VOID ClearBufferMdlFxRequestSystemBuffer177 ClearBufferMdl( 178 VOID 179 ) 180 { 181 m_Buffer = NULL; 182 m_Mdl = NULL; 183 } 184 185 protected: 186 __inline 187 VOID SetBufferFxRequestSystemBuffer188 SetBuffer( 189 PVOID Buffer 190 ) 191 { 192 ASSERT(m_Buffer == NULL); 193 m_Buffer = Buffer; 194 } 195 196 __inline 197 VOID SetMdlFxRequestSystemBuffer198 SetMdl( 199 PMDL Mdl 200 ) 201 { 202 ASSERT(m_Mdl == NULL); 203 m_Mdl = Mdl; 204 } 205 206 FxRequest* 207 GetRequest( 208 VOID 209 ); 210 211 protected: 212 // 213 // The current irp stack location indicates which type to use 214 // 215 // The buffer / MDL is cached away as a copy instead of using the PIRP values 216 // directly because we want to capture the current state of the irp when 217 // returning the WDFMEMORY. For instance, if used the PIRP value directly 218 // when implementing GetBuffer(), we are subject to the PIRP being formatted 219 // for the next stack location and changing the buffer pointer, or worse, 220 // changing the MDL value and have the resulting MDL not be mapped, and then 221 // a call to MmGetSystemAddressForMdlSafe can return NULL, and thus GetBuffer(), 222 // return NULL, which would violate the contract for GetBuffer(). 223 // 224 // As an example, let's 225 // 1) the WDFREQUEST/PIRP comes in as a read on a direct io device object, 226 // so Irp->MdlAddress = <read MDL> 227 // 2) This WDFMEMORY will return <read MDL VA> in GetBuffer() 228 // 3) the WDFREQUEST is formatted for an IOCTL which is METHOD_OUT_DIRECT 229 // with a new output buffer. Irp->MdlAddres = <IOCTL MDL> now. 230 // 4) This same WDFMEMORY will now return <IOCTL MDL VA> in GetBuffer() 231 // 232 // Essentialy, formatting the WDFREQUEST causes unintended side affects for 233 // the WDFMEMORYs it returns. To eliminate those side affects, we capture 234 // the original buffer. 235 // 236 union { 237 PVOID m_Buffer; 238 PMDL m_Mdl; 239 }; 240 }; 241 242 struct FxRequestOutputBuffer : public IFxMemory { 243 friend FxRequest; 244 245 public: FxRequestOutputBufferFxRequestOutputBuffer246 FxRequestOutputBuffer( 247 VOID 248 ) 249 { 250 m_Buffer = NULL; 251 } 252 253 virtual 254 PVOID 255 GetBuffer( 256 VOID 257 ); 258 259 virtual 260 size_t 261 GetBufferSize( 262 VOID 263 ); 264 265 _Must_inspect_result_ 266 virtual 267 PMDL 268 GetMdl( 269 VOID 270 ); 271 272 virtual 273 WDFMEMORY 274 GetHandle( 275 VOID 276 ); 277 278 virtual 279 USHORT 280 GetFlags( 281 VOID 282 ); 283 284 virtual 285 PFX_DRIVER_GLOBALS 286 GetDriverGlobals( 287 VOID 288 ); 289 290 virtual 291 ULONG 292 AddRef( 293 __in PVOID Tag, 294 __in LONG Line, 295 __in_opt PSTR File 296 ); 297 298 virtual 299 ULONG 300 Release( 301 __in PVOID Tag, 302 __in LONG Line, 303 __in_opt PSTR File 304 ); 305 306 virtual 307 VOID 308 Delete( 309 VOID 310 ); 311 312 __inline 313 BOOLEAN IsBufferSetFxRequestOutputBuffer314 IsBufferSet( 315 VOID 316 ) 317 { 318 return m_Buffer != NULL ? TRUE : FALSE; 319 } 320 321 __inline 322 VOID ClearBufferMdlFxRequestOutputBuffer323 ClearBufferMdl( 324 VOID 325 ) 326 { 327 m_Buffer = NULL; 328 m_Mdl = NULL; 329 } 330 331 protected: 332 __inline 333 VOID SetBufferFxRequestOutputBuffer334 SetBuffer( 335 __in PVOID Buffer 336 ) 337 { 338 ASSERT(m_Buffer == NULL); 339 m_Buffer = Buffer; 340 } 341 342 __inline 343 VOID SetMdlFxRequestOutputBuffer344 SetMdl( 345 __in PMDL Mdl 346 ) 347 { 348 ASSERT(m_Mdl == NULL); 349 m_Mdl = Mdl; 350 } 351 352 FxRequest* 353 GetRequest( 354 VOID 355 ); 356 357 protected: 358 // 359 // The current irp stack location indicates which type to use 360 // 361 // See comments in FxRequestSystemBuffer's union for why we capture the 362 // values vs using them directly from the PIRP. 363 // 364 union { 365 PVOID m_Buffer; 366 PMDL m_Mdl; 367 }; 368 }; 369 370 // begin_wpp enum 371 enum FxListEntryNames { 372 FxListEntryNameCleanup = 0, 373 374 // this entry is used when the request is owned by the framework 375 FxListEntryQueueOwned, 376 377 // this entry is used when the request is presented to the driver 378 FxListEntryDriverOwned, 379 380 // this entry is used for forward progress 381 FxListEntryForwardProgress 382 }; 383 384 enum FxRequestPowerStopState { 385 FxRequestPowerStopUnknown = 0, // Initial state 386 387 // Set when the driver calls WdfRequestStopAcknowledge 388 FxRequestPowerStopAcknowledged = 0x1, 389 390 // Set when the driver WdfRequestStopAcknowledge with requeue option 391 FxRequestPowerStopAcknowledgedWithRequeue = 0x2, 392 }; 393 394 // end_wpp 395 396 class FxRequest : public FxRequestBase { 397 398 friend FxIoTarget; 399 friend FxIoQueue; 400 401 friend FxRequestMemory; 402 friend FxRequestOutputBuffer; 403 friend FxRequestSystemBuffer; 404 friend VOID GetTriageInfo(VOID); 405 406 protected: 407 // 408 // This field points to the queue that the request is currently 409 // associated with. 410 // 411 FxIoQueue* m_IoQueue; 412 413 FxRequestSystemBuffer m_SystemBuffer; 414 415 FxRequestOutputBuffer m_OutputBuffer; 416 417 // 418 // This is for use by the owner of the FxRequest which is FxIoQueue OR FxIoTarget 419 // 420 LIST_ENTRY m_OwnerListEntry; 421 422 LIST_ENTRY m_OwnerListEntry2; 423 424 // 425 // This is used by the queue to keep track of all forward progress requests 426 // 427 LIST_ENTRY m_ForwardProgressList; 428 429 // 430 // Used when the request is a reserved request to track the queue it was 431 // originally allocated for, so that it can be returned to the forward 432 // progress queue for reuse when the request is completed. 433 // 434 FxIoQueue *m_ForwardProgressQueue; 435 436 // 437 // Generic context exposed to other modules. 438 // 439 PVOID m_InternalContext; 440 441 // 442 // If TRUE, the client driver has been presented with this WDFREQUEST at 443 // least once. 444 // 445 BOOLEAN m_Presented; 446 447 // 448 // For tracking whether the driver has acknowledged power stop/purge notifications. 449 // 450 BYTE m_PowerStopState; 451 452 // 453 // If TRUE, this is a reserved request 454 // 455 BOOLEAN m_Reserved; 456 457 // 458 // If TRUE, this is used to determine how to free the request - 459 // either to the lookaside list or using ExFreePool 460 // 461 BOOLEAN m_ForwardRequestToParent; 462 463 public: 464 465 // 466 // Normally, this is available by the object implementing 467 // IFxListEntry, but currently all callers of this know they 468 // are dealing with an FxRequest*. 469 // 470 // If FxRequests must go on a general typeless list, then 471 // the IFxListEntry interface should be added to FxRequest. 472 // 473 __inline 474 PLIST_ENTRY GetListEntry(__in FxListEntryNames Index)475 GetListEntry( 476 __in FxListEntryNames Index 477 ) 478 { 479 switch (Index) { 480 case FxListEntryQueueOwned: return &m_OwnerListEntry; 481 case FxListEntryDriverOwned: return &m_OwnerListEntry2; 482 case FxListEntryForwardProgress: return &m_ForwardProgressList; 483 default: ASSERT(FALSE); return NULL; 484 } 485 } 486 487 static 488 FxRequest* _FromOwnerListEntry(__in FxListEntryNames Index,__in PLIST_ENTRY OwnerListEntry)489 _FromOwnerListEntry( 490 __in FxListEntryNames Index, 491 __in PLIST_ENTRY OwnerListEntry 492 ) 493 { 494 switch (Index) { 495 case FxListEntryQueueOwned: 496 return CONTAINING_RECORD(OwnerListEntry, FxRequest, m_OwnerListEntry); 497 case FxListEntryDriverOwned: 498 return CONTAINING_RECORD(OwnerListEntry, FxRequest, m_OwnerListEntry2); 499 case FxListEntryForwardProgress: 500 return CONTAINING_RECORD(OwnerListEntry, FxRequest, m_ForwardProgressList); 501 default: 502 ASSERT(FALSE); 503 return NULL; 504 } 505 } 506 507 __inline 508 VOID CopyCurrentIrpStackLocationToNext(VOID)509 CopyCurrentIrpStackLocationToNext( 510 VOID 511 ) 512 { 513 FxIrp* irp = GetSubmitFxIrp(); 514 irp->CopyCurrentIrpStackLocationToNext(); 515 } 516 517 _Must_inspect_result_ 518 NTSTATUS 519 Reuse( 520 __in PWDF_REQUEST_REUSE_PARAMS ReuseParams 521 ); 522 523 __inline 524 BOOLEAN IsCancelled(VOID)525 IsCancelled( 526 VOID 527 ) 528 { 529 return m_Irp.IsCanceled() || m_Canceled; 530 } 531 532 __inline 533 VOID CopyCompletionParams(__in PWDF_REQUEST_COMPLETION_PARAMS Params)534 CopyCompletionParams( 535 __in PWDF_REQUEST_COMPLETION_PARAMS Params 536 ) 537 { 538 if (m_RequestContext != NULL) { 539 RtlCopyMemory(Params, 540 &m_RequestContext->m_CompletionParams, 541 sizeof(WDF_REQUEST_COMPLETION_PARAMS)); 542 } 543 else { 544 DoTraceLevelMessage( 545 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 546 "WdfRequestGetCompletionParams will not return valid information if the" 547 " request is not formatted using WdfIoTargetFormatxxx DDIs" 548 ); 549 550 FxVerifierDbgBreakPoint(GetDriverGlobals()); 551 552 WDF_REQUEST_COMPLETION_PARAMS_INIT(Params); 553 } 554 } 555 556 VOID 557 __inline SetPresented(VOID)558 SetPresented( 559 VOID 560 ) 561 { 562 // 563 // No need to synchronize setting this value with checking it because 564 // we check it in the complete path. We will not be about to present 565 // and completing the request in 2 simultaneous contexts. 566 // 567 m_Presented = TRUE; 568 } 569 570 VOID 571 AddIrpReference( 572 VOID 573 ); 574 575 VOID 576 ReleaseIrpReference( 577 VOID 578 ); 579 580 virtual 581 ULONG 582 AddRefOverride( 583 __in WDFOBJECT_OFFSET Offset, 584 __in PVOID Tag = NULL, 585 __in LONG Line = 0, 586 __in_opt PSTR File = NULL 587 ); 588 589 virtual 590 ULONG 591 ReleaseOverride( 592 __in WDFOBJECT_OFFSET Offset, 593 __in PVOID Tag = NULL, 594 __in LONG Line = 0, 595 __in_opt PSTR File = NULL 596 ); 597 598 __inline 599 CfxDevice* GetDevice(VOID)600 GetDevice( 601 VOID 602 ) 603 { 604 return m_Device; 605 } 606 607 __inline 608 BOOLEAN IsReserved()609 IsReserved( 610 ) 611 { 612 return m_Reserved; 613 } 614 615 __inline 616 VOID SetReserved()617 SetReserved( 618 ) 619 { 620 m_Reserved = TRUE; 621 } 622 623 __inline 624 VOID SetForwardProgressQueue(__in FxIoQueue * Queue)625 SetForwardProgressQueue( 626 __in FxIoQueue *Queue 627 ) 628 { 629 m_ForwardProgressQueue = Queue; 630 } 631 632 protected: 633 FxRequest( 634 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 635 __in MdIrp Irp, 636 __in FxRequestIrpOwnership Ownership, 637 __in FxRequestConstructorCaller Caller, 638 __in USHORT ObjectSize 639 ); 640 641 #if DBG 642 ~FxRequest( 643 VOID 644 ); 645 #endif // DBG 646 647 __inline 648 VOID SetCurrentQueue(__in FxIoQueue * Queue)649 SetCurrentQueue( 650 __in FxIoQueue *Queue 651 ) 652 { 653 m_IoQueue = Queue; 654 } 655 656 657 WDFMEMORY GetMemoryHandle(__in USHORT Offset)658 GetMemoryHandle( 659 __in USHORT Offset 660 ) 661 { 662 ULONG_PTR handle; 663 664 // 665 // The offset into this object must be self relative. 666 // 667 ASSERT(*((PUSHORT) WDF_PTR_ADD_OFFSET(this, Offset)) == Offset); 668 669 handle = (ULONG_PTR) WDF_PTR_ADD_OFFSET(this, Offset); 670 671 // 672 // Make sure initial value has the flag bits cleared. 673 // 674 ASSERT((handle & FxHandleFlagMask) == 0); 675 676 // 677 // We always apply the mask. 678 // 679 handle = handle ^ FxHandleValueMask; 680 681 // 682 // Make sure final value (before we set the flag) has the flag bits 683 // cleared. 684 // 685 ASSERT((handle & FxHandleFlagMask) == 0); 686 687 // 688 // This handle is an offset 689 handle |= FxHandleFlagIsOffset; 690 691 return (WDFMEMORY) handle; 692 } 693 694 _Must_inspect_result_ 695 virtual 696 NTSTATUS 697 QueryInterface( 698 __in FxQueryInterfaceParams* Params 699 ); 700 701 public: 702 // Factory functions to create FxRequest* objects 703 _Must_inspect_result_ 704 static 705 NTSTATUS 706 _CreateForPackage( 707 __in CfxDevice* Device, 708 __in PWDF_OBJECT_ATTRIBUTES RequestAttributes, 709 __in MdIrp Irp, 710 __deref_out FxRequest** Request 711 ); 712 713 _Must_inspect_result_ 714 static 715 NTSTATUS 716 _Create( 717 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 718 __in_opt PWDF_OBJECT_ATTRIBUTES RequestAttributes, 719 __in_opt MdIrp Irp, 720 __in_opt FxIoTarget* Target, 721 __in FxRequestIrpOwnership Ownership, 722 __in FxRequestConstructorCaller Caller, 723 __deref_out FxRequest** Request 724 ); 725 726 _Must_inspect_result_ 727 FxIoQueue* GetCurrentQueue(VOID)728 GetCurrentQueue( 729 VOID 730 ) 731 { 732 if(m_Completed) { 733 return NULL; 734 } 735 736 return m_IoQueue; 737 } 738 739 FxRequestCompletionState 740 SetCompletionState( 741 __in FxRequestCompletionState NewState 742 ); 743 744 VOID 745 __inline SetStatus(__in NTSTATUS Status)746 SetStatus( 747 __in NTSTATUS Status 748 ) 749 { 750 m_Irp.SetStatus(Status); 751 } 752 753 NTSTATUS 754 SetInformation( 755 __in ULONG_PTR Information 756 ); 757 758 ULONG_PTR 759 GetInformation( 760 VOID 761 ); 762 763 KPROCESSOR_MODE 764 GetRequestorMode( 765 VOID 766 ); 767 768 __inline 769 NTSTATUS Complete(__in NTSTATUS Status)770 Complete( 771 __in NTSTATUS Status 772 ) 773 { 774 CfxDevice* const fxDevice = GetDevice(); 775 776 // 777 // Complete the current request object. Can be called directly 778 // by the FxIoQueue to complete a request. 779 // 780 // When an FxRequest is completed, it is marked as completed, 781 // removed from any CSQ it may be a member of, and any registered 782 // callback functions are called. Then the NT IRP is completed, 783 // and the reference count on the object due to the callback routine 784 // is released if a callback routine was specified. 785 // 786 // Completing a request object can cause its reference 787 // count to go to zero, thus deleting it. So the caller 788 // must either reference it explicitly, or not touch it 789 // any more after calling complete. 790 // 791 792 DoTraceLevelMessage( 793 GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 794 "Completing WDFREQUEST 0x%p for IRP 0x%p with " 795 "Information 0x%I64x, %!STATUS!", 796 GetHandle(), m_Irp.GetIrp(), m_Irp.GetInformation(), Status); 797 798 if (fxDevice != NULL) { 799 SetPriorityBoost(fxDevice->GetDefaultPriorityBoost()); 800 } 801 else { 802 SetPriorityBoost(0); 803 } 804 805 return CompleteInternal(Status); 806 } 807 808 __inline 809 NTSTATUS CompleteWithInformation(__in NTSTATUS Status,__in ULONG_PTR Information)810 CompleteWithInformation( 811 __in NTSTATUS Status, 812 __in ULONG_PTR Information 813 ) 814 { 815 // 816 // Complete the request object. If the status is success, get the 817 // priority boost for the owning device type, and complete the request. 818 // 819 m_Irp.SetInformation(Information); 820 return Complete(Status); 821 } 822 823 __inline 824 NTSTATUS CompleteWithPriority(__in NTSTATUS Status,__in CCHAR PriorityBoost)825 CompleteWithPriority( 826 __in NTSTATUS Status, 827 __in CCHAR PriorityBoost 828 ) 829 { 830 // 831 // Complete the current request object. Can be called directly 832 // by the FxIoQueue to complete a request. 833 // 834 // When an FxRequest is completed, it is marked as completed, 835 // removed from any CSQ it may be a member of, and any registered 836 // callback functions are called. Then the NT IRP is completed, 837 // and the reference count on the object due to the callback routine 838 // is released if a callback routine was specified. 839 // 840 // Completing a request object can cause its reference 841 // count to go to zero, thus deleting it. So the caller 842 // must either reference it explicitly, or not touch it 843 // any more after calling complete. 844 // 845 846 DoTraceLevelMessage( 847 GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 848 "Completing WDFREQUEST 0x%p for IRP 0x%p with " 849 "Information 0x%I64x, %!STATUS!", 850 GetHandle(), m_Irp.GetIrp(), m_Irp.GetInformation(), Status); 851 852 SetPriorityBoost(PriorityBoost); 853 return CompleteInternal(Status); 854 } 855 856 // Do not specify argument names 857 FX_DECLARE_VF_FUNCTION( 858 VOID, 859 VerifyPreProcessSendAndForget 860 ); 861 862 VOID 863 PreProcessSendAndForget( 864 VOID 865 ); 866 867 VOID 868 PostProcessSendAndForget( 869 VOID 870 ); 871 872 NTSTATUS 873 GetStatus( 874 VOID 875 ); 876 877 _Must_inspect_result_ 878 NTSTATUS 879 GetParameters( 880 __out PWDF_REQUEST_PARAMETERS Parameters 881 ); 882 883 _Must_inspect_result_ 884 NTSTATUS 885 GetMemoryObject( 886 __deref_out IFxMemory** Memory, 887 __out PVOID* Buffer, 888 __out size_t* Length 889 ); 890 891 _Must_inspect_result_ 892 NTSTATUS 893 GetMdl( 894 __out PMDL *pMdl 895 ); 896 897 _Must_inspect_result_ 898 NTSTATUS 899 GetDeviceControlOutputMemoryObject( 900 __deref_out IFxMemory** MemoryObject, 901 __out PVOID* Buffer, 902 __out size_t* Length 903 ); 904 905 _Must_inspect_result_ 906 NTSTATUS 907 GetDeviceControlOutputMdl( 908 __out PMDL *pMdl 909 ); 910 911 // Do not specify argument names 912 FX_DECLARE_VF_FUNCTION( 913 NTSTATUS, 914 VerifyProbeAndLock 915 ); 916 917 _Must_inspect_result_ 918 NTSTATUS 919 ProbeAndLockForRead( 920 __in PVOID Buffer, 921 __in ULONG Length, 922 __deref_out FxRequestMemory** pMemoryObject 923 ); 924 925 _Must_inspect_result_ 926 NTSTATUS 927 ProbeAndLockForWrite( 928 __in PVOID Buffer, 929 __in ULONG Length, 930 __deref_out FxRequestMemory** pMemoryObject 931 ); 932 933 #if (FX_CORE_MODE == FX_CORE_USER_MODE) 934 _Must_inspect_result_ 935 NTSTATUS 936 Impersonate( 937 _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, 938 _In_ PFN_WDF_REQUEST_IMPERSONATE EvtRequestImpersonate, 939 _In_opt_ PVOID Context 940 ); 941 #endif 942 943 VOID SetImpersonationFlags(_In_ ULONG Flags)944 SetImpersonationFlags( 945 _In_ ULONG Flags 946 ) 947 { 948 #if (FX_CORE_MODE == FX_CORE_USER_MODE) 949 GetSubmitFxIrp()->GetIoIrp()->SetFlagsForNextStackLocation( 950 FxIrpStackFlagsFromSendFlags(Flags)); 951 #else 952 UNREFERENCED_PARAMETER(Flags); 953 #endif 954 } 955 956 FxIrp* GetFxIrp(VOID)957 GetFxIrp( 958 VOID 959 ) 960 { 961 return &m_Irp; 962 } 963 964 __inline 965 FxIoQueue* GetIoQueue(VOID)966 GetIoQueue( 967 VOID 968 ) 969 { 970 return m_IoQueue; 971 } 972 973 _Must_inspect_result_ 974 NTSTATUS GetIrp(__deref_out MdIrp * ppIrp)975 GetIrp( 976 __deref_out MdIrp* ppIrp 977 ) 978 { 979 if (GetDriverGlobals()->FxVerifierIO) { 980 NTSTATUS status; 981 KIRQL irql; 982 983 Lock(&irql); 984 985 status = VerifyRequestIsNotCompleted(GetDriverGlobals()); 986 if (!NT_SUCCESS(status)) { 987 *ppIrp = NULL; 988 status = STATUS_INVALID_DEVICE_REQUEST; 989 } 990 else { 991 *ppIrp = m_Irp.GetIrp(); 992 } 993 994 Unlock(irql); 995 996 return status; 997 } 998 else { 999 *ppIrp = m_Irp.GetIrp(); 1000 return STATUS_SUCCESS; 1001 } 1002 } 1003 1004 // 1005 // Return the FxFileObject if associated with this request 1006 // 1007 _Must_inspect_result_ 1008 NTSTATUS 1009 GetFileObject( 1010 __deref_out_opt FxFileObject** pFileObject 1011 ); 1012 1013 // 1014 // Get the IoStack location of the request. 1015 // 1016 // Since this returns the pointer to the underlying IRP 1017 // IO_STACK_LOCATION, it can not be called in a situation 1018 // which the request is completed out from underneath us. 1019 // 1020 // Note: Must implemention a version for the drivers use. 1021 // Must interact with completion events from the 1022 // driver due to cancel as well. 1023 // 1024 // 1025 PIO_STACK_LOCATION GetCurrentIrpStackLocation(VOID)1026 GetCurrentIrpStackLocation( 1027 VOID 1028 ) 1029 { 1030 if (GetDriverGlobals()->FxVerifierIO) { 1031 PIO_STACK_LOCATION ios; 1032 KIRQL irql; 1033 NTSTATUS status; 1034 1035 Lock(&irql); 1036 status = VerifyRequestIsNotCompleted(GetDriverGlobals()); 1037 if (!NT_SUCCESS(status)) { 1038 ios = NULL; 1039 } 1040 else { 1041 ios = m_Irp.GetCurrentIrpStackLocation(); 1042 } 1043 Unlock(irql); 1044 1045 return ios; 1046 } 1047 else { 1048 return m_Irp.GetCurrentIrpStackLocation(); 1049 } 1050 } 1051 1052 // 1053 // The following functions are to support use of 1054 // the Cancel Safe FxIrpQueue. 1055 // 1056 1057 // Do not specify argument names 1058 FX_DECLARE_VF_FUNCTION_P1( 1059 NTSTATUS, 1060 VerifyInsertIrpQueue, 1061 _In_ FxIrpQueue* 1062 ); 1063 1064 // 1065 // Insert the request in the supplied FxIrpQueue 1066 // and associated it with it. 1067 // 1068 _Must_inspect_result_ 1069 NTSTATUS 1070 InsertTailIrpQueue( 1071 __in FxIrpQueue* IrpQueue, 1072 __out_opt ULONG* pRequestCount 1073 ); 1074 1075 _Must_inspect_result_ 1076 NTSTATUS 1077 InsertHeadIrpQueue( 1078 __in FxIrpQueue* IrpQueue, 1079 __out_opt ULONG* pRequestCount 1080 ); 1081 1082 // 1083 // Remove it from the FxIrpQueue it is associated with. 1084 // 1085 // Returns STATUS_CANCELLED if the cancel routine has 1086 // fired and removed it from the queue first. 1087 // 1088 // 1089 _Must_inspect_result_ 1090 NTSTATUS 1091 RemoveFromIrpQueue( 1092 __in FxIrpQueue* IrpQueue 1093 ); 1094 1095 // 1096 // Mark that this request is no longer on the IrpQueue 1097 // 1098 __inline 1099 VOID MarkRemovedFromIrpQueue(VOID)1100 MarkRemovedFromIrpQueue( 1101 VOID 1102 ) 1103 { 1104 m_IrpQueue = NULL; 1105 return; 1106 } 1107 1108 // 1109 // Return the FxRequest's CsqContext address 1110 // 1111 __inline 1112 PMdIoCsqIrpContext GetCsqContext(VOID)1113 GetCsqContext( 1114 VOID 1115 ) 1116 { 1117 return &m_CsqContext; 1118 } 1119 1120 1121 // 1122 // Function to return an FxRequest from an FxIrpQueue 1123 // 1124 _Must_inspect_result_ 1125 static 1126 FxRequest* 1127 GetNextRequest( 1128 __in FxIrpQueue* IrpQueue 1129 ); 1130 1131 _Must_inspect_result_ 1132 static 1133 NTSTATUS 1134 GetNextRequest( 1135 __in FxIrpQueue* IrpQueue, 1136 __in_opt MdFileObject FileObject, 1137 __in_opt FxRequest* TagRequest, 1138 __deref_out FxRequest** ppOutRequest 1139 ); 1140 1141 // 1142 // Allow peeking at requests in the IrpQueue 1143 // 1144 _Must_inspect_result_ 1145 static 1146 NTSTATUS 1147 PeekRequest( 1148 __in FxIrpQueue* IrpQueue, 1149 __in_opt FxRequest* TagRequest, 1150 __in_opt MdFileObject FileObject, 1151 __out_opt PWDF_REQUEST_PARAMETERS Parameters, 1152 __deref_out FxRequest** ppOutRequest 1153 ); 1154 1155 // 1156 // Internal function to retrieve the FxRequest 1157 // structure from a pointer to its CsqContext 1158 // member. 1159 // 1160 __inline 1161 static 1162 FxRequest* RetrieveFromCsqContext(__in PMdIoCsqIrpContext pCsqContext)1163 RetrieveFromCsqContext( 1164 __in PMdIoCsqIrpContext pCsqContext 1165 ) 1166 { 1167 return CONTAINING_RECORD(pCsqContext, FxRequest, m_CsqContext); 1168 } 1169 1170 1171 __inline 1172 BOOLEAN IsInIrpQueue(__in FxIrpQueue * pIrpQueue)1173 IsInIrpQueue( 1174 __in FxIrpQueue* pIrpQueue 1175 ) 1176 { 1177 return pIrpQueue->IsIrpInQueue(GetCsqContext()); 1178 } 1179 1180 1181 // Do not specify argument names 1182 FX_DECLARE_VF_FUNCTION_P1( 1183 NTSTATUS, 1184 VerifyStopAcknowledge, 1185 _In_ BOOLEAN 1186 ); 1187 1188 VOID 1189 StopAcknowledge( 1190 __in BOOLEAN Requeue 1191 ); 1192 1193 __inline 1194 BOOLEAN IsPowerStopAcknowledged(VOID)1195 IsPowerStopAcknowledged( 1196 VOID 1197 ) 1198 { 1199 return ((m_PowerStopState == FxRequestPowerStopAcknowledged) 1200 || 1201 (m_PowerStopState == FxRequestPowerStopAcknowledgedWithRequeue))? TRUE : FALSE; 1202 } 1203 1204 __inline 1205 BOOLEAN IsPowerStopAcknowledgedWithRequeue(VOID)1206 IsPowerStopAcknowledgedWithRequeue( 1207 VOID 1208 ) 1209 { 1210 return (m_PowerStopState == FxRequestPowerStopAcknowledgedWithRequeue) ? TRUE : FALSE; 1211 } 1212 1213 VOID ClearPowerStopState(VOID)1214 ClearPowerStopState( 1215 VOID 1216 ) 1217 { 1218 m_PowerStopState = FxRequestPowerStopUnknown; 1219 } 1220 1221 // Do not specify argument names 1222 FX_DECLARE_VF_FUNCTION( 1223 VOID, 1224 VerifierBreakpoint_RequestEarlyDisposeDeferred 1225 ); 1226 1227 // Do not specify argument names 1228 FX_DECLARE_VF_FUNCTION( 1229 NTSTATUS, 1230 VerifyRequestIsDriverOwned 1231 ); 1232 1233 // Do not specify argument names 1234 FX_DECLARE_VF_FUNCTION( 1235 NTSTATUS, 1236 VerifyRequestIsCancelable 1237 ); 1238 1239 // Do not specify argument names 1240 FX_DECLARE_VF_FUNCTION( 1241 NTSTATUS, 1242 VerifyRequestIsNotCancelable 1243 ); 1244 1245 // Do not specify argument names 1246 FX_DECLARE_VF_FUNCTION( 1247 NTSTATUS, 1248 VerifyRequestIsInCallerContext 1249 ); 1250 1251 // Do not specify argument names 1252 FX_DECLARE_VF_FUNCTION( 1253 NTSTATUS, 1254 VerifyRequestIsInEvtIoStopContext 1255 ); 1256 1257 // Do not specify argument names 1258 FX_DECLARE_VF_FUNCTION( 1259 NTSTATUS, 1260 VerifyRequestIsNotCompleted 1261 ); 1262 1263 // Do not specify argument names 1264 FX_DECLARE_VF_FUNCTION( 1265 NTSTATUS, 1266 VerifyRequestIsTagRequest 1267 ); 1268 1269 // Do not specify argument names 1270 FX_DECLARE_VF_FUNCTION( 1271 NTSTATUS, 1272 VerifyRequestIsAllocatedFromIo 1273 ); 1274 1275 // Do not specify argument names 1276 FX_DECLARE_VF_FUNCTION( 1277 NTSTATUS, 1278 VerifyRequestIsCurrentStackValid 1279 ); 1280 1281 // Do not specify argument names 1282 FX_DECLARE_VF_FUNCTION( 1283 NTSTATUS, 1284 VerifyRequestCanBeCompleted 1285 ); 1286 1287 VOID 1288 FreeRequest( 1289 VOID 1290 ); 1291 1292 __inline 1293 VOID ClearFieldsForReuse(VOID)1294 ClearFieldsForReuse( 1295 VOID 1296 ) 1297 { 1298 m_SystemBuffer.ClearBufferMdl(); 1299 m_OutputBuffer.ClearBufferMdl(); 1300 1301 ASSERT(m_ForwardRequestToParent == FALSE); 1302 1303 FxRequestBase::ClearFieldsForReuse(); // __super call 1304 } 1305 1306 virtual 1307 ULONG 1308 Release( 1309 __in PVOID Tag, 1310 __in LONG Line, 1311 __in_opt PSTR File 1312 ); 1313 1314 __inline 1315 BOOLEAN IsRequestForwardedToParent(VOID)1316 IsRequestForwardedToParent( 1317 VOID 1318 ) 1319 { 1320 return m_ForwardRequestToParent; 1321 } 1322 1323 private: 1324 FX_DECLARE_VF_FUNCTION_P1( 1325 VOID, 1326 VerifyCompleteInternal, 1327 _In_ NTSTATUS 1328 ); 1329 1330 NTSTATUS 1331 CompleteInternalReserved( 1332 __in NTSTATUS Status, 1333 __in CCHAR PriorityBoost 1334 ); 1335 1336 NTSTATUS 1337 CompleteInternal( 1338 __in NTSTATUS Status 1339 ); 1340 1341 VOID 1342 PostProcessCompletion( 1343 __in FxRequestCompletionState State, 1344 __in FxIoQueue* Queue 1345 ); 1346 1347 VOID 1348 PostProcessCompletionForReserved( 1349 __in FxRequestCompletionState State, 1350 __in FxIoQueue* Queue 1351 ); 1352 1353 VOID 1354 PreProcessCompletionForDriverRequest( 1355 __in FxRequestCompletionState State, 1356 __in FxIoQueue* Queue 1357 ); 1358 1359 VOID 1360 PostProcessCompletionForDriverRequest( 1361 __in FxRequestCompletionState State, 1362 __in FxIoQueue* Queue 1363 ); 1364 1365 static 1366 VOID 1367 CheckAssumptions( 1368 VOID 1369 ); 1370 1371 VOID AssignMemoryBuffers(__in WDF_DEVICE_IO_TYPE IoType)1372 AssignMemoryBuffers( 1373 __in WDF_DEVICE_IO_TYPE IoType 1374 ) 1375 { 1376 1377 switch (m_Irp.GetMajorFunction()) { 1378 case IRP_MJ_DEVICE_CONTROL: 1379 case IRP_MJ_INTERNAL_DEVICE_CONTROL: 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 switch (m_Irp.GetParameterIoctlCodeBufferMethod()) { 1390 case METHOD_BUFFERED: 1391 // 1392 // Set the buffer in the memory interface. For kernel mode, 1393 // GetOutputBuffer is same as GetSystemBuffer, but for user-mode, 1394 // host provides separate buffers, so that input buffer can only be 1395 // read, and output buffer can only be written to. 1396 // 1397 m_SystemBuffer.SetBuffer(m_Irp.GetSystemBuffer()); 1398 m_OutputBuffer.SetBuffer(m_Irp.GetOutputBuffer()); 1399 break; 1400 1401 case METHOD_IN_DIRECT: 1402 // 1403 // InputBuffer is in SystemBuffer 1404 // OutputBuffer is in MdlAddress with read access 1405 // 1406 KMDF_ONLY_CODE_PATH_ASSERT(); 1407 m_SystemBuffer.SetBuffer(m_Irp.GetSystemBuffer()); 1408 break; 1409 1410 case METHOD_OUT_DIRECT: 1411 // 1412 // InputBuffer is in SystemBuffer 1413 // OutputBuffer is in MdlAddress with write access 1414 // 1415 KMDF_ONLY_CODE_PATH_ASSERT(); 1416 m_SystemBuffer.SetBuffer(m_Irp.GetSystemBuffer()); 1417 break; 1418 1419 case METHOD_NEITHER: 1420 // 1421 // Internal device controls are kernel mode to kernel mode, and deal 1422 // with direct unmapped pointers. 1423 // 1424 // In addition, a normal device control with 1425 // RequestorMode == KernelMode is also treated as kernel mode 1426 // to kernel mode since the I/O Manager will not generate requests 1427 // with this setting from a user mode request. 1428 // 1429 KMDF_ONLY_CODE_PATH_ASSERT(); 1430 if (m_Irp.GetMajorFunction() == IRP_MJ_INTERNAL_DEVICE_CONTROL || 1431 (m_Irp.GetRequestorMode() == KernelMode)) { 1432 m_SystemBuffer.SetBuffer( 1433 m_Irp.GetParameterIoctlType3InputBuffer() 1434 ); 1435 m_OutputBuffer.SetBuffer(m_Irp.GetUserBuffer()); 1436 } 1437 else { 1438 return; 1439 } 1440 break; 1441 } 1442 break; 1443 1444 case IRP_MJ_READ: 1445 case IRP_MJ_WRITE: 1446 switch (IoType) { 1447 case WdfDeviceIoBuffered: 1448 m_SystemBuffer.SetBuffer(m_Irp.GetSystemBuffer()); 1449 break; 1450 1451 case WdfDeviceIoNeither: 1452 KMDF_ONLY_CODE_PATH_ASSERT(); 1453 if (m_Irp.GetRequestorMode() == KernelMode) { 1454 m_SystemBuffer.SetBuffer(m_Irp.GetUserBuffer()); 1455 } 1456 else { 1457 return; 1458 } 1459 break; 1460 1461 default: 1462 return; 1463 } 1464 break; 1465 1466 default: 1467 return; 1468 } 1469 1470 if (m_SystemBuffer.IsBufferSet()) { 1471 m_RequestBaseStaticFlags |= FxRequestBaseStaticSystemBufferValid; 1472 } 1473 if (m_OutputBuffer.IsBufferSet()) { 1474 m_RequestBaseStaticFlags |= FxRequestBaseStaticOutputBufferValid; 1475 } 1476 } 1477 1478 1479 public: 1480 __inline 1481 VOID SetInternalContext(PVOID Context)1482 SetInternalContext( 1483 PVOID Context 1484 ) 1485 { 1486 ASSERT(NULL == m_InternalContext); 1487 m_InternalContext = Context; 1488 } 1489 1490 __inline 1491 PVOID GetInternalContext(VOID)1492 GetInternalContext( 1493 VOID 1494 ) 1495 { 1496 PVOID context; 1497 1498 context = m_InternalContext; 1499 m_InternalContext = NULL; 1500 1501 return context; 1502 } 1503 }; 1504 1505 class FxRequestFromLookaside : public FxRequest { 1506 1507 public: 1508 FxRequestFromLookaside( 1509 __in CfxDevice* Device, 1510 __in MdIrp Irp 1511 ); 1512 1513 PVOID 1514 operator new( 1515 __in size_t Size, 1516 __in CfxDevice* Device, 1517 __in_opt PWDF_OBJECT_ATTRIBUTES Attributes 1518 ); 1519 1520 protected: 1521 // 1522 // FxObject override 1523 // 1524 VOID 1525 SelfDestruct( 1526 VOID 1527 ); 1528 }; 1529 1530 #endif // _FXREQUEST_H_ 1531