1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxDevice.hpp 8 9 Abstract: 10 11 This is the definition of the FxDevice object. 12 13 Author: 14 15 16 17 Environment: 18 19 Both kernel and user mode 20 21 Revision History: 22 23 --*/ 24 25 #ifndef _FXDEVICE_H_ 26 #define _FXDEVICE_H_ 27 28 #include "fxcxdeviceinit.hpp" 29 #include "fxdeviceinit.hpp" 30 #include "fxtelemetry.hpp" 31 32 struct FxWdmDeviceExtension { 33 #if (FX_CORE_MODE == FX_CORE_USER_MODE) 34 WUDF_IO_REMOVE_LOCK IoRemoveLock; 35 #else 36 IO_REMOVE_LOCK IoRemoveLock; 37 #endif 38 ULONG RemoveLockOptionFlags; 39 }; 40 41 // 42 // The following enum is used in serializing packet based DMA transactions. 43 // According to the DDK docs: 44 // Only one DMA request can be queued for a device object at any 45 // one time. Therefore, the driver should not call AllocateAdapterChannel 46 // again for another DMA operation on the same device object until the 47 // AdapterControl routine has completed execution. In addition, 48 // a driver must not call AllocateAdapterChannel from within its 49 // AdapterControl routine. 50 // 51 // This is because when AllocateAdapterChannel blocks waiting for 52 // map registers, it obtains its wait context block from the device object. 53 // If AllocateAdapterChannel is then called through a different adapter 54 // object attached to the same device the wait block will be reused and the 55 // map register wait list will be corrupted. 56 // 57 // For this reason, we need to make sure that for a device used in creating 58 // DMA enablers, there can be only one packet base DMA transaction 59 // queued at any one time. 60 // 61 // In WDM, one can workaround this limitation by creating dummy deviceobject. 62 // We can also workaround this limitation by creating a control-device on the 63 // side for additional enabler objects. Since packet based multi-channel 64 // devices are rarity these days, IMO, we will defer this feature until there 65 // is a big demand for it. 66 // 67 enum FxDmaPacketTransactionStatus { 68 FxDmaPacketTransactionCompleted =0, 69 FxDmaPacketTransactionPending, 70 }; 71 72 // 73 // The following enum is used in determining whether the RemLock for a device 74 // object needs to be held while processing an IRP. For processing certain 75 // IRPs, it might not be necessary to hold the RemLock, but it might be 76 // necessary to just test whether the RemLock can be acquired and released. 77 // 78 enum FxDeviceRemLockAction { 79 FxDeviceRemLockNotRequired = 0, 80 FxDeviceRemLockRequired, 81 FxDeviceRemLockTestValid, 82 FxDeviceRemLockOptIn 83 }; 84 85 enum FxPropertyType { 86 FxDeviceProperty = 0, 87 FxInterfaceProperty, 88 }; 89 90 // 91 // This mask is used to validate the WdfDeviceWdmDispatchIrp's Flags. 92 // 93 #define FX_DISPATCH_IRP_TO_IO_QUEUE_FLAGS_MASK \ 94 (WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK |\ 95 WDF_DISPATCH_IRP_TO_IO_QUEUE_PREPROCESSED_IRP) 96 97 // 98 // The following inline functions are used for extracting the normalized file 99 // object class value and checking the file object class's flags. 100 // 101 WDF_FILEOBJECT_CLASS 102 __inline 103 FxFileObjectClassNormalize( 104 __in WDF_FILEOBJECT_CLASS FileObjectClass 105 ) 106 { 107 return (WDF_FILEOBJECT_CLASS)(FileObjectClass & ~WdfFileObjectCanBeOptional); 108 } 109 110 BOOLEAN 111 __inline 112 FxIsFileObjectOptional( 113 __in WDF_FILEOBJECT_CLASS FileObjectClass 114 ) 115 { 116 return (FileObjectClass & WdfFileObjectCanBeOptional) ? TRUE : FALSE; 117 } 118 119 // 120 // Base class for all devices. 121 // 122 class FxDeviceBase : public FxNonPagedObject, public IFxHasCallbacks { 123 124 protected: 125 FxDeviceBase( 126 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 127 __in FxDriver* Driver, 128 __in WDFTYPE Type, 129 __in USHORT Size 130 ); 131 132 ~FxDeviceBase( 133 VOID 134 ); 135 136 VOID 137 Init( 138 __in MdDeviceObject DeviceObject, 139 __in MdDeviceObject AttachedDevice, 140 __in MdDeviceObject PhysicalDevice 141 ); 142 143 public: 144 NTSTATUS 145 ConfigureConstraints( 146 __in_opt PWDF_OBJECT_ATTRIBUTES ObjectAttributes 147 ); 148 149 // begin IFxHasCallbacks overrides 150 VOID 151 GetConstraints( 152 __out_opt WDF_EXECUTION_LEVEL* ExecutionLevel, 153 __out_opt WDF_SYNCHRONIZATION_SCOPE* SynchronizationScope 154 ) ; 155 156 FxCallbackLock* 157 GetCallbackLockPtr( 158 __out_opt FxObject** LockObject 159 ); 160 // end IFxHasCallbacks overrides 161 162 __inline 163 FxDriver* 164 GetDriver( 165 VOID 166 ) 167 { 168 return m_Driver; 169 } 170 171 172 MdDeviceObject 173 __inline 174 GetDeviceObject( 175 VOID 176 ) 177 { 178 return m_DeviceObject.GetObject(); 179 } 180 181 __inline 182 MxDeviceObject* 183 GetMxDeviceObject( 184 VOID 185 ) 186 { 187 return &m_DeviceObject; 188 } 189 190 ULONG 191 __inline 192 GetDeviceObjectFlags( 193 VOID 194 ) 195 { 196 return m_DeviceObject.GetFlags(); 197 } 198 199 VOID 200 __inline 201 SetDeviceObjectFlags( 202 _In_ ULONG Flags 203 ) 204 { 205 m_DeviceObject.SetFlags(Flags); 206 } 207 208 MdDeviceObject 209 __inline 210 GetAttachedDevice( 211 VOID 212 ) 213 { 214 return m_AttachedDevice.GetObject(); 215 } 216 217 ULONG 218 __inline 219 GetAttachedDeviceObjectFlags( 220 VOID 221 ) 222 { 223 return m_AttachedDevice.GetFlags(); 224 } 225 226 MdDeviceObject 227 __inline 228 GetPhysicalDevice( 229 VOID 230 ) 231 { 232 return m_PhysicalDevice.GetObject(); 233 } 234 235 WDFDEVICE 236 __inline 237 GetHandle( 238 VOID 239 ) 240 { 241 return (WDFDEVICE) GetObjectHandle(); 242 } 243 244 virtual 245 _Must_inspect_result_ 246 NTSTATUS 247 AddIoTarget( 248 __inout FxIoTarget* IoTarget 249 ) 250 { 251 UNREFERENCED_PARAMETER(IoTarget); 252 253 // 254 // Intentionally does nothing 255 // 256 return STATUS_SUCCESS; 257 } 258 259 virtual 260 VOID 261 RemoveIoTarget( 262 __inout FxIoTarget* IoTarget 263 ) 264 { 265 // 266 // Intentionally does nothing 267 // 268 UNREFERENCED_PARAMETER(IoTarget); 269 } 270 271 virtual 272 _Must_inspect_result_ 273 NTSTATUS 274 AllocateEnumInfo( 275 VOID 276 ) 277 { 278 return STATUS_SUCCESS; 279 } 280 281 virtual 282 VOID 283 AddChildList( 284 __inout FxChildList* List 285 ) 286 { 287 // 288 // Intentionally does nothing 289 // 290 UNREFERENCED_PARAMETER(List); 291 } 292 293 virtual 294 VOID 295 RemoveChildList( 296 __inout FxChildList* List 297 ) 298 { 299 // 300 // Intentionally does nothing 301 // 302 UNREFERENCED_PARAMETER(List); 303 } 304 305 virtual 306 _Must_inspect_result_ 307 NTSTATUS 308 AllocateDmaEnablerList( 309 VOID 310 ) 311 { 312 return STATUS_SUCCESS; 313 } 314 315 virtual 316 VOID 317 AddDmaEnabler( 318 __inout FxDmaEnabler* Enabler 319 ) 320 { 321 // 322 // Intentionally does nothing 323 // 324 UNREFERENCED_PARAMETER(Enabler); 325 } 326 327 virtual 328 VOID 329 RemoveDmaEnabler( 330 __inout FxDmaEnabler* Enabler 331 ) 332 { 333 // 334 // Intentionally does nothing 335 // 336 UNREFERENCED_PARAMETER(Enabler); 337 } 338 339 virtual 340 VOID 341 SetDeviceTelemetryInfoFlags( 342 _In_ FxDeviceInfoFlags Flag 343 ) 344 { 345 // 346 // Intentionally does nothing 347 // 348 UNREFERENCED_PARAMETER(Flag); 349 } 350 351 __inline 352 _Must_inspect_result_ 353 NTSTATUS 354 AcquireDmaPacketTransaction( 355 VOID 356 ) 357 { 358 // 359 // Set the status to Pending only if the previous transaction is Completed. 360 // 361 if (InterlockedCompareExchange( 362 &m_DmaPacketTransactionStatus, 363 FxDmaPacketTransactionPending, 364 FxDmaPacketTransactionCompleted) == FxDmaPacketTransactionCompleted) { 365 return STATUS_SUCCESS; 366 } else { 367 return STATUS_WDF_BUSY; 368 } 369 } 370 371 __inline 372 VOID 373 ReleaseDmaPacketTransaction( 374 VOID 375 ) 376 { 377 LONG val; 378 379 val = InterlockedExchange(&m_DmaPacketTransactionStatus, 380 FxDmaPacketTransactionCompleted); 381 382 ASSERT(val == FxDmaPacketTransactionPending); // To catch double release 383 UNREFERENCED_PARAMETER(val); 384 } 385 386 VOID 387 AddToDisposeList( 388 __inout FxObject* Object 389 ) 390 { 391 m_DisposeList->Add(Object); 392 } 393 394 // begin FxObject overrides 395 _Must_inspect_result_ 396 NTSTATUS 397 QueryInterface( 398 __inout FxQueryInterfaceParams* Params 399 ); 400 // end FxObject overrides 401 402 static 403 FxDeviceBase* 404 _SearchForDevice( 405 __in FxObject* Object, 406 __out_opt IFxHasCallbacks** Callbacks 407 ); 408 409 static 410 FxDeviceBase* 411 _SearchForDevice( 412 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 413 __in_opt PWDF_OBJECT_ATTRIBUTES Attributes 414 ); 415 416 _Must_inspect_result_ 417 NTSTATUS 418 QueryForInterface( 419 __in const GUID* InterfaceType, 420 __out PINTERFACE Interface, 421 __in USHORT Size, 422 __in USHORT Version, 423 __in PVOID InterfaceSpecificData, 424 __in_opt MdDeviceObject TargetDevice = NULL 425 ); 426 427 __inline 428 MdDeviceObject 429 GetAttachedDeviceReference( 430 VOID 431 ) 432 { 433 return Mx::MxGetAttachedDeviceReference(m_DeviceObject.GetObject()); 434 } 435 436 virtual 437 FxIoTarget* 438 GetDefaultIoTarget( 439 VOID 440 ) 441 { 442 return NULL; 443 } 444 445 _Must_inspect_result_ 446 NTSTATUS 447 AllocateTarget( 448 _Out_ FxIoTarget** Target, 449 _In_ BOOLEAN SelfTarget 450 ); 451 452 // 453 // Note: these fields are carefully aligned to minimize space. If you add 454 // additional fields make sure to insert them correctly. Always 455 // double check your assumptions by loading the amd64 image and 456 // comparing the size of this type before and after. For example the 457 // m_RequestLookasideList is aligned on SYSTEM_CACHE_ALIGNMENT_SIZE (64/128), 458 // a simple change can increase the size by 64/128 bytes. 459 // 460 461 public: 462 // 463 // This is used to defer items that must be cleaned up at passive 464 // level, and FxDevice waits on this list to empty in DeviceRemove. 465 // 466 FxDisposeList* m_DisposeList; 467 468 protected: 469 FxDriver* m_Driver; 470 471 MxDeviceObject m_DeviceObject; 472 MxDeviceObject m_AttachedDevice; 473 MxDeviceObject m_PhysicalDevice; 474 475 FxCallbackLock* m_CallbackLockPtr; 476 FxObject* m_CallbackLockObjectPtr; 477 478 WDF_EXECUTION_LEVEL m_ExecutionLevel; 479 WDF_SYNCHRONIZATION_SCOPE m_SynchronizationScope; 480 481 // 482 // Used to serialize packet dma transactions on this device. 483 // 484 LONG m_DmaPacketTransactionStatus; 485 }; 486 487 class FxDevice : public FxDeviceBase { 488 friend VOID GetTriageInfo(VOID); 489 friend class FxDriver; 490 friend class FxIrp; 491 friend class FxFileObject; 492 friend class FxPkgPnp; 493 494 // 495 // Note: these fields are carefully aligned to minimize space. If you add 496 // additional fileds make sure to insert them correctly. Always 497 // double check your assumptions by loading the amd64 image and 498 // comparing the size of this type before and after. For example the 499 // m_RequestLookasideList is aligned on SYSTEM_CACHE_ALIGNMENT_SIZE (64/128), 500 // a simple change can increase the size by 64/128 bytes. 501 // 502 503 private: 504 // 505 // Maintain the current device states. 506 // 507 WDF_DEVICE_PNP_STATE m_CurrentPnpState; 508 WDF_DEVICE_POWER_STATE m_CurrentPowerState; 509 WDF_DEVICE_POWER_POLICY_STATE m_CurrentPowerPolicyState; 510 511 // 512 // Store the IO type for read/write 513 // 514 WDF_DEVICE_IO_TYPE m_ReadWriteIoType; 515 516 // 517 // Bit-flags, see FxDeviceCallbackFlags for definitions. 518 // 519 BYTE m_CallbackFlags; 520 521 // TRUE if a Filter 522 BOOLEAN m_Filter; 523 524 // 525 // If TRUE, DO_POWER_PAGABLE can be set on m_DeviceObject->Flags if we are 526 // not in a special usage path. 527 // 528 // ***Ignored for filters*** 529 // 530 BOOLEAN m_PowerPageableCapable; 531 532 // 533 // TRUE if the parent is removed while the child is still around 534 // 535 BOOLEAN m_ParentWaitingOnChild; 536 537 // 538 // TRUE if the device only allows one create to succeed at any given time 539 // 540 BOOLEAN m_Exclusive; 541 542 // 543 // More deterministic the m_PkgPnp == NULL since m_PkgPnp can be == NULL 544 // if there is an allocation failure and during deletion due to insufficient 545 // resources we need to know if the device is legacy or not. 546 // 547 BOOLEAN m_Legacy; 548 549 // 550 // If TRUE, m_DeviceObject was deleted in FxDevice::DeleteObject and should 551 // not be deleted again later in the destroy path. 552 // 553 BOOLEAN m_DeviceObjectDeleted; 554 555 // 556 // This boost will be used in IoCompleteRequest 557 // for read, write and ioctl requests if the client driver 558 // completes the request without specifying the boost. 559 // 560 // 561 CHAR m_DefaultPriorityBoost; 562 563 static const CHAR m_PriorityBoosts[]; 564 565 public: 566 // 567 // Track the parent if applicable 568 // 569 CfxDevice *m_ParentDevice; 570 571 // 572 // Properties used during Device Creation 573 // 574 575 // 576 // Store the device name that is used during device creation. 577 // 578 UNICODE_STRING m_DeviceName; 579 580 UNICODE_STRING m_SymbolicLinkName; 581 582 // 583 // Store the name of the resource that is used to store the MOF data 584 // 585 UNICODE_STRING m_MofResourceName; 586 587 // 588 // When reporting a PDO via query device relations, there is a period of 589 // time where it is an "official" PDO as recognized by the pnp subsystem. 590 // In that period of time, we cannot use the soon to be PDO in any export 591 // which expects a PDO as an input parameter. Once this is set to TRUE, 592 // the PDO can be used for such exports. 593 // 594 // No need to use a lock when comparing against this field. Once set, it 595 // will never revert back to FALSE. 596 // 597 // This field is always TRUE for FDOs (in relation to the PDO for its stack). 598 // 599 BOOLEAN m_PdoKnown; 600 601 // 602 // If TRUE, then create/cleanup/close are forwarded down the stack 603 // If FALSE, then create/cleanup/close are completed at this device 604 // 605 BOOLEAN m_AutoForwardCleanupClose; 606 607 // 608 // If TRUE, an Io Target to the client itself is created to support 609 // Self Io Targets. 610 // 611 BOOLEAN m_SelfIoTargetNeeded; 612 613 private: 614 // 615 // bit-map of device info for Telemetry 616 // 617 USHORT m_DeviceTelemetryInfoFlags; 618 619 public: 620 621 WDF_FILEOBJECT_CLASS m_FileObjectClass; 622 623 FxSpinLockTransactionedList m_IoTargetsList; 624 625 // 626 // We'll maintain the prepreocess table "per device" so that it is possible 627 // to have different callbacks for each device. 628 // Note that each device may be associted with multiple class extension in the future. 629 // 630 LIST_ENTRY m_PreprocessInfoListHead; 631 632 // 633 // Optional, list of additional class extension settings. 634 // 635 LIST_ENTRY m_CxDeviceInfoListHead; 636 637 protected: 638 639 // 640 // This is used by the FxFileObject class to manage 641 // the list of FxFileObject's for this FxDevice 642 // 643 LIST_ENTRY m_FileObjectListHead; 644 645 // 646 // Lookaside list to allocate FxRequests from 647 // 648 NPAGED_LOOKASIDE_LIST m_RequestLookasideList; 649 650 // 651 // Total size of an FxRequest + driver context LookasideList element. 652 // 653 size_t m_RequestLookasideListElementSize; 654 655 // 656 // Object attributes to apply to each FxRequest* returned by 657 // m_RequestLookasideList 658 // 659 WDF_OBJECT_ATTRIBUTES m_RequestAttributes; 660 661 public: 662 663 // 664 // This is the set of packages used by this device. I am simply using 665 // FxPackage pointers rather than using the actual types because I want 666 // to allow fredom for FDOs, PDOs, and control objects to use 667 // differnet packages. 668 // 669 FxPkgIo* m_PkgIo; 670 FxPkgPnp* m_PkgPnp; 671 FxPkgGeneral* m_PkgGeneral; 672 FxWmiIrpHandler* m_PkgWmi; 673 FxDefaultIrpHandler* m_PkgDefault; 674 675 // 676 // Note on approaches to having mode-agnoctic code that works for KM and UM 677 // and avoids code with lots of #ifdef which becomes a maintenance nightmare. 678 // To avoid #ifdef such as below, one approach would have been to have a 679 // base class with common data members and virtual funtions , and have 680 // derived classes for km and um,each having data members specific to their 681 // mode, implementing virtual funcions in mode specific manner. This 682 // approach was not taken for following reasons: 683 // 684 // 1. Avoid confusion between logical hierarchy and organizational hierarchy 685 // of objects. E.g. fdo and pdo package is derived from pnp package (logical 686 // hierarchy). However, both pdo and fdo package can also be organized into 687 // fdokm/fdoum deriving from fdo, and pdokm/pdoum deriving from pdo for km 688 // and um flavors, and that would be organizational hierarchy. Mixing these 689 // two approaches may create more confusion. If we were to extend the 690 // classes in future (for whatever reason), this may become more complex. 691 // 692 // 2. Even with organizational hierarchy, we need to have #ifdef at the 693 // point of creation. 694 // 695 // Luckily, we don't have many objects that need to be have mode specific 696 // data members (currently only FxDevice and interrupt to some extent). 697 // Note that member functions are already implemented in mode specific 698 // manner, for example, FxDevice::CreateDevice is implemented for UM and KM 699 // in FxDeviceUm.cpp and FxDeviceKm.cpp. So #ifdef usage is not a whole lot 700 // but we can definitely improve on it. 701 // 702 // With the current approach, we can do better by avoiding #ifdef as much as 703 // possible. We can achieve that with better abstraction, but also having 704 // host provide more interfaces so as to mimic closely those interfaces 705 // that kernel provides would also help (this way framework has to maintain 706 // less info, because it can always get it from host the way kernel 707 // framework would). 708 // 709 #if (FX_CORE_MODE == FX_CORE_USER_MODE) 710 public: 711 // 712 // On failed create during AddDevice, KMDF sends a simulated remove event 713 // to pnp state machine and thereafter detaches from stack so that windows 714 // I/O manager can't send a remove irp. UMDF imitates windows I/O manager 715 // in that when AddDevice sent by host is failed by driver, host sends a 716 // simulated remove irp to Fx so that it can cleanup. 717 // 718 // This causes a conflict in merged code because for UMDF, Fx doesn't 719 // detach from stack as part of remove event (since lifetime of umdf stack 720 721 // is controlled by host including detach and deletiton), so unless we 722 // prevent, Fx will end up processing remove event twice, once by Pnp sm's 723 // simulated event and another by host simulated remove irp. 724 // 725 // The solution is to allow one remove event to be processed and that would 726 // be Fx's remove event (to minimize disparity between KM and UM Fx). The 727 // field below tracks the fact that create failed and allows the Fx remove 728 // event to be processed and then also allows the device object to detach 729 // before returning from failure so that host is not able to send simulated 730 // remove to the device. 731 // 732 BOOLEAN m_CleanupFromFailedCreate; 733 734 // 735 // This object implements the IFxMessageDispatch that contains entry points 736 // to driver, and is used by host to dispatch irp and other messages. 737 // 738 FxMessageDispatch* m_Dispatcher; 739 740 // 741 //Weak reference to host side device stack 742 // 743 IWudfDeviceStack* m_DevStack; 744 745 // 746 // PnP devinode hw key handle 747 // 748 HKEY m_PdoDevKey; 749 750 // 751 // Device key registry path 752 // 753 PWSTR m_DeviceKeyPath; 754 755 // 756 // Kernel redirector's side object name. 757 // 758 PWSTR m_KernelDeviceName; 759 760 // 761 // PDO Instance ID 762 // 763 PWSTR m_DeviceInstanceId; 764 765 // 766 // The retrieval mode and i/o type preferences requested 767 // by this device. Note that ReadWriteIoType is common to both KMDF and UMDF 768 // so no new UM-specific field is required. 769 // 770 UMINT::WDF_DEVICE_IO_BUFFER_RETRIEVAL m_RetrievalMode; 771 WDF_DEVICE_IO_TYPE m_IoctlIoType; 772 ULONG m_DirectTransferThreshold; 773 774 // 775 // Tells whether hardware access is allowed. 776 // 777 WDF_DIRECT_HARDWARE_ACCESS_TYPE m_DirectHardwareAccess; 778 779 // 780 // Tells whether hardware register read/write is done using user-mode 781 // mapped virtual addresses 782 // 783 WDF_REGISTER_ACCESS_MODE_TYPE m_RegisterAccessMode; 784 785 // 786 // File object policy set through INF directive 787 // 788 WDF_FILE_OBJECT_POLICY_TYPE m_FileObjectPolicy; 789 790 // 791 // Fs context use policy set through INF directive 792 // 793 WDF_FS_CONTEXT_USE_POLICY_TYPE m_FsContextUsePolicy; 794 795 // 796 // Thread pool for interrupt servicing 797 // 798 FxInterruptThreadpool* m_InteruptThreadpool; 799 800 #endif // (FX_CORE_MODE == FX_CORE_USER_MODE) 801 802 private: 803 // 804 // A method called by the constructor(s) to initialize the device state. 805 // 806 VOID 807 SetInitialState( 808 VOID 809 ); 810 811 _Must_inspect_result_ 812 NTSTATUS 813 PreprocessIrp( 814 __in MdIrp Irp 815 ); 816 817 _Must_inspect_result_ 818 NTSTATUS 819 DeleteDeviceFromFailedCreateNoDelete( 820 __in NTSTATUS FailedStatus, 821 __in BOOLEAN UseStateMachine 822 ); 823 824 VOID 825 SetFilterIoType( 826 VOID 827 ); 828 829 static 830 MdCompletionRoutineType 831 _CompletionRoutineForRemlockMaintenance; 832 833 static 834 _Must_inspect_result_ 835 NTSTATUS 836 _AcquireOptinRemoveLock( 837 __in MdDeviceObject DeviceObject, 838 __in MdIrp Irp 839 ); 840 841 VOID 842 DestructorInternal( 843 VOID 844 ); 845 846 NTSTATUS 847 WmiPkgRegister( 848 VOID 849 ); 850 851 VOID 852 WmiPkgDeregister( 853 VOID 854 ); 855 856 VOID 857 WmiPkgCleanup( 858 VOID 859 ); 860 861 public: 862 863 FxDevice( 864 __in FxDriver *ArgDriver 865 ); 866 867 ~FxDevice( 868 VOID 869 ); 870 871 static 872 _Must_inspect_result_ 873 NTSTATUS 874 _Create( 875 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 876 __in PWDFDEVICE_INIT* DeviceInit, 877 __in_opt PWDF_OBJECT_ATTRIBUTES DeviceAttributes, 878 __out FxDevice** Device 879 ); 880 881 _Must_inspect_result_ 882 NTSTATUS 883 DeleteDeviceFromFailedCreate( 884 __in NTSTATUS FailedStatus, 885 __in BOOLEAN UseStateMachine 886 ); 887 888 __inline 889 FxPackage* 890 GetDispatchPackage( 891 __in UCHAR MajorFunction 892 ) 893 { 894 switch (MajorFunction) { 895 case IRP_MJ_CREATE: 896 case IRP_MJ_CLOSE: 897 case IRP_MJ_CLEANUP: 898 case IRP_MJ_SHUTDOWN: 899 return (FxPackage*) m_PkgGeneral; 900 901 case IRP_MJ_READ: 902 case IRP_MJ_WRITE: 903 case IRP_MJ_DEVICE_CONTROL: 904 case IRP_MJ_INTERNAL_DEVICE_CONTROL: 905 return (FxPackage*) m_PkgIo; 906 907 case IRP_MJ_SYSTEM_CONTROL: 908 return (FxPackage*) m_PkgWmi; 909 910 case IRP_MJ_PNP: 911 case IRP_MJ_POWER: 912 if (m_PkgPnp != NULL) { 913 return (FxPackage*) m_PkgPnp; 914 } 915 else { 916 return (FxPackage*) m_PkgDefault; 917 } 918 break; 919 920 default: 921 return (FxPackage*) m_PkgDefault; 922 } 923 } 924 925 MdRemoveLock 926 GetRemoveLock( 927 VOID 928 ); 929 930 static 931 FxDeviceRemLockAction 932 __inline 933 _RequiresRemLock( 934 __in UCHAR MajorCode, 935 __in UCHAR MinorCode 936 ) 937 { 938 switch (MajorCode) { 939 // 940 // We require remove locks for power irps because they can show 941 // up after the device has been removed if the Power subysystem has 942 // taken a reference on the device object that raced with the 943 // remove irp (or if we are attached above the power policy owner 944 // and the power policy owner requests a power irp during remove 945 // processing. 946 // 947 // What it boils down to is that we do it for power because 948 // that is the only valid irp which can be sent with an outstanding 949 // reference w/out coordination to the device's pnp state. We 950 // assume that for all other irps, the sender has synchronized with 951 // the pnp state of the device. 952 // 953 // We also acquire the remove lock for WMI IRPs because they can 954 // come into the stack while we are processing a remove. For 955 // instance, a WMI irp can come into the stack to the attached 956 // device before it has a change to process the remove device and 957 // unregister with WMI. 958 // 959 // PNP irps can come in at any time as well. For instance, query 960 // device relations for removal or ejection relations can be sent 961 // at any time (and there are pnp stress tests which send them 962 // during remove). 963 // 964 case IRP_MJ_PNP: 965 // 966 // We special case remove device and only acquire the remove lock 967 // in the minor code handler itself. If handled remove device in 968 // the normal way and there was a preprocess routine for it, then 969 // we could deadlock if the irp was dispatched back to KMDF in the 970 // preprocess routine with an extra outstandling remlock acquire 971 // (which won't be released until the preprocess routine returns, 972 // which will be too late). 973 // 974 if (MinorCode == IRP_MN_REMOVE_DEVICE) { 975 return FxDeviceRemLockTestValid; 976 } 977 case IRP_MJ_POWER: 978 case IRP_MJ_SYSTEM_CONTROL: 979 return FxDeviceRemLockRequired; 980 981 default: 982 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 983 return FxDeviceRemLockOptIn; 984 #else 985 // 986 // There is no forseeable scenario where a UMDF driver would need to 987 // need to support remove lock for IO IRPs. While this ifdef can be safely 988 // removed and UMDF can also return FxDeviceRemLockOptIn, that is 989 // being avoided here so that the caller does not need to test the 990 // remove lock flags for IO which would never be set. 991 // 992 return FxDeviceRemLockNotRequired; 993 #endif 994 } 995 } 996 997 static 998 FxDevice* 999 GetFxDevice( 1000 __in MdDeviceObject DeviceObject 1001 ); 1002 1003 MdDeviceObject 1004 __inline 1005 GetSafePhysicalDevice( 1006 VOID 1007 ) 1008 { 1009 // 1010 // Makes sure that the PDO we think we have is 1011 // 1) reported to pnp (m_PdoKnown check) 1012 // 2) actually there (m_PhysicalDevice != NULL check) 1013 // 1014 if (m_PdoKnown && m_PhysicalDevice.GetObject() != NULL) { 1015 return m_PhysicalDevice.GetObject(); 1016 } 1017 else { 1018 return NULL; 1019 } 1020 } 1021 1022 static 1023 _Must_inspect_result_ 1024 NTSTATUS 1025 STDCALL 1026 Dispatch( 1027 __in MdDeviceObject DeviceObject, 1028 __in MdIrp OriginalIrp 1029 ); 1030 1031 #if (FX_CORE_MODE==FX_CORE_USER_MODE) 1032 static 1033 VOID 1034 DispatchUm( 1035 _In_ MdDeviceObject DeviceObject, 1036 _In_ MdIrp Irp, 1037 _In_opt_ IUnknown* Context 1038 ); 1039 1040 static 1041 VOID 1042 DispatchWithLockUm( 1043 _In_ MdDeviceObject DeviceObject, 1044 _In_ MdIrp Irp, 1045 _In_opt_ IUnknown* Context 1046 ); 1047 1048 VOID 1049 SetInterruptThreadpool( 1050 _In_ FxInterruptThreadpool* Pool 1051 ) 1052 { 1053 m_InteruptThreadpool = Pool; 1054 } 1055 1056 FxInterruptThreadpool* 1057 GetInterruptThreadpool( 1058 VOID 1059 ) 1060 { 1061 return m_InteruptThreadpool; 1062 } 1063 1064 #endif // (FX_CORE_MODE == FX_CORE_USER_MODE) 1065 1066 static 1067 _Must_inspect_result_ 1068 NTSTATUS 1069 STDCALL 1070 DispatchWithLock( 1071 __in MdDeviceObject DeviceObject, 1072 __in MdIrp OriginalIrp 1073 ); 1074 1075 _Must_inspect_result_ 1076 NTSTATUS 1077 DispatchPreprocessedIrp( 1078 __in MdIrp Irp, 1079 __in PVOID DispatchContext 1080 ); 1081 1082 __inline 1083 WDF_DEVICE_IO_TYPE 1084 GetIoType( 1085 VOID 1086 ) 1087 { 1088 return m_ReadWriteIoType; 1089 } 1090 1091 __inline 1092 WDF_DEVICE_IO_TYPE 1093 GetIoTypeForReadWriteBufferAccess( 1094 VOID 1095 ) 1096 { 1097 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 1098 return m_ReadWriteIoType; 1099 #else 1100 // 1101 // For UM, both buffer-copy and direct-access i/o buffer access types 1102 // follow the same storage and retrieval model in internal structures 1103 // as in buffered I/O so always return WdfDeviceIoBuffered. 1104 // 1105 return WdfDeviceIoBuffered; 1106 #endif 1107 } 1108 1109 __inline 1110 CHAR 1111 GetDefaultPriorityBoost( 1112 VOID 1113 ) 1114 { 1115 return m_DefaultPriorityBoost; 1116 } 1117 1118 // 1119 // Return FileObjectClass 1120 // 1121 __inline 1122 WDF_FILEOBJECT_CLASS 1123 GetFileObjectClass( 1124 VOID 1125 ) 1126 { 1127 return m_FileObjectClass; 1128 } 1129 1130 // 1131 // Configuration time fileobject support setting 1132 // 1133 __inline 1134 VOID 1135 SetFileObjectClass( 1136 __in WDF_FILEOBJECT_CLASS FileObjectClass 1137 ) 1138 { 1139 m_FileObjectClass = FileObjectClass; 1140 } 1141 1142 VOID 1143 InstallPackage( 1144 __inout FxPackage *Package 1145 ); 1146 1147 __inline 1148 WDF_DEVICE_PNP_STATE 1149 GetDevicePnpState( 1150 ) 1151 { 1152 return m_CurrentPnpState; 1153 } 1154 1155 __inline 1156 WDF_DEVICE_POWER_STATE 1157 GetDevicePowerState( 1158 ) 1159 { 1160 return m_CurrentPowerState; 1161 } 1162 1163 __inline 1164 WDF_DEVICE_POWER_POLICY_STATE 1165 GetDevicePowerPolicyState( 1166 ) 1167 { 1168 return m_CurrentPowerPolicyState; 1169 } 1170 1171 __inline 1172 VOID 1173 SetDevicePnpState( 1174 __in WDF_DEVICE_PNP_STATE DeviceState 1175 ) 1176 { 1177 m_CurrentPnpState = DeviceState; 1178 } 1179 1180 __inline 1181 VOID 1182 SetDevicePowerState( 1183 __in WDF_DEVICE_POWER_STATE DeviceState 1184 ) 1185 { 1186 m_CurrentPowerState = DeviceState; 1187 } 1188 1189 __inline 1190 VOID 1191 SetDevicePowerPolicyState( 1192 __in WDF_DEVICE_POWER_POLICY_STATE DeviceState 1193 ) 1194 { 1195 m_CurrentPowerPolicyState = DeviceState; 1196 } 1197 1198 __inline 1199 BOOLEAN 1200 IsPnp( 1201 VOID 1202 ) 1203 { 1204 return m_PkgPnp != NULL ? TRUE : FALSE; 1205 } 1206 1207 __inline 1208 BOOLEAN 1209 IsLegacy( 1210 VOID 1211 ) 1212 { 1213 return m_Legacy; 1214 } 1215 1216 __inline 1217 BOOLEAN 1218 IsExclusive( 1219 VOID 1220 ) 1221 { 1222 return m_Exclusive; 1223 } 1224 1225 __inline 1226 BOOLEAN 1227 IsFdo( 1228 VOID 1229 ) 1230 { 1231 return m_PkgPnp->GetType() == FX_TYPE_PACKAGE_FDO; 1232 } 1233 1234 __inline 1235 FxPkgFdo* 1236 GetFdoPkg( 1237 VOID 1238 ) 1239 { 1240 return (FxPkgFdo*) m_PkgPnp; 1241 } 1242 1243 __inline 1244 BOOLEAN 1245 IsPdo( 1246 VOID 1247 ) 1248 { 1249 return (IsPnp() && m_PkgPnp->GetType() == FX_TYPE_PACKAGE_PDO); 1250 } 1251 1252 __inline 1253 FxPkgPdo* 1254 GetPdoPkg( 1255 VOID 1256 ) 1257 { 1258 return (FxPkgPdo*) m_PkgPnp; 1259 } 1260 1261 _Must_inspect_result_ 1262 NTSTATUS 1263 CreateDevice( 1264 __in PWDFDEVICE_INIT DeviceInit 1265 ); 1266 1267 __inline 1268 VOID 1269 SetParentWaitingOnRemoval( 1270 VOID 1271 ) 1272 { 1273 m_ParentWaitingOnChild = TRUE; 1274 } 1275 1276 // 1277 1278 // There are really three steps in device creation. 1279 // 1280 // - Creating the device 1281 // - Creating the device object that goes with the device (Initialize) 1282 // - Finilizing the initialization after packages are installed, attached, 1283 // etc. 1284 1285 1286 1287 1288 1289 VOID 1290 FinishInitializing( 1291 VOID 1292 ); 1293 1294 VOID 1295 Destroy( 1296 VOID 1297 ); 1298 1299 // <begin> FxObject overrides 1300 virtual 1301 VOID 1302 DeleteObject( 1303 VOID 1304 ); 1305 1306 virtual 1307 BOOLEAN 1308 Dispose( 1309 VOID 1310 ); 1311 // <end> FxObject overrides 1312 1313 __inline 1314 PWDF_OBJECT_ATTRIBUTES 1315 GetRequestAttributes( 1316 VOID 1317 ) 1318 { 1319 return &m_RequestAttributes; 1320 } 1321 1322 PVOID 1323 AllocateRequestMemory( 1324 __in_opt PWDF_OBJECT_ATTRIBUTES Attributes 1325 ); 1326 1327 VOID 1328 FreeRequestMemory( 1329 __in FxRequest* Request 1330 ); 1331 1332 // begin FxDeviceBase overrides 1333 virtual 1334 _Must_inspect_result_ 1335 NTSTATUS 1336 AddIoTarget( 1337 __inout FxIoTarget* IoTarget 1338 ); 1339 1340 virtual 1341 VOID 1342 RemoveIoTarget( 1343 __inout FxIoTarget* IoTarget 1344 ); 1345 1346 virtual 1347 _Must_inspect_result_ 1348 NTSTATUS 1349 AllocateEnumInfo( 1350 VOID 1351 ); 1352 1353 virtual 1354 VOID 1355 AddChildList( 1356 __inout FxChildList* List 1357 ); 1358 1359 virtual 1360 VOID 1361 RemoveChildList( 1362 __inout FxChildList* List 1363 ); 1364 1365 virtual 1366 _Must_inspect_result_ 1367 NTSTATUS 1368 AllocateDmaEnablerList( 1369 VOID 1370 ); 1371 1372 virtual 1373 VOID 1374 AddDmaEnabler( 1375 __inout FxDmaEnabler* Enabler 1376 ); 1377 1378 virtual 1379 VOID 1380 RemoveDmaEnabler( 1381 __inout FxDmaEnabler* Enabler 1382 ); 1383 1384 virtual 1385 FxIoTarget* 1386 GetDefaultIoTarget( 1387 VOID 1388 ); 1389 1390 FxIoTargetSelf* 1391 GetSelfIoTarget( 1392 VOID 1393 ); 1394 1395 virtual 1396 _Must_inspect_result_ 1397 NTSTATUS 1398 QueryInterface( 1399 __inout FxQueryInterfaceParams* Params 1400 ); 1401 // end FxDeviceBase overrides 1402 1403 // 1404 // Filter Driver Support 1405 // 1406 __inline 1407 BOOLEAN 1408 IsFilter() 1409 { 1410 return m_Filter; 1411 } 1412 1413 _Must_inspect_result_ 1414 NTSTATUS 1415 SetFilter( 1416 __in BOOLEAN Value 1417 ); 1418 1419 __inline 1420 BOOLEAN 1421 IsPowerPageableCapable( 1422 VOID 1423 ) 1424 { 1425 return m_PowerPageableCapable; 1426 } 1427 1428 _Must_inspect_result_ 1429 NTSTATUS 1430 Initialize( 1431 __in PWDFDEVICE_INIT DeviceInit, 1432 __in_opt PWDF_OBJECT_ATTRIBUTES DeviceAttributes 1433 ); 1434 1435 VOID 1436 ConfigureAutoForwardCleanupClose( 1437 __in PWDFDEVICE_INIT DeviceInit 1438 ); 1439 1440 _Must_inspect_result_ 1441 NTSTATUS 1442 PostInitialize( 1443 VOID 1444 ); 1445 1446 _Must_inspect_result_ 1447 NTSTATUS 1448 PdoInitialize( 1449 __in PWDFDEVICE_INIT DeviceInit 1450 ); 1451 1452 _Must_inspect_result_ 1453 NTSTATUS 1454 FdoInitialize( 1455 __in PWDFDEVICE_INIT DeviceInit 1456 ); 1457 1458 _Must_inspect_result_ 1459 NTSTATUS 1460 ControlDeviceInitialize( 1461 __in PWDFDEVICE_INIT DeviceInit 1462 ); 1463 1464 VOID 1465 ControlDeviceDelete( 1466 VOID 1467 ) 1468 { 1469 // 1470 // FxDevice::DeleteObject() has already run, so we must call the super 1471 // class's version of DeleteObject(); 1472 // 1473 ASSERT(m_DeviceObjectDeleted); 1474 1475 FxDeviceBase::DeleteObject(); // __super call 1476 } 1477 1478 _Must_inspect_result_ 1479 NTSTATUS 1480 OpenSettingsKey( 1481 __out HANDLE* Key, 1482 __in ACCESS_MASK DesiredAccess = STANDARD_RIGHTS_ALL 1483 ); 1484 1485 VOID 1486 DeleteSymbolicLink( 1487 VOID 1488 ); 1489 1490 __inline 1491 BYTE 1492 GetCallbackFlagsLocked( 1493 VOID 1494 ) 1495 { 1496 return m_CallbackFlags; 1497 } 1498 1499 __inline 1500 BYTE 1501 GetCallbackFlags( 1502 VOID 1503 ) 1504 { 1505 BYTE flags; 1506 KIRQL irql; 1507 1508 Lock(&irql); 1509 flags = GetCallbackFlagsLocked(); 1510 Unlock(irql); 1511 1512 return flags; 1513 } 1514 1515 __inline 1516 VOID 1517 SetCallbackFlagsLocked( 1518 __in BYTE Flags 1519 ) 1520 { 1521 m_CallbackFlags |= Flags; 1522 } 1523 1524 __inline 1525 VOID 1526 SetCallbackFlags( 1527 __in BYTE Flags 1528 ) 1529 { 1530 KIRQL irql; 1531 1532 Lock(&irql); 1533 SetCallbackFlagsLocked(Flags); 1534 Unlock(irql); 1535 } 1536 1537 __inline 1538 VOID 1539 ClearCallbackFlagsLocked( 1540 __in BYTE Flags 1541 ) 1542 { 1543 m_CallbackFlags &= ~Flags; 1544 } 1545 1546 __inline 1547 VOID 1548 ClearCallbackFlags( 1549 __in BYTE Flags 1550 ) 1551 { 1552 KIRQL irql; 1553 1554 Lock(&irql); 1555 ClearCallbackFlagsLocked(Flags); 1556 Unlock(irql); 1557 } 1558 1559 FxCxDeviceInfo* 1560 GetCxDeviceInfo( 1561 __in FxDriver* CxDriver 1562 ) 1563 { 1564 FxCxDeviceInfo* cxDeviceInfo; 1565 PLIST_ENTRY next; 1566 1567 // 1568 // Check if we are using I/O class extensions. 1569 // 1570 for (next = m_CxDeviceInfoListHead.Flink; 1571 next != &m_CxDeviceInfoListHead; 1572 next = next->Flink) { 1573 1574 cxDeviceInfo = CONTAINING_RECORD(next, FxCxDeviceInfo, ListEntry); 1575 if (cxDeviceInfo->Driver == CxDriver) { 1576 return cxDeviceInfo; 1577 } 1578 } 1579 1580 return NULL; 1581 } 1582 1583 __inline 1584 BOOLEAN 1585 IsCxDriverInIoPath( 1586 __in FxDriver* CxDriver 1587 ) 1588 { 1589 return (GetCxDeviceInfo(CxDriver) != NULL) ? TRUE : FALSE; 1590 } 1591 1592 __inline 1593 BOOLEAN 1594 IsCxInIoPath( 1595 VOID 1596 ) 1597 { 1598 return IsListEmpty(&m_CxDeviceInfoListHead) ? FALSE : TRUE; 1599 } 1600 1601 #if DBG 1602 __inline 1603 FxCxDeviceInfo* 1604 GetFirstCxDeviceInfo( 1605 VOID 1606 ) 1607 { 1608 if (IsListEmpty(&m_CxDeviceInfoListHead)) { 1609 return NULL; 1610 } 1611 else { 1612 return CONTAINING_RECORD(m_CxDeviceInfoListHead.Flink, 1613 FxCxDeviceInfo, 1614 ListEntry); 1615 } 1616 } 1617 1618 __inline 1619 FxCxDeviceInfo* 1620 GetNextCxDeviceInfo( 1621 __in FxCxDeviceInfo* CxDeviceInfo 1622 ) 1623 { 1624 ASSERT(CxDeviceInfo != NULL); 1625 if (CxDeviceInfo->ListEntry.Flink == &m_CxDeviceInfoListHead) { 1626 return NULL; 1627 } 1628 else { 1629 return CONTAINING_RECORD(CxDeviceInfo->ListEntry.Flink, 1630 FxCxDeviceInfo, 1631 ListEntry); 1632 } 1633 } 1634 1635 #endif 1636 1637 __inline 1638 static 1639 CCHAR 1640 GetCxDriverIndex( 1641 __in FxCxDeviceInfo* CxDeviceInfo 1642 ) 1643 { 1644 if (CxDeviceInfo != NULL) { 1645 return CxDeviceInfo->Index; 1646 } 1647 else { 1648 return 0; 1649 } 1650 } 1651 1652 __inline 1653 FxDriver* 1654 GetCxDriver( 1655 __in FxCxDeviceInfo* CxDeviceInfo 1656 ) 1657 { 1658 if (CxDeviceInfo != NULL) { 1659 return CxDeviceInfo->Driver; 1660 } 1661 else { 1662 return GetDriver(); 1663 } 1664 } 1665 1666 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 1667 1668 static 1669 __inline 1670 NTSTATUS 1671 _OpenDeviceRegistryKey( 1672 _In_ MdDeviceObject DeviceObject, 1673 _In_ ULONG DevInstKeyType, 1674 _In_ ACCESS_MASK DesiredAccess, 1675 _Out_ PHANDLE DevInstRegKey 1676 ); 1677 1678 __inline 1679 static 1680 NTSTATUS 1681 _GetDeviceProperty( 1682 _In_ MdDeviceObject DeviceObject, 1683 _In_ DEVICE_REGISTRY_PROPERTY DeviceProperty, 1684 _In_ ULONG BufferLength, 1685 _Out_opt_ PVOID PropertyBuffer, 1686 _Out_ PULONG ResultLength 1687 ); 1688 1689 #elif (FX_CORE_MODE == FX_CORE_USER_MODE) 1690 1691 static 1692 NTSTATUS 1693 _OpenDeviceRegistryKey( 1694 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, 1695 _In_ IWudfDeviceStack* DeviceStack, 1696 _In_ PWSTR DriverName, 1697 _In_ ULONG DevInstKeyType, 1698 _In_ ACCESS_MASK DesiredAccess, 1699 _Out_ PHANDLE DevInstRegKey 1700 ); 1701 1702 static 1703 NTSTATUS 1704 _GetDeviceProperty( 1705 _In_ PVOID DeviceStack, 1706 _In_ DEVICE_REGISTRY_PROPERTY DeviceProperty, 1707 _In_ ULONG BufferLength, 1708 _Out_opt_ PVOID PropertyBuffer, 1709 _Out_ PULONG ResultLength 1710 ); 1711 1712 #endif 1713 1714 static 1715 _Must_inspect_result_ 1716 NTSTATUS 1717 _ValidateOpenKeyParams( 1718 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, 1719 _In_opt_ PWDFDEVICE_INIT DeviceInit, 1720 _In_opt_ FxDevice* Device 1721 ); 1722 1723 static 1724 _Must_inspect_result_ 1725 NTSTATUS 1726 _OpenKey( 1727 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, 1728 _In_opt_ PWDFDEVICE_INIT DeviceInit, 1729 _In_opt_ FxDevice* Device, 1730 _In_ ULONG DeviceInstanceKeyType, 1731 _In_ ACCESS_MASK DesiredAccess, 1732 _In_opt_ PWDF_OBJECT_ATTRIBUTES KeyAttributes, 1733 _Out_ WDFKEY* Key 1734 ); 1735 1736 static 1737 _Must_inspect_result_ 1738 NTSTATUS 1739 _AllocAndQueryProperty( 1740 _In_ PFX_DRIVER_GLOBALS Globals, 1741 _In_opt_ PWDFDEVICE_INIT DeviceInit, 1742 _In_opt_ FxDevice* Device, 1743 _In_opt_ MdDeviceObject RemotePdo, 1744 _In_ DEVICE_REGISTRY_PROPERTY DeviceProperty, 1745 _In_ POOL_TYPE PoolType, 1746 _In_opt_ PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes, 1747 _Out_ WDFMEMORY* PropertyMemory 1748 ); 1749 1750 static 1751 _Must_inspect_result_ 1752 NTSTATUS 1753 _QueryProperty( 1754 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, 1755 _In_opt_ PWDFDEVICE_INIT DeviceInit, 1756 _In_opt_ FxDevice* Device, 1757 _In_opt_ MdDeviceObject RemotePdo, 1758 _In_ DEVICE_REGISTRY_PROPERTY DeviceProperty, 1759 _In_ ULONG BufferLength, 1760 _Out_opt_ PVOID PropertyBuffer, 1761 _Out_opt_ PULONG ResultLength 1762 ); 1763 1764 static 1765 VOID 1766 STDCALL 1767 _InterfaceReferenceNoOp( 1768 __in_opt PVOID Context 1769 ) 1770 { 1771 // NoOp reference stub for query interface 1772 UNREFERENCED_PARAMETER(Context); 1773 } 1774 1775 static 1776 VOID 1777 STDCALL 1778 _InterfaceDereferenceNoOp( 1779 __in_opt PVOID Context 1780 ) 1781 { 1782 // NoOp dereference stub for query interface 1783 UNREFERENCED_PARAMETER(Context); 1784 } 1785 1786 static 1787 FxWdmDeviceExtension* 1788 _GetFxWdmExtension( 1789 __in MdDeviceObject DeviceObject 1790 ); 1791 1792 BOOLEAN 1793 IsRemoveLockEnabledForIo( 1794 VOID 1795 ); 1796 1797 VOID 1798 FxLogDeviceStartTelemetryEvent( 1799 VOID 1800 ) 1801 { 1802 // LogDeviceStartTelemetryEvent(GetDriverGlobals(), this); __REACTOS__ : no-op 1803 } 1804 1805 virtual 1806 VOID 1807 SetDeviceTelemetryInfoFlags( 1808 _In_ FxDeviceInfoFlags Flag 1809 ) 1810 { 1811 m_DeviceTelemetryInfoFlags |= Flag; 1812 } 1813 1814 USHORT 1815 GetDeviceTelemetryInfoFlags( 1816 VOID 1817 ) 1818 { 1819 return m_DeviceTelemetryInfoFlags; 1820 } 1821 1822 __inline 1823 CHAR 1824 GetStackSize( 1825 VOID 1826 ) 1827 { 1828 return m_DeviceObject.GetStackSize(); 1829 } 1830 1831 __inline 1832 VOID 1833 SetStackSize( 1834 _In_ CHAR Size 1835 ) 1836 { 1837 m_DeviceObject.SetStackSize(Size); 1838 } 1839 1840 NTSTATUS 1841 UpdateInterruptThreadpoolLimits( 1842 VOID 1843 ) 1844 { 1845 1846 1847 1848 1849 1850 return STATUS_SUCCESS; 1851 } 1852 1853 FxCmResList* 1854 GetTranslatedResources( 1855 ) 1856 { 1857 return m_PkgPnp->GetTranslatedResourceList(); 1858 } 1859 1860 VOID 1861 DetachDevice( 1862 VOID 1863 ); 1864 1865 VOID 1866 InvalidateDeviceState( 1867 VOID 1868 ); 1869 1870 NTSTATUS 1871 CreateSymbolicLink( 1872 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, 1873 _In_ PCUNICODE_STRING SymbolicLinkName 1874 ); 1875 1876 VOID 1877 SetCleanupFromFailedCreate( 1878 BOOLEAN Value 1879 ) 1880 { 1881 #if (FX_CORE_MODE == FX_CORE_USER_MODE) 1882 m_CleanupFromFailedCreate = Value; 1883 #else 1884 UNREFERENCED_PARAMETER(Value); 1885 #endif 1886 } 1887 1888 BOOLEAN 1889 IsInterfaceRegistered( 1890 _In_ const GUID* InterfaceClassGUID, 1891 _In_opt_ PCUNICODE_STRING RefString 1892 ); 1893 1894 static 1895 _Must_inspect_result_ 1896 NTSTATUS 1897 _AllocAndQueryPropertyEx( 1898 _In_ PFX_DRIVER_GLOBALS DriverGlobals, 1899 _In_opt_ PWDFDEVICE_INIT DeviceInit, 1900 _In_opt_ FxDevice* Device, 1901 _In_ PVOID PropertyData, 1902 _In_ FxPropertyType FxPropertyType, 1903 _In_ POOL_TYPE PoolType, 1904 _In_opt_ PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes, 1905 _Out_ WDFMEMORY* PropertyMemory, 1906 _Out_ PDEVPROPTYPE PropertyType 1907 ); 1908 1909 static 1910 _Must_inspect_result_ 1911 NTSTATUS 1912 _QueryPropertyEx( 1913 _In_ PFX_DRIVER_GLOBALS DriverGlobals, 1914 _In_opt_ PWDFDEVICE_INIT DeviceInit, 1915 _In_opt_ FxDevice* Device, 1916 _In_ PVOID PropertyData, 1917 _In_ FxPropertyType FxPropertyType, 1918 _In_ ULONG BufferLength, 1919 _Out_ PVOID PropertyBuffer, 1920 _Out_ PULONG ResultLength, 1921 _Out_ PDEVPROPTYPE PropertyType 1922 ); 1923 1924 _Must_inspect_result_ 1925 NTSTATUS 1926 OpenDevicemapKeyWorker( 1927 _In_ PFX_DRIVER_GLOBALS pFxDriverGlobals, 1928 _In_ PCUNICODE_STRING KeyName, 1929 _In_ ACCESS_MASK DesiredAccess, 1930 _In_ FxRegKey* pKey 1931 ); 1932 1933 _Must_inspect_result_ 1934 NTSTATUS 1935 AssignProperty ( 1936 _In_ PVOID PropertyData, 1937 _In_ FxPropertyType FxPropertyType, 1938 _In_ DEVPROPTYPE Type, 1939 _In_ ULONG BufferLength, 1940 _In_opt_ PVOID PropertyBuffer 1941 ); 1942 1943 #if (FX_CORE_MODE==FX_CORE_USER_MODE) 1944 1945 _Must_inspect_result_ 1946 NTSTATUS 1947 FxValidateInterfacePropertyData( 1948 _In_ PWDF_DEVICE_INTERFACE_PROPERTY_DATA PropertyData 1949 ); 1950 1951 VOID 1952 GetDeviceStackIoType ( 1953 _Out_ WDF_DEVICE_IO_TYPE* ReadWriteIoType, 1954 _Out_ WDF_DEVICE_IO_TYPE* IoControlIoType 1955 ); 1956 1957 __inline 1958 UMINT::WDF_DEVICE_IO_BUFFER_RETRIEVAL 1959 GetRetrievalMode( 1960 VOID 1961 ) 1962 { 1963 return m_RetrievalMode; 1964 } 1965 1966 __inline 1967 WDF_DEVICE_IO_TYPE 1968 GetPreferredRWTransferMode( 1969 VOID 1970 ) 1971 { 1972 return m_ReadWriteIoType; 1973 } 1974 1975 __inline 1976 WDF_DEVICE_IO_TYPE 1977 GetPreferredIoctlTransferMode( 1978 VOID 1979 ) 1980 { 1981 return m_IoctlIoType; 1982 } 1983 1984 __inline 1985 ULONG 1986 GetDirectTransferThreshold( 1987 VOID 1988 ) 1989 { 1990 return m_DirectTransferThreshold; 1991 } 1992 1993 static 1994 VOID 1995 GetPreferredTransferMode( 1996 _In_ MdDeviceObject DeviceObject, 1997 _Out_ UMINT::WDF_DEVICE_IO_BUFFER_RETRIEVAL *RetrievalMode, 1998 _Out_ WDF_DEVICE_IO_TYPE *RWPreference, 1999 _Out_ WDF_DEVICE_IO_TYPE *IoctlPreference 2000 ); 2001 2002 NTSTATUS 2003 ProcessWmiPowerQueryOrSetData ( 2004 _In_ RdWmiPowerAction Action, 2005 _Out_ BOOLEAN * QueryResult 2006 ); 2007 2008 static 2009 WUDF_INTERFACE_CONTEXT 2010 RemoteInterfaceArrival ( 2011 _In_ IWudfDevice * DeviceObject, 2012 _In_ LPCGUID DeviceInterfaceGuid, 2013 _In_ PCWSTR SymbolicLink 2014 ); 2015 2016 static 2017 void 2018 RemoteInterfaceRemoval ( 2019 _In_ IWudfDevice * DeviceObject, 2020 _In_ WUDF_INTERFACE_CONTEXT RemoteInterfaceID 2021 ); 2022 2023 static 2024 void 2025 PoFxDevicePowerRequired ( 2026 _In_ MdDeviceObject DeviceObject 2027 ); 2028 2029 static 2030 void 2031 PoFxDevicePowerNotRequired ( 2032 _In_ MdDeviceObject DeviceObject 2033 ); 2034 2035 static 2036 BOOL 2037 TransportQueryId ( 2038 _In_ IWudfDevice * DeviceObject, 2039 _In_ DWORD Id, 2040 _In_ PVOID DataBuffer, 2041 _In_ SIZE_T cbDataBufferSize 2042 ); 2043 2044 static 2045 NTSTATUS 2046 NtStatusFromHr ( 2047 _In_ IWudfDeviceStack * DevStack, 2048 _In_ HRESULT Hr 2049 ); 2050 2051 NTSTATUS 2052 NtStatusFromHr ( 2053 _In_ HRESULT Hr 2054 ); 2055 2056 IWudfDeviceStack* 2057 GetDeviceStack( 2058 VOID 2059 ); 2060 2061 IWudfDeviceStack2 * 2062 GetDeviceStack2( 2063 VOID 2064 ); 2065 2066 VOID 2067 RetrieveDeviceRegistrySettings( 2068 VOID 2069 ); 2070 2071 BOOLEAN 2072 IsDirectHardwareAccessAllowed( 2073 ) 2074 { 2075 return (m_DirectHardwareAccess == WdfAllowDirectHardwareAccess); 2076 } 2077 2078 BOOLEAN 2079 IsInterruptAccessAllowed( 2080 VOID 2081 ) 2082 { 2083 // 2084 // Allow access to interrupts if the device has any connection resources, 2085 // regardless of the UmdfDirectHardwareAccess INF directive. 2086 // 2087 return IsDirectHardwareAccessAllowed() || 2088 GetTranslatedResources()->HasConnectionResources(); 2089 } 2090 2091 BOOLEAN 2092 AreRegistersMappedToUsermode( 2093 VOID 2094 ) 2095 { 2096 return (m_RegisterAccessMode == WdfRegisterAccessUsingUserModeMapping); 2097 } 2098 2099 PVOID 2100 GetPseudoAddressFromSystemAddress( 2101 __in PVOID SystemAddress 2102 ) 2103 { 2104 return SystemAddress; 2105 } 2106 2107 PVOID 2108 GetSystemAddressFromPseudoAddress( 2109 __in PVOID PseudoAddress 2110 ) 2111 { 2112 return PseudoAddress; 2113 } 2114 2115 static 2116 ULONG 2117 __inline 2118 GetLength( 2119 __in WDF_DEVICE_HWACCESS_TARGET_SIZE Size 2120 ) 2121 { 2122 ULONG length = 0; 2123 2124 switch(Size) { 2125 case WdfDeviceHwAccessTargetSizeUchar: 2126 length = sizeof(UCHAR); 2127 break; 2128 case WdfDeviceHwAccessTargetSizeUshort: 2129 length = sizeof(USHORT); 2130 break; 2131 case WdfDeviceHwAccessTargetSizeUlong: 2132 length = sizeof(ULONG); 2133 break; 2134 case WdfDeviceHwAccessTargetSizeUlong64: 2135 length = sizeof(ULONG64); 2136 break; 2137 default: 2138 ASSERT(FALSE); 2139 } 2140 2141 return length; 2142 } 2143 2144 BOOL 2145 IsRegister( 2146 __in WDF_DEVICE_HWACCESS_TARGET_TYPE Type 2147 ) 2148 { 2149 if (Type == WdfDeviceHwAccessTargetTypeRegister || 2150 Type == WdfDeviceHwAccessTargetTypeRegisterBuffer) { 2151 return TRUE; 2152 } 2153 2154 return FALSE; 2155 } 2156 2157 BOOL 2158 IsPort( 2159 __in WDF_DEVICE_HWACCESS_TARGET_TYPE Type 2160 ) 2161 { 2162 if (Type == WdfDeviceHwAccessTargetTypePort || 2163 Type == WdfDeviceHwAccessTargetTypePortBuffer) { 2164 return TRUE; 2165 } 2166 2167 return FALSE; 2168 } 2169 2170 BOOL 2171 IsBufferType( 2172 __in WDF_DEVICE_HWACCESS_TARGET_TYPE Type 2173 ) 2174 { 2175 if (Type == WdfDeviceHwAccessTargetTypeRegisterBuffer || 2176 Type == WdfDeviceHwAccessTargetTypePortBuffer) { 2177 return TRUE; 2178 } 2179 2180 return FALSE; 2181 } 2182 2183 SIZE_T 2184 ReadRegister( 2185 __in WDF_DEVICE_HWACCESS_TARGET_SIZE Size, 2186 __in PVOID Register 2187 ); 2188 2189 VOID 2190 ReadRegisterBuffer( 2191 __in WDF_DEVICE_HWACCESS_TARGET_SIZE Size, 2192 __in PVOID Register, 2193 __out_ecount_full(Count) PVOID Buffer, 2194 __in ULONG Count 2195 ); 2196 2197 VOID 2198 WriteRegister( 2199 __in WDF_DEVICE_HWACCESS_TARGET_SIZE Size, 2200 __in PVOID Register, 2201 __in SIZE_T Value 2202 ); 2203 2204 VOID 2205 WriteRegisterBuffer( 2206 __in WDF_DEVICE_HWACCESS_TARGET_SIZE Size, 2207 __in PVOID Register, 2208 __in_ecount(Count) PVOID Buffer, 2209 __in ULONG Count 2210 ); 2211 2212 VOID 2213 RetrieveDeviceInfoRegistrySettings( 2214 _Out_ PCWSTR* GroupId, 2215 _Out_ PUMDF_DRIVER_REGSITRY_INFO DeviceRegInfo 2216 ); 2217 2218 #endif // (FX_CORE_MODE == FX_CORE_USER_MODE) 2219 2220 }; 2221 2222 class FxMpDevice : public FxDeviceBase { 2223 public: 2224 FxMpDevice( 2225 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 2226 __in FxDriver* Driver, 2227 __in MdDeviceObject DeviceObject, 2228 __in MdDeviceObject AttachedDevice, 2229 __in MdDeviceObject PDO 2230 ) : 2231 FxDeviceBase(FxDriverGlobals, Driver, FX_TYPE_MP_DEVICE, sizeof(*this)) 2232 { 2233 Init(DeviceObject, AttachedDevice, PDO); 2234 m_DefaultTarget = NULL; 2235 2236 Mx::MxReferenceObject(m_DeviceObject.GetObject()); 2237 2238 MarkDisposeOverride(ObjectDoNotLock); 2239 } 2240 2241 // begin FxObject overrides 2242 BOOLEAN 2243 Dispose( 2244 VOID 2245 ) 2246 { 2247 // 2248 // Important that the cleanup routine be called while the MdDeviceObject 2249 // is valid! 2250 // 2251 CallCleanup(); 2252 2253 // 2254 // Manually destroy the children now so that by the time we wait on the 2255 // dispose empty out, all of the children will have been added to it. 2256 // 2257 DestroyChildren(); 2258 2259 if (m_DisposeList != NULL) { 2260 m_DisposeList->WaitForEmpty(); 2261 } 2262 2263 // 2264 // No device object to delete since the caller's own the 2265 // WDM device. Simulate what FxDevice::Destroy does by NULL'ing out the 2266 // device objects. 2267 // 2268 Mx::MxDereferenceObject(m_DeviceObject.GetObject()); 2269 m_DeviceObject = NULL; 2270 m_AttachedDevice = NULL; 2271 2272 return FALSE; 2273 } 2274 // end FxObject overrides 2275 2276 // begin FxDeviceBase overrides 2277 virtual 2278 FxIoTarget* 2279 GetDefaultIoTarget( 2280 VOID 2281 ) 2282 { 2283 return m_DefaultTarget; 2284 } 2285 // end FxDeviceBase overrides 2286 2287 public: 2288 // 2289 // Default I/O target for this miniport device 2290 // 2291 FxIoTarget *m_DefaultTarget; 2292 }; 2293 2294 #if (FX_CORE_MODE==FX_CORE_KERNEL_MODE) 2295 #include "fxdevicekm.hpp" 2296 #else 2297 #include "fxdeviceum.hpp" 2298 #endif 2299 2300 2301 #endif // _FXDEVICE_H_ 2302