1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxDeviceApiKm.cpp
8 
9 Abstract:
10 
11     This module exposes the "C" interface to the FxDevice object.
12 
13 Author:
14 
15 
16 
17 Environment:
18 
19     Kernel mode only
20 
21 Revision History:
22 
23 --*/
24 
25 #include "coreprivshared.hpp"
26 #include "fxiotarget.hpp"
27 
28 extern "C" {
29 // #include "FxDeviceApiKm.tmh"
30 }
31 
32 //
33 // extern "C" the entire file
34 //
35 extern "C" {
36 
37 //
38 // Verifier Functions
39 //
40 // Do not specify argument names
41 FX_DECLARE_VF_FUNCTION_P3(
42 VOID,
43 VerifyWdfDeviceWdmDispatchIrp,
44     _In_ PWDF_DRIVER_GLOBALS,
45     _In_ FxDevice*,
46     _In_ WDFCONTEXT
47     );
48 
49 // Do not specify argument names
50 FX_DECLARE_VF_FUNCTION_P4(
51 NTSTATUS,
52 VerifyWdfDeviceWdmDispatchIrpToIoQueue,
53     _In_ FxDevice*,
54     _In_ MdIrp,
55     _In_ FxIoQueue*,
56     _In_ ULONG
57     );
58 
__drv_maxIRQL(DISPATCH_LEVEL)59 __drv_maxIRQL(DISPATCH_LEVEL)
60 WDFDEVICE
61 STDCALL
62 WDFEXPORT(WdfWdmDeviceGetWdfDeviceHandle)(
63     __in
64     PWDF_DRIVER_GLOBALS DriverGlobals,
65     __in
66     PDEVICE_OBJECT DeviceObject
67     )
68 {
69     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceObject);
70 
71     return FxDevice::GetFxDevice(DeviceObject)->GetHandle();
72 }
73 
__drv_maxIRQL(DISPATCH_LEVEL)74 __drv_maxIRQL(DISPATCH_LEVEL)
75 PDEVICE_OBJECT
76 STDCALL
77 WDFEXPORT(WdfDeviceWdmGetDeviceObject)(
78     __in
79     PWDF_DRIVER_GLOBALS DriverGlobals,
80     __in
81     WDFDEVICE Device
82     )
83 {
84     FxDeviceBase *pDevice;
85 
86     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
87                          Device,
88                          FX_TYPE_DEVICE_BASE,
89                          (PVOID*) &pDevice);
90 
91     return pDevice->GetDeviceObject();
92 }
93 
__drv_maxIRQL(DISPATCH_LEVEL)94 __drv_maxIRQL(DISPATCH_LEVEL)
95 PDEVICE_OBJECT
96 STDCALL
97 WDFEXPORT(WdfDeviceWdmGetAttachedDevice)(
98     __in
99     PWDF_DRIVER_GLOBALS DriverGlobals,
100     __in
101     WDFDEVICE Device
102     )
103 {
104     FxDeviceBase *pDevice;
105 
106     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
107                          Device,
108                          FX_TYPE_DEVICE_BASE,
109                          (PVOID*) &pDevice);
110 
111     return pDevice->GetAttachedDevice();
112 }
113 
114 
__drv_maxIRQL(DISPATCH_LEVEL)115 __drv_maxIRQL(DISPATCH_LEVEL)
116 PDEVICE_OBJECT
117 STDCALL
118 WDFEXPORT(WdfDeviceWdmGetPhysicalDevice)(
119     __in
120     PWDF_DRIVER_GLOBALS DriverGlobals,
121     __in
122     WDFDEVICE Device
123     )
124 {
125     FxDeviceBase *pDevice;
126 
127     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
128                          Device,
129                          FX_TYPE_DEVICE_BASE,
130                          (PVOID*) &pDevice);
131 
132     return pDevice->GetPhysicalDevice();
133 }
134 
__drv_maxIRQL(DISPATCH_LEVEL)135 __drv_maxIRQL(DISPATCH_LEVEL)
136 WDFFILEOBJECT
137 STDCALL
138 WDFEXPORT(WdfDeviceGetFileObject)(
139     __in
140     PWDF_DRIVER_GLOBALS DriverGlobals,
141     __in
142     WDFDEVICE Device,
143     __in
144     MdFileObject FileObject
145     )
146 /*++
147 
148 Routine Description:
149 
150     This functions returns the WDFFILEOBJECT corresponding to the WDM fileobject.
151 
152 Arguments:
153 
154     Device - Handle to the device to which the WDM fileobject is related to.
155 
156     FileObject - WDM FILE_OBJECT structure.
157 
158 Return Value:
159 
160 --*/
161 
162 {
163     PFX_DRIVER_GLOBALS pFxDriverGlobals;
164     NTSTATUS status;
165     FxFileObject* pFxFO;
166     FxDevice *pDevice;
167 
168     pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
169 
170 
171 
172 
173 
174 
175     pFxFO = NULL;
176 
177     //
178     // Validate the Device object handle, and get its FxDevice*
179     //
180     FxObjectHandleGetPtr(pFxDriverGlobals,
181                          Device,
182                          FX_TYPE_DEVICE,
183                          (PVOID*)&pDevice);
184 
185     //
186     // Call the static GetFileObjectFromWdm function. This will return an error if the
187     // WDM fileObject is NULL and the device is not exclusive or the device is
188     // configured to have a WDFFILEOBJECT for every open handle.
189     //
190     status = FxFileObject::_GetFileObjectFromWdm(
191         pDevice,
192         pDevice->GetFileObjectClass(),
193         FileObject,
194         &pFxFO
195         );
196 
197     if (!NT_SUCCESS(status)) {
198          DoTraceLevelMessage(
199              pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
200              "FxFileObject::_GetFileObjectFromWdm returned an error %!STATUS!",
201              status);
202          return NULL;
203     }
204 
205     //
206     // pFxFO can be NULL if the device is configured with FileObjectClass WdfFileObjectNotRequired.
207     //
208     return pFxFO != NULL ? pFxFO->GetHandle() : NULL;
209 }
210 
211 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)212 __drv_maxIRQL(DISPATCH_LEVEL)
213 NTSTATUS
214 STDCALL
215 WDFEXPORT(WdfDeviceWdmDispatchPreprocessedIrp)(
216     __in
217     PWDF_DRIVER_GLOBALS DriverGlobals,
218     __in
219     WDFDEVICE Device,
220     __in
221     MdIrp Irp
222     )
223 {
224     FxDevice            *device;
225     PFX_DRIVER_GLOBALS  fxDriverGlobals;
226 
227     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
228                                    Device,
229                                    FX_TYPE_DEVICE,
230                                    (PVOID*) &device,
231                                    &fxDriverGlobals);
232 
233     FxPointerNotNull(fxDriverGlobals, Irp);
234 
235     //
236     // Verifier checks.
237     // This API can only be called by the client driver, Cx must call
238     // WdfDeviceWdmDispatchIrp from its preprocess callback.
239     // Also, Cx must register for a Preprocessor routine using
240     // WdfCxDeviceInitAssignWdmIrpPreprocessCallback.
241     //
242     if (fxDriverGlobals->IsVerificationEnabled(1, 11, OkForDownLevel)) {
243         if (device->IsCxInIoPath()) {
244             FxDriver* driver = GetFxDriverGlobals(DriverGlobals)->Driver;
245 
246             if (IsListEmpty(&device->m_PreprocessInfoListHead) ||
247                 device->IsCxDriverInIoPath(driver)) {
248 
249                 DoTraceLevelMessage(
250                         fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO,
251                         "This API can only be called by client driver from its "
252                         "pre-process IRP callback, STATUS_INVALID_DEVICE_REQUEST");
253                 FxVerifierDbgBreakPoint(fxDriverGlobals);
254             }
255         }
256     }
257 
258     //
259     // OK, ready to dispatch IRP.
260     //
261     return device->DispatchPreprocessedIrp(
262                         Irp,
263                         device->m_PreprocessInfoListHead.Flink->Flink);
264 }
265 
266 VOID
FX_VF_FUNCTION(VerifyWdfDeviceWdmDispatchIrp)267 FX_VF_FUNCTION(VerifyWdfDeviceWdmDispatchIrp) (
268     _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
269     _In_ PWDF_DRIVER_GLOBALS DriverGlobals,
270     _In_ FxDevice* device,
271     _In_ WDFCONTEXT  DispatchContext
272     )
273 {
274     UNREFERENCED_PARAMETER(FxDriverGlobals);
275     FxDriver*   driver;
276     BOOLEAN     ctxValid;
277     PLIST_ENTRY next;
278     NTSTATUS    status;
279 
280     PAGED_CODE_LOCKED();
281 
282     status = STATUS_SUCCESS;
283     driver = GetFxDriverGlobals(DriverGlobals)->Driver;
284     ctxValid = (PLIST_ENTRY)DispatchContext ==
285                 &device->m_PreprocessInfoListHead ? TRUE : FALSE;
286     //
287     // Driver should be a cx.
288     //
289     if (device->IsCxDriverInIoPath(driver) == FALSE) {
290         status = STATUS_INVALID_DEVICE_REQUEST;
291         DoTraceLevelMessage(
292                 device->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIO,
293                 "This API can only be called by wdf extension driver "
294                 "from its pre-process IRP callback, %!STATUS!",
295                 status);
296         FxVerifierDbgBreakPoint(device->GetDriverGlobals());
297     }
298 
299     //
300     // Validate DispatchContext.
301     //
302 
303     for (next = device->m_PreprocessInfoListHead.Flink;
304          next != &device->m_PreprocessInfoListHead;
305          next = next->Flink) {
306         if ((PLIST_ENTRY)DispatchContext == next) {
307             ctxValid = TRUE;
308             break;
309         }
310     }
311 
312     if (FALSE == ctxValid) {
313         status = STATUS_INVALID_PARAMETER;
314         DoTraceLevelMessage(
315                 device->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIO,
316                 "DispatchContext 0x%p is invalid, %!STATUS!",
317                 DispatchContext, status);
318         FxVerifierDbgBreakPoint(device->GetDriverGlobals());
319     }
320 }
321 
322 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)323 __drv_maxIRQL(DISPATCH_LEVEL)
324 NTSTATUS
325 STDCALL
326 WDFEXPORT(WdfDeviceWdmDispatchIrp)(
327     __in
328     PWDF_DRIVER_GLOBALS DriverGlobals,
329     __in
330     WDFDEVICE Device,
331     __in
332     MdIrp Irp,
333     __in
334     WDFCONTEXT DispatchContext
335     )
336 
337 /*++
338 
339 Routine Description:
340 
341     Client driver calls this API from its dispatch callback when it decides to hand the IRP
342     back to framework.
343 
344     Cx calls this API from (a) its pre-process callback or (b) its dispatch callback when
345     it decides to hand the IRP back to the framework.
346 
347 Arguments:
348     Device - WDF Device handle.
349 
350     IRP - WDM request.
351 
352     DispatchContext - WDF's context (input arg to callback).
353 
354 Returns:
355     IRP's status.
356 
357 --*/
358 
359 {
360     FxDevice *device;
361     NTSTATUS status;
362 
363     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
364                          Device,
365                          FX_TYPE_DEVICE,
366                          (PVOID*) &device);
367 
368     FxPointerNotNull(device->GetDriverGlobals(), Irp);
369     FxPointerNotNull(device->GetDriverGlobals(), DispatchContext);
370 
371     if ((UCHAR)(ULONG_PTR)DispatchContext & FX_IN_DISPATCH_CALLBACK) {
372         //
373         // Called from a dispach irp callback.
374         //
375         DispatchContext =
376             (WDFCONTEXT)((ULONG_PTR)DispatchContext & ~FX_IN_DISPATCH_CALLBACK);
377 
378         //
379         // DispatchContext is validated by DispatchStep1.
380         //
381         status = device->m_PkgIo->DispatchStep1(Irp, DispatchContext);
382     }
383     else {
384         //
385         // Called from a pre-process irp callback.
386         //
387 
388         //
389         // Verifier checks.
390         //
391         VerifyWdfDeviceWdmDispatchIrp(device->GetDriverGlobals(),
392                                       DriverGlobals,
393                                       device,
394                                       DispatchContext);
395 
396         status = device->DispatchPreprocessedIrp(Irp, DispatchContext);
397     }
398 
399     return status;
400 }
401 
402 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)403 __drv_maxIRQL(DISPATCH_LEVEL)
404 NTSTATUS
405 STDCALL
406 WDFEXPORT(WdfDeviceWdmDispatchIrpToIoQueue)(
407     __in
408     PWDF_DRIVER_GLOBALS DriverGlobals,
409     __in
410     WDFDEVICE Device,
411     __in
412     MdIrp Irp,
413     __in
414     WDFQUEUE Queue,
415     __in
416     ULONG Flags
417     )
418 {
419     FxIoQueue           *queue;
420     FxDevice            *device;
421     PFX_DRIVER_GLOBALS  fxDriverGlobals;
422     PIO_STACK_LOCATION  stack;
423     NTSTATUS            status;
424     FxIoInCallerContext* ioInCallerCtx;
425 
426     queue = NULL;
427     ioInCallerCtx = NULL;
428 
429     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
430                          Device,
431                          FX_TYPE_DEVICE,
432                          (PVOID*) &device);
433 
434     fxDriverGlobals = device->GetDriverGlobals();
435     FX_TRACK_DRIVER(fxDriverGlobals);
436 
437     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
438                          Queue,
439                          FX_TYPE_QUEUE,
440                          (PVOID*)&queue);
441 
442     FxPointerNotNull(fxDriverGlobals, Irp);
443 
444     //
445     // If the caller is a preprocess routine, the contract for this DDI is just like IoCallDriver.
446     // The caller sets up their stack location and then the DDI advances to the next stack
447     // location. This means that the caller either has to call IoSkipCurrentIrpStackLocation
448     // or IoCopyCurrentIrpStackLocationToNext before calling this DDI.
449     //
450     if (Flags & WDF_DISPATCH_IRP_TO_IO_QUEUE_PREPROCESSED_IRP) {
451         IoSetNextIrpStackLocation(Irp);
452     }
453 
454     //
455     // Verifier checks.
456     //
457     status = VerifyWdfDeviceWdmDispatchIrpToIoQueue(fxDriverGlobals,
458                                                     device,
459                                                     Irp,
460                                                     queue,
461                                                     Flags);
462     if(!NT_SUCCESS(status)) {
463         Irp->IoStatus.Status = status;
464         Irp->IoStatus.Information = 0;
465         IoCompleteRequest(Irp, IO_NO_INCREMENT);
466 
467         return status;
468     }
469 
470     //
471     // Adjust stack if IRP needs to be forwarded to parent device.
472     //
473     if (device->m_ParentDevice == queue->GetDevice()) {
474         IoCopyCurrentIrpStackLocationToNext(Irp);
475         IoSetNextIrpStackLocation(Irp);
476 
477         //
478         // From now on use new device.
479         //
480         device = device->m_ParentDevice;
481 
482         //
483         // Save a pointer to the device object for this request so that it can
484         // be used later in completion.
485         //
486         stack = IoGetCurrentIrpStackLocation(Irp);
487         stack->DeviceObject = device->GetDeviceObject();
488     }
489 
490     //
491     // Get in-context caller callback if required.
492     //
493     if (Flags & WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK) {
494         ioInCallerCtx = device->m_PkgIo->GetIoInCallerContextCallback(
495                                                 queue->GetCxDeviceInfo());
496     }
497 
498     //
499     // DispatchStep2 will convert the IRP into a WDFREQUEST, queue it and if
500     // possible dispatch the request to the driver.
501     //
502     return device->m_PkgIo->DispatchStep2(Irp, ioInCallerCtx, queue);
503 }
504 
505 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)506 __drv_maxIRQL(DISPATCH_LEVEL)
507 NTSTATUS
508 STDCALL
509 WDFEXPORT(WdfDeviceAddDependentUsageDeviceObject)(
510     __in
511     PWDF_DRIVER_GLOBALS DriverGlobals,
512     __in
513     WDFDEVICE Device,
514     __in
515     PDEVICE_OBJECT DependentDevice
516     )
517 {
518     PFX_DRIVER_GLOBALS pFxDriverGlobals;
519     FxDevice *pDevice;
520 
521     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
522                                    Device,
523                                    FX_TYPE_DEVICE,
524                                    (PVOID *) &pDevice,
525                                    &pFxDriverGlobals);
526 
527     FxPointerNotNull(pFxDriverGlobals, DependentDevice);
528 
529     return pDevice->m_PkgPnp->AddUsageDevice(DependentDevice);
530 }
531 
__drv_maxIRQL(DISPATCH_LEVEL)532 __drv_maxIRQL(DISPATCH_LEVEL)
533 VOID
534 STDCALL
535 WDFEXPORT(WdfDeviceRemoveDependentUsageDeviceObject)(
536     __in
537     PWDF_DRIVER_GLOBALS DriverGlobals,
538     __in
539     WDFDEVICE Device,
540     __in
541     PDEVICE_OBJECT DependentDevice
542     )
543 {
544     PFX_DRIVER_GLOBALS pFxDriverGlobals;
545     FxDevice *pDevice;
546 
547     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
548                                    Device,
549                                    FX_TYPE_DEVICE,
550                                    (PVOID *) &pDevice,
551                                    &pFxDriverGlobals);
552 
553     FxPointerNotNull(pFxDriverGlobals, DependentDevice);
554 
555     return pDevice->m_PkgPnp->RemoveUsageDevice(DependentDevice);
556 }
557 
558 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)559 __drv_maxIRQL(PASSIVE_LEVEL)
560 NTSTATUS
561 STDCALL
562 WDFEXPORT(WdfDeviceAssignMofResourceName)(
563     __in
564     PWDF_DRIVER_GLOBALS DriverGlobals,
565     __in
566     WDFDEVICE Device,
567     __in
568     PCUNICODE_STRING MofResourceName
569     )
570 {
571     PFX_DRIVER_GLOBALS pFxDriverGlobals;
572     FxDevice *pDevice;
573     NTSTATUS status;
574 
575     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
576                                    Device,
577                                    FX_TYPE_DEVICE,
578                                    (PVOID *) &pDevice,
579                                    &pFxDriverGlobals);
580 
581     FxPointerNotNull(pFxDriverGlobals, MofResourceName);
582 
583     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
584     if (!NT_SUCCESS(status)) {
585         return status;
586     }
587 
588     status = FxValidateUnicodeString(pFxDriverGlobals, MofResourceName);
589     if (!NT_SUCCESS(status)) {
590         return status;
591     }
592 
593     if (pDevice->m_MofResourceName.Buffer !=  NULL) {
594         status = STATUS_INVALID_DEVICE_REQUEST;
595 
596         DoTraceLevelMessage(
597             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
598             "WDFDEVICE %p MofResourceName already assigned, %!STATUS!",
599             Device, status);
600 
601         return status;
602     }
603 
604     status = FxDuplicateUnicodeString(pFxDriverGlobals,
605                                       MofResourceName,
606                                       &pDevice->m_MofResourceName);
607 
608     if (!NT_SUCCESS(status)) {
609         DoTraceLevelMessage(
610             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
611             "WDFDEVICE %p couldn't creat duplicate buffer, %!STATUS!",
612             Device, status);
613     }
614 
615     return status;
616 }
617 
__drv_maxIRQL(DISPATCH_LEVEL)618 __drv_maxIRQL(DISPATCH_LEVEL)
619 VOID
620 STDCALL
621 WDFEXPORT(WdfDeviceSetSpecialFileSupport)(
622     __in
623     PWDF_DRIVER_GLOBALS DriverGlobals,
624     __in
625     WDFDEVICE Device,
626     __in
627     WDF_SPECIAL_FILE_TYPE FileType,
628     __in
629     BOOLEAN Supported
630     )
631 {
632     FxDevice* pDevice;
633     PFX_DRIVER_GLOBALS pFxDriverGlobals;
634 
635     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
636                                    Device,
637                                    FX_TYPE_DEVICE,
638                                    (PVOID *) &pDevice,
639                                    &pFxDriverGlobals);
640 
641     if (FileType < WdfSpecialFilePaging  || FileType >= WdfSpecialFileMax) {
642         DoTraceLevelMessage(
643             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
644             "WDFDEVICE 0x%p FileType %d specified is not in valid range",
645             Device, FileType);
646         FxVerifierDbgBreakPoint(pFxDriverGlobals);
647         return;
648     }
649 
650     FxObjectHandleGetPtr(pFxDriverGlobals,
651                          Device,
652                          FX_TYPE_DEVICE,
653                          (PVOID*) &pDevice);
654 
655     pDevice->m_PkgPnp->SetSpecialFileSupport(FileType, Supported);
656 }
657 
658 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)659 __drv_maxIRQL(DISPATCH_LEVEL)
660 NTSTATUS
661 STDCALL
662 WDFEXPORT(WdfDeviceIndicateWakeStatus)(
663     __in
664     PWDF_DRIVER_GLOBALS DriverGlobals,
665     __in
666     WDFDEVICE Device,
667     __in
668     NTSTATUS WaitWakeStatus
669     )
670 {
671     NTSTATUS status;
672     FxDevice *pDevice;
673     PFX_DRIVER_GLOBALS pFxDriverGlobals;
674 
675     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
676                                    Device,
677                                    FX_TYPE_DEVICE,
678                                    (PVOID *) &pDevice,
679                                    &pFxDriverGlobals);
680 
681     if (Device == NULL ||
682         WaitWakeStatus == STATUS_PENDING || WaitWakeStatus == STATUS_CANCELLED) {
683         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
684                             "NULL WDFDEVICE handle %p or invalid %!STATUS!",
685                             Device, WaitWakeStatus);
686         return STATUS_INVALID_PARAMETER;
687     }
688 
689     if (pDevice->m_PkgPnp->m_SharedPower.m_WaitWakeOwner) {
690         if (pDevice->m_PkgPnp->PowerIndicateWaitWakeStatus(WaitWakeStatus)) {
691             status = STATUS_SUCCESS;
692         }
693         else {
694             //
695             // There was no request to complete
696             //
697             DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
698                                 "WDFDEVICE 0x%p  No request to complete"
699                                 " STATUS_INVALID_DEVICE_REQUEST",
700                                 Device);
701 
702             status = STATUS_INVALID_DEVICE_REQUEST;
703         }
704     }
705     else {
706         //
707         // We cannot complete what we do not own
708         //
709         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
710                             "WDFDEVICE 0x%p  Not the waitwake owner"
711                             " STATUS_INVALID_DEVICE_STATE",
712                             Device);
713 
714         status = STATUS_INVALID_DEVICE_STATE;
715     }
716 
717     return status;
718 }
719 
__drv_maxIRQL(DISPATCH_LEVEL)720 __drv_maxIRQL(DISPATCH_LEVEL)
721 VOID
722 STDCALL
723 WDFEXPORT(WdfDeviceSetBusInformationForChildren)(
724     __in
725     PWDF_DRIVER_GLOBALS DriverGlobals,
726     __in
727     WDFDEVICE Device,
728     __in
729     PPNP_BUS_INFORMATION BusInformation
730     )
731 {
732     FxDevice* pDevice;
733 
734     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
735                          Device,
736                          FX_TYPE_DEVICE,
737                          (PVOID*) &pDevice);
738 
739     FxPointerNotNull(pDevice->GetDriverGlobals(), BusInformation);
740 
741     pDevice->m_PkgPnp->SetChildBusInformation(BusInformation);
742 }
743 
744 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)745 __drv_maxIRQL(DISPATCH_LEVEL)
746 NTSTATUS
747 STDCALL
748 WDFEXPORT(WdfDeviceAddRemovalRelationsPhysicalDevice)(
749     __in
750     PWDF_DRIVER_GLOBALS DriverGlobals,
751     __in
752     WDFDEVICE Device,
753     __in
754     PDEVICE_OBJECT PhysicalDevice
755     )
756 /*++
757 
758 Routine Description:
759     Registers a PDO from another non descendant (not verifiable though) pnp
760     stack to be reported as also requiring removal when this PDO is removed.
761 
762     The PDO could be another device enumerated by this driver.
763 
764 Arguments:
765     Device - this driver's PDO
766 
767     PhysicalDevice - PDO for another stack
768 
769 Return Value:
770     NTSTATUS
771 
772   --*/
773 {
774     FxDevice* pDevice;
775 
776     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
777                          Device,
778                          FX_TYPE_DEVICE,
779                          (PVOID*) &pDevice);
780 
781     FxPointerNotNull(pDevice->GetDriverGlobals(), PhysicalDevice);
782 
783     return pDevice->m_PkgPnp->AddRemovalDevice(PhysicalDevice);
784 }
785 
__drv_maxIRQL(DISPATCH_LEVEL)786 __drv_maxIRQL(DISPATCH_LEVEL)
787 VOID
788 STDCALL
789 WDFEXPORT(WdfDeviceRemoveRemovalRelationsPhysicalDevice)(
790     __in
791     PWDF_DRIVER_GLOBALS DriverGlobals,
792     __in
793     WDFDEVICE Device,
794     __in
795     PDEVICE_OBJECT PhysicalDevice
796     )
797 /*++
798 
799 Routine Description:
800     Deregisters a PDO from another non descendant (not verifiable though) pnp
801     stack to not be reported as also requiring removal when this PDO is removed.
802 
803     The PDO could be another device enumerated by this driver.
804 
805 Arguments:
806     Device - this driver's PDO
807 
808     PhysicalDevice - PDO for another stack
809 
810 Return Value:
811     None
812 
813   --*/
814 {
815     FxDevice* pDevice;
816 
817     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
818                          Device,
819                          FX_TYPE_DEVICE,
820                          (PVOID*) &pDevice);
821 
822     FxPointerNotNull(pDevice->GetDriverGlobals(), PhysicalDevice);
823 
824     pDevice->m_PkgPnp->RemoveRemovalDevice(PhysicalDevice);
825 }
826 
__drv_maxIRQL(DISPATCH_LEVEL)827 __drv_maxIRQL(DISPATCH_LEVEL)
828 VOID
829 STDCALL
830 WDFEXPORT(WdfDeviceClearRemovalRelationsDevices)(
831     __in
832     PWDF_DRIVER_GLOBALS DriverGlobals,
833     __in
834     WDFDEVICE Device
835     )
836 /*++
837 
838 Routine Description:
839     Deregisters all PDOs to not be reported as also requiring removal when this
840     PDO is removed.
841 
842 Arguments:
843     Device - this driver's PDO
844 
845 Return Value:
846     None
847 
848   --*/
849 {
850     FxDevice* pDevice;
851 
852     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
853                          Device,
854                          FX_TYPE_DEVICE,
855                          (PVOID*) &pDevice);
856 
857     pDevice->m_PkgPnp->ClearRemovalDevicesList();
858 }
859 
860 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)861 __drv_maxIRQL(PASSIVE_LEVEL)
862 NTSTATUS
863 STDCALL
864 WDFEXPORT(WdfDeviceWdmAssignPowerFrameworkSettings)(
865     __in
866     PWDF_DRIVER_GLOBALS DriverGlobals,
867     __in
868     WDFDEVICE Device,
869     __in
870     PWDF_POWER_FRAMEWORK_SETTINGS PowerFrameworkSettings
871     )
872 /*++
873 
874 Routine Description:
875     The DDI is invoked by KMDF client drivers for single-component devices to
876     specify their power framework settings to KMDF. KMDF uses these settings on
877     Win8+ when registering with the power framework.
878 
879     On Win7 and older operating systems the power framework is not available, so
880     KMDF does nothing.
881 
882 Arguments:
883 
884     Device - Handle to the framework device object for which power framework
885       settings are being specified.
886 
887     PowerFrameworkSettings - Pointer to a WDF_POWER_FRAMEWORK_SETTINGS structure
888       that contains the client driver's power framework settings.
889 
890 Return Value:
891     An NTSTATUS value that denotes success or failure of the DDI
892 
893 --*/
894 {
895     NTSTATUS status;
896     PFX_DRIVER_GLOBALS pFxDriverGlobals;
897     FxDevice *pDevice;
898 
899     //
900     // Validate the Device object handle and get its FxDevice. Also get the
901     // driver globals pointer.
902     //
903     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
904                                    Device,
905                                    FX_TYPE_DEVICE,
906                                    (PVOID *) &pDevice,
907                                    &pFxDriverGlobals);
908 
909     FxPointerNotNull(pFxDriverGlobals, PowerFrameworkSettings);
910 
911     //
912     // Only power policy owners should call this DDI
913     //
914     if (pDevice->m_PkgPnp->IsPowerPolicyOwner() == FALSE) {
915         status = STATUS_INVALID_DEVICE_REQUEST;
916         DoTraceLevelMessage(
917             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
918             "WDFDEVICE 0x%p is not the power policy owner, so the caller cannot"
919             " assign power framework settings %!STATUS!", Device, status);
920         FxVerifierDbgBreakPoint(pFxDriverGlobals);
921         return status;
922     }
923 
924     //
925     // Validate the Settings parameter
926     //
927     if (PowerFrameworkSettings->Size != sizeof(WDF_POWER_FRAMEWORK_SETTINGS)) {
928         status = STATUS_INFO_LENGTH_MISMATCH;
929         DoTraceLevelMessage(
930             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
931             "WDFDEVICE 0x%p Expected PowerFrameworkSettings size %d, actual %d,"
932             " %!STATUS!",
933             Device,
934             sizeof(WDF_POWER_FRAMEWORK_SETTINGS),
935             PowerFrameworkSettings->Size,
936             status);
937         FxVerifierDbgBreakPoint(pFxDriverGlobals);
938         return status;
939     }
940 
941     //
942     // If settings for component 0 are specified, make sure it contains at least
943     // one F-state.
944     //
945     if (NULL != PowerFrameworkSettings->Component) {
946 
947         if (0 == PowerFrameworkSettings->Component->IdleStateCount) {
948             status = STATUS_INVALID_PARAMETER;
949             DoTraceLevelMessage(
950                 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
951                 "WDFDEVICE 0x%p Component settings are specified but "
952                 "IdleStateCount is 0. %!STATUS!", Device, status);
953             FxVerifierDbgBreakPoint(pFxDriverGlobals);
954             return status;
955         }
956 
957         if (NULL == PowerFrameworkSettings->Component->IdleStates) {
958             status = STATUS_INVALID_PARAMETER;
959             DoTraceLevelMessage(
960                 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
961                 "WDFDEVICE 0x%p Component settings are specified but IdleStates"
962                 " is NULL. %!STATUS!", Device, status);
963             FxVerifierDbgBreakPoint(pFxDriverGlobals);
964             return status;
965         }
966     }
967 
968     //
969     // Assign the driver's settings
970     //
971     status = pDevice->m_PkgPnp->AssignPowerFrameworkSettings(
972                                             PowerFrameworkSettings);
973 
974     return status;
975 }
976 
977 } // extern "C"
978