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