1 /*++
2 
3 Copyright (c) Microsoft. All rights reserved.
4 
5 Module Name:
6 
7     FxPkgPdo.hpp
8 
9 Abstract:
10 
11     This module implements the pnp package for Pdo objects.
12 
13 Author:
14 
15 
16 
17 Environment:
18 
19     Both kernel and user mode
20 
21 Revision History:
22 
23 
24 --*/
25 
26 #ifndef _FXPKGPDO_H_
27 #define _FXPKGPDO_H_
28 
29 typedef NTSTATUS (FxPkgPdo::*PFN_PDO_HANDLER)(FxIrp *Irp);
30 
31 class FxPkgPdo : public FxPkgPnp
32 {
33 public:
34     //
35     // Properties used in handling IRP_MN_QUERY_DEVICE_TEXT
36     //
37     SINGLE_LIST_ENTRY m_DeviceTextHead;
38     LCID m_DefaultLocale;
39 
40     FxDeviceDescriptionEntry* m_Description;
41 
42     FxChildList* m_OwningChildList;
43 
44     //
45     // The following structure contains the function pointer table
46     // for the "events" this package can raise.
47     //
48     FxPnpDeviceResourcesQuery            m_DeviceResourcesQuery;
49     FxPnpDeviceResourceRequirementsQuery m_DeviceResourceRequirementsQuery;
50     FxPnpDeviceEject                     m_DeviceEject;
51     FxPnpDeviceSetLock                   m_DeviceSetLock;
52 
53     FxPowerDeviceEnableWakeAtBus         m_DeviceEnableWakeAtBus;
54     FxPowerDeviceDisableWakeAtBus        m_DeviceDisableWakeAtBus;
55 
56     // added in 1.11
57     FxPnpDeviceReportedMissing           m_DeviceReportedMissing;
58 
59     BOOLEAN m_RawOK;
60 
61     BOOLEAN m_Static;
62 
63     BOOLEAN m_AddedToStaticList;
64 
65     //
66     // This field is used to indicate that Requests on this PDO could be
67     // forwarded to the parent.
68     //
69     BOOLEAN m_AllowForwardRequestToParent;
70 
71 protected:
72     //
73     // Pointer to a null terminated string which is the device ID.  This is
74     // not a pointer that can be freed.   m_IDsAllocation is the beginning of
75     // the allocation that can be freed.
76     //
77     PWSTR m_DeviceID;
78 
79     //
80     // Pointer to a null terminated string which is the instance ID.  This is
81     // not a pointer that can be freed.   m_IDsAllocation is the beginning of
82     // the allocation that can be freed.
83     //
84     PWSTR m_InstanceID;
85 
86     //
87     // Pointer to a multi sz which is the hardware IDs.  This is
88     // not a pointer that can be freed.   m_IDsAllocation is the beginning of
89     // the allocation that can be freed.
90     //
91     PWSTR m_HardwareIDs;
92 
93     //
94     // Pointer to a multi sz which is the compatible IDs.  This is
95     // not a pointer that can be freed.   m_IDsAllocation is the beginning of
96     // the allocation that can be freed.
97     //
98     PWSTR m_CompatibleIDs;
99 
100     //
101     // Pointer to a null terminated string which is the unique ID.  This is
102     // not a pointer that can be freed.   m_IDsAllocation is the beginning of
103     // the allocation that can be freed.
104     //
105     PWSTR m_ContainerID;
106 
107     //
108     // Single allocation for all static ID strings (device, instance, hw, compat)
109     // for the device
110     //
111     PWSTR m_IDsAllocation;
112 
113     FxRelatedDeviceList* m_EjectionDeviceList;
114 
115     //
116     // IRP_MN_EJECT needs to be handled synchronously because PnP manager does
117     // not serialize it with other state changing PnP irps if not handled
118     // synchronously. This event is used to signal the completion of
119     // IRP_MN_EJECT processing.
120     //
121     MxEvent* m_DeviceEjectProcessed;
122 
123     BOOLEAN m_CanBeDeleted;
124 
125     //
126     // Parameter to track whether the EvtDeviceEnableWakeAtBus callback was
127     // invoked and to determine whether the EvtDeviceDisableWakeAtBus callback
128     // should be invoked or not.  The EnableWakeAtBus callback may not get
129     // invoked if an upper driver in the stack completed the wait wake irp
130     // instead of passing it down the stack and the power policy owner is
131     // a PDO.
132     //
133     // This parameter can be referenced by either the power state machine or
134     // the power policy state machine when a PDO is the power policy owner
135     // but there is no locking mechanism necessary to synchronize access to
136     // the field.  This is because the arrival of a Dx irp will move the power
137     // state machine to a state where it can no longer affect the value of
138     // this field and hence provides an implicit guard that allows the power
139     // policy state machine to use this field while processing the Dx irp.
140     //
141     BOOLEAN m_EnableWakeAtBusInvoked;
142 
143 private:
144     //
145     // Table of internal methods to handle PnP minor function codes.
146     //
147     static const PFN_PNP_POWER_CALLBACK m_PdoPnpFunctionTable[IRP_MN_SURPRISE_REMOVAL + 1];
148 
149     //
150     // Table of internal methods to handle power minor function codes.
151     //
152     static const PFN_PNP_POWER_CALLBACK  m_PdoPowerFunctionTable[IRP_MN_QUERY_POWER + 1];
153 
154 public:
155 
156     FxPkgPdo(
157         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
158         __in CfxDevice *Device
159         );
160 
161     ~FxPkgPdo();
162 
163     _Must_inspect_result_
164     virtual
165     NTSTATUS
166     Initialize(
167         __in PWDFDEVICE_INIT DeviceInit
168         );
169 
170     virtual
171     VOID
172     FinishInitialize(
173         __in PWDFDEVICE_INIT DeviceInit
174         );
175 
176     VOID
177     RegisterCallbacks(
178         __in PWDF_PDO_EVENT_CALLBACKS DispatchTable
179         );
180 
181     _Must_inspect_result_
182     NTSTATUS
183     AddEjectionDevice(
184         __in MdDeviceObject DependentDevice
185         );
186 
187     VOID
188     RemoveEjectionDevice(
189         __in MdDeviceObject DependentDevice
190         );
191 
192     VOID
193     ClearEjectionDevicesList(
194         VOID
195         );
196 
197     _Must_inspect_result_
198     NTSTATUS
199     HandleQueryInterfaceForReenumerate(
200         __in  FxIrp* Irp,
201         __out PBOOLEAN CompleteRequest
202         );
203 
204     __inline
205     BOOLEAN
IsForwardRequestToParentEnabled(VOID)206     IsForwardRequestToParentEnabled(
207         VOID
208         )
209     {
210         return m_AllowForwardRequestToParent;
211     }
212 
213 
214 private:
215     _Must_inspect_result_
216     virtual
217     NTSTATUS
218     SendIrpSynchronously(
219         __in FxIrp* Irp
220         );
221 
222     _Must_inspect_result_
223     virtual
224     NTSTATUS
225     FireAndForgetIrp(
226         __inout FxIrp* Irp
227         );
228 
229     //
230     // The following are static member function.  The only reason
231     // I've defined them as member functions at all is so they can see
232     // the private data in this class.
233     //
234 
235     _Must_inspect_result_
236     static
237     NTSTATUS
238     _PnpCompleteIrp(
239         __in    FxPkgPnp* This,
240         __inout FxIrp *Irp
241         );
242 
243     _Must_inspect_result_
244     static
245     NTSTATUS
246     _PnpQueryDeviceRelations(
247         __in    FxPkgPnp* This,
248         __inout FxIrp *Irp
249         );
250 
251     _Must_inspect_result_
252     NTSTATUS
253     PnpQueryDeviceRelations(
254         __inout FxIrp *Irp
255         );
256 
257     _Must_inspect_result_
258     static
259     NTSTATUS
260     _PnpQueryInterface(
261         IN FxPkgPnp* This,
262         IN FxIrp *Irp
263         );
264 
265     _Must_inspect_result_
266     static
267     NTSTATUS
268     _PnpQueryCapabilities(
269         __inout FxPkgPnp* This,
270         __inout FxIrp *Irp
271         );
272 
273     _Must_inspect_result_
274     NTSTATUS
275     PnpQueryCapabilities(
276         __inout FxIrp *Irp
277         );
278 
279     VOID
280     HandleQueryCapabilities(
281         __inout PDEVICE_CAPABILITIES ReportedCaps,
282         __in    PDEVICE_CAPABILITIES ParentCaps
283         );
284 
285     static
286     VOID
287     STDCALL
288     _QueryCapsWorkItem(
289         __in MdDeviceObject DeviceObject,
290         __in PVOID Context
291         );
292 
293     _Must_inspect_result_
294     static
295     NTSTATUS
296     _PnpQueryResources(
297         __inout FxPkgPnp* This,
298         __inout FxIrp *Irp
299         );
300 
301     _Must_inspect_result_
302     NTSTATUS
303     PnpQueryResources(
304         __inout FxIrp *Irp
305         );
306 
307     _Must_inspect_result_
308     static
309     NTSTATUS
310     _PnpQueryResourceRequirements(
311         __inout FxPkgPnp* This,
312         __inout FxIrp *Irp
313         );
314 
315     _Must_inspect_result_
316     NTSTATUS
317     PnpQueryResourceRequirements(
318         __inout FxIrp *Irp
319         );
320 
321     _Must_inspect_result_
322     static
323     NTSTATUS
324     _PnpQueryDeviceText(
325         __inout FxPkgPnp* This,
326         __inout FxIrp *Irp
327         );
328 
329     _Must_inspect_result_
330     static
331     NTSTATUS
332     _PnpFilterResourceRequirements(
333         __inout FxPkgPnp* This,
334         __inout FxIrp *Irp
335         );
336 
337     _Must_inspect_result_
338     static
339     NTSTATUS
340     _PnpEject(
341         __inout FxPkgPnp* This,
342         __inout FxIrp *Irp
343         );
344 
345     virtual
346     BOOLEAN
347     PnpSendStartDeviceDownTheStackOverload(
348         VOID
349         );
350 
351     virtual
352     WDF_DEVICE_PNP_STATE
353     PnpEventEjectHardwareOverload(
354         VOID
355         );
356 
357     virtual
358     WDF_DEVICE_PNP_STATE
359     PnpEventCheckForDevicePresenceOverload(
360         VOID
361         );
362 
363     virtual
364     WDF_DEVICE_PNP_STATE
365     PnpEventPdoRemovedOverload(
366         VOID
367         );
368 
369     virtual
370     WDF_DEVICE_PNP_STATE
371     PnpEventFdoRemovedOverload(
372         VOID
373         );
374 
375     virtual
376     VOID
377     PnpEventSurpriseRemovePendingOverload(
378         VOID
379         );
380 
381     virtual
382     WDF_DEVICE_PNP_STATE
383     PnpGetPostRemoveState(
384         VOID
385         );
386 
387     _Must_inspect_result_
388     static
389     NTSTATUS
390     _PnpSetLock(
391         __inout FxPkgPnp* This,
392         __inout FxIrp *Irp
393         );
394 
395     _Must_inspect_result_
396     static
397     NTSTATUS
398     _PnpQueryId(
399         __inout FxPkgPnp* This,
400         __inout FxIrp *Irp
401         );
402 
403     _Must_inspect_result_
404     static
405     NTSTATUS
406     _PnpQueryPnpDeviceState(
407         __inout FxPkgPnp* This,
408         __inout FxIrp *Irp
409         );
410 
411     _Must_inspect_result_
412     static
413     NTSTATUS
414     _PnpQueryBusInformation(
415         __inout FxPkgPnp* This,
416         __inout FxIrp *Irp
417         );
418 
419     _Must_inspect_result_
420     static
421     NTSTATUS
422     _PnpSurpriseRemoval(
423         __inout FxPkgPnp* This,
424         __inout FxIrp *Irp
425         );
426 
427     static
428     _Must_inspect_result_
429     NTSTATUS
430     _DispatchPowerSequence(
431         __inout FxPkgPnp* This,
432         __in FxIrp *Irp
433         );
434 
435     static
436     _Must_inspect_result_
437     NTSTATUS
438     _DispatchSetPower(
439         __inout FxPkgPnp* This,
440         __in FxIrp *Irp
441         );
442 
443     _Must_inspect_result_
444     NTSTATUS
445     DispatchSystemSetPower(
446         __in FxIrp *Irp
447         );
448 
449     _Must_inspect_result_
450     NTSTATUS
451     DispatchDeviceSetPower(
452         __in FxIrp *Irp
453         );
454 
455     static
456     _Must_inspect_result_
457     NTSTATUS
458     _DispatchQueryPower(
459         __inout FxPkgPnp* This,
460         __in FxIrp *Irp
461         );
462 
463     virtual
464     _Must_inspect_result_
465     NTSTATUS
466     PowerCheckParentOverload(
467         __in BOOLEAN* ParentOn
468         );
469 
470     virtual
471     WDF_DEVICE_POWER_STATE
472     PowerCheckDeviceTypeOverload(
473         VOID
474         );
475 
476     virtual
477     WDF_DEVICE_POWER_STATE
478     PowerCheckDeviceTypeNPOverload(
479         VOID
480         );
481 
482     virtual
483     _Must_inspect_result_
484     NTSTATUS
485     PowerEnableWakeAtBusOverload(
486         VOID
487         );
488 
489     virtual
490     VOID
491     PowerDisableWakeAtBusOverload(
492         VOID
493         );
494 
495     virtual
496     VOID
497     PowerParentPowerDereference(
498         VOID
499         );
500 
501     virtual
502     VOID
503     PowerReleasePendingDeviceIrp(
504         __in BOOLEAN IrpMustBePresent = TRUE
505         );
506 
507     _Must_inspect_result_
508     virtual
509     NTSTATUS
510     ProcessRemoveDeviceOverload(
511         __inout FxIrp* Irp
512         );
513 
514     virtual
515     VOID
516     DeleteSymbolicLinkOverload(
517         __in BOOLEAN GracefulRemove
518         );
519 
520     virtual
521     VOID
QueryForReenumerationInterface(VOID)522     QueryForReenumerationInterface(
523         VOID
524         )
525     {
526         //
527         // As the PDO, we already have the interface built in
528         //
529         DO_NOTHING();
530     }
531 
532     virtual
533     VOID
ReleaseReenumerationInterface(VOID)534     ReleaseReenumerationInterface(
535         VOID
536         )
537     {
538         //
539         // As the PDO, we already have the interface built in
540         //
541         DO_NOTHING();
542     }
543 
544     _Must_inspect_result_
545     virtual
546     NTSTATUS
547     AskParentToRemoveAndReenumerate(
548         VOID
549         );
550 
551     _Must_inspect_result_
552     virtual
553     NTSTATUS
554     QueryForPowerThread(
555         VOID
556         );
557 
558     virtual
559     const PFN_PNP_POWER_CALLBACK*
GetDispatchPnp(VOID)560     GetDispatchPnp(
561         VOID
562         )
563     {
564         return m_PdoPnpFunctionTable;
565     }
566 
567     virtual
568     const PFN_PNP_POWER_CALLBACK*
GetDispatchPower(VOID)569     GetDispatchPower(
570         VOID
571         )
572     {
573         return m_PdoPowerFunctionTable;
574     }
575 
576     static
577     VOID
578     STDCALL
579     _RemoveAndReenumerateSelf(
580         __in PVOID Context
581         );
582 
583     VOID
584     PowerNotifyParentChildWakeArmed(
585         VOID
586         );
587 
588     VOID
589     PowerNotifyParentChildWakeDisarmed(
590         VOID
591         );
592 };
593 
594 #endif // _FXPKGPDO_H
595