1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxDeviceInitApi.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 
27 extern "C" {
28 // #include "FxDeviceInitApi.tmh"
29 }
30 
31 typedef struct _WDF_PNPPOWER_EVENT_CALLBACKS_V1_9 {
32     //
33     // Size of this structure in bytes
34     //
35     ULONG Size;
36 
37     PFN_WDF_DEVICE_D0_ENTRY                 EvtDeviceD0Entry;
38 
39     PFN_WDF_DEVICE_D0_ENTRY_POST_INTERRUPTS_ENABLED EvtDeviceD0EntryPostInterruptsEnabled;
40 
41     PFN_WDF_DEVICE_D0_EXIT                  EvtDeviceD0Exit;
42 
43     PFN_WDF_DEVICE_D0_EXIT_PRE_INTERRUPTS_DISABLED EvtDeviceD0ExitPreInterruptsDisabled;
44 
45     PFN_WDF_DEVICE_PREPARE_HARDWARE         EvtDevicePrepareHardware;
46 
47     PFN_WDF_DEVICE_RELEASE_HARDWARE         EvtDeviceReleaseHardware;
48 
49     PFN_WDF_DEVICE_SELF_MANAGED_IO_CLEANUP  EvtDeviceSelfManagedIoCleanup;
50 
51     PFN_WDF_DEVICE_SELF_MANAGED_IO_FLUSH    EvtDeviceSelfManagedIoFlush;
52 
53     PFN_WDF_DEVICE_SELF_MANAGED_IO_INIT     EvtDeviceSelfManagedIoInit;
54 
55     PFN_WDF_DEVICE_SELF_MANAGED_IO_SUSPEND  EvtDeviceSelfManagedIoSuspend;
56 
57     PFN_WDF_DEVICE_SELF_MANAGED_IO_RESTART  EvtDeviceSelfManagedIoRestart;
58 
59     PFN_WDF_DEVICE_SURPRISE_REMOVAL         EvtDeviceSurpriseRemoval;
60 
61     PFN_WDF_DEVICE_QUERY_REMOVE             EvtDeviceQueryRemove;
62 
63     PFN_WDF_DEVICE_QUERY_STOP               EvtDeviceQueryStop;
64 
65     PFN_WDF_DEVICE_USAGE_NOTIFICATION       EvtDeviceUsageNotification;
66 
67     PFN_WDF_DEVICE_RELATIONS_QUERY          EvtDeviceRelationsQuery;
68 
69 } WDF_PNPPOWER_EVENT_CALLBACKS_V1_9, *PWDF_PNPPOWER_EVENT_CALLBACKS_V1_9;
70 
71 
72 typedef struct _WDF_POWER_POLICY_EVENT_CALLBACKS_V1_5 {
73     //
74     // Size of this structure in bytes
75     //
76     ULONG Size;
77 
78     PFN_WDF_DEVICE_ARM_WAKE_FROM_S0         EvtDeviceArmWakeFromS0;
79 
80     PFN_WDF_DEVICE_DISARM_WAKE_FROM_S0      EvtDeviceDisarmWakeFromS0;
81 
82     PFN_WDF_DEVICE_WAKE_FROM_S0_TRIGGERED   EvtDeviceWakeFromS0Triggered;
83 
84     PFN_WDF_DEVICE_ARM_WAKE_FROM_SX         EvtDeviceArmWakeFromSx;
85 
86     PFN_WDF_DEVICE_DISARM_WAKE_FROM_SX      EvtDeviceDisarmWakeFromSx;
87 
88     PFN_WDF_DEVICE_WAKE_FROM_SX_TRIGGERED   EvtDeviceWakeFromSxTriggered;
89 
90 } WDF_POWER_POLICY_EVENT_CALLBACKS_V1_5, *PWDF_POWER_POLICY_EVENT_CALLBACKS_V1_5;
91 
92 typedef struct _WDF_PDO_EVENT_CALLBACKS_V1_9 {
93     //
94     // The size of this structure in bytes
95     //
96     ULONG Size;
97 
98     //
99     // Called in response to IRP_MN_QUERY_RESOURCES
100     //
101     PFN_WDF_DEVICE_RESOURCES_QUERY EvtDeviceResourcesQuery;
102 
103     //
104     // Called in response to IRP_MN_QUERY_RESOURCE_REQUIREMENTS
105     //
106     PFN_WDF_DEVICE_RESOURCE_REQUIREMENTS_QUERY EvtDeviceResourceRequirementsQuery;
107 
108     //
109     // Called in response to IRP_MN_EJECT
110     //
111     PFN_WDF_DEVICE_EJECT EvtDeviceEject;
112 
113     //
114     // Called in response to IRP_MN_SET_LOCK
115     //
116     PFN_WDF_DEVICE_SET_LOCK EvtDeviceSetLock;
117 
118     //
119     // Called in response to the power policy owner sending a wait wake to the
120     // PDO.  Bus generic arming shoulding occur here.
121     //
122     PFN_WDF_DEVICE_ENABLE_WAKE_AT_BUS       EvtDeviceEnableWakeAtBus;
123 
124     //
125     // Called in response to the power policy owner sending a wait wake to the
126     // PDO.  Bus generic disarming shoulding occur here.
127     //
128     PFN_WDF_DEVICE_DISABLE_WAKE_AT_BUS      EvtDeviceDisableWakeAtBus;
129 
130 } WDF_PDO_EVENT_CALLBACKS_V1_9, *PWDF_PDO_EVENT_CALLBACKS_V1_9;
131 
132 
133 //
134 // Extern "C" the entire file
135 //
136 extern "C" {
137 
138 __drv_maxIRQL(DISPATCH_LEVEL)
139 VOID
140 STDCALL
141 WDFEXPORT(WdfDeviceInitFree)(
142     __in
143     PWDF_DRIVER_GLOBALS DriverGlobals,
144     __in
145     PWDFDEVICE_INIT DeviceInit
146     )
147 {
148     DDI_ENTRY();
149 
150     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
151 
152     if (DeviceInit->CreatedOnStack == FALSE) {
153         delete DeviceInit;
154     }
155 }
156 
157 __drv_maxIRQL(DISPATCH_LEVEL)
158 VOID
159 STDCALL
160 WDFEXPORT(WdfDeviceInitSetIoType)(
161     __in
162     PWDF_DRIVER_GLOBALS DriverGlobals,
163     __in
164     PWDFDEVICE_INIT DeviceInit,
165     __in
166     WDF_DEVICE_IO_TYPE IoType
167     )
168 {
169     DDI_ENTRY();
170 
171     WDF_IO_TYPE_CONFIG ioTypeConfig;
172 
173     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
174 
175     WDF_IO_TYPE_CONFIG_INIT(&ioTypeConfig);
176     ioTypeConfig.ReadWriteIoType = IoType;
177 
178     DeviceInit->AssignIoType(&ioTypeConfig);
179 }
180 
181 _IRQL_requires_max_(PASSIVE_LEVEL)
182 WDFAPI
183 VOID
184 STDCALL
185 WDFEXPORT(WdfDeviceInitSetIoTypeEx)(
186     _In_
187     PWDF_DRIVER_GLOBALS DriverGlobals,
188     _In_
189     PWDFDEVICE_INIT DeviceInit,
190     _In_
191     PWDF_IO_TYPE_CONFIG IoTypeConfig
192     )
193 {
194     DDI_ENTRY();
195 
196     NTSTATUS status;
197     PFX_DRIVER_GLOBALS pFxDriverGlobals;
198 
199     pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
200 
201     FxPointerNotNull(pFxDriverGlobals, DeviceInit);
202 
203     if (IoTypeConfig->Size != sizeof(WDF_IO_TYPE_CONFIG)) {
204         status = STATUS_INFO_LENGTH_MISMATCH;
205         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
206                      "IoTypeConfig size (%d) incorrect, expected %d, %!STATUS!",
207                      IoTypeConfig->Size,
208                      sizeof(WDF_IO_TYPE_CONFIG), status);
209         return;
210     }
211 
212     DeviceInit->AssignIoType(IoTypeConfig);
213 }
214 
215 __drv_maxIRQL(DISPATCH_LEVEL)
216 VOID
217 STDCALL
218 WDFEXPORT(WdfDeviceInitSetExclusive)(
219     __in
220     PWDF_DRIVER_GLOBALS DriverGlobals,
221     __in
222     PWDFDEVICE_INIT DeviceInit,
223     __in
224     BOOLEAN Exclusive
225     )
226 {
227     DDI_ENTRY();
228 
229     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
230 
231     DeviceInit->Exclusive = Exclusive;
232 }
233 
234 __drv_maxIRQL(DISPATCH_LEVEL)
235 VOID
236 STDCALL
237 WDFEXPORT(WdfDeviceInitSetDeviceType)(
238     __in
239     PWDF_DRIVER_GLOBALS DriverGlobals,
240     __in
241     PWDFDEVICE_INIT DeviceInit,
242     __in
243     DEVICE_TYPE DeviceType
244     )
245 {
246     DDI_ENTRY();
247 
248     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
249 
250     DeviceInit->DeviceType = DeviceType;
251 }
252 
253 __drv_maxIRQL(DISPATCH_LEVEL)
254 VOID
255 STDCALL
256 WDFEXPORT(WdfDeviceInitSetPowerNotPageable)(
257     __in
258     PWDF_DRIVER_GLOBALS DriverGlobals,
259     __in
260     PWDFDEVICE_INIT DeviceInit
261     )
262 {
263     DDI_ENTRY();
264 
265     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
266 
267     DeviceInit->PowerPageable = FALSE;
268 }
269 
270 __drv_maxIRQL(DISPATCH_LEVEL)
271 VOID
272 STDCALL
273 WDFEXPORT(WdfDeviceInitSetPowerPageable)(
274     __in
275     PWDF_DRIVER_GLOBALS DriverGlobals,
276     __in
277     PWDFDEVICE_INIT DeviceInit
278     )
279 {
280     DDI_ENTRY();
281 
282     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
283 
284     DeviceInit->PowerPageable = TRUE;
285 }
286 
287 __drv_maxIRQL(DISPATCH_LEVEL)
288 VOID
289 STDCALL
290 WDFEXPORT(WdfDeviceInitSetPowerInrush)(
291     __in
292     PWDF_DRIVER_GLOBALS DriverGlobals,
293     __in
294     PWDFDEVICE_INIT DeviceInit
295     )
296 {
297     DDI_ENTRY();
298 
299     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
300 
301     //
302     // If you are inrush, there is no way  you can be power pageable
303     //
304     DeviceInit->Inrush = TRUE;
305     DeviceInit->PowerPageable = FALSE;
306 }
307 
308 _Must_inspect_result_
309 __drv_maxIRQL(PASSIVE_LEVEL)
310 NTSTATUS
311 STDCALL
312 WDFEXPORT(WdfDeviceInitAssignName)(
313     __in
314     PWDF_DRIVER_GLOBALS DriverGlobals,
315     __in
316     PWDFDEVICE_INIT DeviceInit,
317     __in_opt
318     PCUNICODE_STRING DeviceName
319     )
320 {
321     DDI_ENTRY();
322 
323     NTSTATUS status;
324 
325     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
326 
327     status = FxVerifierCheckIrqlLevel(DeviceInit->DriverGlobals,
328                                       PASSIVE_LEVEL);
329     if (!NT_SUCCESS(status)) {
330         return status;
331     }
332 
333     if (DeviceName != NULL) {
334         status = FxValidateUnicodeString(DeviceInit->DriverGlobals,
335                                          DeviceName);
336         if (!NT_SUCCESS(status)) {
337             return status;
338         }
339     }
340 
341     if (DeviceName == NULL) {
342         if (DeviceInit->DeviceName != NULL) {
343             DeviceInit->DeviceName->RELEASE(NULL);
344             DeviceInit->DeviceName = NULL;
345         }
346 
347         if (DeviceInit->IsPdoInit()) {
348             //
349             // Make sure a PDO has a name
350             //
351             DeviceInit->Characteristics |= FILE_AUTOGENERATED_DEVICE_NAME;
352         }
353 
354         return STATUS_SUCCESS;
355     }
356 
357     return DeviceInit->AssignName(DeviceInit->DriverGlobals, DeviceName);
358 
359 }
360 
361 __drv_maxIRQL(DISPATCH_LEVEL)
362 VOID
363 STDCALL
364 WDFEXPORT(WdfDeviceInitSetCharacteristics)(
365     __in
366     PWDF_DRIVER_GLOBALS DriverGlobals,
367     __in
368     PWDFDEVICE_INIT DeviceInit,
369     __in
370     ULONG DeviceCharacteristics,
371     __in
372     BOOLEAN OrInValues
373     )
374 {
375     DDI_ENTRY();
376 
377     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
378 
379     if (OrInValues) {
380         DeviceInit->Characteristics |= DeviceCharacteristics | FILE_DEVICE_SECURE_OPEN;
381     }
382     else {
383         DeviceInit->Characteristics = DeviceCharacteristics | FILE_DEVICE_SECURE_OPEN;
384     }
385 
386     //
387     // If the autogenerate flag is on, clear out the device name
388     //
389     if ((DeviceCharacteristics & FILE_AUTOGENERATED_DEVICE_NAME) &&
390         DeviceInit->DeviceName != NULL) {
391         DeviceInit->DeviceName->RELEASE(NULL);
392         DeviceInit->DeviceName = NULL;
393     }
394 }
395 
396 __drv_maxIRQL(DISPATCH_LEVEL)
397 VOID
398 STDCALL
399 WDFEXPORT(WdfDeviceInitSetFileObjectConfig)(
400     __in
401     PWDF_DRIVER_GLOBALS DriverGlobals,
402     __in
403     PWDFDEVICE_INIT DeviceInit,
404     __in
405     PWDF_FILEOBJECT_CONFIG FileObjectConfig,
406     __in_opt
407     PWDF_OBJECT_ATTRIBUTES FileObjectAttributes
408     )
409 
410 /*++
411 
412 Routine Description:
413 
414     Registers callbacks for file object support.
415 
416     Defaults to WdfDeviceFileObjectNoFsContext.
417 
418 Arguments:
419 
420 Returns:
421 
422 --*/
423 
424 {
425     DDI_ENTRY();
426 
427     NTSTATUS status;
428     PFX_DRIVER_GLOBALS pFxDriverGlobals;
429     WDF_FILEOBJECT_CLASS normalizedFileClass;
430     WDF_FILEOBJECT_CLASS fileClass;
431 
432     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
433     pFxDriverGlobals = DeviceInit->DriverGlobals;
434 
435     FxPointerNotNull(pFxDriverGlobals, FileObjectConfig);
436 
437     if (FileObjectConfig->Size != sizeof(WDF_FILEOBJECT_CONFIG)) {
438         DoTraceLevelMessage(
439             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
440             "Invalid FileObjectConfig Size %d, expected %d",
441             FileObjectConfig->Size, sizeof(WDF_FILEOBJECT_CONFIG));
442 
443         FxVerifierDbgBreakPoint(pFxDriverGlobals);
444         return;
445     }
446 
447     status = FxValidateObjectAttributes(
448         pFxDriverGlobals,
449         FileObjectAttributes,
450         FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED |
451             FX_VALIDATE_OPTION_EXECUTION_LEVEL_ALLOWED |
452             FX_VALIDATE_OPTION_SYNCHRONIZATION_SCOPE_ALLOWED
453         );
454 
455     if (!NT_SUCCESS(status)) {
456         FxVerifierDbgBreakPoint(pFxDriverGlobals);
457         return;
458     }
459 
460     //
461     // Validate AutoForwardCleanupClose
462     //
463     switch (FileObjectConfig->AutoForwardCleanupClose) {
464     case WdfTrue:
465     case WdfFalse:
466     case WdfUseDefault:
467         break;
468 
469     default:
470         DoTraceLevelMessage(
471             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
472             "Invalid FileObjectConfig->AutoForwardCleanupClose value 0x%x, "
473             "expected WDF_TRI_STATE value", FileObjectConfig->AutoForwardCleanupClose);
474 
475         FxVerifierDbgBreakPoint(pFxDriverGlobals);
476         return;
477     }
478 
479     DeviceInit->FileObject.Set = TRUE;
480 
481     DeviceInit->FileObject.AutoForwardCleanupClose =
482         FileObjectConfig->AutoForwardCleanupClose;
483 
484     fileClass = FileObjectConfig->FileObjectClass;
485 
486     //
487     // Remove bit flags and validate file object class value.
488     //
489     normalizedFileClass = FxFileObjectClassNormalize(fileClass);
490 
491     if (normalizedFileClass == WdfFileObjectInvalid ||
492         normalizedFileClass > WdfFileObjectWdfCannotUseFsContexts)  {
493         DoTraceLevelMessage(
494             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
495             "Out of range FileObjectConfig->FileObjectClass %d",
496             fileClass);
497         FxVerifierDbgBreakPoint(pFxDriverGlobals);
498         return;
499     }
500 
501     //
502     // UMDF doesn't support storing object handle at FsContext or FxContxt2.
503     // Update the class to WdfFileObjectWdfCannotUseFsContexts for UMDF.
504     //
505     if (pFxDriverGlobals->IsUserModeDriver &&
506         (normalizedFileClass == WdfFileObjectWdfCanUseFsContext ||
507          normalizedFileClass == WdfFileObjectWdfCanUseFsContext2)) {
508 
509         //
510         // update the FileObjectClass value
511         //
512         BOOLEAN canBeOptional =
513             (fileClass & WdfFileObjectCanBeOptional) ? TRUE : FALSE;
514 
515         fileClass = WdfFileObjectWdfCannotUseFsContexts;
516         if (canBeOptional) {
517             fileClass = (WDF_FILEOBJECT_CLASS)
518                 (fileClass | WdfFileObjectCanBeOptional);
519         }
520 
521         DoTraceLevelMessage(
522              pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGDEVICE,
523              "FileObjectConfig->FileObjectClass value (%d) has been updated"
524              " to a UMDF-supported value %d", normalizedFileClass,
525              WdfFileObjectWdfCannotUseFsContexts);
526 
527         //
528         // re-obtain the normalized class
529         //
530         normalizedFileClass = FxFileObjectClassNormalize(fileClass);
531     }
532 
533     //
534     // The optional flag can only be combined with a subset of values.
535     //
536     if (FxIsFileObjectOptional(fileClass)) {
537         switch(normalizedFileClass) {
538         case WdfFileObjectWdfCanUseFsContext:
539         case WdfFileObjectWdfCanUseFsContext2:
540         case WdfFileObjectWdfCannotUseFsContexts:
541             break;
542 
543         default:
544             DoTraceLevelMessage(
545                 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
546                 "Invalid FileObjectConfig->FileObjectClass %d",
547                 fileClass);
548             FxVerifierDbgBreakPoint(pFxDriverGlobals);
549             return;
550             break; // just in case static verification tools complain.
551         }
552     }
553 
554     DeviceInit->FileObject.Class = fileClass;
555 
556     RtlCopyMemory(&DeviceInit->FileObject.Callbacks,
557                   FileObjectConfig,
558                   sizeof(DeviceInit->FileObject.Callbacks));
559 
560     if (FileObjectAttributes != NULL) {
561         RtlCopyMemory(&DeviceInit->FileObject.Attributes,
562                       FileObjectAttributes,
563                       sizeof(DeviceInit->FileObject.Attributes));
564     }
565 }
566 
567 __drv_maxIRQL(DISPATCH_LEVEL)
568 VOID
569 STDCALL
570 WDFEXPORT(WdfDeviceInitSetRequestAttributes)(
571     __in
572     PWDF_DRIVER_GLOBALS DriverGlobals,
573     __in
574     PWDFDEVICE_INIT DeviceInit,
575     __in
576     PWDF_OBJECT_ATTRIBUTES RequestAttributes
577     )
578 {
579     DDI_ENTRY();
580 
581     PFX_DRIVER_GLOBALS pFxDriverGlobals;
582     NTSTATUS status;
583 
584     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
585     pFxDriverGlobals = DeviceInit->DriverGlobals;
586 
587     FxPointerNotNull(pFxDriverGlobals, RequestAttributes);
588 
589     //
590     // Parent of all requests created from WDFDEVICE are parented by the
591     // WDFDEVICE.
592     //
593     status = FxValidateObjectAttributes(pFxDriverGlobals,
594                                         RequestAttributes,
595                                         FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
596 
597     if (!NT_SUCCESS(status)) {
598         FxVerifierDbgBreakPoint(pFxDriverGlobals);
599         return;
600     }
601 
602     RtlCopyMemory(&DeviceInit->RequestAttributes,
603                   RequestAttributes,
604                   sizeof(WDF_OBJECT_ATTRIBUTES));
605 }
606 
607 _Must_inspect_result_
608 __drv_maxIRQL(PASSIVE_LEVEL)
609 NTSTATUS
610 STDCALL
611 WDFEXPORT(WdfDeviceInitAssignSDDLString)(
612     __in
613     PWDF_DRIVER_GLOBALS DriverGlobals,
614     __in
615     PWDFDEVICE_INIT DeviceInit,
616     __in_opt
617     PCUNICODE_STRING SDDLString
618     )
619 {
620     DDI_ENTRY();
621 
622     PFX_DRIVER_GLOBALS pFxDriverGlobals;
623     NTSTATUS status;
624 
625     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
626     pFxDriverGlobals = DeviceInit->DriverGlobals;
627 
628     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
629     if (!NT_SUCCESS(status)) {
630         return status;
631     }
632 
633     if (SDDLString == NULL) {
634         //
635         // Since we require the SDDL on control device creation, you can't
636         // clear it!
637         //
638         if (DeviceInit->IsControlDeviceInit()) {
639             return STATUS_INVALID_DEVICE_REQUEST;
640         }
641 
642         if (DeviceInit->Security.Sddl != NULL) {
643             DeviceInit->Security.Sddl->RELEASE(NULL);
644             DeviceInit->Security.Sddl = NULL;
645         }
646 
647         return STATUS_SUCCESS;
648     }
649 
650     status = FxValidateUnicodeString(pFxDriverGlobals, SDDLString);
651     if (!NT_SUCCESS(status)) {
652         return status;
653     }
654 
655     if (DeviceInit->Security.Sddl == NULL) {
656         DeviceInit->Security.Sddl = new(pFxDriverGlobals,
657                                         WDF_NO_OBJECT_ATTRIBUTES)
658             FxString(pFxDriverGlobals);
659 
660         if (DeviceInit->Security.Sddl == NULL) {
661              DoTraceLevelMessage(
662                  pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
663                  "Couldn't create Security descriptor"
664                  " STATUS_INSUFFICIENT_RESOURCES ");
665 
666              return STATUS_INSUFFICIENT_RESOURCES;
667         }
668     }
669 
670     return DeviceInit->Security.Sddl->Assign(SDDLString);
671 }
672 
673 __drv_maxIRQL(DISPATCH_LEVEL)
674 VOID
675 STDCALL
676 WDFEXPORT(WdfDeviceInitSetDeviceClass)(
677     __in
678     PWDF_DRIVER_GLOBALS DriverGlobals,
679     __in
680     PWDFDEVICE_INIT DeviceInit,
681     __in
682     CONST GUID* DeviceClassGuid
683     )
684 {
685     DDI_ENTRY();
686 
687     PFX_DRIVER_GLOBALS pFxDriverGlobals;
688 
689     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
690     pFxDriverGlobals = DeviceInit->DriverGlobals;
691 
692     FxPointerNotNull(pFxDriverGlobals, DeviceClassGuid);
693 
694     DeviceInit->Security.DeviceClassSet = TRUE;
695     RtlCopyMemory(&DeviceInit->Security.DeviceClass,
696                   DeviceClassGuid,
697                   sizeof(GUID));
698 }
699 
700 __drv_maxIRQL(DISPATCH_LEVEL)
701 VOID
702 STDCALL
703 WDFEXPORT(WdfDeviceInitSetPnpPowerEventCallbacks)(
704     __in
705     PWDF_DRIVER_GLOBALS DriverGlobals,
706     __in
707     PWDFDEVICE_INIT DeviceInit,
708     __in
709     PWDF_PNPPOWER_EVENT_CALLBACKS PnpPowerEventCallbacks
710     )
711 {
712     DDI_ENTRY();
713 
714     PFX_DRIVER_GLOBALS pFxDriverGlobals;
715 
716     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
717     pFxDriverGlobals = DeviceInit->DriverGlobals;
718 
719     FxPointerNotNull(pFxDriverGlobals, PnpPowerEventCallbacks);
720 
721     if (PnpPowerEventCallbacks->Size != sizeof(WDF_PNPPOWER_EVENT_CALLBACKS) &&
722         PnpPowerEventCallbacks->Size != sizeof(_WDF_PNPPOWER_EVENT_CALLBACKS_V1_9)) {
723 
724         DoTraceLevelMessage(
725             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
726             "PnpPowerEventCallbacks size %d is invalid, exptected %d",
727             PnpPowerEventCallbacks->Size, sizeof(WDF_PNPPOWER_EVENT_CALLBACKS)
728             );
729 
730         FxVerifierDbgBreakPoint(pFxDriverGlobals);
731 
732         return;
733     }
734 
735     //
736     // Make sure only one of the callbacks EvtDeviceUsageNotification or
737     // EvtDeviceUsageNotificationEx is provided by driver for >V1.9.
738     //
739     if (PnpPowerEventCallbacks->Size > sizeof(WDF_PNPPOWER_EVENT_CALLBACKS_V1_9) &&
740         PnpPowerEventCallbacks->EvtDeviceUsageNotification != NULL &&
741         PnpPowerEventCallbacks->EvtDeviceUsageNotificationEx != NULL) {
742 
743         DoTraceLevelMessage(
744             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
745             "Driver can provide either EvtDeviceUsageNotification or "
746             "EvtDeviceUsageNotificationEx callback but not both");
747 
748         FxVerifierDbgBreakPoint(pFxDriverGlobals);
749 
750         return;
751     }
752 
753     //
754     // Driver's PnpPowerEventCallbacks structure may be from a previous
755     // version and therefore may be different in size than the current version
756     // that framework is using. Therefore, copy only PnpPowerEventCallbacks->Size
757     // bytes and not sizeof(PnpPowerEventCallbacks) bytes.
758     //
759     RtlCopyMemory(&DeviceInit->PnpPower.PnpPowerEventCallbacks,
760                   PnpPowerEventCallbacks,
761                   PnpPowerEventCallbacks->Size);
762 }
763 
764 __drv_maxIRQL(DISPATCH_LEVEL)
765 VOID
766 STDCALL
767 WDFEXPORT(WdfDeviceInitSetPowerPolicyEventCallbacks)(
768     __in
769     PWDF_DRIVER_GLOBALS DriverGlobals,
770     __in
771     PWDFDEVICE_INIT DeviceInit,
772     __in
773     PWDF_POWER_POLICY_EVENT_CALLBACKS PowerPolicyEventCallbacks
774     )
775 {
776     DDI_ENTRY();
777 
778     PFX_DRIVER_GLOBALS pFxDriverGlobals;
779 
780     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
781     pFxDriverGlobals = DeviceInit->DriverGlobals;
782 
783     FxPointerNotNull(pFxDriverGlobals, PowerPolicyEventCallbacks);
784 
785     //
786     // The WDF_POWER_POLICY_EVENT_CALLBACKS structure size increased after v1.5.
787     // Since this api is backwards compatible, it can accept either the current
788     // structure or the older version. Validate the size of the structure here
789     // so that it is one of the two supported sizes.
790     //
791     if (PowerPolicyEventCallbacks->Size != sizeof(WDF_POWER_POLICY_EVENT_CALLBACKS) &&
792         PowerPolicyEventCallbacks->Size != sizeof(WDF_POWER_POLICY_EVENT_CALLBACKS_V1_5)) {
793         DoTraceLevelMessage(
794             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
795             "PowerPolicyEventCallbacks size %d is invalid, expected %d",
796             PowerPolicyEventCallbacks->Size, sizeof(WDF_POWER_POLICY_EVENT_CALLBACKS)
797             );
798 
799         FxVerifierDbgBreakPoint(pFxDriverGlobals);
800         return;
801     }
802 
803     //
804     // Only one of EvtDeviceArmWakeFromSx and EvtDeviceArmWakeFromSxWithReason
805     // callbacks should be specified if the given power policy callbacks structure
806     // is from a version after v1.5
807     //
808     if (PowerPolicyEventCallbacks->Size > sizeof(WDF_POWER_POLICY_EVENT_CALLBACKS_V1_5) &&
809         PowerPolicyEventCallbacks->EvtDeviceArmWakeFromSx != NULL &&
810         PowerPolicyEventCallbacks->EvtDeviceArmWakeFromSxWithReason != NULL) {
811         DoTraceLevelMessage(
812             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
813             "PowerPolicyEventCallbacks can have either EvtDeviceArmWakeFromSx "
814             "or EvtDeviceArmWakeFromSxWithReason callback pointer, but not both"
815             );
816 
817         FxVerifierDbgBreakPoint(pFxDriverGlobals);
818         return;
819     }
820 
821     RtlCopyMemory(&DeviceInit->PnpPower.PolicyEventCallbacks,
822                   PowerPolicyEventCallbacks,
823                   PowerPolicyEventCallbacks->Size);
824 }
825 
826 __drv_maxIRQL(DISPATCH_LEVEL)
827 VOID
828 STDCALL
829 WDFEXPORT(WdfDeviceInitSetPowerPolicyOwnership)(
830     __in
831     PWDF_DRIVER_GLOBALS DriverGlobals,
832     __in
833     PWDFDEVICE_INIT DeviceInit,
834     __in
835     BOOLEAN IsPowerPolicyOwner
836     )
837 {
838     DDI_ENTRY();
839 
840      FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
841 
842      DeviceInit->PnpPower.PowerPolicyOwner = IsPowerPolicyOwner ? WdfTrue : WdfFalse;
843 }
844 
845 _Must_inspect_result_
846 __drv_maxIRQL(PASSIVE_LEVEL)
847 NTSTATUS
848 STDCALL
849 WDFEXPORT(WdfDeviceInitRegisterPnpStateChangeCallback)(
850     __in
851     PWDF_DRIVER_GLOBALS DriverGlobals,
852     __in
853     PWDFDEVICE_INIT DeviceInit,
854     __in
855     WDF_DEVICE_PNP_STATE PnpState,
856     __in
857     PFN_WDF_DEVICE_PNP_STATE_CHANGE_NOTIFICATION EvtDevicePnpStateChange,
858     __in
859     ULONG CallbackTypes
860     )
861 {
862     DDI_ENTRY();
863 
864     FxPnpStateCallbackInfo* pCallback;
865     PFX_DRIVER_GLOBALS pFxDriverGlobals;
866     ULONG normalizedState;
867     NTSTATUS status;
868 
869     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
870     pFxDriverGlobals = DeviceInit->DriverGlobals;
871 
872     FxPointerNotNull(pFxDriverGlobals, EvtDevicePnpStateChange);
873 
874     normalizedState = WdfDevStateNormalize(PnpState);
875 
876     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
877     if (!NT_SUCCESS(status)) {
878         return status;
879     }
880 
881     if (normalizedState < WdfDevStatePnpObjectCreated || normalizedState > WdfDevStatePnpNull) {
882         status = STATUS_INVALID_PARAMETER;
883 
884         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
885                             "Pnp State is invalid %!STATUS!", status);
886 
887         return status;
888     }
889 
890     if ((CallbackTypes & ~StateNotificationAllStates) != 0 ||
891         CallbackTypes == 0x0) {
892         status = STATUS_INVALID_PARAMETER;
893 
894         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
895                             "CallbackTypes is invalid %!STATUS!", status);
896 
897         return status;
898     }
899 
900     if (DeviceInit->PnpPower.PnpStateCallbacks == NULL) {
901 
902         DeviceInit->PnpPower.PnpStateCallbacks =
903             new (pFxDriverGlobals) FxPnpStateCallback();
904 
905         if (DeviceInit->PnpPower.PnpStateCallbacks == NULL) {
906             status = STATUS_INVALID_PARAMETER;
907 
908             DoTraceLevelMessage(
909                 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
910                 "Couldn't create object PnpStateCallbacks %!STATUS!", status);
911 
912             return status;
913         }
914     }
915 
916     pCallback = &DeviceInit->PnpPower.PnpStateCallbacks->m_Methods[
917         normalizedState - WdfDevStatePnpObjectCreated];
918 
919     pCallback->Callback = EvtDevicePnpStateChange;
920     pCallback->Types = CallbackTypes;
921 
922     return STATUS_SUCCESS;
923 }
924 
925 _Must_inspect_result_
926 __drv_maxIRQL(PASSIVE_LEVEL)
927 NTSTATUS
928 STDCALL
929 WDFEXPORT(WdfDeviceInitRegisterPowerStateChangeCallback)(
930     __in
931     PWDF_DRIVER_GLOBALS DriverGlobals,
932     __in
933     PWDFDEVICE_INIT DeviceInit,
934     __in
935     WDF_DEVICE_POWER_STATE PowerState,
936     __in
937     PFN_WDF_DEVICE_POWER_STATE_CHANGE_NOTIFICATION EvtDevicePowerStateChange,
938     __in
939     ULONG CallbackTypes
940     )
941 {
942     DDI_ENTRY();
943 
944     FxPowerStateCallbackInfo* pCallback;
945     PFX_DRIVER_GLOBALS pFxDriverGlobals;
946     ULONG normalizedState;
947     NTSTATUS status;
948 
949     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
950     pFxDriverGlobals = DeviceInit->DriverGlobals;
951 
952     FxPointerNotNull(pFxDriverGlobals, EvtDevicePowerStateChange);
953 
954     normalizedState = WdfDevStateNormalize(PowerState);
955 
956     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
957     if (!NT_SUCCESS(status)) {
958         return status;
959     }
960 
961     if (normalizedState < WdfDevStatePowerObjectCreated ||
962         normalizedState >= WdfDevStatePowerNull) {
963         status = STATUS_INVALID_PARAMETER;
964 
965         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
966                             "PowerState State is invalid %!STATUS!", status);
967 
968         return status;
969     }
970 
971     if ((CallbackTypes & ~StateNotificationAllStates) != 0 ||
972         CallbackTypes == 0x0) {
973         status = STATUS_INVALID_PARAMETER;
974 
975         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
976                             "CallbackTypes is invalid %!STATUS!"
977                             "STATUS_INVALID_PARAMETER", status);
978 
979         return status;
980     }
981 
982     if (DeviceInit->PnpPower.PowerStateCallbacks == NULL) {
983         DeviceInit->PnpPower.PowerStateCallbacks =
984             new (pFxDriverGlobals) FxPowerStateCallback();
985 
986         if (DeviceInit->PnpPower.PowerStateCallbacks == NULL) {
987             status = STATUS_INVALID_PARAMETER;
988 
989             DoTraceLevelMessage(
990                 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
991                 "Couldn't create object PowerStateCallbacks %!STATUS!", status);
992 
993             return status;
994         }
995     }
996 
997     pCallback = &DeviceInit->PnpPower.PowerStateCallbacks->m_Methods[
998         normalizedState - WdfDevStatePowerObjectCreated];
999 
1000     pCallback->Callback = EvtDevicePowerStateChange;
1001     pCallback->Types = CallbackTypes;
1002 
1003     return STATUS_SUCCESS;
1004 }
1005 
1006 _Must_inspect_result_
1007 __drv_maxIRQL(PASSIVE_LEVEL)
1008 NTSTATUS
1009 STDCALL
1010 WDFEXPORT(WdfDeviceInitRegisterPowerPolicyStateChangeCallback)(
1011     __in
1012     PWDF_DRIVER_GLOBALS DriverGlobals,
1013     __in
1014     PWDFDEVICE_INIT DeviceInit,
1015     __in
1016     WDF_DEVICE_POWER_POLICY_STATE PowerPolicyState,
1017     __in
1018     PFN_WDF_DEVICE_POWER_POLICY_STATE_CHANGE_NOTIFICATION EvtDevicePowerPolicyStateChange,
1019     __in
1020     ULONG CallbackTypes
1021     )
1022 {
1023     DDI_ENTRY();
1024 
1025     FxPowerPolicyStateCallbackInfo* pCallback;
1026     PFX_DRIVER_GLOBALS pFxDriverGlobals;
1027     ULONG normalizedState;
1028     NTSTATUS status;
1029 
1030     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
1031     pFxDriverGlobals = DeviceInit->DriverGlobals;
1032 
1033     FxPointerNotNull(pFxDriverGlobals, EvtDevicePowerPolicyStateChange);
1034 
1035     normalizedState = WdfDevStateNormalize(PowerPolicyState);
1036 
1037     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1038     if (!NT_SUCCESS(status)) {
1039         return status;
1040     }
1041 
1042     if (normalizedState < WdfDevStatePwrPolObjectCreated ||
1043         normalizedState >= WdfDevStatePwrPolNull) {
1044         status = STATUS_INVALID_PARAMETER;
1045 
1046         DoTraceLevelMessage(
1047             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1048             "PowerPolicyState State is invalid %!STATUS!", status);
1049 
1050         return status;
1051     }
1052 
1053     if ((CallbackTypes & ~StateNotificationAllStates) != 0 ||
1054         CallbackTypes == 0x0) {
1055         status = STATUS_INVALID_PARAMETER;
1056 
1057         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1058                             "CallbackTypes is invalid %!STATUS!", status);
1059 
1060         return status;
1061     }
1062 
1063     if (DeviceInit->PnpPower.PowerPolicyStateCallbacks == NULL) {
1064         DeviceInit->PnpPower.PowerPolicyStateCallbacks =
1065             new (pFxDriverGlobals) FxPowerPolicyStateCallback();
1066 
1067         if (DeviceInit->PnpPower.PowerPolicyStateCallbacks == NULL) {
1068             status = STATUS_INVALID_PARAMETER;
1069 
1070             DoTraceLevelMessage(
1071                 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1072                 "Couldn't create object PowerPolicyStateCallbacks %!STATUS!", status);
1073 
1074             return status;
1075         }
1076     }
1077 
1078     pCallback = &DeviceInit->PnpPower.PowerPolicyStateCallbacks->m_Methods[
1079          normalizedState - WdfDevStatePwrPolObjectCreated];
1080 
1081     pCallback->Callback = EvtDevicePowerPolicyStateChange;
1082     pCallback->Types = CallbackTypes;
1083 
1084     return STATUS_SUCCESS;
1085 }
1086 
1087 _Must_inspect_result_
1088 __drv_maxIRQL(DISPATCH_LEVEL)
1089 WDFAPI
1090 NTSTATUS
1091 STDCALL
1092 WDFEXPORT(WdfDeviceInitAssignWdmIrpPreprocessCallback)(
1093     __in
1094     PWDF_DRIVER_GLOBALS DriverGlobals,
1095     __in
1096     PWDFDEVICE_INIT DeviceInit,
1097     __in
1098     PFN_WDFDEVICE_WDM_IRP_PREPROCESS EvtDeviceWdmIrpPreprocess,
1099     __in
1100     UCHAR MajorFunction,
1101     __drv_when(NumMinorFunctions > 0, __in_bcount(NumMinorFunctions))
1102     __drv_when(NumMinorFunctions == 0, __in_opt)
1103     PUCHAR MinorFunctions,
1104     __in
1105     ULONG NumMinorFunctions
1106     )
1107 {
1108     DDI_ENTRY();
1109 
1110     PFX_DRIVER_GLOBALS pFxDriverGlobals;
1111 
1112     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
1113     pFxDriverGlobals = DeviceInit->DriverGlobals;
1114 
1115     FxPointerNotNull(pFxDriverGlobals, EvtDeviceWdmIrpPreprocess);
1116 
1117     if (NumMinorFunctions > 0) {
1118         FxPointerNotNull(pFxDriverGlobals, MinorFunctions);
1119     }
1120 
1121     //
1122     // ARRAY_SIZE(DeviceInit->PreprocessInfo->Dispatch) just returns a constant
1123     // size, it does not actually deref PreprocessInfo (which could be NULL)
1124     //
1125     if (MajorFunction >= ARRAY_SIZE(DeviceInit->PreprocessInfo->Dispatch)) {
1126         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1127                             "MajorFunction is invalid"
1128                             "STATUS_INVALID_PARAMETER"
1129                             );
1130 
1131         return STATUS_INVALID_PARAMETER;
1132     }
1133 
1134     if (DeviceInit->PreprocessInfo == NULL) {
1135         DeviceInit->PreprocessInfo = new(pFxDriverGlobals) FxIrpPreprocessInfo();
1136 
1137         if (DeviceInit->PreprocessInfo == NULL) {
1138             DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1139                                 "Couldn't create object PreprocessInfo"
1140                                 "STATUS_INSUFFICIENT_RESOURCES"
1141                                 );
1142 
1143 
1144             return STATUS_INSUFFICIENT_RESOURCES;
1145         }
1146     }
1147 
1148     if (NumMinorFunctions > 0) {
1149         if (DeviceInit->PreprocessInfo->Dispatch[MajorFunction].NumMinorFunctions != 0) {
1150 
1151             DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1152                                 "Already assigned Minorfunctions"
1153                                 "STATUS_INVALID_DEVICE_REQUEST"
1154                                 );
1155             return STATUS_INVALID_DEVICE_REQUEST;
1156         }
1157 
1158         DeviceInit->PreprocessInfo->Dispatch[MajorFunction].MinorFunctions =
1159             (PUCHAR) FxPoolAllocate(pFxDriverGlobals,
1160                                     NonPagedPool,
1161                                     sizeof(UCHAR) * NumMinorFunctions);
1162 
1163         if (DeviceInit->PreprocessInfo->Dispatch[MajorFunction].MinorFunctions == NULL) {
1164 
1165             DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1166                                 "Couldn't create object MinorFunctions"
1167                                 "STATUS_INSUFFICIENT_RESOURCES"
1168                                 );
1169 
1170             return STATUS_INSUFFICIENT_RESOURCES;
1171         }
1172 
1173         RtlCopyMemory(
1174             &DeviceInit->PreprocessInfo->Dispatch[MajorFunction].MinorFunctions[0],
1175             &MinorFunctions[0],
1176             NumMinorFunctions
1177             );
1178 
1179         DeviceInit->PreprocessInfo->Dispatch[MajorFunction].NumMinorFunctions =
1180             NumMinorFunctions;
1181     }
1182 
1183     DeviceInit->PreprocessInfo->Dispatch[MajorFunction].EvtDevicePreprocess =
1184         EvtDeviceWdmIrpPreprocess;
1185 
1186     return STATUS_SUCCESS;
1187 }
1188 
1189 
1190 __drv_maxIRQL(DISPATCH_LEVEL)
1191 VOID
1192 STDCALL
1193 WDFEXPORT(WdfDeviceInitSetIoInCallerContextCallback)(
1194     __in
1195     PWDF_DRIVER_GLOBALS DriverGlobals,
1196     __in
1197     PWDFDEVICE_INIT DeviceInit,
1198     __in
1199     PFN_WDF_IO_IN_CALLER_CONTEXT EvtIoInCallerContext
1200     )
1201 
1202 /*++
1203 
1204 Routine Description:
1205 
1206     Registers an I/O pre-processing callback for the device.
1207 
1208     If registered, any I/O for the device is first presented to this
1209     callback function before being placed in any I/O Queue's.
1210 
1211     The callback is invoked in the thread and/or DPC context of the
1212     original WDM caller as presented to the I/O package. No framework
1213     threading, locking, synchronization, or queuing occurs, and
1214     responsibility for synchronization is up to the device driver.
1215 
1216     This API is intended to support METHOD_NEITHER IRP_MJ_DEVICE_CONTROL's
1217     which must access the user buffer in the original callers context. The
1218     driver would probe and lock the buffer pages from within this event
1219     handler using the functions supplied on the WDFREQUEST object, storing
1220     any required mapped buffers and/or pointers on the WDFREQUEST context
1221     whose size is set by the RequestContextSize of the WDF_DRIVER_CONFIG structure.
1222 
1223     It is the responsibility of this routine to either complete the request, or
1224     pass it on to the I/O package through WdfDeviceEnqueueRequest(Device, Request).
1225 
1226 Arguments:
1227     DeviceInit - Device initialization structure
1228 
1229     EvtIoInCallerContext - Pointer to driver supplied callback function
1230 
1231 Return Value:
1232 
1233 --*/
1234 {
1235     DDI_ENTRY();
1236 
1237     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
1238     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), EvtIoInCallerContext);
1239 
1240     DeviceInit->IoInCallerContextCallback = EvtIoInCallerContext;
1241 
1242     return;
1243 }
1244 
1245 __drv_maxIRQL(DISPATCH_LEVEL)
1246 VOID
1247 STDCALL
1248 WDFEXPORT(WdfDeviceInitSetRemoveLockOptions)(
1249     __in
1250     PWDF_DRIVER_GLOBALS DriverGlobals,
1251     __in
1252     PWDFDEVICE_INIT DeviceInit,
1253     __in
1254     PWDF_REMOVE_LOCK_OPTIONS RemoveLockOptions
1255     )
1256 {
1257     DDI_ENTRY();
1258 
1259     PFX_DRIVER_GLOBALS fxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
1260     ULONG validFlags = WDF_REMOVE_LOCK_OPTION_ACQUIRE_FOR_IO;
1261 
1262     FxPointerNotNull(fxDriverGlobals, DeviceInit);
1263 
1264     FxPointerNotNull(fxDriverGlobals, RemoveLockOptions);
1265 
1266     if (RemoveLockOptions->Size != sizeof(WDF_REMOVE_LOCK_OPTIONS)) {
1267         //
1268         // Size is wrong, bail out
1269         //
1270         DoTraceLevelMessage(fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
1271                             "RemoveLockOptions %p Size incorrect, expected %d, "
1272                             "got %d",
1273                             RemoveLockOptions, sizeof(WDF_REMOVE_LOCK_OPTIONS),
1274                             RemoveLockOptions->Size);
1275 
1276         FxVerifierDbgBreakPoint(fxDriverGlobals);
1277         goto Done;
1278     }
1279 
1280     if ((RemoveLockOptions->Flags & ~validFlags) != 0) {
1281         //
1282         // Invalid flag
1283         //
1284         DoTraceLevelMessage(fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
1285                             "RemoveLockOptions %p Flags 0x%x invalid, "
1286                             "valid mask is 0x%x",
1287                             RemoveLockOptions, RemoveLockOptions->Flags,
1288                             validFlags);
1289 
1290         FxVerifierDbgBreakPoint(fxDriverGlobals);
1291         goto Done;
1292     }
1293 
1294     if (FxDeviceInitTypeControlDevice == DeviceInit->InitType) {
1295         //
1296         // At this time this feature is not supported on control-devices.
1297         //
1298         DoTraceLevelMessage(fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
1299                             "WdfDeviceInitSetRemoveLockOptions is not "
1300                             "supported on control devices");
1301 
1302         FxVerifierDbgBreakPoint(fxDriverGlobals);
1303         goto Done;
1304     }
1305 
1306     DeviceInit->RemoveLockOptionFlags = RemoveLockOptions->Flags;
1307 Done:
1308     return;
1309 }
1310 
1311 __drv_maxIRQL(DISPATCH_LEVEL)
1312 VOID
1313 STDCALL
1314 WDFEXPORT(WdfDeviceInitSetReleaseHardwareOrderOnFailure)(
1315     __in
1316     PWDF_DRIVER_GLOBALS DriverGlobals,
1317     __in
1318     PWDFDEVICE_INIT DeviceInit,
1319     __in
1320     WDF_RELEASE_HARDWARE_ORDER_ON_FAILURE ReleaseHardwareOrderOnFailure
1321     )
1322 {
1323     DDI_ENTRY();
1324 
1325     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
1326 
1327     if ((ReleaseHardwareOrderOnFailure ==
1328             WdfReleaseHardwareOrderOnFailureInvalid) ||
1329         (ReleaseHardwareOrderOnFailure >
1330             WdfReleaseHardwareOrderOnFailureAfterDescendants)) {
1331         DoTraceLevelMessage(
1332             DeviceInit->DriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1333             "Out of range WDF_RELEASE_HARDWARE_ORDER_ON_FAILURE %d",
1334             ReleaseHardwareOrderOnFailure);
1335         FxVerifierDbgBreakPoint(DeviceInit->DriverGlobals);
1336         return;
1337     }
1338 
1339     DeviceInit->ReleaseHardwareOrderOnFailure = ReleaseHardwareOrderOnFailure;
1340 }
1341 
1342 _IRQL_requires_max_(DISPATCH_LEVEL)
1343 VOID
1344 STDCALL
1345 WDFEXPORT(WdfDeviceInitAllowSelfIoTarget)(
1346     _In_
1347     PWDF_DRIVER_GLOBALS DriverGlobals,
1348     _In_
1349     PWDFDEVICE_INIT DeviceInit
1350     )
1351 /*++
1352 
1353 Routine Description:
1354 
1355     A client or Cx calls this API to indicate that it would like to leverage an
1356     Self IO target.
1357 
1358     For now the Self targets are not supported for PDOs, Miniport Device,
1359     or non pnp Devices.
1360 
1361 Arguments:
1362 
1363     DeviceInit - Pointer to the WDFDEVICE_INIT structure
1364 
1365 Returns:
1366 
1367     VOID
1368 
1369 --*/
1370 {
1371     DDI_ENTRY();
1372 
1373     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
1374 
1375     DeviceInit->RequiresSelfIoTarget = TRUE;
1376 }
1377 
1378 
1379 
1380 //
1381 // BEGIN FDO specific functions
1382 //
1383 
1384 __drv_maxIRQL(DISPATCH_LEVEL)
1385 PDEVICE_OBJECT
1386 STDCALL
1387 WDFEXPORT(WdfFdoInitWdmGetPhysicalDevice)(
1388     __in
1389     PWDF_DRIVER_GLOBALS DriverGlobals,
1390     __in
1391     PWDFDEVICE_INIT DeviceInit
1392     )
1393 {
1394     DDI_ENTRY();
1395 
1396     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
1397 
1398     if (DeviceInit->IsNotFdoInit()) {
1399         DoTraceLevelMessage(
1400             DeviceInit->DriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1401             "Not a PWDFDEVICE_INIT for an FDO"
1402             );
1403 
1404         return NULL;
1405     }
1406 
1407     return reinterpret_cast<PDEVICE_OBJECT>(DeviceInit->Fdo.PhysicalDevice);
1408 }
1409 
1410 _Must_inspect_result_
1411 __drv_maxIRQL(PASSIVE_LEVEL)
1412 NTSTATUS
1413 STDCALL
1414 WDFEXPORT(WdfFdoInitOpenRegistryKey)(
1415     __in
1416     PWDF_DRIVER_GLOBALS DriverGlobals,
1417     __in
1418     PWDFDEVICE_INIT DeviceInit,
1419     __in
1420     ULONG DeviceInstanceKeyType,
1421     __in
1422     ACCESS_MASK DesiredAccess,
1423     __in_opt
1424     PWDF_OBJECT_ATTRIBUTES KeyAttributes,
1425     __out
1426     WDFKEY* Key
1427     )
1428 {
1429     DDI_ENTRY();
1430 
1431     PFX_DRIVER_GLOBALS pFxDriverGlobals;
1432     NTSTATUS status;
1433 
1434     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
1435     pFxDriverGlobals = DeviceInit->DriverGlobals;
1436 
1437     FxPointerNotNull(pFxDriverGlobals, Key);
1438 
1439     *Key = NULL;
1440 
1441     if (DeviceInit->IsNotFdoInit()) {
1442         status = STATUS_INVALID_PARAMETER;
1443         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1444                             "Not a PWDFDEVICE_INIT for an FDO, %!STATUS!",
1445                             status);
1446         return status;
1447     }
1448 
1449     status = FxValidateObjectAttributes(pFxDriverGlobals, KeyAttributes);
1450     if (!NT_SUCCESS(status)) {
1451         return status;
1452     }
1453 
1454     return FxDevice::_OpenKey(pFxDriverGlobals,
1455                               DeviceInit,
1456                               NULL,
1457                               DeviceInstanceKeyType,
1458                               DesiredAccess,
1459                               KeyAttributes,
1460                               Key);
1461 }
1462 
1463 __drv_maxIRQL(PASSIVE_LEVEL)
1464 VOID
1465 STDCALL
1466 WDFEXPORT(WdfFdoInitSetFilter)(
1467     __in
1468     PWDF_DRIVER_GLOBALS DriverGlobals,
1469     __in
1470     PWDFDEVICE_INIT DeviceInit
1471     )
1472 {
1473     DDI_ENTRY();
1474 
1475     PFX_DRIVER_GLOBALS pFxDriverGlobals;
1476 
1477     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
1478     pFxDriverGlobals = DeviceInit->DriverGlobals;
1479 
1480     if (!NT_SUCCESS(FxVerifierCheckIrqlLevel(pFxDriverGlobals,
1481                                              PASSIVE_LEVEL))) {
1482         return;
1483     }
1484     if (DeviceInit->IsNotFdoInit()) {
1485         DoTraceLevelMessage(
1486             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1487             "Not a PWDFDEVICE_INIT for an FDO");
1488 
1489         FxVerifierDbgBreakPoint(pFxDriverGlobals);
1490         return;
1491     }
1492 
1493     DeviceInit->Fdo.Filter = TRUE;
1494 }
1495 
1496 _Must_inspect_result_
1497 __drv_maxIRQL(PASSIVE_LEVEL)
1498 NTSTATUS
1499 STDCALL
1500 WDFEXPORT(WdfFdoInitQueryProperty)(
1501     __in
1502     PWDF_DRIVER_GLOBALS DriverGlobals,
1503     __in
1504     PWDFDEVICE_INIT DeviceInit,
1505     __in
1506     DEVICE_REGISTRY_PROPERTY  DeviceProperty,
1507     __in
1508     ULONG BufferLength,
1509     __out_bcount_full_opt(BufferLength)
1510     PVOID PropertyBuffer,
1511     __out
1512     PULONG ResultLength
1513     )
1514 /*++
1515 
1516 Routine Description:
1517     Retrieves the requested device property for the given device
1518 
1519 Arguments:
1520     DeviceInit - Device initialization structure
1521 
1522     DeviceProperty - the property being queried
1523 
1524     BufferLength - length of PropertyBuffer in bytes
1525 
1526     PropertyBuffer - Buffer which will receive the property being queried
1527 
1528     ResultLength - if STATUS_BUFFER_TOO_SMALL is returned, then this will contain
1529                    the required length
1530 
1531 Return Value:
1532     NTSTATUS
1533 
1534   --*/
1535 {
1536     DDI_ENTRY();
1537 
1538     PFX_DRIVER_GLOBALS pFxDriverGlobals;
1539     NTSTATUS status;
1540 
1541     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
1542     pFxDriverGlobals = DeviceInit->DriverGlobals;
1543 
1544     FxPointerNotNull(pFxDriverGlobals, ResultLength);
1545     if (BufferLength > 0) {
1546         FxPointerNotNull(pFxDriverGlobals, PropertyBuffer);
1547     }
1548 
1549     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1550     if (!NT_SUCCESS(status)) {
1551         return status;
1552     }
1553 
1554     if (DeviceInit->IsNotFdoInit()) {
1555         status = STATUS_INVALID_DEVICE_REQUEST;
1556         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1557                             "Not a PWDFDEVICE_INIT for an FDO, %!STATUS!",
1558                             status);
1559         return status;
1560     }
1561 
1562     status = FxDevice::_QueryProperty(pFxDriverGlobals,
1563                                       DeviceInit,
1564                                       NULL,
1565                                       NULL,
1566                                       DeviceProperty,
1567                                       BufferLength,
1568                                       PropertyBuffer,
1569                                       ResultLength);
1570     return status;
1571 }
1572 
1573 _Must_inspect_result_
1574 __drv_maxIRQL(PASSIVE_LEVEL)
1575 NTSTATUS
1576 STDCALL
1577 WDFEXPORT(WdfFdoInitAllocAndQueryProperty)(
1578     __in
1579     PWDF_DRIVER_GLOBALS DriverGlobals,
1580     __in
1581     PWDFDEVICE_INIT DeviceInit,
1582     __in
1583     DEVICE_REGISTRY_PROPERTY DeviceProperty,
1584     __in
1585     __drv_strictTypeMatch(__drv_typeExpr)
1586     POOL_TYPE PoolType,
1587     __in_opt
1588     PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes,
1589     __out
1590     WDFMEMORY* PropertyMemory
1591     )
1592 /*++
1593 
1594 Routine Description:
1595     Allocates and retrieves the requested device property for the given device init
1596 
1597 Arguments:
1598     DeviceInit - Device initialization structure
1599 
1600     DeviceProperty - the property being queried
1601 
1602     PoolType - what type of pool to allocate
1603 
1604     PropertyMemoryAttributes - attributes to associate with PropertyMemory
1605 
1606     PropertyMemory - handle which will receive the property buffer
1607 
1608 Return Value:
1609     NTSTATUS
1610 
1611   --*/
1612 {
1613     DDI_ENTRY();
1614 
1615     PFX_DRIVER_GLOBALS pFxDriverGlobals;
1616     NTSTATUS status;
1617 
1618     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
1619     pFxDriverGlobals = DeviceInit->DriverGlobals;
1620 
1621     FxPointerNotNull(pFxDriverGlobals, PropertyMemory);
1622 
1623     *PropertyMemory = NULL;
1624 
1625     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1626     if (!NT_SUCCESS(status)) {
1627         return status;
1628     }
1629 
1630     FxVerifierCheckNxPoolType(pFxDriverGlobals, PoolType, pFxDriverGlobals->Tag);
1631 
1632     status = FxValidateObjectAttributes(pFxDriverGlobals, PropertyMemoryAttributes);
1633     if (!NT_SUCCESS(status)) {
1634         return status;
1635     }
1636 
1637     if (DeviceInit->IsNotFdoInit()) {
1638         status = STATUS_INVALID_DEVICE_REQUEST;
1639 
1640         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1641                             "Not a PWDFDEVICE_INIT for an FDO, %!STATUS!",
1642                             status);
1643 
1644         return status;
1645     }
1646 
1647     status = FxDevice::_AllocAndQueryProperty(pFxDriverGlobals,
1648                                               DeviceInit,
1649                                               NULL,
1650                                               NULL,
1651                                               DeviceProperty,
1652                                               PoolType,
1653                                               PropertyMemoryAttributes,
1654                                               PropertyMemory);
1655     return status;
1656 }
1657 
1658 __drv_maxIRQL(PASSIVE_LEVEL)
1659 VOID
1660 STDCALL
1661 WDFEXPORT(WdfFdoInitSetEventCallbacks)(
1662     __in
1663     PWDF_DRIVER_GLOBALS DriverGlobals,
1664     __in
1665     PWDFDEVICE_INIT DeviceInit,
1666     __in
1667     PWDF_FDO_EVENT_CALLBACKS FdoEventCallbacks
1668     )
1669 {
1670     DDI_ENTRY();
1671 
1672     PFX_DRIVER_GLOBALS pFxDriverGlobals;
1673 
1674     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
1675     pFxDriverGlobals = DeviceInit->DriverGlobals;
1676 
1677     FxPointerNotNull(pFxDriverGlobals, FdoEventCallbacks);
1678 
1679     if (!NT_SUCCESS(FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL))) {
1680         return;
1681     }
1682 
1683     if (DeviceInit->IsNotFdoInit()) {
1684         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1685                             "Not a PWDFDEVICE_INIT for an FDO");
1686         FxVerifierDbgBreakPoint(pFxDriverGlobals);
1687         return;
1688     }
1689 
1690     if (FdoEventCallbacks->Size != sizeof(WDF_FDO_EVENT_CALLBACKS)) {
1691         DoTraceLevelMessage(
1692             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1693             "FdoEventCallbacks size %d is invalid, expected %d",
1694             FdoEventCallbacks->Size, sizeof(WDF_FDO_EVENT_CALLBACKS)
1695             );
1696         FxVerifierDbgBreakPoint(pFxDriverGlobals);
1697         return;
1698     }
1699 
1700     if (FdoEventCallbacks->EvtDeviceFilterAddResourceRequirements != NULL &&
1701         FdoEventCallbacks->EvtDeviceRemoveAddedResources == NULL) {
1702         //
1703         // Not allowed to add resources without filtering them out later
1704         //
1705         DoTraceLevelMessage(
1706             GetFxDriverGlobals(DriverGlobals), TRACE_LEVEL_ERROR, TRACINGPNP,
1707             "Must set EvtDeviceRemoveAddedResources if "
1708             "EvtDeviceFilterAddResourceRequirements (%p) is set",
1709             FdoEventCallbacks->EvtDeviceFilterAddResourceRequirements);
1710 
1711         FxVerifierDbgBreakPoint(GetFxDriverGlobals(DriverGlobals));
1712         return;
1713     }
1714 
1715     RtlCopyMemory(&DeviceInit->Fdo.EventCallbacks,
1716                   FdoEventCallbacks,
1717                   sizeof(DeviceInit->Fdo.EventCallbacks));
1718 }
1719 
1720 __drv_maxIRQL(PASSIVE_LEVEL)
1721 VOID
1722 STDCALL
1723 WDFEXPORT(WdfFdoInitSetDefaultChildListConfig)(
1724     __in
1725     PWDF_DRIVER_GLOBALS DriverGlobals,
1726     __inout
1727     PWDFDEVICE_INIT DeviceInit,
1728     __in
1729     PWDF_CHILD_LIST_CONFIG Config,
1730     __in_opt
1731     PWDF_OBJECT_ATTRIBUTES DefaultDeviceListAttributes
1732     )
1733 {
1734     DDI_ENTRY();
1735 
1736     PFX_DRIVER_GLOBALS pFxDriverGlobals;
1737     NTSTATUS status;
1738     size_t totalDescriptionSize;
1739 
1740     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
1741     pFxDriverGlobals = DeviceInit->DriverGlobals;
1742     totalDescriptionSize = 0;
1743 
1744     FxPointerNotNull(pFxDriverGlobals, Config);
1745 
1746     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1747     if (!NT_SUCCESS(status)) {
1748         return;
1749     }
1750 
1751     if (DeviceInit->IsNotFdoInit()) {
1752         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1753                             "Not a PWDFDEVICE_INIT for an FDO");
1754         FxVerifierDbgBreakPoint(pFxDriverGlobals);
1755         return;
1756     }
1757 
1758     status = FxChildList::_ValidateConfig(pFxDriverGlobals,
1759                                           Config,
1760                                           &totalDescriptionSize);
1761     if (!NT_SUCCESS(status)) {
1762         FxVerifierDbgBreakPoint(pFxDriverGlobals);
1763         return;
1764     }
1765 
1766     if (DefaultDeviceListAttributes != NULL) {
1767         status = FxValidateObjectAttributes(pFxDriverGlobals,
1768                                             DefaultDeviceListAttributes,
1769                                             FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
1770         if (!NT_SUCCESS(status)) {
1771             FxVerifierDbgBreakPoint(pFxDriverGlobals);
1772             return;
1773         }
1774 
1775         RtlCopyMemory(&DeviceInit->Fdo.ListConfigAttributes,
1776                       DefaultDeviceListAttributes,
1777                       sizeof(DeviceInit->Fdo.ListConfigAttributes));
1778     }
1779 
1780     RtlCopyMemory(&DeviceInit->Fdo.ListConfig,
1781                   Config,
1782                   sizeof(WDF_CHILD_LIST_CONFIG));
1783 }
1784 
1785 _Must_inspect_result_
1786 _IRQL_requires_max_(PASSIVE_LEVEL)
1787 WDFAPI
1788 NTSTATUS
1789 STDCALL
1790 WDFEXPORT(WdfFdoInitQueryPropertyEx)(
1791     _In_
1792     PWDF_DRIVER_GLOBALS DriverGlobals,
1793     _In_
1794     PWDFDEVICE_INIT DeviceInit,
1795     _In_
1796     PWDF_DEVICE_PROPERTY_DATA DeviceProperty,
1797     _In_
1798     ULONG BufferLength,
1799     _Out_
1800     PVOID PropertyBuffer,
1801     _Out_
1802     PULONG ResultLength,
1803     _Out_
1804     PDEVPROPTYPE Type
1805     )
1806 /*++
1807 
1808 Routine Description:
1809 
1810     This routine queries device property.
1811 
1812 Arguments:
1813 
1814     DriverGlobals - DriverGlobals pointer
1815 
1816     DeviceInit - WDF DeviceInit structure pointer.
1817 
1818     DeviceProperty - A pointer to WDF_DEVICE_PROPERTY_DATA structure.
1819 
1820     BufferLength - The size, in bytes, of the buffer that is pointed to by
1821                    PropertyBuffer.
1822 
1823     PropertyBuffer - A caller-supplied pointer to a caller-allocated buffer that
1824                   receives the requested information. The pointer can be NULL
1825                   if the BufferLength parameter is zero.
1826 
1827     ResultLength - A caller-supplied location that, on return, contains the
1828                   size, in bytes, of the information that the method stored in
1829                   PropertyBuffer. If the function's return value is
1830                   STATUS_BUFFER_TOO_SMALL, this location receives the required
1831                   buffer size.
1832 
1833     Type - A pointer to a DEVPROPTYPE variable. If method successfully retrieves
1834                   the property data, the routine writes the property type value
1835                   to this variable. This value indicates the type of property
1836                   data that is in the Data buffer.
1837 
1838 Return Value:
1839 
1840     Method returns an NTSTATUS value. This routine might return one of the
1841     following values.
1842 
1843     STATUS_BUFFER_TOO_SMALL - The supplied buffer is too small to receive the
1844                             information. The ResultLength member receives the
1845                             size of buffer required.
1846     STATUS_SUCCESS  - The operation succeeded.
1847     STATUS_INVALID_PARAMETER - One of the parameters is incorrect.
1848 
1849     The method might return other NTSTATUS values.
1850 
1851 --*/
1852 
1853 {
1854     DDI_ENTRY();
1855 
1856     PFX_DRIVER_GLOBALS pFxDriverGlobals;
1857     NTSTATUS status;
1858 
1859     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
1860     pFxDriverGlobals = DeviceInit->DriverGlobals;
1861 
1862     FxPointerNotNull(pFxDriverGlobals, DeviceProperty);
1863 
1864     if (DeviceProperty->Size != sizeof(WDF_DEVICE_PROPERTY_DATA)) {
1865         status = STATUS_INFO_LENGTH_MISMATCH;
1866         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
1867                      "PropertyData size (%d) incorrect, expected %d, %!STATUS!",
1868                      DeviceProperty->Size,
1869                      sizeof(WDF_DEVICE_PROPERTY_DATA), status);
1870         return status;
1871     }
1872 
1873     FxPointerNotNull(pFxDriverGlobals, ResultLength);
1874     if (BufferLength > 0) {
1875         FxPointerNotNull(pFxDriverGlobals, PropertyBuffer);
1876     }
1877 
1878     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1879     if (!NT_SUCCESS(status)) {
1880         return status;
1881     }
1882 
1883     if (DeviceInit->IsNotFdoInit()) {
1884         status = STATUS_INVALID_DEVICE_REQUEST;
1885         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1886                             "Not a PWDFDEVICE_INIT for an FDO, %!STATUS!",
1887                             status);
1888         return status;
1889     }
1890 
1891     status = FxDevice::_QueryPropertyEx(pFxDriverGlobals,
1892                                         DeviceInit,
1893                                         NULL,
1894                                         DeviceProperty,
1895                                         FxDeviceProperty,
1896                                         BufferLength,
1897                                         PropertyBuffer,
1898                                         ResultLength,
1899                                         Type);
1900     return status;
1901 }
1902 
1903 _Must_inspect_result_
1904 _IRQL_requires_max_(PASSIVE_LEVEL)
1905 WDFAPI
1906 NTSTATUS
1907 STDCALL
1908 WDFEXPORT(WdfFdoInitAllocAndQueryPropertyEx)(
1909     _In_
1910     PWDF_DRIVER_GLOBALS DriverGlobals,
1911     _In_
1912     PWDFDEVICE_INIT DeviceInit,
1913     _In_
1914     PWDF_DEVICE_PROPERTY_DATA DeviceProperty,
1915     _In_
1916     _Strict_type_match_
1917     POOL_TYPE PoolType,
1918     _In_opt_
1919     PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes,
1920     _Out_
1921     WDFMEMORY* PropertyMemory,
1922     _Out_
1923     PDEVPROPTYPE Type
1924     )
1925 /*++
1926 
1927 Routine Description:
1928 
1929     This routine queries device property.
1930 
1931 Arguments:
1932 
1933     DriverGlobals - DriverGlobals pointer
1934 
1935     DeviceInit - WDF DeviceInit pointer.
1936 
1937     PropertyData - A pointer to WDF_DEVICE_PROPERTY_ DATA structure.
1938 
1939     PoolType - A POOL_TYPE-typed enumerator that specifies the type of memory
1940                to be allocated.
1941 
1942     PropertyMemoryAttributes - optional, A pointer to a caller-allocated
1943                WDF_OBJECT_ATTRIBUTES structure that describes object attributes
1944                for the memory object that the function will allocate. This
1945                parameter is optional and can be WDF_NO_OBJECT_ATTRIBUTES.
1946 
1947     PropertyMemory - A pointer to a WDFMEMORY-typed location that receives a
1948                handle to a framework memory object.
1949 
1950     Type - A pointer to a DEVPROPTYPE variable. If method successfully retrieves
1951                the property data, the routine writes the property type value to
1952                this variable. This value indicates the type of property data
1953                that is in the Data buffer.
1954 
1955 Return Value:
1956 
1957     Method returns an NTSTATUS value. This routine might return one of the
1958     following values. It might return other NTSTATUS-codes as well.
1959 
1960     STATUS_SUCCESS  The operation succeeded.
1961     STATUS_INVALID_PARAMETER    One of the parameters is incorrect.
1962 
1963 --*/
1964 {
1965     DDI_ENTRY();
1966 
1967     PFX_DRIVER_GLOBALS pFxDriverGlobals;
1968     NTSTATUS status;
1969 
1970     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
1971     pFxDriverGlobals = DeviceInit->DriverGlobals;
1972 
1973     FxPointerNotNull(pFxDriverGlobals, DeviceProperty);
1974 
1975     if (DeviceProperty->Size != sizeof(WDF_DEVICE_PROPERTY_DATA)) {
1976         status = STATUS_INFO_LENGTH_MISMATCH;
1977         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
1978                      "PropertyData size (%d) incorrect, expected %d, %!STATUS!",
1979                      DeviceProperty->Size,
1980                      sizeof(WDF_DEVICE_PROPERTY_DATA), status);
1981         return status;
1982     }
1983 
1984     FxPointerNotNull(pFxDriverGlobals, PropertyMemory);
1985 
1986     *PropertyMemory = NULL;
1987 
1988     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1989     if (!NT_SUCCESS(status)) {
1990         return status;
1991     }
1992 
1993     FxVerifierCheckNxPoolType(pFxDriverGlobals, PoolType, pFxDriverGlobals->Tag);
1994 
1995     status = FxValidateObjectAttributes(pFxDriverGlobals, PropertyMemoryAttributes);
1996     if (!NT_SUCCESS(status)) {
1997         return status;
1998     }
1999 
2000     if (DeviceInit->IsNotFdoInit()) {
2001         status = STATUS_INVALID_DEVICE_REQUEST;
2002 
2003         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2004                             "Not a PWDFDEVICE_INIT for an FDO, %!STATUS!",
2005                             status);
2006 
2007         return status;
2008     }
2009 
2010     status = FxDevice::_AllocAndQueryPropertyEx(pFxDriverGlobals,
2011                                                 DeviceInit,
2012                                                 NULL,
2013                                                 DeviceProperty,
2014                                                 FxDeviceProperty,
2015                                                 PoolType,
2016                                                 PropertyMemoryAttributes,
2017                                                 PropertyMemory,
2018                                                 Type);
2019     return status;
2020 }
2021 
2022 //
2023 // END FDO specific functions
2024 //
2025 
2026 //
2027 // BEGIN PDO specific functions
2028 //
2029 _Must_inspect_result_
2030 __drv_maxIRQL(PASSIVE_LEVEL)
2031 PWDFDEVICE_INIT
2032 STDCALL
2033 WDFEXPORT(WdfPdoInitAllocate)(
2034     __in
2035     PWDF_DRIVER_GLOBALS DriverGlobals,
2036     __in
2037     WDFDEVICE ParentDevice
2038     )
2039 {
2040     DDI_ENTRY();
2041 
2042     PFX_DRIVER_GLOBALS pFxDriverGlobals;
2043     PWDFDEVICE_INIT pInit;
2044     FxDevice* pDevice;
2045     NTSTATUS status;
2046 
2047     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
2048                                    ParentDevice,
2049                                    FX_TYPE_DEVICE,
2050                                    (PVOID*) &pDevice,
2051                                    &pFxDriverGlobals);
2052 
2053     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
2054     if (!NT_SUCCESS(status)) {
2055         return NULL;
2056     }
2057 
2058     if (pDevice->IsFdo() == FALSE) {
2059         DoTraceLevelMessage(
2060             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2061             "Parent device is not a FDO (must use WDFCHILDLIST to use a PDO as a parent)"
2062             );
2063 
2064         return NULL;
2065     }
2066 
2067     pInit = new(pFxDriverGlobals) WDFDEVICE_INIT(pDevice->GetDriver());
2068     if (pInit == NULL) {
2069         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2070                             "Couldn't create WDFDEVICE_INIT object");
2071 
2072         return NULL;
2073     }
2074 
2075     pInit->SetPdo(pDevice);
2076 
2077     //
2078     // Dynamically created PDOs are not created with this API, rather they go
2079     // through WDFCHILDLIST's callback.
2080     //
2081     pInit->Pdo.Static = TRUE;
2082 
2083     return pInit;
2084 }
2085 
2086 __drv_maxIRQL(PASSIVE_LEVEL)
2087 VOID
2088 STDCALL
2089 WDFEXPORT(WdfPdoInitSetEventCallbacks)(
2090     __in
2091     PWDF_DRIVER_GLOBALS DriverGlobals,
2092     __in
2093     PWDFDEVICE_INIT DeviceInit,
2094     __in
2095     PWDF_PDO_EVENT_CALLBACKS DispatchTable
2096     )
2097 {
2098     DDI_ENTRY();
2099 
2100     PFX_DRIVER_GLOBALS pFxDriverGlobals;
2101 
2102     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
2103     pFxDriverGlobals = DeviceInit->DriverGlobals;
2104 
2105     FxPointerNotNull(pFxDriverGlobals, DispatchTable);
2106 
2107     if (!NT_SUCCESS(FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL))) {
2108         return;
2109     }
2110 
2111     if (DeviceInit->IsNotPdoInit()) {
2112         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2113                             "Not a PWDFDEVICE_INIT for a PDO");
2114         FxVerifierDbgBreakPoint(pFxDriverGlobals);
2115         return;
2116     }
2117 
2118     if (DispatchTable->Size != sizeof(WDF_PDO_EVENT_CALLBACKS) &&
2119         DispatchTable->Size != sizeof(WDF_PDO_EVENT_CALLBACKS_V1_9)) {
2120         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2121                             "DispatchTable size %d is invalid, expected %d",
2122                             DispatchTable->Size, sizeof(WDF_PDO_EVENT_CALLBACKS));
2123         FxVerifierDbgBreakPoint(pFxDriverGlobals);
2124         return; // STATUS_INFO_LENGTH_MISMATCH;
2125     }
2126 
2127     RtlCopyMemory(&DeviceInit->Pdo.EventCallbacks,
2128                   DispatchTable,
2129                   sizeof(WDF_PDO_EVENT_CALLBACKS));
2130 }
2131 
2132 _Must_inspect_result_
2133 __drv_maxIRQL(PASSIVE_LEVEL)
2134 NTSTATUS
2135 STDCALL
2136 WDFEXPORT(WdfPdoInitAssignDeviceID)(
2137     __in
2138     PWDF_DRIVER_GLOBALS DriverGlobals,
2139     __in
2140     PWDFDEVICE_INIT DeviceInit,
2141     __in
2142     PCUNICODE_STRING DeviceID
2143     )
2144 {
2145     DDI_ENTRY();
2146 
2147     PFX_DRIVER_GLOBALS pFxDriverGlobals;
2148     NTSTATUS status;
2149 
2150     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
2151     pFxDriverGlobals = DeviceInit->DriverGlobals;
2152 
2153     FxPointerNotNull(pFxDriverGlobals, DeviceID);
2154 
2155     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
2156     if (!NT_SUCCESS(status)) {
2157         return status;
2158     }
2159 
2160     status = FxValidateUnicodeString(pFxDriverGlobals, DeviceID);
2161     if (!NT_SUCCESS(status)) {
2162         return status;
2163     }
2164 
2165     if (DeviceInit->IsNotPdoInit()) {
2166         status = STATUS_INVALID_DEVICE_REQUEST;
2167         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2168                             "Not a PWDFDEVICE_INIT for a PDO, %!STATUS!",
2169                             status);
2170         return status;
2171     }
2172 
2173     if (DeviceInit->Pdo.DeviceID == NULL) {
2174         DeviceInit->Pdo.DeviceID = new(pFxDriverGlobals, WDF_NO_OBJECT_ATTRIBUTES)
2175             FxString(pFxDriverGlobals);
2176 
2177         if (DeviceInit->Pdo.DeviceID == NULL) {
2178             status = STATUS_INSUFFICIENT_RESOURCES;
2179             DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2180                             "Couldn't allocate DeviceID object, %!STATUS!",
2181                             status);
2182             return status;
2183         }
2184     }
2185 
2186     status = DeviceInit->Pdo.DeviceID->Assign(DeviceID);
2187 
2188     return status;
2189 }
2190 
2191 _Must_inspect_result_
2192 __drv_maxIRQL(PASSIVE_LEVEL)
2193 NTSTATUS
2194 STDCALL
2195 WDFEXPORT(WdfPdoInitAssignInstanceID)(
2196     __in
2197     PWDF_DRIVER_GLOBALS DriverGlobals,
2198     __in
2199     PWDFDEVICE_INIT DeviceInit,
2200     __in
2201     PCUNICODE_STRING InstanceID
2202     )
2203 {
2204     DDI_ENTRY();
2205 
2206     PFX_DRIVER_GLOBALS pFxDriverGlobals;
2207     NTSTATUS status;
2208 
2209     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
2210     pFxDriverGlobals = DeviceInit->DriverGlobals;
2211 
2212     FxPointerNotNull(pFxDriverGlobals, InstanceID);
2213 
2214     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
2215     if (!NT_SUCCESS(status)) {
2216         return status;
2217     }
2218 
2219     status = FxValidateUnicodeString(pFxDriverGlobals, InstanceID);
2220     if (!NT_SUCCESS(status)) {
2221         return status;
2222     }
2223 
2224     if (DeviceInit->IsNotPdoInit()) {
2225         status = STATUS_INVALID_DEVICE_REQUEST ;
2226         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2227                             "Not a PWDFDEVICE_INIT for a PDO, %!STATUS!",
2228                             status);
2229         return status;
2230     }
2231 
2232     if (DeviceInit->Pdo.InstanceID == NULL) {
2233         DeviceInit->Pdo.InstanceID = new(pFxDriverGlobals, WDF_NO_OBJECT_ATTRIBUTES)
2234             FxString(pFxDriverGlobals);
2235 
2236         if (DeviceInit->Pdo.InstanceID == NULL) {
2237             status = STATUS_INSUFFICIENT_RESOURCES;
2238             DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2239                             "Couldn't allocate InstanceID object, %!STATUS!",
2240                             status);
2241             return status;
2242         }
2243     }
2244 
2245     status = DeviceInit->Pdo.InstanceID->Assign(InstanceID);
2246 
2247     return status;
2248 }
2249 
2250 _Must_inspect_result_
2251 __drv_maxIRQL(PASSIVE_LEVEL)
2252 NTSTATUS
2253 STDCALL
2254 WDFEXPORT(WdfPdoInitAddHardwareID)(
2255     __in
2256     PWDF_DRIVER_GLOBALS DriverGlobals,
2257     __in
2258     PWDFDEVICE_INIT DeviceInit,
2259     __in
2260     PCUNICODE_STRING HardwareID
2261     )
2262 {
2263     DDI_ENTRY();
2264 
2265     PFX_DRIVER_GLOBALS pFxDriverGlobals;
2266     FxString* pID;
2267     NTSTATUS status;
2268 
2269     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
2270     pFxDriverGlobals = DeviceInit->DriverGlobals;
2271 
2272     FxPointerNotNull(pFxDriverGlobals, HardwareID);
2273 
2274     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
2275     if (!NT_SUCCESS(status)) {
2276         return status;
2277     }
2278 
2279     status = FxValidateUnicodeString(pFxDriverGlobals, HardwareID);
2280     if (!NT_SUCCESS(status)) {
2281         return status;
2282     }
2283 
2284     if (DeviceInit->IsNotPdoInit()) {
2285         status = STATUS_INVALID_DEVICE_REQUEST ;
2286         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2287                             "Not a PWDFDEVICE_INIT for a PDO, %!STATUS!",
2288                             status);
2289         return status;
2290     }
2291 
2292     pID = new(pFxDriverGlobals, WDF_NO_OBJECT_ATTRIBUTES) FxString(pFxDriverGlobals);
2293     if (pID == NULL) {
2294         status = STATUS_INSUFFICIENT_RESOURCES;
2295         DoTraceLevelMessage(
2296             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2297             "Couldn't allocate String object %!STATUS!", status);
2298         return status;
2299     }
2300 
2301     status = pID->Assign(HardwareID);
2302     if (NT_SUCCESS(status)) {
2303         status = (DeviceInit->Pdo.HardwareIDs.Add(pFxDriverGlobals, pID)) ?
2304             STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
2305     }
2306 
2307     //
2308     // Upon success, the FxCollection will have taken a reference.
2309     // Upon failure, this is object cleanup.
2310     //
2311     pID->Release();
2312 
2313     return status;
2314 }
2315 
2316 _Must_inspect_result_
2317 __drv_maxIRQL(PASSIVE_LEVEL)
2318 NTSTATUS
2319 STDCALL
2320 WDFEXPORT(WdfPdoInitAddCompatibleID)(
2321     __in
2322     PWDF_DRIVER_GLOBALS DriverGlobals,
2323     __in
2324     PWDFDEVICE_INIT DeviceInit,
2325     __in
2326     PCUNICODE_STRING CompatibleID
2327     )
2328 {
2329     DDI_ENTRY();
2330 
2331     PFX_DRIVER_GLOBALS pFxDriverGlobals;
2332     FxString* pID;
2333     NTSTATUS status;
2334 
2335     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
2336     pFxDriverGlobals = DeviceInit->DriverGlobals;
2337 
2338     FxPointerNotNull(pFxDriverGlobals, CompatibleID);
2339 
2340     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
2341     if (!NT_SUCCESS(status)) {
2342         return status;
2343     }
2344 
2345     status = FxValidateUnicodeString(pFxDriverGlobals, CompatibleID);
2346     if (!NT_SUCCESS(status)) {
2347         return status;
2348     }
2349 
2350     if (DeviceInit->IsNotPdoInit()) {
2351         status = STATUS_INVALID_DEVICE_REQUEST;
2352         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2353                             "Not a PWDFDEVICE_INIT for a PDO, %!STATUS!",
2354                             status);
2355         return status;
2356     }
2357 
2358     pID = new(pFxDriverGlobals, WDF_NO_OBJECT_ATTRIBUTES) FxString(pFxDriverGlobals);
2359     if (pID == NULL) {
2360         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2361                         "Couldn't allocate String object"
2362                         "STATUS_INSUFFICIENT_RESOURCES "
2363                         );
2364         return STATUS_INSUFFICIENT_RESOURCES;
2365     }
2366 
2367     status = pID->Assign(CompatibleID);
2368     if (NT_SUCCESS(status)) {
2369         status = (DeviceInit->Pdo.CompatibleIDs.Add(pFxDriverGlobals, pID)) ?
2370             STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
2371     }
2372 
2373     //
2374     // Upon success, the FxCollection will have taken a reference. Upon failure,
2375     // this is object cleanup.
2376     //
2377     pID->Release();
2378 
2379     return status;
2380 }
2381 
2382 _Must_inspect_result_
2383 __drv_maxIRQL(PASSIVE_LEVEL)
2384 NTSTATUS
2385 STDCALL
2386 WDFEXPORT(WdfPdoInitAssignContainerID)(
2387     __in
2388     PWDF_DRIVER_GLOBALS DriverGlobals,
2389     __in
2390     PWDFDEVICE_INIT DeviceInit,
2391     __in
2392     PCUNICODE_STRING ContainerID
2393     )
2394 {
2395     DDI_ENTRY();
2396 
2397     PFX_DRIVER_GLOBALS pFxDriverGlobals;
2398     NTSTATUS status;
2399 
2400     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
2401     pFxDriverGlobals = DeviceInit->DriverGlobals;
2402 
2403     FxPointerNotNull(pFxDriverGlobals, ContainerID);
2404 
2405     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
2406     if (!NT_SUCCESS(status)) {
2407         return status;
2408     }
2409 
2410     status = FxValidateUnicodeString(pFxDriverGlobals, ContainerID);
2411     if (!NT_SUCCESS(status)) {
2412         return status;
2413     }
2414 
2415     if (DeviceInit->IsNotPdoInit()) {
2416         status = STATUS_INVALID_DEVICE_REQUEST ;
2417         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2418                             "Not a PWDFDEVICE_INIT for a PDO, %!STATUS!",
2419                             status);
2420         return status;
2421     }
2422 
2423     if (DeviceInit->Pdo.ContainerID == NULL) {
2424         DeviceInit->Pdo.ContainerID = new(pFxDriverGlobals,
2425                                           WDF_NO_OBJECT_ATTRIBUTES)
2426             FxString(pFxDriverGlobals);
2427 
2428         if (DeviceInit->Pdo.ContainerID == NULL) {
2429             status = STATUS_INSUFFICIENT_RESOURCES;
2430             DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2431                             "Couldn't allocate ContainerID object, %!STATUS!",
2432                             status);
2433 
2434             return status;
2435         }
2436     }
2437 
2438     status = DeviceInit->Pdo.ContainerID->Assign(ContainerID);
2439 
2440     return status;
2441 }
2442 
2443 _Must_inspect_result_
2444 __drv_maxIRQL(PASSIVE_LEVEL)
2445 NTSTATUS
2446 STDCALL
2447 WDFEXPORT(WdfPdoInitAddDeviceText)(
2448     __in
2449     PWDF_DRIVER_GLOBALS DriverGlobals,
2450     __in
2451     PWDFDEVICE_INIT DeviceInit,
2452     __in
2453     PCUNICODE_STRING DeviceDescription,
2454     __in
2455     PCUNICODE_STRING DeviceLocation,
2456     __in
2457     LCID LocaleId
2458     )
2459 {
2460     DDI_ENTRY();
2461 
2462     PFX_DRIVER_GLOBALS pFxDriverGlobals;
2463     FxDeviceText *pDeviceText;
2464     NTSTATUS status;
2465 
2466     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
2467     pFxDriverGlobals = DeviceInit->DriverGlobals;
2468 
2469     FxPointerNotNull(pFxDriverGlobals, DeviceDescription);
2470     FxPointerNotNull(pFxDriverGlobals, DeviceLocation);
2471 
2472     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
2473     if (!NT_SUCCESS(status)) {
2474         return status;
2475     }
2476 
2477     status = FxValidateUnicodeString(pFxDriverGlobals, DeviceDescription);
2478     if (!NT_SUCCESS(status)) {
2479         return status;
2480     }
2481 
2482     status = FxValidateUnicodeString(pFxDriverGlobals, DeviceLocation);
2483     if (!NT_SUCCESS(status)) {
2484         return status;
2485     }
2486 
2487     if (DeviceInit->IsNotPdoInit()) {
2488         status = STATUS_INVALID_DEVICE_REQUEST;
2489         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2490                             "Not a PWDFDEVICE_INIT for a PDO, %!STATUS!", status);
2491         return status;
2492     }
2493 
2494     pDeviceText = new(pFxDriverGlobals, PagedPool) FxDeviceText();
2495 
2496     if (pDeviceText == NULL) {
2497         status = STATUS_INSUFFICIENT_RESOURCES;
2498 
2499         DoTraceLevelMessage(
2500             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2501             "Couldn't allocate DeviceText object, %!STATUS!", status);
2502 
2503         return status;
2504     }
2505 
2506     pDeviceText->m_LocaleId = LocaleId;
2507 
2508     pDeviceText->m_Description = FxDuplicateUnicodeStringToString(
2509         pFxDriverGlobals, DeviceDescription);
2510 
2511     if (pDeviceText->m_Description == NULL) {
2512         status = STATUS_INSUFFICIENT_RESOURCES;
2513 
2514         DoTraceLevelMessage(
2515             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2516             "Couldn't allocate DeviceDescription string, %!STATUS!", status);
2517 
2518         goto Done;
2519     }
2520 
2521     pDeviceText->m_LocationInformation = FxDuplicateUnicodeStringToString(
2522         pFxDriverGlobals, DeviceLocation);
2523 
2524     if (pDeviceText->m_LocationInformation == NULL) {
2525         status = STATUS_INSUFFICIENT_RESOURCES;
2526 
2527         DoTraceLevelMessage(
2528             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2529             "Couldn't allocate DeviceLocation string, %!STATUS!", status);
2530 
2531         goto Done;
2532     }
2533 
2534     //
2535     // Insert at the end of the list and update end of the list
2536     //
2537     *DeviceInit->Pdo.LastDeviceTextEntry = &pDeviceText->m_Entry;
2538     DeviceInit->Pdo.LastDeviceTextEntry = &pDeviceText->m_Entry.Next;
2539 
2540 Done:
2541     if (!NT_SUCCESS(status)) {
2542         delete pDeviceText;
2543     }
2544 
2545     return status;
2546 }
2547 
2548 __drv_maxIRQL(PASSIVE_LEVEL)
2549 VOID
2550 STDCALL
2551 WDFEXPORT(WdfPdoInitSetDefaultLocale)(
2552     __in
2553     PWDF_DRIVER_GLOBALS DriverGlobals,
2554     __in
2555     PWDFDEVICE_INIT DeviceInit,
2556     __in
2557     LCID LocaleId
2558     )
2559 {
2560     DDI_ENTRY();
2561 
2562     PFX_DRIVER_GLOBALS pFxDriverGlobals;
2563 
2564     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
2565     pFxDriverGlobals = DeviceInit->DriverGlobals;
2566 
2567     if (!NT_SUCCESS(FxVerifierCheckIrqlLevel(pFxDriverGlobals,
2568                                              PASSIVE_LEVEL))) {
2569         return;
2570     }
2571 
2572     if (DeviceInit->IsNotPdoInit()) {
2573         DoTraceLevelMessage(
2574             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2575             "Not a PWDFDEVICE_INIT for a PDO");
2576         FxVerifierDbgBreakPoint(pFxDriverGlobals);
2577         return;
2578     }
2579 
2580     DeviceInit->Pdo.DefaultLocale = LocaleId;
2581 }
2582 
2583 _Must_inspect_result_
2584 __drv_maxIRQL(PASSIVE_LEVEL)
2585 NTSTATUS
2586 STDCALL
2587 WDFEXPORT(WdfPdoInitAssignRawDevice)(
2588     __in
2589     PWDF_DRIVER_GLOBALS DriverGlobals,
2590     __in
2591     PWDFDEVICE_INIT DeviceInit,
2592     __in
2593     CONST GUID* DeviceClassGuid
2594     )
2595 {
2596     DDI_ENTRY();
2597 
2598     PFX_DRIVER_GLOBALS pFxDriverGlobals;
2599     NTSTATUS status;
2600 
2601     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
2602     pFxDriverGlobals = DeviceInit->DriverGlobals;
2603 
2604     FxPointerNotNull(pFxDriverGlobals, DeviceClassGuid);
2605 
2606     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
2607     if (!NT_SUCCESS(status)) {
2608         return status;
2609     }
2610 
2611     if (DeviceInit->IsNotPdoInit()) {
2612         status = STATUS_INVALID_PARAMETER;
2613         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2614                             "Not a PWDFDEVICE_INIT for a PDO, %!STATUS!",
2615                             status);
2616         return status;
2617     }
2618 
2619     DeviceInit->Pdo.Raw = TRUE;
2620     DeviceInit->Security.DeviceClassSet = TRUE;
2621     RtlCopyMemory(&DeviceInit->Security.DeviceClass,
2622                   DeviceClassGuid,
2623                   sizeof(GUID));
2624 
2625     return STATUS_SUCCESS;
2626 }
2627 
2628 __drv_maxIRQL(PASSIVE_LEVEL)
2629 VOID
2630 STDCALL
2631 WDFEXPORT(WdfPdoInitAllowForwardingRequestToParent)(
2632     __in
2633     PWDF_DRIVER_GLOBALS DriverGlobals,
2634     __in
2635     PWDFDEVICE_INIT DeviceInit
2636     )
2637 {
2638     DDI_ENTRY();
2639 
2640     PFX_DRIVER_GLOBALS pFxDriverGlobals;
2641     NTSTATUS status;
2642 
2643     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
2644     pFxDriverGlobals = DeviceInit->DriverGlobals;
2645 
2646     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
2647     if (!NT_SUCCESS(status)) {
2648         return;
2649     }
2650 
2651     if (DeviceInit->IsNotPdoInit()) {
2652         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2653                             "Not a PWDFDEVICE_INIT for a PDO, %!STATUS!",
2654                             status);
2655         FxVerifierDbgBreakPoint(pFxDriverGlobals);
2656         return;
2657     }
2658 
2659     DeviceInit->Pdo.ForwardRequestToParent = TRUE;
2660     return ;
2661 }
2662 
2663 
2664 
2665 //
2666 // END PDO specific functions
2667 //
2668 
2669 //
2670 // BEGIN CONTROL DEVICE specific functions
2671 //
2672 
2673 _Must_inspect_result_
2674 __drv_maxIRQL(PASSIVE_LEVEL)
2675 PWDFDEVICE_INIT
2676 STDCALL
2677 WDFEXPORT(WdfControlDeviceInitAllocate)(
2678     __in
2679     PWDF_DRIVER_GLOBALS DriverGlobals,
2680     __in
2681     WDFDRIVER Driver,
2682     __in
2683     CONST UNICODE_STRING* SDDLString
2684     )
2685 {
2686     DDI_ENTRY();
2687 
2688     PFX_DRIVER_GLOBALS pFxDriverGlobals;
2689     FxDriver* pDriver;
2690     NTSTATUS status;
2691 
2692     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
2693                                    Driver,
2694                                    FX_TYPE_DRIVER,
2695                                    (PVOID*) &pDriver,
2696                                    &pFxDriverGlobals);
2697 
2698     FxPointerNotNull(pFxDriverGlobals, SDDLString);
2699 
2700     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
2701     if (!NT_SUCCESS(status)) {
2702         return NULL;
2703     }
2704 
2705     status = FxValidateUnicodeString(pFxDriverGlobals, SDDLString);
2706     if (!NT_SUCCESS(status)) {
2707         return NULL;
2708     }
2709 
2710     return WDFDEVICE_INIT::_AllocateControlDeviceInit(pDriver, SDDLString);
2711 }
2712 
2713 __drv_maxIRQL(PASSIVE_LEVEL)
2714 VOID
2715 STDCALL
2716 WDFEXPORT(WdfControlDeviceInitSetShutdownNotification)(
2717     __in
2718     PWDF_DRIVER_GLOBALS DriverGlobals,
2719     __in
2720     PWDFDEVICE_INIT DeviceInit,
2721     __in
2722     PFN_WDF_DEVICE_SHUTDOWN_NOTIFICATION Notification,
2723     __in
2724     UCHAR Flags
2725     )
2726 {
2727     DDI_ENTRY();
2728 
2729     PFX_DRIVER_GLOBALS pFxDriverGlobals;
2730 
2731     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
2732     pFxDriverGlobals = DeviceInit->DriverGlobals;
2733 
2734     FxPointerNotNull(pFxDriverGlobals, Notification);
2735 
2736     if (DeviceInit->IsNotControlDeviceInit()) {
2737         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2738                             "Not a PWDFDEVICE_INIT for a control device");
2739         FxVerifierDbgBreakPoint(pFxDriverGlobals);
2740         return;
2741     }
2742 
2743     if ((Flags & ~(WdfDeviceShutdown | WdfDeviceLastChanceShutdown)) != 0) {
2744         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
2745                             "WdfDeviceShutdown Flags 0x%x are invalid", Flags);
2746         FxVerifierDbgBreakPoint(pFxDriverGlobals);
2747         return;
2748     }
2749 
2750     DeviceInit->Control.ShutdownNotification = Notification;
2751     DeviceInit->Control.Flags |= Flags;
2752 }
2753 
2754 //
2755 // END CONTROL DEVICE specific functions
2756 //
2757 
2758 } // extern "C"
2759