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
FxFileObjectClassNormalize(__in WDF_FILEOBJECT_CLASS FileObjectClass)103 FxFileObjectClassNormalize(
104 __in WDF_FILEOBJECT_CLASS FileObjectClass
105 )
106 {
107 return (WDF_FILEOBJECT_CLASS)(FileObjectClass & ~WdfFileObjectCanBeOptional);
108 }
109
110 BOOLEAN
111 __inline
FxIsFileObjectOptional(__in WDF_FILEOBJECT_CLASS FileObjectClass)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*
GetDriver(VOID)164 GetDriver(
165 VOID
166 )
167 {
168 return m_Driver;
169 }
170
171
172 MdDeviceObject
173 __inline
GetDeviceObject(VOID)174 GetDeviceObject(
175 VOID
176 )
177 {
178 return m_DeviceObject.GetObject();
179 }
180
181 __inline
182 MxDeviceObject*
GetMxDeviceObject(VOID)183 GetMxDeviceObject(
184 VOID
185 )
186 {
187 return &m_DeviceObject;
188 }
189
190 ULONG
191 __inline
GetDeviceObjectFlags(VOID)192 GetDeviceObjectFlags(
193 VOID
194 )
195 {
196 return m_DeviceObject.GetFlags();
197 }
198
199 VOID
200 __inline
SetDeviceObjectFlags(_In_ ULONG Flags)201 SetDeviceObjectFlags(
202 _In_ ULONG Flags
203 )
204 {
205 m_DeviceObject.SetFlags(Flags);
206 }
207
208 MdDeviceObject
209 __inline
GetAttachedDevice(VOID)210 GetAttachedDevice(
211 VOID
212 )
213 {
214 return m_AttachedDevice.GetObject();
215 }
216
217 ULONG
218 __inline
GetAttachedDeviceObjectFlags(VOID)219 GetAttachedDeviceObjectFlags(
220 VOID
221 )
222 {
223 return m_AttachedDevice.GetFlags();
224 }
225
226 MdDeviceObject
227 __inline
GetPhysicalDevice(VOID)228 GetPhysicalDevice(
229 VOID
230 )
231 {
232 return m_PhysicalDevice.GetObject();
233 }
234
235 WDFDEVICE
236 __inline
GetHandle(VOID)237 GetHandle(
238 VOID
239 )
240 {
241 return (WDFDEVICE) GetObjectHandle();
242 }
243
244 virtual
245 _Must_inspect_result_
246 NTSTATUS
AddIoTarget(__inout FxIoTarget * IoTarget)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
RemoveIoTarget(__inout FxIoTarget * IoTarget)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
AllocateEnumInfo(VOID)274 AllocateEnumInfo(
275 VOID
276 )
277 {
278 return STATUS_SUCCESS;
279 }
280
281 virtual
282 VOID
AddChildList(__inout FxChildList * List)283 AddChildList(
284 __inout FxChildList* List
285 )
286 {
287 //
288 // Intentionally does nothing
289 //
290 UNREFERENCED_PARAMETER(List);
291 }
292
293 virtual
294 VOID
RemoveChildList(__inout FxChildList * List)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
AllocateDmaEnablerList(VOID)308 AllocateDmaEnablerList(
309 VOID
310 )
311 {
312 return STATUS_SUCCESS;
313 }
314
315 virtual
316 VOID
AddDmaEnabler(__inout FxDmaEnabler * Enabler)317 AddDmaEnabler(
318 __inout FxDmaEnabler* Enabler
319 )
320 {
321 //
322 // Intentionally does nothing
323 //
324 UNREFERENCED_PARAMETER(Enabler);
325 }
326
327 virtual
328 VOID
RemoveDmaEnabler(__inout FxDmaEnabler * Enabler)329 RemoveDmaEnabler(
330 __inout FxDmaEnabler* Enabler
331 )
332 {
333 //
334 // Intentionally does nothing
335 //
336 UNREFERENCED_PARAMETER(Enabler);
337 }
338
339 virtual
340 VOID
SetDeviceTelemetryInfoFlags(_In_ FxDeviceInfoFlags Flag)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
AcquireDmaPacketTransaction(VOID)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
ReleaseDmaPacketTransaction(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
AddToDisposeList(__inout FxObject * Object)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
GetAttachedDeviceReference(VOID)429 GetAttachedDeviceReference(
430 VOID
431 )
432 {
433 return Mx::MxGetAttachedDeviceReference(m_DeviceObject.GetObject());
434 }
435
436 virtual
437 FxIoTarget*
GetDefaultIoTarget(VOID)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*
GetDispatchPackage(__in UCHAR MajorFunction)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
_RequiresRemLock(__in UCHAR MajorCode,__in UCHAR MinorCode)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
GetSafePhysicalDevice(VOID)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
SetInterruptThreadpool(_In_ FxInterruptThreadpool * Pool)1049 SetInterruptThreadpool(
1050 _In_ FxInterruptThreadpool* Pool
1051 )
1052 {
1053 m_InteruptThreadpool = Pool;
1054 }
1055
1056 FxInterruptThreadpool*
GetInterruptThreadpool(VOID)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
GetIoType(VOID)1084 GetIoType(
1085 VOID
1086 )
1087 {
1088 return m_ReadWriteIoType;
1089 }
1090
1091 __inline
1092 WDF_DEVICE_IO_TYPE
GetIoTypeForReadWriteBufferAccess(VOID)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
GetDefaultPriorityBoost(VOID)1111 GetDefaultPriorityBoost(
1112 VOID
1113 )
1114 {
1115 return m_DefaultPriorityBoost;
1116 }
1117
1118 //
1119 // Return FileObjectClass
1120 //
1121 __inline
1122 WDF_FILEOBJECT_CLASS
GetFileObjectClass(VOID)1123 GetFileObjectClass(
1124 VOID
1125 )
1126 {
1127 return m_FileObjectClass;
1128 }
1129
1130 //
1131 // Configuration time fileobject support setting
1132 //
1133 __inline
1134 VOID
SetFileObjectClass(__in WDF_FILEOBJECT_CLASS FileObjectClass)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
GetDevicePnpState()1149 GetDevicePnpState(
1150 )
1151 {
1152 return m_CurrentPnpState;
1153 }
1154
1155 __inline
1156 WDF_DEVICE_POWER_STATE
GetDevicePowerState()1157 GetDevicePowerState(
1158 )
1159 {
1160 return m_CurrentPowerState;
1161 }
1162
1163 __inline
1164 WDF_DEVICE_POWER_POLICY_STATE
GetDevicePowerPolicyState()1165 GetDevicePowerPolicyState(
1166 )
1167 {
1168 return m_CurrentPowerPolicyState;
1169 }
1170
1171 __inline
1172 VOID
SetDevicePnpState(__in WDF_DEVICE_PNP_STATE DeviceState)1173 SetDevicePnpState(
1174 __in WDF_DEVICE_PNP_STATE DeviceState
1175 )
1176 {
1177 m_CurrentPnpState = DeviceState;
1178 }
1179
1180 __inline
1181 VOID
SetDevicePowerState(__in WDF_DEVICE_POWER_STATE DeviceState)1182 SetDevicePowerState(
1183 __in WDF_DEVICE_POWER_STATE DeviceState
1184 )
1185 {
1186 m_CurrentPowerState = DeviceState;
1187 }
1188
1189 __inline
1190 VOID
SetDevicePowerPolicyState(__in WDF_DEVICE_POWER_POLICY_STATE DeviceState)1191 SetDevicePowerPolicyState(
1192 __in WDF_DEVICE_POWER_POLICY_STATE DeviceState
1193 )
1194 {
1195 m_CurrentPowerPolicyState = DeviceState;
1196 }
1197
1198 __inline
1199 BOOLEAN
IsPnp(VOID)1200 IsPnp(
1201 VOID
1202 )
1203 {
1204 return m_PkgPnp != NULL ? TRUE : FALSE;
1205 }
1206
1207 __inline
1208 BOOLEAN
IsLegacy(VOID)1209 IsLegacy(
1210 VOID
1211 )
1212 {
1213 return m_Legacy;
1214 }
1215
1216 __inline
1217 BOOLEAN
IsExclusive(VOID)1218 IsExclusive(
1219 VOID
1220 )
1221 {
1222 return m_Exclusive;
1223 }
1224
1225 __inline
1226 BOOLEAN
IsFdo(VOID)1227 IsFdo(
1228 VOID
1229 )
1230 {
1231 return m_PkgPnp->GetType() == FX_TYPE_PACKAGE_FDO;
1232 }
1233
1234 __inline
1235 FxPkgFdo*
GetFdoPkg(VOID)1236 GetFdoPkg(
1237 VOID
1238 )
1239 {
1240 return (FxPkgFdo*) m_PkgPnp;
1241 }
1242
1243 __inline
1244 BOOLEAN
IsPdo(VOID)1245 IsPdo(
1246 VOID
1247 )
1248 {
1249 return (IsPnp() && m_PkgPnp->GetType() == FX_TYPE_PACKAGE_PDO);
1250 }
1251
1252 __inline
1253 FxPkgPdo*
GetPdoPkg(VOID)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
SetParentWaitingOnRemoval(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
GetRequestAttributes(VOID)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
IsFilter()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
IsPowerPageableCapable(VOID)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
ControlDeviceDelete(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
GetCallbackFlagsLocked(VOID)1492 GetCallbackFlagsLocked(
1493 VOID
1494 )
1495 {
1496 return m_CallbackFlags;
1497 }
1498
1499 __inline
1500 BYTE
GetCallbackFlags(VOID)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
SetCallbackFlagsLocked(__in BYTE Flags)1517 SetCallbackFlagsLocked(
1518 __in BYTE Flags
1519 )
1520 {
1521 m_CallbackFlags |= Flags;
1522 }
1523
1524 __inline
1525 VOID
SetCallbackFlags(__in BYTE Flags)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
ClearCallbackFlagsLocked(__in BYTE Flags)1539 ClearCallbackFlagsLocked(
1540 __in BYTE Flags
1541 )
1542 {
1543 m_CallbackFlags &= ~Flags;
1544 }
1545
1546 __inline
1547 VOID
ClearCallbackFlags(__in BYTE Flags)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*
GetCxDeviceInfo(__in FxDriver * CxDriver)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
IsCxDriverInIoPath(__in FxDriver * CxDriver)1585 IsCxDriverInIoPath(
1586 __in FxDriver* CxDriver
1587 )
1588 {
1589 return (GetCxDeviceInfo(CxDriver) != NULL) ? TRUE : FALSE;
1590 }
1591
1592 __inline
1593 BOOLEAN
IsCxInIoPath(VOID)1594 IsCxInIoPath(
1595 VOID
1596 )
1597 {
1598 return IsListEmpty(&m_CxDeviceInfoListHead) ? FALSE : TRUE;
1599 }
1600
1601 #if DBG
1602 __inline
1603 FxCxDeviceInfo*
GetFirstCxDeviceInfo(VOID)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*
GetNextCxDeviceInfo(__in FxCxDeviceInfo * CxDeviceInfo)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
GetCxDriverIndex(__in FxCxDeviceInfo * CxDeviceInfo)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*
GetCxDriver(__in FxCxDeviceInfo * CxDeviceInfo)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
_InterfaceReferenceNoOp(__in_opt PVOID Context)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
_InterfaceDereferenceNoOp(__in_opt PVOID Context)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
FxLogDeviceStartTelemetryEvent(VOID)1798 FxLogDeviceStartTelemetryEvent(
1799 VOID
1800 )
1801 {
1802 // LogDeviceStartTelemetryEvent(GetDriverGlobals(), this); __REACTOS__ : no-op
1803 }
1804
1805 virtual
1806 VOID
SetDeviceTelemetryInfoFlags(_In_ FxDeviceInfoFlags Flag)1807 SetDeviceTelemetryInfoFlags(
1808 _In_ FxDeviceInfoFlags Flag
1809 )
1810 {
1811 m_DeviceTelemetryInfoFlags |= Flag;
1812 }
1813
1814 USHORT
GetDeviceTelemetryInfoFlags(VOID)1815 GetDeviceTelemetryInfoFlags(
1816 VOID
1817 )
1818 {
1819 return m_DeviceTelemetryInfoFlags;
1820 }
1821
1822 __inline
1823 CHAR
GetStackSize(VOID)1824 GetStackSize(
1825 VOID
1826 )
1827 {
1828 return m_DeviceObject.GetStackSize();
1829 }
1830
1831 __inline
1832 VOID
SetStackSize(_In_ CHAR Size)1833 SetStackSize(
1834 _In_ CHAR Size
1835 )
1836 {
1837 m_DeviceObject.SetStackSize(Size);
1838 }
1839
1840 NTSTATUS
UpdateInterruptThreadpoolLimits(VOID)1841 UpdateInterruptThreadpoolLimits(
1842 VOID
1843 )
1844 {
1845
1846
1847
1848
1849
1850 return STATUS_SUCCESS;
1851 }
1852
1853 FxCmResList*
GetTranslatedResources()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
SetCleanupFromFailedCreate(BOOLEAN Value)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
GetRetrievalMode(VOID)1959 GetRetrievalMode(
1960 VOID
1961 )
1962 {
1963 return m_RetrievalMode;
1964 }
1965
1966 __inline
1967 WDF_DEVICE_IO_TYPE
GetPreferredRWTransferMode(VOID)1968 GetPreferredRWTransferMode(
1969 VOID
1970 )
1971 {
1972 return m_ReadWriteIoType;
1973 }
1974
1975 __inline
1976 WDF_DEVICE_IO_TYPE
GetPreferredIoctlTransferMode(VOID)1977 GetPreferredIoctlTransferMode(
1978 VOID
1979 )
1980 {
1981 return m_IoctlIoType;
1982 }
1983
1984 __inline
1985 ULONG
GetDirectTransferThreshold(VOID)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
IsDirectHardwareAccessAllowed()2072 IsDirectHardwareAccessAllowed(
2073 )
2074 {
2075 return (m_DirectHardwareAccess == WdfAllowDirectHardwareAccess);
2076 }
2077
2078 BOOLEAN
IsInterruptAccessAllowed(VOID)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
AreRegistersMappedToUsermode(VOID)2092 AreRegistersMappedToUsermode(
2093 VOID
2094 )
2095 {
2096 return (m_RegisterAccessMode == WdfRegisterAccessUsingUserModeMapping);
2097 }
2098
2099 PVOID
GetPseudoAddressFromSystemAddress(__in PVOID SystemAddress)2100 GetPseudoAddressFromSystemAddress(
2101 __in PVOID SystemAddress
2102 )
2103 {
2104 return SystemAddress;
2105 }
2106
2107 PVOID
GetSystemAddressFromPseudoAddress(__in PVOID PseudoAddress)2108 GetSystemAddressFromPseudoAddress(
2109 __in PVOID PseudoAddress
2110 )
2111 {
2112 return PseudoAddress;
2113 }
2114
2115 static
2116 ULONG
2117 __inline
GetLength(__in WDF_DEVICE_HWACCESS_TARGET_SIZE Size)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
IsRegister(__in WDF_DEVICE_HWACCESS_TARGET_TYPE Type)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
IsPort(__in WDF_DEVICE_HWACCESS_TARGET_TYPE Type)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
IsBufferType(__in WDF_DEVICE_HWACCESS_TARGET_TYPE Type)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:
FxMpDevice(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in FxDriver * Driver,__in MdDeviceObject DeviceObject,__in MdDeviceObject AttachedDevice,__in MdDeviceObject PDO)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
Dispose(VOID)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*
GetDefaultIoTarget(VOID)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