1 /*++
2
3 Copyright (c) Microsoft Corporation
4
5 Module Name:
6
7 FxDeviceApi.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 Both kernel and user mode
20
21 Revision History:
22
23 --*/
24
25 #include "coreprivshared.hpp"
26 #include "fxiotarget.hpp"
27
28 extern "C" {
29 // #include "FxDeviceApi.tmh"
30 }
31
32 struct FxOffsetAndName {
33 __nullterminated PCHAR Name;
34 UCHAR Offset;
35 };
36
37 #define OFFSET_AND_NAME(type, offset) { #offset, FIELD_OFFSET(type, offset) }
38
39 //
40 // extern "C" the entire file
41 //
42 extern "C" {
43
__drv_maxIRQL(DISPATCH_LEVEL)44 __drv_maxIRQL(DISPATCH_LEVEL)
45 WDFDRIVER
46 STDCALL
47 WDFEXPORT(WdfDeviceGetDriver)(
48 __in
49 PWDF_DRIVER_GLOBALS DriverGlobals,
50 __in
51 WDFDEVICE Device
52 )
53 /*++
54
55 Routine Description:
56
57 Given a Device Handle, return a Handle to the Driver object
58 containing this device.
59
60 Arguments:
61 Device - WDF Device handle.
62
63 Returns:
64 WDF Driver handle.
65
66 --*/
67
68 {
69 DDI_ENTRY();
70
71 FxDevice* pDevice;
72
73 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
74 Device,
75 FX_TYPE_DEVICE,
76 (PVOID*) &pDevice);
77
78 //
79 // No need to ref count the driver handle b/c it will be around as long
80 // as the device handle is.
81 //
82 return pDevice->GetDriver()->GetHandle();
83 }
84
__drv_maxIRQL(DISPATCH_LEVEL)85 __drv_maxIRQL(DISPATCH_LEVEL)
86 WDFIOTARGET
87 STDCALL
88 WDFEXPORT(WdfDeviceGetIoTarget)(
89 __in
90 PWDF_DRIVER_GLOBALS DriverGlobals,
91 __in
92 WDFDEVICE Device
93 )
94 {
95 DDI_ENTRY();
96
97 FxIoTarget* pTarget;
98 FxDeviceBase *pDeviceBase;
99
100 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
101 Device,
102 FX_TYPE_DEVICE_BASE,
103 (PVOID*) &pDeviceBase);
104
105 pTarget = pDeviceBase->GetDefaultIoTarget();
106
107 if (pTarget != NULL) {
108 return pTarget->GetHandle();
109 }
110
111 return NULL;
112 }
113
_IRQL_requires_max_(DISPATCH_LEVEL)114 _IRQL_requires_max_(DISPATCH_LEVEL)
115 WDFIOTARGET
116 STDCALL
117 WDFEXPORT(WdfDeviceGetSelfIoTarget)(
118 _In_
119 PWDF_DRIVER_GLOBALS DriverGlobals,
120 _In_
121 WDFDEVICE Device
122 )
123
124 /*++
125
126 Routine Description:
127
128 Return the handle to the Self IO target for the device. A Self
129 IO target is only created if the client opted for it by calling
130 WdfDeviceInitAllowSelfTarget
131
132 Arguments:
133
134 Device - Handle to the Device Object for which Self IO target is needed
135
136 Returns:
137
138 WDFIOTARGET handle to the Self IO Target. NULL is returned in case the
139 device does not have an Self IO target.
140
141 --*/
142
143 {
144 DDI_ENTRY();
145
146 FxIoTargetSelf* pTarget;
147 FxDevice *pDevice;
148
149 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
150 Device,
151 FX_TYPE_DEVICE,
152 (PVOID*) &pDevice);
153
154 pTarget = pDevice->GetSelfIoTarget();
155
156 if (pTarget != NULL) {
157 return pTarget->GetHandle();
158 }
159
160 return NULL;
161 }
162
163 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)164 __drv_maxIRQL(PASSIVE_LEVEL)
165 NTSTATUS
166 STDCALL
167 WDFEXPORT(WdfDeviceRetrieveDeviceName)(
168 __in
169 PWDF_DRIVER_GLOBALS DriverGlobals,
170 __in
171 WDFDEVICE Device,
172 __in
173 WDFSTRING String
174 )
175 {
176 DDI_ENTRY();
177
178 PFX_DRIVER_GLOBALS pFxDriverGlobals;
179 FxDevice *pDevice;
180 FxString* pString;
181 NTSTATUS status;
182
183 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
184 Device,
185 FX_TYPE_DEVICE,
186 (PVOID *) &pDevice,
187 &pFxDriverGlobals);
188
189 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
190 if (!NT_SUCCESS(status)) {
191 return status;
192 }
193
194 FxObjectHandleGetPtr(pFxDriverGlobals,
195 String,
196 FX_TYPE_STRING,
197 (PVOID*) &pString);
198
199 if (pDevice->m_DeviceName.Buffer != NULL) {
200 status = pString->Assign(&pDevice->m_DeviceName);
201 }
202 else {
203 status = STATUS_INVALID_PARAMETER;
204 DoTraceLevelMessage(
205 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
206 "Device name for WDFDEVICE 0x%p is NULL. Possibly incorrect "
207 "device handle was passed, %!STATUS!", Device, status);
208 }
209
210 return status;
211 }
212
__drv_maxIRQL(DISPATCH_LEVEL)213 __drv_maxIRQL(DISPATCH_LEVEL)
214 VOID
215 STDCALL
216 WDFEXPORT(WdfDeviceSetCharacteristics)(
217 __in
218 PWDF_DRIVER_GLOBALS DriverGlobals,
219 __in
220 WDFDEVICE Device,
221 __in
222 ULONG DeviceCharacteristics
223 )
224 {
225 DDI_ENTRY();
226
227 FxDevice *pDevice;
228 MxDeviceObject deviceObject;
229
230 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
231 Device,
232 FX_TYPE_DEVICE,
233 (PVOID*) &pDevice);
234
235 deviceObject.SetObject(pDevice->GetDeviceObject());
236 deviceObject.SetCharacteristics(DeviceCharacteristics |
237 FILE_DEVICE_SECURE_OPEN);
238 }
239
__drv_maxIRQL(DISPATCH_LEVEL)240 __drv_maxIRQL(DISPATCH_LEVEL)
241 ULONG
242 STDCALL
243 WDFEXPORT(WdfDeviceGetCharacteristics)(
244 __in
245 PWDF_DRIVER_GLOBALS DriverGlobals,
246 __in
247 WDFDEVICE Device
248 )
249 {
250 DDI_ENTRY();
251
252 FxDevice *pDevice;
253 MxDeviceObject deviceObject;
254
255 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
256 Device,
257 FX_TYPE_DEVICE,
258 (PVOID*) &pDevice);
259
260 deviceObject.SetObject(pDevice->GetDeviceObject());
261
262 return deviceObject.GetCharacteristics();
263 }
264
__drv_maxIRQL(DISPATCH_LEVEL)265 __drv_maxIRQL(DISPATCH_LEVEL)
266 ULONG
267 STDCALL
268 WDFEXPORT(WdfDeviceGetAlignmentRequirement)(
269 __in
270 PWDF_DRIVER_GLOBALS DriverGlobals,
271 __in
272 WDFDEVICE Device
273 )
274 {
275 DDI_ENTRY();
276
277 FxDeviceBase* pDeviceBase;
278 MxDeviceObject deviceObject;
279
280 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
281 Device,
282 FX_TYPE_DEVICE_BASE,
283 (PVOID*) &pDeviceBase);
284
285 deviceObject.SetObject(pDeviceBase->GetDeviceObject());
286
287 return deviceObject.GetAlignmentRequirement();
288 }
289
__drv_maxIRQL(DISPATCH_LEVEL)290 __drv_maxIRQL(DISPATCH_LEVEL)
291 VOID
292 STDCALL
293 WDFEXPORT(WdfDeviceSetAlignmentRequirement)(
294 __in
295 PWDF_DRIVER_GLOBALS DriverGlobals,
296 __in
297 WDFDEVICE Device,
298 __in
299 ULONG AlignmentRequirement
300 )
301 {
302 DDI_ENTRY();
303
304 FxDeviceBase* pDeviceBase;
305 MxDeviceObject deviceObject;
306
307 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
308 Device,
309 FX_TYPE_DEVICE_BASE,
310 (PVOID*) &pDeviceBase);
311
312 deviceObject.SetObject(pDeviceBase->GetDeviceObject());
313
314 deviceObject.SetAlignmentRequirement(AlignmentRequirement);
315 }
316
__drv_maxIRQL(DISPATCH_LEVEL)317 __drv_maxIRQL(DISPATCH_LEVEL)
318 WDF_DEVICE_PNP_STATE
319 STDCALL
320 WDFEXPORT(WdfDeviceGetDevicePnpState)(
321 __in
322 PWDF_DRIVER_GLOBALS DriverGlobals,
323 __in
324 WDFDEVICE Device
325 )
326 {
327 DDI_ENTRY();
328
329 FxDevice *pDevice;
330
331 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
332 Device,
333 FX_TYPE_DEVICE,
334 (PVOID*) &pDevice);
335
336 return pDevice->GetDevicePnpState();
337 }
338
__drv_maxIRQL(DISPATCH_LEVEL)339 __drv_maxIRQL(DISPATCH_LEVEL)
340 WDF_DEVICE_POWER_STATE
341 STDCALL
342 WDFEXPORT(WdfDeviceGetDevicePowerState)(
343 __in
344 PWDF_DRIVER_GLOBALS DriverGlobals,
345 __in
346 WDFDEVICE Device
347 )
348 {
349 DDI_ENTRY();
350
351 FxDevice *pDevice;
352
353 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
354 Device,
355 FX_TYPE_DEVICE,
356 (PVOID*) &pDevice);
357
358 return pDevice->GetDevicePowerState();
359 }
360
__drv_maxIRQL(DISPATCH_LEVEL)361 __drv_maxIRQL(DISPATCH_LEVEL)
362 WDF_DEVICE_POWER_POLICY_STATE
363 STDCALL
364 WDFEXPORT(WdfDeviceGetDevicePowerPolicyState)(
365 __in
366 PWDF_DRIVER_GLOBALS DriverGlobals,
367 __in
368 WDFDEVICE Device
369 )
370 {
371 DDI_ENTRY();
372
373 FxDevice *pDevice;
374
375 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
376 Device,
377 FX_TYPE_DEVICE,
378 (PVOID*) &pDevice);
379
380 return pDevice->GetDevicePowerPolicyState();
381 }
382
383 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)384 __drv_maxIRQL(DISPATCH_LEVEL)
385 NTSTATUS
386 STDCALL
387 WDFEXPORT(WdfDeviceAssignS0IdleSettings)(
388 __in
389 PWDF_DRIVER_GLOBALS DriverGlobals,
390 __in
391 WDFDEVICE Device,
392 __in
393 PWDF_DEVICE_POWER_POLICY_IDLE_SETTINGS Settings
394 )
395 {
396 DDI_ENTRY();
397
398 PFX_DRIVER_GLOBALS pFxDriverGlobals;
399 NTSTATUS status;
400 FxDevice* pDevice;
401
402 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
403 Device,
404 FX_TYPE_DEVICE,
405 (PVOID *) &pDevice,
406 &pFxDriverGlobals);
407
408 FxPointerNotNull(pFxDriverGlobals, Settings);
409
410 if (pDevice->m_PkgPnp->IsPowerPolicyOwner() == FALSE) {
411 status = STATUS_INVALID_DEVICE_REQUEST;
412
413 DoTraceLevelMessage(
414 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
415 "Device 0x%p is not the power policy owner, caller cannot set S0"
416 " idle settings %!STATUS!", Device, status);
417
418 return status;
419 }
420
421 //
422 // Validate the Settings parameter
423 //
424 if (Settings->Size != sizeof(WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS) &&
425 Settings->Size != sizeof(WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_V1_9) &&
426 Settings->Size != sizeof(WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_V1_7)) {
427 status = STATUS_INFO_LENGTH_MISMATCH;
428 DoTraceLevelMessage(
429 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
430 "Expected Settings Size %d, got %d, %!STATUS!",
431 sizeof(WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS), Settings->Size,
432 status);
433 return status;
434 }
435 else if (Settings->DxState < PowerDeviceD1 ||
436 Settings->DxState > PowerDeviceMaximum ||
437 Settings->IdleCaps < IdleCannotWakeFromS0 ||
438 Settings->IdleCaps > IdleUsbSelectiveSuspend ||
439 Settings->UserControlOfIdleSettings < IdleDoNotAllowUserControl ||
440 Settings->UserControlOfIdleSettings > IdleAllowUserControl ||
441 Settings->Enabled < WdfFalse ||
442 Settings->Enabled > WdfUseDefault) {
443
444 status = STATUS_INVALID_PARAMETER;
445 DoTraceLevelMessage(
446 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
447 "a field (DxState, IdleCaps, Enabled, or UserControlOfIdleSettings)"
448 " is out range, %!STATUS!", status);
449 return status;
450 }
451
452 //
453 // PowerUpIdleDeviceOnSystemWake is available only on > 1.7 and can be set to true
454 // only when IdleCaps is IdleCannotWakeFromS0
455 //
456 if (Settings->Size > sizeof(WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_V1_7)) {
457 if (Settings->PowerUpIdleDeviceOnSystemWake < WdfFalse ||
458 Settings->PowerUpIdleDeviceOnSystemWake > WdfUseDefault) {
459
460 status = STATUS_INVALID_PARAMETER;
461 DoTraceLevelMessage(
462 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
463 "value of field PowerUpIdleDeviceOnSystemWake is out of range,"
464 " %!STATUS!", status);
465 return status;
466 }
467 else if (Settings->IdleCaps != IdleCannotWakeFromS0 &&
468 Settings->PowerUpIdleDeviceOnSystemWake != WdfUseDefault) {
469
470 status = STATUS_INVALID_PARAMETER;
471 DoTraceLevelMessage(
472 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
473 "value of field PowerUpIdleDeviceOnSystemWake should be set only when"
474 " IdleCaps is IdleCannotWakeFromS0, %!STATUS!", status);
475 return status;
476 }
477 }
478
479 //
480 // IdleTimeoutType is available only on > 1.9
481 //
482 if (Settings->Size > sizeof(WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_V1_9)) {
483 if (Settings->IdleTimeoutType > SystemManagedIdleTimeoutWithHint) {
484 status = STATUS_INVALID_PARAMETER;
485 DoTraceLevelMessage(
486 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
487 "WDFDEVICE %p, value of field IdleTimeoutType is out of range,"
488 " %!STATUS!", Device, status);
489 return status;
490 }
491 }
492
493 return pDevice->m_PkgPnp->PowerPolicySetS0IdleSettings(Settings);
494 }
495
496 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)497 __drv_maxIRQL(DISPATCH_LEVEL)
498 NTSTATUS
499 STDCALL
500 WDFEXPORT(WdfDeviceAssignSxWakeSettings)(
501 __in
502 PWDF_DRIVER_GLOBALS DriverGlobals,
503 __in
504 WDFDEVICE Device,
505 __in
506 PWDF_DEVICE_POWER_POLICY_WAKE_SETTINGS Settings
507 )
508 {
509 DDI_ENTRY();
510
511 NTSTATUS status;
512 FxDevice* pDevice;
513 PFX_DRIVER_GLOBALS pFxDriverGlobals;
514 BOOLEAN armForWakeIfChildrenAreArmedForWake;
515 BOOLEAN indicateChildWakeOnParentWake;
516
517 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
518 Device,
519 FX_TYPE_DEVICE,
520 (PVOID *) &pDevice,
521 &pFxDriverGlobals);
522
523 FxPointerNotNull(pFxDriverGlobals, Settings);
524
525 if (pDevice->m_PkgPnp->IsPowerPolicyOwner() == FALSE) {
526 status = STATUS_INVALID_DEVICE_REQUEST;
527
528 DoTraceLevelMessage(
529 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
530 "Device 0x%p is not the power policy owner, caller cannot set Sx"
531 " wake settings %!STATUS!", Device, status);
532
533 return status;
534 }
535
536 //
537 // Validate the Settings parameter
538 //
539 if (Settings->Size != sizeof(WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS) &&
540 Settings->Size != sizeof(WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_V1_5)) {
541 status = STATUS_INFO_LENGTH_MISMATCH;
542 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
543 "Expected Settings Size %x, got %x, %!STATUS!",
544 sizeof(WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS),
545 Settings->Size,
546 status);
547 return status;
548 }
549 else if (Settings->DxState < PowerDeviceD1 ||
550 Settings->DxState > PowerDeviceMaximum ||
551 Settings->UserControlOfWakeSettings < WakeDoNotAllowUserControl ||
552 Settings->UserControlOfWakeSettings > WakeAllowUserControl ||
553 Settings->Enabled < WdfFalse ||
554 Settings->Enabled > WdfUseDefault) {
555
556 status = STATUS_INVALID_PARAMETER;
557 DoTraceLevelMessage(
558 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
559 "a field (DxState, Enabled, or UserControlOfIdleSettings) is out "
560 "range, %!STATUS!", status);
561 return status;
562 }
563
564 //
565 // Extract the values from the structure for all the parameters that were
566 // added after v1.5. Since the size of the structure can only grow, get
567 // the values only if we are using a version of the struct after v1.5
568 //
569
570 //
571 // ArmForWakeIfChildrenAreArmedForWake added after v1.5
572 //
573 armForWakeIfChildrenAreArmedForWake =
574 (Settings->Size > sizeof(WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_V1_5)) ?
575 Settings->ArmForWakeIfChildrenAreArmedForWake :
576 FALSE;
577
578 //
579 // IndicateChildWakeOnParentWake added after v1.5
580 //
581 indicateChildWakeOnParentWake =
582 (Settings->Size > sizeof(WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_V1_5)) ?
583 Settings->IndicateChildWakeOnParentWake :
584 FALSE;
585
586 return pDevice->m_PkgPnp->PowerPolicySetSxWakeSettings(
587 Settings,
588 armForWakeIfChildrenAreArmedForWake,
589 indicateChildWakeOnParentWake);
590 }
591
592 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)593 __drv_maxIRQL(PASSIVE_LEVEL)
594 NTSTATUS
595 STDCALL
596 WDFEXPORT(WdfDeviceOpenRegistryKey)(
597 __in
598 PWDF_DRIVER_GLOBALS DriverGlobals,
599 __in
600 WDFDEVICE Device,
601 __in
602 ULONG DeviceInstanceKeyType,
603 __in
604 ACCESS_MASK DesiredAccess,
605 __in_opt
606 PWDF_OBJECT_ATTRIBUTES KeyAttributes,
607 __out
608 WDFKEY* Key
609 )
610 {
611 DDI_ENTRY();
612
613 NTSTATUS status;
614 FxDevice* pDevice;
615 PFX_DRIVER_GLOBALS pFxDriverGlobals;
616
617 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
618 Device,
619 FX_TYPE_DEVICE,
620 (PVOID *) &pDevice,
621 &pFxDriverGlobals);
622
623 FxPointerNotNull(pFxDriverGlobals, Key);
624
625 *Key = NULL;
626
627 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
628 if (!NT_SUCCESS(status)) {
629 FxVerifierDbgBreakPoint(pFxDriverGlobals);
630 return status;
631 }
632
633 status = FxValidateObjectAttributes(pFxDriverGlobals, KeyAttributes,
634 FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
635 if (!NT_SUCCESS(status)) {
636
637 return status;
638 }
639
640 return FxDevice::_OpenKey(pDevice->GetDriverGlobals(),
641 NULL,
642 pDevice,
643 DeviceInstanceKeyType,
644 DesiredAccess,
645 KeyAttributes,
646 Key);
647 }
648
649 _Must_inspect_result_
_IRQL_requires_max_(PASSIVE_LEVEL)650 _IRQL_requires_max_(PASSIVE_LEVEL)
651 NTSTATUS
652 STDCALL
653 WDFEXPORT(WdfDeviceOpenDevicemapKey) (
654 _In_
655 PWDF_DRIVER_GLOBALS DriverGlobals,
656 _In_
657 WDFDEVICE Device,
658 _In_
659 PCUNICODE_STRING KeyName,
660 _In_
661 ACCESS_MASK DesiredAccess,
662 _In_opt_
663 PWDF_OBJECT_ATTRIBUTES KeyAttributes,
664 _Out_
665 WDFKEY* Key
666 )
667 {
668 DDI_ENTRY();
669
670 NTSTATUS status;
671 FxDevice* pDevice;
672 PFX_DRIVER_GLOBALS pFxDriverGlobals;
673 FxRegKey* pKey = NULL;
674 WDFKEY keyHandle;
675
676 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
677 Device,
678 FX_TYPE_DEVICE,
679 (PVOID *) &pDevice,
680 &pFxDriverGlobals);
681
682 FxPointerNotNull(pFxDriverGlobals, Key);
683
684 *Key = NULL;
685
686 status = FxValidateUnicodeString(pFxDriverGlobals, KeyName);
687 if (!NT_SUCCESS(status)) {
688 return status;
689 }
690
691 if (KeyName->Length == 0) {
692 status = STATUS_INVALID_PARAMETER;
693 DoTraceLevelMessage(
694 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
695 "The subkey cannot be of length zero, %!STATUS!", status);
696 return status;
697 }
698
699 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
700 if (!NT_SUCCESS(status)) {
701 FxVerifierDbgBreakPoint(pFxDriverGlobals);
702 return status;
703 }
704
705 status = FxValidateObjectAttributes(pFxDriverGlobals, KeyAttributes,
706 FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
707 if (!NT_SUCCESS(status)) {
708 return status;
709 }
710
711 pKey = new(pFxDriverGlobals, KeyAttributes) FxRegKey(pFxDriverGlobals);
712
713 if (pKey == NULL) {
714 status = STATUS_INSUFFICIENT_RESOURCES;
715 DoTraceLevelMessage(
716 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
717 "Unable to allocate memory for WDFKEY object, %!STATUS!", status);
718 return status;
719 }
720
721 pKey->SetDeviceBase(pDevice);
722
723 status = pKey->Commit(KeyAttributes, (WDFOBJECT*)&keyHandle);
724 if (NT_SUCCESS(status)) {
725
726 status = pDevice->OpenDevicemapKeyWorker(pFxDriverGlobals,
727 KeyName,
728 DesiredAccess,
729 pKey);
730 if (NT_SUCCESS(status)) {
731 *Key = keyHandle;
732 }
733 }
734
735 if (!NT_SUCCESS(status)) {
736 pKey->DeleteFromFailedCreate();
737 pKey = NULL;
738 }
739
740 return status;
741 }
742
__drv_maxIRQL(DISPATCH_LEVEL)743 __drv_maxIRQL(DISPATCH_LEVEL)
744 VOID
745 STDCALL
746 WDFEXPORT(WdfDeviceGetDeviceState)(
747 __in
748 PWDF_DRIVER_GLOBALS DriverGlobals,
749 __in
750 WDFDEVICE Device,
751 __out
752 PWDF_DEVICE_STATE DeviceState
753 )
754 {
755 DDI_ENTRY();
756
757 FxDevice *pDevice;
758 PFX_DRIVER_GLOBALS pFxDriverGlobals;
759
760 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
761 Device,
762 FX_TYPE_DEVICE,
763 (PVOID *) &pDevice,
764 &pFxDriverGlobals);
765
766 FxPointerNotNull(pFxDriverGlobals, DeviceState);
767
768 if (DeviceState->Size != sizeof(WDF_DEVICE_STATE)) {
769 DoTraceLevelMessage(
770 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
771 "WDFDEVICE 0x%p DeviceState Size %d, expected %d",
772 Device, DeviceState->Size, sizeof(WDF_DEVICE_STATE));
773
774 FxVerifierDbgBreakPoint(pFxDriverGlobals);
775
776 return; // STATUS_INFO_LENGTH_MISMATCH;
777 }
778
779 pDevice->m_PkgPnp->GetPnpState(DeviceState);
780 }
781
__drv_maxIRQL(DISPATCH_LEVEL)782 __drv_maxIRQL(DISPATCH_LEVEL)
783 VOID
784 STDCALL
785 WDFEXPORT(WdfDeviceSetDeviceState)(
786 __in
787 PWDF_DRIVER_GLOBALS DriverGlobals,
788 __in
789 WDFDEVICE Device,
790 __in
791 PWDF_DEVICE_STATE DeviceState
792 )
793 {
794 DDI_ENTRY();
795
796 FxDevice *pDevice;
797 PFX_DRIVER_GLOBALS pFxDriverGlobals;
798 ULONG i;
799
800 const static FxOffsetAndName offsets[] = {
801 OFFSET_AND_NAME(WDF_DEVICE_STATE, Disabled),
802 OFFSET_AND_NAME(WDF_DEVICE_STATE, DontDisplayInUI),
803 OFFSET_AND_NAME(WDF_DEVICE_STATE, Failed),
804 OFFSET_AND_NAME(WDF_DEVICE_STATE, NotDisableable),
805 OFFSET_AND_NAME(WDF_DEVICE_STATE, Removed),
806 OFFSET_AND_NAME(WDF_DEVICE_STATE, ResourcesChanged),
807 };
808
809 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
810 Device,
811 FX_TYPE_DEVICE,
812 (PVOID *) &pDevice,
813 &pFxDriverGlobals);
814
815 FxPointerNotNull(pFxDriverGlobals, DeviceState);
816
817 if (DeviceState->Size != sizeof(WDF_DEVICE_STATE)) {
818 DoTraceLevelMessage(
819 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
820 "WDFDEVICE 0x%p, DeviceState Size %d, expected %d",
821 Device, DeviceState->Size, sizeof(WDF_DEVICE_STATE));
822
823 FxVerifierDbgBreakPoint(pFxDriverGlobals);
824 return; // STATUS_INFO_LENGTH_MISMATCH;
825 }
826
827 for (i = 0; i < ARRAY_SIZE(offsets); i++) {
828 WDF_TRI_STATE value;
829
830 //
831 // This check makes prefast happy
832 //
833 if (offsets[i].Offset + sizeof(WDF_TRI_STATE) > sizeof(*DeviceState)) {
834 return;
835 }
836
837 value = *(WDF_TRI_STATE*) WDF_PTR_ADD_OFFSET(DeviceState,
838 offsets[i].Offset);
839
840 switch (value) {
841 case WdfFalse:
842 case WdfTrue:
843 case WdfUseDefault:
844 break;
845
846 default:
847 DoTraceLevelMessage(
848 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
849 "WDFDEVICE 0x%p DeviceState WDF_TRI_STATE %s value out of range, "
850 "value is %d", Device, offsets[i].Name, value);
851 FxVerifierDbgBreakPoint(pFxDriverGlobals);
852
853 return; // STATUS_INVALID_PARAMETER
854 }
855 }
856
857 pDevice->m_PkgPnp->SetPnpState(DeviceState);
858
859 pDevice->InvalidateDeviceState();
860 }
861
862
863 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)864 __drv_maxIRQL(PASSIVE_LEVEL)
865 NTSTATUS
866 STDCALL
867 WDFEXPORT(WdfDeviceCreate)(
868 __in
869 PWDF_DRIVER_GLOBALS DriverGlobals,
870
871
872 __inout
873
874 PWDFDEVICE_INIT* DeviceInit,
875 __in_opt
876 PWDF_OBJECT_ATTRIBUTES DeviceAttributes,
877 __out
878 WDFDEVICE* Device
879 )
880 {
881 DDI_ENTRY();
882
883 FxDevice* pDevice;
884 NTSTATUS status;
885 PFX_DRIVER_GLOBALS pFxDriverGlobals;
886
887 pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
888
889 FxPointerNotNull(pFxDriverGlobals, DeviceInit);
890 FxPointerNotNull(pFxDriverGlobals, *DeviceInit);
891 FxPointerNotNull(pFxDriverGlobals, Device);
892
893 //
894 // Use the object's globals, not the caller's globals
895 //
896 pFxDriverGlobals = (*DeviceInit)->DriverGlobals;
897
898 *Device = NULL;
899
900 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
901 if (!NT_SUCCESS(status)) {
902 return status;
903 }
904
905 //
906 // Make sure the device attributes is initialized properly if passed in
907 //
908 status = FxValidateObjectAttributes(pFxDriverGlobals,
909 DeviceAttributes,
910 (FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED |
911 FX_VALIDATE_OPTION_EXECUTION_LEVEL_ALLOWED |
912 FX_VALIDATE_OPTION_SYNCHRONIZATION_SCOPE_ALLOWED));
913
914 if (!NT_SUCCESS(status)) {
915 return status;
916 }
917
918 if ((*DeviceInit)->CreatedDevice != NULL) {
919 //
920 // Already created the device!
921 //
922 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
923 "WDFDEVICE 0x%p already created"
924 "STATUS_INVALID_DEVICE_STATE",
925 Device);
926
927 return STATUS_INVALID_DEVICE_STATE;
928 }
929
930 //
931 // If security is specified, then the device being created *must* have a
932 // name to apply that security too.
933 //
934 if ((*DeviceInit)->Security.Sddl != NULL || (*DeviceInit)->Security.DeviceClassSet) {
935 if ((*DeviceInit)->HasName()) {
936 //
937 // Driver writer specified a name, all is good
938 //
939 DO_NOTHING();
940 }
941 else {
942 status = STATUS_INVALID_SECURITY_DESCR;
943
944 DoTraceLevelMessage(
945 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
946 "Device init: has device class or SDDL set, but does not have "
947 "a name, %!STATUS!", status);
948
949 return status;
950 }
951 }
952
953 if ((*DeviceInit)->RequiresSelfIoTarget) {
954 if ((*DeviceInit)->InitType != FxDeviceInitTypeFdo) {
955 status = STATUS_INVALID_DEVICE_REQUEST;
956 DoTraceLevelMessage(
957 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
958 "Client called WdfDeviceInitAllowSelfTarget. Self "
959 "IO Targets are supported only for FDOs, %!STATUS!", status);
960 return status;
961 }
962 }
963
964 status = FxDevice::_Create(pFxDriverGlobals,
965 DeviceInit,
966 DeviceAttributes,
967 &pDevice);
968 if (NT_SUCCESS(status)) {
969 *Device = pDevice->GetHandle();
970 }
971
972 return status;
973 }
974
975 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)976 __drv_maxIRQL(PASSIVE_LEVEL)
977 NTSTATUS
978 STDCALL
979 WDFEXPORT(WdfDeviceCreateSymbolicLink)(
980 __in
981 PWDF_DRIVER_GLOBALS DriverGlobals,
982 __in
983 WDFDEVICE Device,
984 __in
985 PCUNICODE_STRING SymbolicLinkName
986 )
987 {
988 DDI_ENTRY();
989
990 PFX_DRIVER_GLOBALS pFxDriverGlobals;
991 FxAutoString pdoName;
992 FxDevice* pDevice;
993 NTSTATUS status;
994
995 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
996 Device,
997 FX_TYPE_DEVICE,
998 (PVOID *) &pDevice,
999 &pFxDriverGlobals);
1000
1001 FxPointerNotNull(pFxDriverGlobals, SymbolicLinkName);
1002
1003 if (SymbolicLinkName->Length == 0) {
1004 status = STATUS_INVALID_DEVICE_REQUEST;
1005
1006 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1007 "WDFDEVICE %p, SymbolicLinkName has no length, %!STATUS!",
1008 Device, status);
1009
1010 return status;
1011 }
1012
1013 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1014 if (!NT_SUCCESS(status)) {
1015 return status;
1016 }
1017
1018 status = FxValidateUnicodeString(pFxDriverGlobals, SymbolicLinkName);
1019 if (!NT_SUCCESS(status)) {
1020 return status;
1021 }
1022
1023 if (pDevice->m_SymbolicLinkName.Buffer != NULL) {
1024 status = STATUS_INVALID_DEVICE_REQUEST;
1025
1026 DoTraceLevelMessage(
1027 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1028 "WDFDEVICE %p already has a symbolic link associated with it, %!STATUS!",
1029 Device, status);
1030
1031 return status;
1032 }
1033
1034 status = pDevice->CreateSymbolicLink(pFxDriverGlobals, SymbolicLinkName);
1035
1036 return status;
1037 }
1038
1039 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)1040 __drv_maxIRQL(PASSIVE_LEVEL)
1041 NTSTATUS
1042 STDCALL
1043 WDFEXPORT(WdfDeviceQueryProperty)(
1044 __in
1045 PWDF_DRIVER_GLOBALS DriverGlobals,
1046 __in
1047 WDFDEVICE Device,
1048 __in
1049 DEVICE_REGISTRY_PROPERTY DeviceProperty,
1050 __in
1051 ULONG BufferLength,
1052 __out_bcount_full(BufferLength)
1053 PVOID PropertyBuffer,
1054 __out
1055 PULONG ResultLength
1056 )
1057 /*++
1058
1059 Routine Description:
1060 Retrieves the requested device property for the given device
1061
1062 Arguments:
1063 Device - the device whose PDO whose will be queried
1064
1065 DeviceProperty - the property being queried
1066
1067 BufferLength - length of PropertyBuffer in bytes
1068
1069 PropertyBuffer - Buffer which will receive the property being queried
1070
1071 ResultLength - if STATUS_BUFFER_TOO_SMALL is returned, then this will contain
1072 the required length
1073
1074 Return Value:
1075 NTSTATUS
1076
1077 --*/
1078 {
1079 DDI_ENTRY();
1080
1081 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1082 FxDevice* pDevice;
1083 NTSTATUS status;
1084
1085 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1086 Device,
1087 FX_TYPE_DEVICE,
1088 (PVOID *) &pDevice,
1089 &pFxDriverGlobals);
1090
1091 FxPointerNotNull(pFxDriverGlobals, ResultLength);
1092 if (BufferLength > 0) {
1093 FxPointerNotNull(pFxDriverGlobals, PropertyBuffer);
1094 }
1095
1096 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1097 if (!NT_SUCCESS(status)) {
1098 return status;
1099 }
1100
1101 if (pDevice->IsLegacy()) {
1102 status = STATUS_INVALID_DEVICE_REQUEST;
1103
1104 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1105 "WDFDEVICE 0x%p is not a PnP device %!STATUS!",
1106 Device, status);
1107
1108 return status;
1109 }
1110
1111 status = FxDevice::_QueryProperty(pFxDriverGlobals,
1112 NULL,
1113 pDevice,
1114 NULL,
1115 DeviceProperty,
1116 BufferLength,
1117 PropertyBuffer,
1118 ResultLength);
1119
1120 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGDEVICE,
1121 "exit WDFDEVICE %p, Property %d, %!STATUS!",
1122 Device, DeviceProperty, status);
1123
1124 return status;
1125 }
1126
1127 _Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)1128 __drv_maxIRQL(PASSIVE_LEVEL)
1129 NTSTATUS
1130 STDCALL
1131 WDFEXPORT(WdfDeviceAllocAndQueryProperty)(
1132 __in
1133 PWDF_DRIVER_GLOBALS DriverGlobals,
1134 __in
1135 WDFDEVICE Device,
1136 __in
1137 DEVICE_REGISTRY_PROPERTY DeviceProperty,
1138 __in
1139 __drv_strictTypeMatch(__drv_typeExpr)
1140 POOL_TYPE PoolType,
1141 __in_opt
1142 PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes,
1143 __out
1144 WDFMEMORY* PropertyMemory
1145 )
1146 /*++
1147
1148 Routine Description:
1149 Allocates and retrieves the requested device property for the given device
1150
1151 Arguments:
1152 Device - the pnp device whose PDO whose will be queried
1153
1154 DeviceProperty - the property being queried
1155
1156 PoolType - what type of pool to allocate
1157
1158 PropertyMemoryAttributes - attributes to associate with PropertyMemory
1159
1160 PropertyMemory - handle which will receive the property buffer
1161
1162 Return Value:
1163 NTSTATUS
1164
1165 --*/
1166 {
1167 DDI_ENTRY();
1168
1169 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1170 FxDevice* pDevice;
1171 NTSTATUS status;
1172
1173 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1174 Device,
1175 FX_TYPE_DEVICE,
1176 (PVOID *) &pDevice,
1177 &pFxDriverGlobals);
1178
1179 FxPointerNotNull(pFxDriverGlobals, PropertyMemory);
1180
1181 *PropertyMemory = NULL;
1182
1183 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1184 if (!NT_SUCCESS(status)) {
1185 return status;
1186 }
1187
1188 FxVerifierCheckNxPoolType(pFxDriverGlobals, PoolType, pFxDriverGlobals->Tag);
1189
1190 status = FxValidateObjectAttributes(pFxDriverGlobals, PropertyMemoryAttributes);
1191 if (!NT_SUCCESS(status)) {
1192 return status;
1193 }
1194
1195 if (pDevice->IsLegacy()) {
1196 status = STATUS_INVALID_DEVICE_REQUEST;
1197
1198 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1199 "WDFDEVICE %p is not a PnP device, %!STATUS!",
1200 Device, status);
1201
1202 return status;
1203 }
1204
1205 status = FxDevice::_AllocAndQueryProperty(pFxDriverGlobals,
1206 NULL,
1207 pDevice,
1208 NULL,
1209 DeviceProperty,
1210 PoolType,
1211 PropertyMemoryAttributes,
1212 PropertyMemory);
1213
1214 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGDEVICE,
1215 "exit WDFDEVICE %p, Property %d, %!STATUS!",
1216 Device, DeviceProperty, status);
1217
1218 return status;
1219 }
1220
__drv_maxIRQL(DISPATCH_LEVEL)1221 __drv_maxIRQL(DISPATCH_LEVEL)
1222 VOID
1223 STDCALL
1224 WDFEXPORT(WdfDeviceSetStaticStopRemove)(
1225 __in
1226 PWDF_DRIVER_GLOBALS DriverGlobals,
1227 __in
1228 WDFDEVICE Device,
1229 __in
1230 BOOLEAN Stoppable
1231 )
1232 {
1233 DDI_ENTRY();
1234
1235 FxDevice *pDevice;
1236
1237 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
1238 Device,
1239 FX_TYPE_DEVICE,
1240 (PVOID*) &pDevice);
1241
1242 if (Stoppable) {
1243 //
1244 // Stoppable means that query stop / query remove can succeed.
1245 // This means m_DeviceStopCount == 0 (eventually if there are nested
1246 // calls to this function).
1247 //
1248 ASSERT(pDevice->m_PkgPnp->m_DeviceStopCount > 0);
1249 InterlockedDecrement((PLONG) &pDevice->m_PkgPnp->m_DeviceStopCount);
1250 }
1251 else {
1252 InterlockedIncrement((PLONG) &pDevice->m_PkgPnp->m_DeviceStopCount);
1253 }
1254
1255 return;
1256 }
1257
__drv_maxIRQL(DISPATCH_LEVEL)1258 __drv_maxIRQL(DISPATCH_LEVEL)
1259 VOID
1260 STDCALL
1261 WDFEXPORT(WdfDeviceSetFailed)(
1262 __in
1263 PWDF_DRIVER_GLOBALS DriverGlobals,
1264 __in
1265 WDFDEVICE Device,
1266 __in
1267 WDF_DEVICE_FAILED_ACTION FailedAction
1268 )
1269 {
1270 DDI_ENTRY();
1271
1272 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1273 FxDevice *pDevice;
1274
1275 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1276 Device,
1277 FX_TYPE_DEVICE,
1278 (PVOID *) &pDevice,
1279 &pFxDriverGlobals);
1280
1281 if (FailedAction < WdfDeviceFailedAttemptRestart ||
1282 FailedAction > WdfDeviceFailedNoRestart) {
1283 DoTraceLevelMessage(
1284 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1285 "Invalid FailedAction %d", FailedAction);
1286 FxVerifierDbgBreakPoint(pDevice->GetDriverGlobals());
1287 return;
1288 }
1289
1290 DoTraceLevelMessage(
1291 pFxDriverGlobals, TRACE_LEVEL_INFORMATION, TRACINGDEVICE,
1292 "WDFDEVICE %p, !devobj %p SetFailed %!WDF_DEVICE_FAILED_ACTION!",
1293 Device, pDevice->GetDeviceObject(), FailedAction);
1294
1295 pDevice->m_PkgPnp->SetDeviceFailed(FailedAction);
1296 }
1297
1298 __inline
1299 NTSTATUS
StopIdleWorker(__in PWDF_DRIVER_GLOBALS DriverGlobals,__in WDFDEVICE Device,__in BOOLEAN WaitForD0,__in PVOID Tag,__in LONG Line,__in PSTR File)1300 StopIdleWorker(
1301 __in
1302 PWDF_DRIVER_GLOBALS DriverGlobals,
1303 __in
1304 WDFDEVICE Device,
1305 __in
1306 BOOLEAN WaitForD0,
1307 __in
1308 PVOID Tag,
1309 __in
1310 LONG Line,
1311 __in
1312 PSTR File
1313 )
1314 {
1315 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1316 NTSTATUS status;
1317 FxDevice *pDevice;
1318
1319 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1320 Device,
1321 FX_TYPE_DEVICE,
1322 (PVOID *) &pDevice,
1323 &pFxDriverGlobals);
1324
1325 if (WaitForD0) {
1326 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals,
1327 PASSIVE_LEVEL);
1328 if (!NT_SUCCESS(status)) {
1329 return status;
1330 }
1331 }
1332
1333
1334 if (pDevice->m_PkgPnp->IsPowerPolicyOwner() == FALSE) {
1335 status = STATUS_INVALID_DEVICE_STATE;
1336 DoTraceLevelMessage(
1337 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1338 "WDFDEVICE %p WdfDeviceStopIdle does nothing if you are not the power "
1339 "policy owner for the stack, %!STATUS!", Device, status);
1340 return status;
1341 }
1342
1343 status = pDevice->m_PkgPnp->PowerReference(WaitForD0, Tag, Line, File);
1344
1345 DoTraceLevelMessage(
1346 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGDEVICE,
1347 "WDFDEVICE %p WdfDeviceStopIdle, WaitForD0 %d %!STATUS!",
1348 Device, WaitForD0, status);
1349
1350 return status;
1351 }
1352
1353 __inline
1354 VOID
ResumeIdleWorker(__in PWDF_DRIVER_GLOBALS DriverGlobals,__in WDFDEVICE Device,__in PVOID Tag,__in LONG Line,__in PSTR File)1355 ResumeIdleWorker(
1356 __in
1357 PWDF_DRIVER_GLOBALS DriverGlobals,
1358 __in
1359 WDFDEVICE Device,
1360 __in
1361 PVOID Tag,
1362 __in
1363 LONG Line,
1364 __in
1365 PSTR File
1366 )
1367 {
1368 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1369 FxDevice *pDevice;
1370
1371 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1372 Device,
1373 FX_TYPE_DEVICE,
1374 (PVOID *) &pDevice,
1375 &pFxDriverGlobals);
1376
1377 if (pDevice->m_PkgPnp->IsPowerPolicyOwner() == FALSE) {
1378 DoTraceLevelMessage(
1379 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1380 "WdfDeviceResumeIdle does nothing if you are not the power "
1381 "policy owner for the stack");
1382 return;
1383 }
1384
1385 pDevice->m_PkgPnp->PowerDereference(Tag, Line, File);
1386 }
1387
1388 _Must_inspect_result_
1389 __drv_when(WaitForD0 == 0, __drv_maxIRQL(DISPATCH_LEVEL))
1390 __drv_when(WaitForD0 != 0, __drv_maxIRQL(PASSIVE_LEVEL))
1391 NTSTATUS
1392 STDCALL
WDFEXPORT(WdfDeviceStopIdleNoTrack)1393 WDFEXPORT(WdfDeviceStopIdleNoTrack)(
1394 __in
1395 PWDF_DRIVER_GLOBALS DriverGlobals,
1396 __in
1397 WDFDEVICE Device,
1398 __in
1399 BOOLEAN WaitForD0
1400 )
1401 {
1402 DDI_ENTRY();
1403
1404 NTSTATUS status;
1405
1406 status = StopIdleWorker(DriverGlobals,
1407 Device,
1408 WaitForD0,
1409 NULL,
1410 0,
1411 NULL);
1412
1413 return status;
1414 }
1415
1416 _Must_inspect_result_
1417 __drv_when(WaitForD0 == 0, __drv_maxIRQL(DISPATCH_LEVEL))
1418 __drv_when(WaitForD0 != 0, __drv_maxIRQL(PASSIVE_LEVEL))
1419 NTSTATUS
1420 STDCALL
WDFEXPORT(WdfDeviceStopIdleActual)1421 WDFEXPORT(WdfDeviceStopIdleActual)(
1422 __in
1423 PWDF_DRIVER_GLOBALS DriverGlobals,
1424 __in
1425 WDFDEVICE Device,
1426 __in
1427 BOOLEAN WaitForD0,
1428 __in_opt
1429 PVOID Tag,
1430 __in
1431 LONG Line,
1432 __in
1433 PSTR File
1434 )
1435 {
1436 DDI_ENTRY();
1437
1438 NTSTATUS status;
1439
1440 status = StopIdleWorker(DriverGlobals,
1441 Device,
1442 WaitForD0,
1443 Tag,
1444 Line,
1445 File);
1446
1447 return status;
1448 }
1449
__drv_maxIRQL(DISPATCH_LEVEL)1450 __drv_maxIRQL(DISPATCH_LEVEL)
1451 VOID
1452 STDCALL
1453 WDFEXPORT(WdfDeviceResumeIdleNoTrack)(
1454 __in
1455 PWDF_DRIVER_GLOBALS DriverGlobals,
1456 __in
1457 WDFDEVICE Device
1458 )
1459 {
1460 DDI_ENTRY();
1461
1462 ResumeIdleWorker(DriverGlobals,
1463 Device,
1464 NULL,
1465 0,
1466 NULL);
1467 }
1468
__drv_maxIRQL(DISPATCH_LEVEL)1469 __drv_maxIRQL(DISPATCH_LEVEL)
1470 VOID
1471 STDCALL
1472 WDFEXPORT(WdfDeviceResumeIdleActual)(
1473 __in
1474 PWDF_DRIVER_GLOBALS DriverGlobals,
1475 __in
1476 WDFDEVICE Device,
1477 __in_opt
1478 PVOID Tag,
1479 __in
1480 LONG Line,
1481 __in
1482 PSTR File
1483 )
1484 {
1485 DDI_ENTRY();
1486
1487 ResumeIdleWorker(DriverGlobals,
1488 Device,
1489 Tag,
1490 Line,
1491 File);
1492 }
1493
__drv_maxIRQL(DISPATCH_LEVEL)1494 __drv_maxIRQL(DISPATCH_LEVEL)
1495 VOID
1496 STDCALL
1497 WDFEXPORT(WdfDeviceSetPnpCapabilities)(
1498 __in
1499 PWDF_DRIVER_GLOBALS DriverGlobals,
1500 __in
1501 WDFDEVICE Device,
1502 __in
1503 PWDF_DEVICE_PNP_CAPABILITIES PnpCapabilities
1504 )
1505 /*++
1506
1507 Routine Description:
1508 Sets the pnp capabilities of the device. This function is usually called
1509 during AddDevice or EvtDevicePrepareHardware since these values are queried
1510 by the stack and pnp during start device processing or immediately afterwards.
1511
1512 Arguments:
1513 Device - Device being set
1514
1515 PnpCapabilities - Caps being set
1516
1517 Return Value:
1518 None
1519
1520 --*/
1521 {
1522 DDI_ENTRY();
1523
1524 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1525 FxDevice* pDevice;
1526 ULONG i;
1527
1528 const static FxOffsetAndName offsets[] = {
1529 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, LockSupported),
1530 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, EjectSupported),
1531 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, Removable),
1532 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, DockDevice),
1533 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, UniqueID),
1534 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, SilentInstall),
1535 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, SurpriseRemovalOK),
1536 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, HardwareDisabled),
1537 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, NoDisplayInUI),
1538 };
1539
1540 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1541 Device,
1542 FX_TYPE_DEVICE,
1543 (PVOID *) &pDevice,
1544 &pFxDriverGlobals);
1545
1546 FxPointerNotNull(pFxDriverGlobals, PnpCapabilities);
1547
1548 if (PnpCapabilities->Size != sizeof(WDF_DEVICE_PNP_CAPABILITIES)) {
1549 DoTraceLevelMessage(
1550 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1551 "WDFDEVICE 0x%p PnpCapabilities Size %d, expected %d",
1552 Device, PnpCapabilities->Size, sizeof(WDF_DEVICE_PNP_CAPABILITIES));
1553 FxVerifierDbgBreakPoint(pFxDriverGlobals);
1554
1555 return; // STATUS_INFO_LENGTH_MISMATCH;
1556 }
1557 else {
1558 for (i = 0; i < ARRAY_SIZE(offsets); i++) {
1559 WDF_TRI_STATE value;
1560
1561 //
1562 // This check makes prefast happy
1563 //
1564 if (offsets[i].Offset + sizeof(WDF_TRI_STATE) >
1565 sizeof(*PnpCapabilities)) {
1566 return;
1567 }
1568
1569 value = *(WDF_TRI_STATE*) WDF_PTR_ADD_OFFSET(PnpCapabilities,
1570 offsets[i].Offset);
1571 switch (value) {
1572 case WdfFalse:
1573 case WdfTrue:
1574 case WdfUseDefault:
1575 break;
1576
1577 default:
1578 DoTraceLevelMessage(
1579 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1580 "WDFDEVICE 0x%p PnpCapabilities WDF_TRI_STATE %s value out "
1581 "of range, value is %d", Device, offsets[i].Name, value);
1582 FxVerifierDbgBreakPoint(pFxDriverGlobals);
1583
1584 return; // STATUS_INVALID_PARAMETER
1585 }
1586 }
1587 }
1588
1589 pDevice->m_PkgPnp->SetPnpCaps(PnpCapabilities);
1590 }
1591
__drv_maxIRQL(DISPATCH_LEVEL)1592 __drv_maxIRQL(DISPATCH_LEVEL)
1593 VOID
1594 STDCALL
1595 WDFEXPORT(WdfDeviceSetPowerCapabilities)(
1596 __in
1597 PWDF_DRIVER_GLOBALS DriverGlobals,
1598 __in
1599 WDFDEVICE Device,
1600 __in
1601 PWDF_DEVICE_POWER_CAPABILITIES PowerCapabilities
1602 )
1603 /*++
1604
1605 Routine Description:
1606 Sets the power capabilities of the device. This function is usually called
1607 during AddDevice or EvtDevicePrepareHardware since these values are queried
1608 by the stack and power during start device processing or immediately afterwards.
1609
1610 Arguments:
1611 Device - Device being set
1612
1613 PowerCapabilities - Caps being set
1614
1615 Return Value:
1616 None
1617
1618 --*/
1619 {
1620 DDI_ENTRY();
1621
1622 FxDevice* pDevice;
1623 ULONG i;
1624 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1625
1626 const static FxOffsetAndName offsets[] = {
1627 OFFSET_AND_NAME(WDF_DEVICE_POWER_CAPABILITIES, DeviceD1),
1628 OFFSET_AND_NAME(WDF_DEVICE_POWER_CAPABILITIES, DeviceD2),
1629 OFFSET_AND_NAME(WDF_DEVICE_POWER_CAPABILITIES, WakeFromD0),
1630 OFFSET_AND_NAME(WDF_DEVICE_POWER_CAPABILITIES, WakeFromD1),
1631 OFFSET_AND_NAME(WDF_DEVICE_POWER_CAPABILITIES, WakeFromD2),
1632 OFFSET_AND_NAME(WDF_DEVICE_POWER_CAPABILITIES, WakeFromD3),
1633 };
1634
1635 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1636 Device,
1637 FX_TYPE_DEVICE,
1638 (PVOID *) &pDevice,
1639 &pFxDriverGlobals);
1640
1641 FxPointerNotNull(pFxDriverGlobals, PowerCapabilities);
1642
1643 if (PowerCapabilities->Size != sizeof(WDF_DEVICE_POWER_CAPABILITIES)) {
1644
1645 DoTraceLevelMessage(
1646 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1647 "WDFDEVICE 0x%p PowerCapabilities Size %d, expected %d",
1648 Device, PowerCapabilities->Size,
1649 sizeof(WDF_DEVICE_POWER_CAPABILITIES));
1650
1651 FxVerifierDbgBreakPoint(pFxDriverGlobals);
1652
1653 return; // STATUS_INFO_LENGTH_MISMATCH;
1654 }
1655 else {
1656 for (i = 0; i < ARRAY_SIZE(offsets); i++) {
1657 WDF_TRI_STATE value;
1658
1659 //
1660 // This check makes prefast happy
1661 //
1662 if (offsets[i].Offset + sizeof(WDF_TRI_STATE) >
1663 sizeof(*PowerCapabilities)) {
1664 return;
1665 }
1666
1667 value = *(WDF_TRI_STATE*) WDF_PTR_ADD_OFFSET(PowerCapabilities,
1668 offsets[i].Offset);
1669 switch (value) {
1670 case WdfFalse:
1671 case WdfTrue:
1672 case WdfUseDefault:
1673 break;
1674
1675 default:
1676 DoTraceLevelMessage(
1677 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1678 "WDFDEVICE 0x%p PowerCapabilities WDF_TRI_STATE %s value out "
1679 "of range, value is %d",
1680 Device, offsets[i].Name, value);
1681 FxVerifierDbgBreakPoint(pFxDriverGlobals);
1682
1683 return; // STATUS_INVALID_PARAMETER
1684 }
1685 }
1686
1687 for (i = 0; i < ARRAY_SIZE(PowerCapabilities->DeviceState); i++) {
1688 if (PowerCapabilities->DeviceState[i] < PowerDeviceUnspecified ||
1689 PowerCapabilities->DeviceState[i] > PowerDeviceMaximum) {
1690
1691 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1692 "WDFDEVICE 0x%p PowerCapabilities DeviceState is invalid",
1693 Device);
1694
1695 FxVerifierDbgBreakPoint(pFxDriverGlobals);
1696
1697 return; // STATUS_INVALID_PARAMETER;
1698 }
1699 }
1700
1701 if (PowerCapabilities->DeviceWake < PowerDeviceUnspecified ||
1702 PowerCapabilities->DeviceWake > PowerDeviceMaximum) {
1703
1704 DoTraceLevelMessage(
1705 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1706 "WDFDEVICE 0x%p PowerCapabilities DeviceWake %d is out of range",
1707 Device, PowerCapabilities->DeviceWake);
1708
1709 FxVerifierDbgBreakPoint(pFxDriverGlobals);
1710
1711 return; // STATUS_INVALID_PARAMETER;
1712 }
1713
1714 if (PowerCapabilities->SystemWake < PowerSystemUnspecified ||
1715 PowerCapabilities->SystemWake > PowerSystemMaximum) {
1716
1717 DoTraceLevelMessage(
1718 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1719 "WDFDEVICE 0x%p PowerCapabilities SystemWake %d is out of range",
1720 Device, PowerCapabilities->SystemWake);
1721
1722 FxVerifierDbgBreakPoint(pFxDriverGlobals);
1723
1724 return; // STATUS_INVALID_PARAMETER;
1725 }
1726
1727 if (pDevice->m_PkgPnp->IsPowerPolicyOwner() == FALSE &&
1728 PowerCapabilities->IdealDxStateForSx != PowerDeviceMaximum) {
1729 DoTraceLevelMessage(
1730 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1731 "WDFDEVICE 0x%p PowerCapabilities IdealDxStateForSx %d can only"
1732 " be set by the power policy owner",
1733 Device, PowerCapabilities->IdealDxStateForSx);
1734
1735 FxVerifierDbgBreakPoint(pFxDriverGlobals);
1736
1737 return; // STATUS_INVALID_PARAMETER;
1738 }
1739
1740 //
1741 // D0 is not allowed as an ideal Dx state
1742 //
1743 if (PowerCapabilities->IdealDxStateForSx < PowerDeviceD1 ||
1744 PowerCapabilities->IdealDxStateForSx > PowerDeviceMaximum) {
1745
1746 DoTraceLevelMessage(
1747 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1748 "WDFDEVICE 0x%p PowerCapabilities IdealDxStateForSx %d is out "
1749 "of range", Device, PowerCapabilities->IdealDxStateForSx);
1750
1751 FxVerifierDbgBreakPoint(pFxDriverGlobals);
1752
1753 return; // STATUS_INVALID_PARAMETER;
1754 }
1755 }
1756
1757
1758 pDevice->m_PkgPnp->SetPowerCaps(PowerCapabilities);
1759 }
1760
1761 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)1762 __drv_maxIRQL(DISPATCH_LEVEL)
1763 NTSTATUS
1764 STDCALL
1765 WDFEXPORT(WdfDeviceConfigureRequestDispatching)(
1766 __in
1767 PWDF_DRIVER_GLOBALS DriverGlobals,
1768 __in
1769 WDFDEVICE Device,
1770 __in
1771 WDFQUEUE Queue,
1772 __in
1773 __drv_strictTypeMatch(__drv_typeCond)
1774 WDF_REQUEST_TYPE RequestType
1775 )
1776
1777 /*++
1778
1779 Routine Description:
1780
1781 Configure which IRP_MJ_* requests are automatically
1782 forwarded by the I/O package to the specified Queue.
1783
1784 By default the I/O package sends all requests to the
1785 devices default queue. This API allows certain requests
1786 to be specified to their own queues under driver control.
1787
1788 Arguments:
1789
1790 Device - The device which is handling the IO.
1791
1792 Queue - I/O Queue object to forward specified request to.
1793
1794 RequestType - WDF Request type to be forwarded to the queue
1795
1796 Returns:
1797
1798 NTSTATUS
1799
1800 --*/
1801
1802 {
1803 DDI_ENTRY();
1804
1805 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1806 NTSTATUS status;
1807 FxDevice* pDevice;
1808 FxIoQueue* pFxIoQueue;
1809
1810 pDevice = NULL;
1811 pFxIoQueue = NULL;
1812
1813 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1814 Device,
1815 FX_TYPE_DEVICE,
1816 (PVOID *) &pDevice,
1817 &pFxDriverGlobals);
1818
1819 if (RequestType != WdfRequestTypeCreate &&
1820 RequestType != WdfRequestTypeRead &&
1821 RequestType != WdfRequestTypeWrite &&
1822 RequestType != WdfRequestTypeDeviceControl &&
1823 RequestType != WdfRequestTypeDeviceControlInternal) {
1824 status = STATUS_INVALID_PARAMETER;
1825 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO,
1826 "Invalid RequestType %!WDF_REQUEST_TYPE!, %!STATUS!",
1827 RequestType, status);
1828 return status;
1829 }
1830
1831 //
1832 // Validate the Queue handle
1833 //
1834 FxObjectHandleGetPtr(pFxDriverGlobals,
1835 Queue,
1836 FX_TYPE_QUEUE,
1837 (PVOID*)&pFxIoQueue);
1838
1839 if (pDevice != pFxIoQueue->GetDevice()) {
1840 status = STATUS_INVALID_DEVICE_REQUEST;
1841
1842 DoTraceLevelMessage(
1843 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO,
1844 "Input WDFQUEUE 0x%p doesn't belong to the WDFDEVICE 0x%p, %!STATUS!",
1845 Queue, Device, status);
1846
1847 return status;
1848 }
1849
1850 if (pDevice->IsLegacy()) {
1851 //
1852 // This is a controldevice. Make sure the create is called after the device
1853 // is initialized and ready to accept I/O.
1854 //
1855 MxDeviceObject deviceObject(pDevice->GetDeviceObject());
1856 if ((deviceObject.GetFlags() & DO_DEVICE_INITIALIZING) == 0x0) {
1857
1858 status = STATUS_INVALID_DEVICE_STATE;
1859 DoTraceLevelMessage(
1860 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
1861 "Queue cannot be configured for automatic dispatching"
1862 " after WdfControlDeviceFinishInitializing"
1863 "is called on the WDFDEVICE %p is called %!STATUS!",
1864 Device,
1865 status);
1866 return status;
1867 }
1868 }
1869 else {
1870 //
1871 // This is either FDO or PDO. Make sure it's not started yet.
1872 //
1873 if (pDevice->GetDevicePnpState() != WdfDevStatePnpInit) {
1874 status = STATUS_INVALID_DEVICE_STATE;
1875 DoTraceLevelMessage(
1876 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
1877 "Queue cannot be configured for automatic dispatching"
1878 "after the WDFDEVICE %p is started, %!STATUS!",
1879 Device, status);
1880 return status;
1881 }
1882 }
1883
1884 if (RequestType == WdfRequestTypeCreate) {
1885 status = pDevice->m_PkgGeneral->ConfigureForwarding(pFxIoQueue);
1886 }
1887 else {
1888 status = pDevice->m_PkgIo->ConfigureForwarding(pFxIoQueue, RequestType);
1889 }
1890
1891 return status;
1892 }
1893
__drv_maxIRQL(DISPATCH_LEVEL)1894 __drv_maxIRQL(DISPATCH_LEVEL)
1895 WDFQUEUE
1896 STDCALL
1897 WDFEXPORT(WdfDeviceGetDefaultQueue)(
1898 __in
1899 PWDF_DRIVER_GLOBALS DriverGlobals,
1900 __in
1901 WDFDEVICE Device
1902 )
1903
1904 /*++
1905
1906 Routine Description:
1907
1908 Return the handle to the default queue for the device.
1909
1910 Arguments:
1911
1912 Device - Handle to the Device Object
1913
1914 Returns:
1915
1916 WDFQUEUE
1917
1918 --*/
1919
1920 {
1921 DDI_ENTRY();
1922
1923 FxPkgIo* pPkgIo;;
1924 FxIoQueue* pFxIoQueue;;
1925 FxDevice * pFxDevice;
1926 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1927
1928 pPkgIo = NULL;
1929 pFxIoQueue = NULL;
1930
1931 //
1932 // Validate the I/O Package handle, and get the FxPkgIo*
1933 //
1934 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1935 Device,
1936 FX_TYPE_DEVICE,
1937 (PVOID *) &pFxDevice,
1938 &pFxDriverGlobals);
1939
1940 pPkgIo = (FxPkgIo *) pFxDevice->m_PkgIo;
1941 pFxIoQueue = pPkgIo->GetDefaultQueue();
1942
1943 //
1944 // A default queue is optional
1945 //
1946 if (pFxIoQueue == NULL) {
1947 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGIO,
1948 "No default Queue configured "
1949 "for Device 0x%p", Device);
1950 return NULL;
1951 }
1952
1953 return (WDFQUEUE)pFxIoQueue->GetObjectHandle();;
1954 }
1955
1956 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)1957 __drv_maxIRQL(DISPATCH_LEVEL)
1958 NTSTATUS
1959 STDCALL
1960 WDFEXPORT(WdfDeviceEnqueueRequest)(
1961 __in
1962 PWDF_DRIVER_GLOBALS DriverGlobals,
1963 __in
1964 WDFDEVICE Device,
1965 __in
1966 WDFREQUEST Request
1967 )
1968
1969 /*++
1970
1971 Routine Description:
1972
1973 Inserts a request into the I/O Package processing pipeline.
1974
1975 The given request is processed by the I/O package, forwarding
1976 it to its configured destination or the default queue.
1977
1978 If an EvtIoInCallerContext is callback is registered, it is not called.
1979
1980 Arguments:
1981
1982 Device - Handle to the Device Object
1983
1984 Request - Request to insert in the processing pipeline
1985
1986 Return Value:
1987
1988 STATUS_SUCCESS - Request has been inserted into the I/O processing pipeline
1989
1990 !NT_SUCCESS(status)
1991 STATUS_WDF_BUSY - Device is not accepting requests, the driver still owns the
1992 the request and must complete it, or correct the conditions.
1993
1994 --*/
1995
1996 {
1997 DDI_ENTRY();
1998
1999 PFX_DRIVER_GLOBALS pFxDriverGlobals;
2000 FxDevice *pDevice;
2001 FxRequest* pRequest;
2002
2003 //
2004 // Validate the device object handle
2005 //
2006 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
2007 Device,
2008 FX_TYPE_DEVICE,
2009 (PVOID *) &pDevice,
2010 &pFxDriverGlobals);
2011 //
2012 // Validate Device object handle
2013 //
2014 FxObjectHandleGetPtr(pFxDriverGlobals,
2015 Device,
2016 FX_TYPE_DEVICE,
2017 (PVOID *) &pDevice);
2018
2019 //
2020 // Validate the request object handle
2021 //
2022 FxObjectHandleGetPtr(pFxDriverGlobals,
2023 Request,
2024 FX_TYPE_REQUEST,
2025 (PVOID *) &pRequest);
2026
2027 //
2028 // Dispatch it to the Io Package object
2029 //
2030 return pDevice->m_PkgIo->EnqueueRequest(pDevice, pRequest);
2031 }
2032
__drv_maxIRQL(DISPATCH_LEVEL)2033 __drv_maxIRQL(DISPATCH_LEVEL)
2034 POWER_ACTION
2035 STDCALL
2036 WDFEXPORT(WdfDeviceGetSystemPowerAction)(
2037 __in
2038 PWDF_DRIVER_GLOBALS DriverGlobals,
2039 __in
2040 WDFDEVICE Device
2041 )
2042
2043 /*++
2044
2045 Routine Description:
2046
2047 This DDI returns the System power action.
2048
2049 If the DDI is called in the power down path of a device, it will return the
2050 current system power transition type because of which the device is powering
2051 down. If the DDI is called in the power up path of a device, it will return
2052 the system power transition type which initially put the device into a lower
2053 power state. If the DDI is called during the normal functioning of a device
2054 that is not undergoing a power state transition, or if the device is powering
2055 up as part of the system start up, the DDI will return the PowerActionNone
2056 value.
2057
2058 Arguments:
2059
2060 Device - Handle to the Device Object
2061
2062 Return Value:
2063
2064 Returns a POWER_ACTION enum value that represents the current system power
2065 action with regards to any system power transition underway.
2066
2067 --*/
2068
2069 {
2070 DDI_ENTRY();
2071
2072 FxDevice *pDevice;
2073
2074 //
2075 // Validate Device object handle
2076 //
2077 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
2078 Device,
2079 FX_TYPE_DEVICE,
2080 (PVOID*) &pDevice);
2081
2082 return pDevice->m_PkgPnp->GetSystemPowerAction();
2083 }
2084
2085 _Must_inspect_result_
_IRQL_requires_max_(APC_LEVEL)2086 _IRQL_requires_max_(APC_LEVEL)
2087 WDFAPI
2088 NTSTATUS
2089 STDCALL
2090 WDFEXPORT(WdfDeviceQueryPropertyEx)(
2091 _In_
2092 PWDF_DRIVER_GLOBALS DriverGlobals,
2093 _In_
2094 WDFDEVICE Device,
2095 _In_
2096 PWDF_DEVICE_PROPERTY_DATA DeviceProperty,
2097 _In_
2098 ULONG BufferLength,
2099 _Out_
2100 PVOID PropertyBuffer,
2101 _Out_
2102 PULONG RequiredSize,
2103 _Out_
2104 PDEVPROPTYPE Type
2105 )
2106 /*++
2107
2108 Routine Description:
2109
2110 This routine queries interface property.
2111
2112 Arguments:
2113
2114 DriverGlobals - DriverGlobals pointer
2115
2116 Device - WDF Device handle.
2117
2118 DeviceProperty - A pointer to WDF_DEVICE_PROPERTY_ DATA structure.
2119
2120 BufferLength - The size, in bytes, of the buffer that is pointed to by
2121 PropertyBuffer.
2122
2123 PropertyBuffer - A caller-supplied pointer to a caller-allocated buffer that
2124 receives the requested information. The pointer can be NULL
2125 if the BufferLength parameter is zero.
2126
2127 ResultLength - A caller-supplied location that, on return, contains the
2128 size, in bytes, of the information that the method stored in
2129 PropertyBuffer. If the function's return value is
2130 STATUS_BUFFER_TOO_SMALL, this location receives the required
2131 buffer size.
2132
2133 Type - A pointer to a DEVPROPTYPE variable. If method successfully retrieves
2134 the property data, the routine writes the property type value
2135 to this variable. This value indicates the type of property
2136 data that is in the Data buffer.
2137
2138 Return Value:
2139
2140 Method returns an NTSTATUS value. This routine might return one of the
2141 following values.
2142
2143 STATUS_BUFFER_TOO_SMALL - The supplied buffer is too small to receive the
2144 information. The ResultLength member receives the
2145 size of buffer required.
2146 STATUS_SUCCESS - The operation succeeded.
2147 STATUS_INVALID_PARAMETER - One of the parameters is incorrect.
2148
2149 The method might return other NTSTATUS values.
2150
2151 --*/
2152
2153 {
2154 DDI_ENTRY();
2155
2156 PFX_DRIVER_GLOBALS pFxDriverGlobals;
2157 FxDevice* pDevice;
2158 NTSTATUS status;
2159
2160 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
2161 Device,
2162 FX_TYPE_DEVICE,
2163 (PVOID *) &pDevice,
2164 &pFxDriverGlobals);
2165
2166 FxPointerNotNull(pFxDriverGlobals, DeviceProperty);
2167
2168 //
2169 // Validate PropertyData
2170 //
2171 if (DeviceProperty->Size != sizeof(WDF_DEVICE_PROPERTY_DATA)) {
2172 status = STATUS_INFO_LENGTH_MISMATCH;
2173 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
2174 "PropertyData size (%d) incorrect, expected %d, %!STATUS!",
2175 DeviceProperty->Size,
2176 sizeof(WDF_DEVICE_PROPERTY_DATA), status);
2177 return status;
2178 }
2179
2180 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, APC_LEVEL);
2181 if (!NT_SUCCESS(status)) {
2182 FxVerifierDbgBreakPoint(pFxDriverGlobals);
2183 return status;
2184 }
2185
2186 FxPointerNotNull(pFxDriverGlobals, RequiredSize);
2187 FxPointerNotNull(pFxDriverGlobals, Type);
2188
2189 if (BufferLength != 0 && PropertyBuffer == NULL) {
2190 status = STATUS_INVALID_PARAMETER;
2191 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2192 "Property buffer size is non-zero, while the buffer is NULL"
2193 ", %!STATUS!", status);
2194 return status;
2195 }
2196
2197 if (BufferLength == 0 && PropertyBuffer != NULL) {
2198 status = STATUS_INVALID_PARAMETER;
2199 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2200 "Property buffer size is zero, while the buffer is non-NULL"
2201 ", %!STATUS!", status);
2202 return status;
2203 }
2204
2205 status = FxDevice::_QueryPropertyEx(pFxDriverGlobals,
2206 NULL,
2207 pDevice,
2208 DeviceProperty,
2209 FxDeviceProperty,
2210 BufferLength,
2211 PropertyBuffer,
2212 RequiredSize,
2213 Type);
2214 return status;
2215 }
2216
2217 _Must_inspect_result_
_IRQL_requires_max_(APC_LEVEL)2218 _IRQL_requires_max_(APC_LEVEL)
2219 WDFAPI
2220 NTSTATUS
2221 STDCALL
2222 WDFEXPORT(WdfDeviceAllocAndQueryPropertyEx)(
2223 _In_
2224 PWDF_DRIVER_GLOBALS DriverGlobals,
2225 _In_
2226 WDFDEVICE Device,
2227 _In_
2228 PWDF_DEVICE_PROPERTY_DATA DeviceProperty,
2229 _In_
2230 _Strict_type_match_
2231 POOL_TYPE PoolType,
2232 _In_opt_
2233 PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes,
2234 _Out_
2235 WDFMEMORY* PropertyMemory,
2236 _Out_
2237 PDEVPROPTYPE Type
2238 )
2239 /*++
2240
2241 Routine Description:
2242
2243 This routine queries device property.
2244
2245 Arguments:
2246
2247 DriverGlobals - DriverGlobals pointer
2248
2249 Device - WDF Device handle.
2250
2251 PropertyData - A pointer to WDF_DEVICE_PROPERTY_ DATA structure.
2252
2253 PoolType - A POOL_TYPE-typed enumerator that specifies the type of memory
2254 to be allocated.
2255
2256 PropertyMemoryAttributes - optional, A pointer to a caller-allocated
2257 WDF_OBJECT_ATTRIBUTES structure that describes object attributes
2258 for the memory object that the function will allocate. This
2259 parameter is optional and can be WDF_NO_OBJECT_ATTRIBUTES.
2260
2261 PropertyMemory - A pointer to a WDFMEMORY-typed location that receives a
2262 handle to a framework memory object.
2263
2264 Type - A pointer to a DEVPROPTYPE variable. If method successfully retrieves
2265 the property data, the routine writes the property type value to
2266 this variable. This value indicates the type of property data
2267 that is in the Data buffer.
2268
2269 Return Value:
2270
2271 Method returns an NTSTATUS value. This routine might return one of the
2272 following values. It might return other NTSTATUS-codes as well.
2273
2274 STATUS_SUCCESS The operation succeeded.
2275 STATUS_INVALID_PARAMETER One of the parameters is incorrect.
2276
2277 --*/
2278 {
2279 DDI_ENTRY();
2280
2281 PFX_DRIVER_GLOBALS pFxDriverGlobals;
2282 FxDevice* pDevice;
2283 NTSTATUS status;
2284
2285 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
2286 Device,
2287 FX_TYPE_DEVICE,
2288 (PVOID *) &pDevice,
2289 &pFxDriverGlobals);
2290
2291 FxPointerNotNull(pFxDriverGlobals, DeviceProperty);
2292
2293 //
2294 // Validate PropertyData
2295 //
2296 if (DeviceProperty->Size != sizeof(WDF_DEVICE_PROPERTY_DATA)) {
2297 status = STATUS_INFO_LENGTH_MISMATCH;
2298 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
2299 "PropertyData size (%d) incorrect, expected %d, %!STATUS!",
2300 DeviceProperty->Size,
2301 sizeof(WDF_DEVICE_PROPERTY_DATA), status);
2302 return status;
2303 }
2304
2305 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, APC_LEVEL);
2306 if (!NT_SUCCESS(status)) {
2307 FxVerifierDbgBreakPoint(pFxDriverGlobals);
2308 return status;
2309 }
2310
2311 FxVerifierCheckNxPoolType(pFxDriverGlobals, PoolType, pFxDriverGlobals->Tag);
2312
2313 FxPointerNotNull(pFxDriverGlobals, PropertyMemory);
2314 FxPointerNotNull(pFxDriverGlobals, Type);
2315
2316 *PropertyMemory = NULL;
2317
2318 status = FxValidateObjectAttributes(pFxDriverGlobals, PropertyMemoryAttributes);
2319 if (!NT_SUCCESS(status)) {
2320 return status;
2321 }
2322
2323 status = FxDevice::_AllocAndQueryPropertyEx(pFxDriverGlobals,
2324 NULL,
2325 pDevice,
2326 DeviceProperty,
2327 FxDeviceProperty,
2328 PoolType,
2329 PropertyMemoryAttributes,
2330 PropertyMemory,
2331 Type);
2332 return status;
2333 }
2334
2335 _Must_inspect_result_
_IRQL_requires_max_(APC_LEVEL)2336 _IRQL_requires_max_(APC_LEVEL)
2337 WDFAPI
2338 NTSTATUS
2339 STDCALL
2340 WDFEXPORT(WdfDeviceAssignProperty)(
2341 _In_
2342 PWDF_DRIVER_GLOBALS DriverGlobals,
2343 _In_
2344 WDFDEVICE Device,
2345 _In_
2346 PWDF_DEVICE_PROPERTY_DATA DeviceProperty,
2347 _In_
2348 DEVPROPTYPE Type,
2349 _In_
2350 ULONG BufferLength,
2351 _In_opt_
2352 PVOID PropertyBuffer
2353 )
2354 /*++
2355
2356 Routine Description:
2357
2358 This routine assigns interface property.
2359
2360 Arguments:
2361
2362 DriverGlobals - DriverGlobals pointer
2363
2364 Device - WDF Device handle.
2365
2366 PropertyData - A pointer to WDF_DEVICE_PROPERTY_ DATA structure.
2367
2368 Type - Set this parameter to the DEVPROPTYPE value that specifies the type
2369 of the data that is supplied in the Data buffer.
2370
2371 BufferLength - Specifies the length, in bytes, of the buffer that
2372 PropertyBuffer points to.
2373
2374 PropertyBuffer - optional, A pointer to the device interface property data.
2375 Set this parameter to NULL to delete the specified property.
2376
2377 Return Value:
2378
2379 Mthod returns an NTSTATUS value. This routine might return one of the
2380 following values. It might return other NTSTATUS-codes as well.
2381
2382 STATUS_SUCCESS - The operation succeeded.
2383 STATUS_INVALID_PARAMETER - One of the parameters is incorrect.
2384
2385 --*/
2386
2387 {
2388 DDI_ENTRY();
2389
2390 PFX_DRIVER_GLOBALS pFxDriverGlobals;
2391 FxDevice *pDevice;
2392 NTSTATUS status;
2393
2394 //
2395 // Validate the Device object handle and get its FxDevice. Also get the
2396 // driver globals pointer.
2397 //
2398 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
2399 Device,
2400 FX_TYPE_DEVICE,
2401 (PVOID *) &pDevice,
2402 &pFxDriverGlobals);
2403
2404 FxPointerNotNull(pFxDriverGlobals, DeviceProperty);
2405
2406 //
2407 // Validate PropertyData
2408 //
2409 if (DeviceProperty->Size != sizeof(WDF_DEVICE_PROPERTY_DATA)) {
2410 status = STATUS_INFO_LENGTH_MISMATCH;
2411 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
2412 "PropertyData size (%d) incorrect, expected %d, %!STATUS!",
2413 DeviceProperty->Size,
2414 sizeof(WDF_DEVICE_PROPERTY_DATA), status);
2415 return status;
2416 }
2417
2418 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, APC_LEVEL);
2419 if (!NT_SUCCESS(status)) {
2420 FxVerifierDbgBreakPoint(pFxDriverGlobals);
2421 return status;
2422 }
2423
2424 if (BufferLength == 0 && PropertyBuffer != NULL) {
2425 status = STATUS_INVALID_PARAMETER;
2426 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2427 "Property buffer size is zero, while the buffer is non-NULL"
2428 ", %!STATUS!", status);
2429 return status;
2430 }
2431
2432 status = pDevice->AssignProperty(DeviceProperty,
2433 FxDeviceProperty,
2434 Type,
2435 BufferLength,
2436 PropertyBuffer
2437 );
2438 return status;
2439 }
2440
2441 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)2442 __drv_maxIRQL(DISPATCH_LEVEL)
2443 WDFAPI
2444 NTSTATUS
2445 STDCALL
2446 WDFEXPORT(WdfDeviceConfigureWdmIrpDispatchCallback)(
2447 _In_
2448 PWDF_DRIVER_GLOBALS DriverGlobals,
2449 _In_
2450 WDFDEVICE Device,
2451 _In_opt_
2452 WDFDRIVER Driver,
2453 _In_
2454 UCHAR MajorFunction,
2455 _In_
2456 PFN_WDFDEVICE_WDM_IRP_DISPATCH EvtDeviceWdmIrpDispatch,
2457 _In_opt_
2458 WDFCONTEXT DriverContext
2459 )
2460
2461 /*++
2462
2463 Routine Description:
2464
2465 Configure callbacks for IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_DEVICE_CONTROL, and
2466 IRP_MJ_INTERNAL_DEVICE_CONTROL (KMDF only). By default the I/O package sends all requests to
2467 a device's default queue, or to the queues configured with
2468 WdfDeviceConfigureRequestDisaptching. This DDI allows a driver specified
2469 callback to select a different queue dynamically during runtime.
2470
2471 Arguments:
2472
2473 Device - The device which is handling the I/O.
2474
2475 Driver - An optional driver handle. Used to associate the
2476 callback with a specific class extension.
2477
2478 MajorFunction - IRP major function type to be forwarded to the callback
2479
2480 EvtDeviceWdmIrpDispatch - Callback invoked when encountering the given major function.
2481
2482 DriverContext - An optional untyped driver specified context.
2483
2484 Returns:
2485
2486 STATUS_SUCCESS on success
2487 STATUS_INVALID_PARAMETER if an incorrect MajorFunction was provided
2488 STATUS_INSUFFICIENT_RESOURCES if insufficient memory was available
2489 STATUS_INVALID_DEVICE_STATE if this DDI was called at an improper time
2490
2491 --*/
2492 {
2493 PFX_DRIVER_GLOBALS pFxDriverGlobals;
2494 NTSTATUS status;
2495 FxDevice* pDevice;
2496 FxCxDeviceInfo* pCxDeviceInfo;
2497 ULONG deviceFlags;
2498
2499 pDevice = NULL;
2500 pCxDeviceInfo = NULL;
2501
2502 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
2503 Device,
2504 FX_TYPE_DEVICE,
2505 (PVOID *) &pDevice,
2506 &pFxDriverGlobals);
2507
2508 //
2509 // Validate the MajorFunction provided. Note that
2510 // IRP_MJ_INTERNAL_DEVICE_CONTROL is KMDF only.
2511 //
2512 switch (MajorFunction) {
2513 case IRP_MJ_WRITE:
2514 case IRP_MJ_READ:
2515 case IRP_MJ_DEVICE_CONTROL:
2516 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
2517 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
2518 #endif
2519 break;
2520 default:
2521 status = STATUS_INVALID_PARAMETER;
2522 DoTraceLevelMessage(
2523 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
2524 "Invalid MajorFunction provided %!IRPMJ!, %!STATUS!",
2525 MajorFunction, status);
2526 goto exit;
2527 }
2528
2529 //
2530 // Validate the driver handle and get (if present) the associated cx info.
2531 //
2532 if (Driver != NULL) {
2533 FxDriver* pDriver;
2534
2535 FxObjectHandleGetPtr(pFxDriverGlobals,
2536 Driver,
2537 FX_TYPE_DRIVER,
2538 (PVOID*)&pDriver);
2539
2540 //
2541 // Find the driver's cx info if it's not the main driver for this device.
2542 // cx struct info can be NULL if cx acts as client driver.
2543 //
2544 pCxDeviceInfo = pDevice->GetCxDeviceInfo(pDriver);
2545 }
2546
2547 //
2548 // Make sure callback is not null.
2549 //
2550 FxPointerNotNull(pFxDriverGlobals, EvtDeviceWdmIrpDispatch);
2551
2552 //
2553 // This callback can only be called during initialization.
2554 //
2555 if (pDevice->IsLegacy()) {
2556
2557 //
2558 // Extract the device flags from the device object
2559 //
2560 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
2561 deviceFlags = pDevice->GetDeviceObject()->Flags;
2562 #else
2563 deviceFlags = pDevice->GetDeviceObject()->GetDeviceObjectWdmFlags();
2564 #endif
2565
2566 //
2567 // This is a controldevice. Make sure the create is called after the device
2568 // is initialized and ready to accept I/O.
2569 //
2570 if ((deviceFlags & DO_DEVICE_INITIALIZING) == 0x0) {
2571 status = STATUS_INVALID_DEVICE_STATE;
2572 DoTraceLevelMessage(
2573 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
2574 "Driver cannot set IRP dispatch callback "
2575 "after WdfControlDeviceFinishInitializing "
2576 "is called on the WDFDEVICE %p, %!STATUS!",
2577 pDevice, status);
2578 goto exit;
2579 }
2580 } else {
2581 //
2582 // This is either FDO or PDO. Make sure it's not started yet.
2583 //
2584 if (pDevice->GetDevicePnpState() != WdfDevStatePnpInit) {
2585 status = STATUS_INVALID_DEVICE_STATE;
2586 DoTraceLevelMessage(
2587 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
2588 "Driver cannot set IRP dispatch callback "
2589 "after the WDFDEVICE %p is started, %!STATUS!",
2590 pDevice, status);
2591 goto exit;
2592 }
2593 }
2594
2595 //
2596 // Let I/O package do the rest.
2597 //
2598 status = pDevice->m_PkgIo->ConfigureDynamicDispatching(MajorFunction,
2599 pCxDeviceInfo,
2600 EvtDeviceWdmIrpDispatch,
2601 DriverContext);
2602 exit:
2603 return status;
2604 }
2605
2606 _Must_inspect_result_
2607 NTSTATUS
FX_VF_FUNCTION(VerifyWdfDeviceWdmDispatchIrpToIoQueue)2608 FX_VF_FUNCTION(VerifyWdfDeviceWdmDispatchIrpToIoQueue) (
2609 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
2610 _In_ FxDevice* device,
2611 _In_ MdIrp Irp,
2612 _In_ FxIoQueue* queue,
2613 _In_ ULONG Flags
2614 )
2615 {
2616 NTSTATUS status = STATUS_SUCCESS;
2617 UCHAR majorFunction, minorFunction;
2618 FxIrp fxIrp(Irp);
2619
2620 PAGED_CODE_LOCKED();
2621
2622 majorFunction = fxIrp.GetMajorFunction();
2623 minorFunction = fxIrp.GetMinorFunction();
2624
2625 DoTraceLevelMessage(
2626 FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIO,
2627 "WDFDEVICE 0x%p !devobj 0x%p %!IRPMJ!, IRP_MN %x, IRP 0x%p",
2628 device->GetHandle(), device->GetDeviceObject(),
2629 majorFunction, minorFunction, Irp);
2630
2631 //
2632 // Validate Flags. For UMDF, this field is reserved and must be zero.
2633 //
2634 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
2635 if (Flags & ~FX_DISPATCH_IRP_TO_IO_QUEUE_FLAGS_MASK) {
2636 #else
2637 if (Flags != WDF_DISPATCH_IRP_TO_IO_QUEUE_NO_FLAGS) {
2638 #endif
2639 status = STATUS_INVALID_PARAMETER;
2640 DoTraceLevelMessage(
2641 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO,
2642 "Flags 0x%x are invalid, %!STATUS!",
2643 Flags, status);
2644 FxVerifierDbgBreakPoint(FxDriverGlobals);
2645 goto Done;
2646 }
2647
2648 //
2649 // Only read/writes/ctrls/internal_ctrls IRPs are allowed, i.e., the I/O request set.
2650 //
2651 if (device->GetDispatchPackage(majorFunction) != device->m_PkgIo) {
2652 status = STATUS_INVALID_PARAMETER;
2653 DoTraceLevelMessage(
2654 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO,
2655 "Only Read/Write/Control/Internal-Control IRPs can be "
2656 "forwarded to I/O Queue 0x%p, Irp 0x%p, %!IRPMJ!, "
2657 "IRP_MN %x, Device 0x%p, %!STATUS!",
2658 queue->GetHandle(), Irp, majorFunction, minorFunction,
2659 device->GetObjectHandle(), status);
2660 FxVerifierDbgBreakPoint(FxDriverGlobals);
2661 goto Done;
2662 }
2663
2664 //
2665 // Make sure queue can handle the request.
2666 //
2667 if (FALSE == queue->IsIoEventHandlerRegistered(
2668 (WDF_REQUEST_TYPE)majorFunction)) {
2669
2670 status = STATUS_INVALID_PARAMETER;
2671 DoTraceLevelMessage(
2672 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO,
2673 "I/O Queue 0x%p cannot handle Irp 0x%p, %!IRPMJ!, "
2674 "IRP_MN %x, Device 0x%p, %!STATUS!",
2675 queue->GetHandle(), Irp, majorFunction, minorFunction,
2676 device->GetObjectHandle(), status);
2677 FxVerifierDbgBreakPoint(FxDriverGlobals);
2678 goto Done;
2679 }
2680
2681 if (device->m_ParentDevice == queue->GetDevice()) {
2682 //
2683 // Send to parent device's queue validation.
2684 //
2685 if (device->m_ParentDevice == NULL) {
2686 status = STATUS_INVALID_PARAMETER;
2687 DoTraceLevelMessage(
2688 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO,
2689 "No parent device for Device 0x%p, %!STATUS!",
2690 device->GetObjectHandle(), status);
2691 FxVerifierDbgBreakPoint(FxDriverGlobals);
2692 goto Done;
2693 }
2694
2695 //
2696 // Make sure the child device is a PDO
2697 //
2698 ASSERT(device->IsPdo());
2699
2700 //
2701 // Check if the WdfPdoInitSetForwardRequestToParent was called to
2702 // increase the StackSize of the child Device to include the stack
2703 // size of the parent Device
2704 //
2705 if (device->IsPnp() &&
2706 device->GetPdoPkg()->m_AllowForwardRequestToParent == FALSE) {
2707 status = STATUS_INVALID_DEVICE_REQUEST;
2708 DoTraceLevelMessage(
2709 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO,
2710 "WdfPdoInitSetForwardRequestToParent not called on "
2711 "Device 0x%p, %!STATUS!",
2712 device->GetObjectHandle(), status);
2713 FxVerifierDbgBreakPoint(FxDriverGlobals);
2714 goto Done;
2715 }
2716 }
2717 else {
2718 //
2719 // Send to current device's queue validation.
2720 //
2721 if (device != queue->GetDevice()) {
2722 status = STATUS_INVALID_PARAMETER;
2723 DoTraceLevelMessage(
2724 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO,
2725 "Cannot forward a request to "
2726 "a different Device 0x%p, %!STATUS!",
2727 queue->GetDevice()->GetObjectHandle(), status);
2728 FxVerifierDbgBreakPoint(FxDriverGlobals);
2729 goto Done;
2730 }
2731 }
2732
2733 Done:
2734 return status;
2735 }
2736
2737 } // extern "C"
2738