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