--- /dev/null
+/*++
+
+Copyright (c) Microsoft Corporation
+
+Module Name:
+
+ FxDeviceInitApi.cpp
+
+Abstract:
+
+ This module exposes the "C" interface to the FxDevice object.
+
+Author:
+
+
+
+Environment:
+
+ Both kernel and user mode
+
+Revision History:
+
+--*/
+
+#include "coreprivshared.hpp"
+
+extern "C" {
+#include "FxDeviceInitApi.tmh"
+}
+
+typedef struct _WDF_PNPPOWER_EVENT_CALLBACKS_V1_9 {
+ //
+ // Size of this structure in bytes
+ //
+ ULONG Size;
+
+ PFN_WDF_DEVICE_D0_ENTRY EvtDeviceD0Entry;
+
+ PFN_WDF_DEVICE_D0_ENTRY_POST_INTERRUPTS_ENABLED EvtDeviceD0EntryPostInterruptsEnabled;
+
+ PFN_WDF_DEVICE_D0_EXIT EvtDeviceD0Exit;
+
+ PFN_WDF_DEVICE_D0_EXIT_PRE_INTERRUPTS_DISABLED EvtDeviceD0ExitPreInterruptsDisabled;
+
+ PFN_WDF_DEVICE_PREPARE_HARDWARE EvtDevicePrepareHardware;
+
+ PFN_WDF_DEVICE_RELEASE_HARDWARE EvtDeviceReleaseHardware;
+
+ PFN_WDF_DEVICE_SELF_MANAGED_IO_CLEANUP EvtDeviceSelfManagedIoCleanup;
+
+ PFN_WDF_DEVICE_SELF_MANAGED_IO_FLUSH EvtDeviceSelfManagedIoFlush;
+
+ PFN_WDF_DEVICE_SELF_MANAGED_IO_INIT EvtDeviceSelfManagedIoInit;
+
+ PFN_WDF_DEVICE_SELF_MANAGED_IO_SUSPEND EvtDeviceSelfManagedIoSuspend;
+
+ PFN_WDF_DEVICE_SELF_MANAGED_IO_RESTART EvtDeviceSelfManagedIoRestart;
+
+ PFN_WDF_DEVICE_SURPRISE_REMOVAL EvtDeviceSurpriseRemoval;
+
+ PFN_WDF_DEVICE_QUERY_REMOVE EvtDeviceQueryRemove;
+
+ PFN_WDF_DEVICE_QUERY_STOP EvtDeviceQueryStop;
+
+ PFN_WDF_DEVICE_USAGE_NOTIFICATION EvtDeviceUsageNotification;
+
+ PFN_WDF_DEVICE_RELATIONS_QUERY EvtDeviceRelationsQuery;
+
+} WDF_PNPPOWER_EVENT_CALLBACKS_V1_9, *PWDF_PNPPOWER_EVENT_CALLBACKS_V1_9;
+
+
+typedef struct _WDF_POWER_POLICY_EVENT_CALLBACKS_V1_5 {
+ //
+ // Size of this structure in bytes
+ //
+ ULONG Size;
+
+ PFN_WDF_DEVICE_ARM_WAKE_FROM_S0 EvtDeviceArmWakeFromS0;
+
+ PFN_WDF_DEVICE_DISARM_WAKE_FROM_S0 EvtDeviceDisarmWakeFromS0;
+
+ PFN_WDF_DEVICE_WAKE_FROM_S0_TRIGGERED EvtDeviceWakeFromS0Triggered;
+
+ PFN_WDF_DEVICE_ARM_WAKE_FROM_SX EvtDeviceArmWakeFromSx;
+
+ PFN_WDF_DEVICE_DISARM_WAKE_FROM_SX EvtDeviceDisarmWakeFromSx;
+
+ PFN_WDF_DEVICE_WAKE_FROM_SX_TRIGGERED EvtDeviceWakeFromSxTriggered;
+
+} WDF_POWER_POLICY_EVENT_CALLBACKS_V1_5, *PWDF_POWER_POLICY_EVENT_CALLBACKS_V1_5;
+
+typedef struct _WDF_PDO_EVENT_CALLBACKS_V1_9 {
+ //
+ // The size of this structure in bytes
+ //
+ ULONG Size;
+
+ //
+ // Called in response to IRP_MN_QUERY_RESOURCES
+ //
+ PFN_WDF_DEVICE_RESOURCES_QUERY EvtDeviceResourcesQuery;
+
+ //
+ // Called in response to IRP_MN_QUERY_RESOURCE_REQUIREMENTS
+ //
+ PFN_WDF_DEVICE_RESOURCE_REQUIREMENTS_QUERY EvtDeviceResourceRequirementsQuery;
+
+ //
+ // Called in response to IRP_MN_EJECT
+ //
+ PFN_WDF_DEVICE_EJECT EvtDeviceEject;
+
+ //
+ // Called in response to IRP_MN_SET_LOCK
+ //
+ PFN_WDF_DEVICE_SET_LOCK EvtDeviceSetLock;
+
+ //
+ // Called in response to the power policy owner sending a wait wake to the
+ // PDO. Bus generic arming shoulding occur here.
+ //
+ PFN_WDF_DEVICE_ENABLE_WAKE_AT_BUS EvtDeviceEnableWakeAtBus;
+
+ //
+ // Called in response to the power policy owner sending a wait wake to the
+ // PDO. Bus generic disarming shoulding occur here.
+ //
+ PFN_WDF_DEVICE_DISABLE_WAKE_AT_BUS EvtDeviceDisableWakeAtBus;
+
+} WDF_PDO_EVENT_CALLBACKS_V1_9, *PWDF_PDO_EVENT_CALLBACKS_V1_9;
+
+
+//
+// Extern "C" the entire file
+//
+extern "C" {
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitFree)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit
+ )
+{
+ DDI_ENTRY();
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+
+ if (DeviceInit->CreatedOnStack == FALSE) {
+ delete DeviceInit;
+ }
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitSetIoType)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ WDF_DEVICE_IO_TYPE IoType
+ )
+{
+ DDI_ENTRY();
+
+ WDF_IO_TYPE_CONFIG ioTypeConfig;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+
+ WDF_IO_TYPE_CONFIG_INIT(&ioTypeConfig);
+ ioTypeConfig.ReadWriteIoType = IoType;
+
+ DeviceInit->AssignIoType(&ioTypeConfig);
+}
+
+_IRQL_requires_max_(PASSIVE_LEVEL)
+WDFAPI
+VOID
+WDFEXPORT(WdfDeviceInitSetIoTypeEx)(
+ _In_
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ _In_
+ PWDFDEVICE_INIT DeviceInit,
+ _In_
+ PWDF_IO_TYPE_CONFIG IoTypeConfig
+ )
+{
+ DDI_ENTRY();
+
+ NTSTATUS status;
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+
+ pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
+
+ FxPointerNotNull(pFxDriverGlobals, DeviceInit);
+
+ if (IoTypeConfig->Size != sizeof(WDF_IO_TYPE_CONFIG)) {
+ status = STATUS_INFO_LENGTH_MISMATCH;
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
+ "IoTypeConfig size (%d) incorrect, expected %d, %!STATUS!",
+ IoTypeConfig->Size,
+ sizeof(WDF_IO_TYPE_CONFIG), status);
+ return;
+ }
+
+ DeviceInit->AssignIoType(IoTypeConfig);
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitSetExclusive)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ BOOLEAN Exclusive
+ )
+{
+ DDI_ENTRY();
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+
+ DeviceInit->Exclusive = Exclusive;
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitSetDeviceType)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ DEVICE_TYPE DeviceType
+ )
+{
+ DDI_ENTRY();
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+
+ DeviceInit->DeviceType = DeviceType;
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitSetPowerNotPageable)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit
+ )
+{
+ DDI_ENTRY();
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+
+ DeviceInit->PowerPageable = FALSE;
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitSetPowerPageable)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit
+ )
+{
+ DDI_ENTRY();
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+
+ DeviceInit->PowerPageable = TRUE;
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitSetPowerInrush)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit
+ )
+{
+ DDI_ENTRY();
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+
+ //
+ // If you are inrush, there is no way you can be power pageable
+ //
+ DeviceInit->Inrush = TRUE;
+ DeviceInit->PowerPageable = FALSE;
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfDeviceInitAssignName)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in_opt
+ PCUNICODE_STRING DeviceName
+ )
+{
+ DDI_ENTRY();
+
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+
+ status = FxVerifierCheckIrqlLevel(DeviceInit->DriverGlobals,
+ PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (DeviceName != NULL) {
+ status = FxValidateUnicodeString(DeviceInit->DriverGlobals,
+ DeviceName);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+ }
+
+ if (DeviceName == NULL) {
+ if (DeviceInit->DeviceName != NULL) {
+ DeviceInit->DeviceName->RELEASE(NULL);
+ DeviceInit->DeviceName = NULL;
+ }
+
+ if (DeviceInit->IsPdoInit()) {
+ //
+ // Make sure a PDO has a name
+ //
+ DeviceInit->Characteristics |= FILE_AUTOGENERATED_DEVICE_NAME;
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ return DeviceInit->AssignName(DeviceInit->DriverGlobals, DeviceName);
+
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitSetCharacteristics)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ ULONG DeviceCharacteristics,
+ __in
+ BOOLEAN OrInValues
+ )
+{
+ DDI_ENTRY();
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+
+ if (OrInValues) {
+ DeviceInit->Characteristics |= DeviceCharacteristics | FILE_DEVICE_SECURE_OPEN;
+ }
+ else {
+ DeviceInit->Characteristics = DeviceCharacteristics | FILE_DEVICE_SECURE_OPEN;
+ }
+
+ //
+ // If the autogenerate flag is on, clear out the device name
+ //
+ if ((DeviceCharacteristics & FILE_AUTOGENERATED_DEVICE_NAME) &&
+ DeviceInit->DeviceName != NULL) {
+ DeviceInit->DeviceName->RELEASE(NULL);
+ DeviceInit->DeviceName = NULL;
+ }
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitSetFileObjectConfig)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PWDF_FILEOBJECT_CONFIG FileObjectConfig,
+ __in_opt
+ PWDF_OBJECT_ATTRIBUTES FileObjectAttributes
+ )
+
+/*++
+
+Routine Description:
+
+ Registers callbacks for file object support.
+
+ Defaults to WdfDeviceFileObjectNoFsContext.
+
+Arguments:
+
+Returns:
+
+--*/
+
+{
+ DDI_ENTRY();
+
+ NTSTATUS status;
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ WDF_FILEOBJECT_CLASS normalizedFileClass;
+ WDF_FILEOBJECT_CLASS fileClass;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, FileObjectConfig);
+
+ if (FileObjectConfig->Size != sizeof(WDF_FILEOBJECT_CONFIG)) {
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Invalid FileObjectConfig Size %d, expected %d",
+ FileObjectConfig->Size, sizeof(WDF_FILEOBJECT_CONFIG));
+
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ status = FxValidateObjectAttributes(
+ pFxDriverGlobals,
+ FileObjectAttributes,
+ FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED |
+ FX_VALIDATE_OPTION_EXECUTION_LEVEL_ALLOWED |
+ FX_VALIDATE_OPTION_SYNCHRONIZATION_SCOPE_ALLOWED
+ );
+
+ if (!NT_SUCCESS(status)) {
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ //
+ // Validate AutoForwardCleanupClose
+ //
+ switch (FileObjectConfig->AutoForwardCleanupClose) {
+ case WdfTrue:
+ case WdfFalse:
+ case WdfUseDefault:
+ break;
+
+ default:
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Invalid FileObjectConfig->AutoForwardCleanupClose value 0x%x, "
+ "expected WDF_TRI_STATE value", FileObjectConfig->AutoForwardCleanupClose);
+
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ DeviceInit->FileObject.Set = TRUE;
+
+ DeviceInit->FileObject.AutoForwardCleanupClose =
+ FileObjectConfig->AutoForwardCleanupClose;
+
+ fileClass = FileObjectConfig->FileObjectClass;
+
+ //
+ // Remove bit flags and validate file object class value.
+ //
+ normalizedFileClass = FxFileObjectClassNormalize(fileClass);
+
+ if (normalizedFileClass == WdfFileObjectInvalid ||
+ normalizedFileClass > WdfFileObjectWdfCannotUseFsContexts) {
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Out of range FileObjectConfig->FileObjectClass %d",
+ fileClass);
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ //
+ // UMDF doesn't support storing object handle at FsContext or FxContxt2.
+ // Update the class to WdfFileObjectWdfCannotUseFsContexts for UMDF.
+ //
+ if (pFxDriverGlobals->IsUserModeDriver &&
+ (normalizedFileClass == WdfFileObjectWdfCanUseFsContext ||
+ normalizedFileClass == WdfFileObjectWdfCanUseFsContext2)) {
+
+ //
+ // update the FileObjectClass value
+ //
+ BOOLEAN canBeOptional =
+ (fileClass & WdfFileObjectCanBeOptional) ? TRUE : FALSE;
+
+ fileClass = WdfFileObjectWdfCannotUseFsContexts;
+ if (canBeOptional) {
+ fileClass = (WDF_FILEOBJECT_CLASS)
+ (fileClass | WdfFileObjectCanBeOptional);
+ }
+
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGDEVICE,
+ "FileObjectConfig->FileObjectClass value (%d) has been updated"
+ " to a UMDF-supported value %d", normalizedFileClass,
+ WdfFileObjectWdfCannotUseFsContexts);
+
+ //
+ // re-obtain the normalized class
+ //
+ normalizedFileClass = FxFileObjectClassNormalize(fileClass);
+ }
+
+ //
+ // The optional flag can only be combined with a subset of values.
+ //
+ if (FxIsFileObjectOptional(fileClass)) {
+ switch(normalizedFileClass) {
+ case WdfFileObjectWdfCanUseFsContext:
+ case WdfFileObjectWdfCanUseFsContext2:
+ case WdfFileObjectWdfCannotUseFsContexts:
+ break;
+
+ default:
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Invalid FileObjectConfig->FileObjectClass %d",
+ fileClass);
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ break; // just in case static verification tools complain.
+ }
+ }
+
+ DeviceInit->FileObject.Class = fileClass;
+
+ RtlCopyMemory(&DeviceInit->FileObject.Callbacks,
+ FileObjectConfig,
+ sizeof(DeviceInit->FileObject.Callbacks));
+
+ if (FileObjectAttributes != NULL) {
+ RtlCopyMemory(&DeviceInit->FileObject.Attributes,
+ FileObjectAttributes,
+ sizeof(DeviceInit->FileObject.Attributes));
+ }
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitSetRequestAttributes)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PWDF_OBJECT_ATTRIBUTES RequestAttributes
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, RequestAttributes);
+
+ //
+ // Parent of all requests created from WDFDEVICE are parented by the
+ // WDFDEVICE.
+ //
+ status = FxValidateObjectAttributes(pFxDriverGlobals,
+ RequestAttributes,
+ FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
+
+ if (!NT_SUCCESS(status)) {
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ RtlCopyMemory(&DeviceInit->RequestAttributes,
+ RequestAttributes,
+ sizeof(WDF_OBJECT_ATTRIBUTES));
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfDeviceInitAssignSDDLString)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in_opt
+ PCUNICODE_STRING SDDLString
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (SDDLString == NULL) {
+ //
+ // Since we require the SDDL on control device creation, you can't
+ // clear it!
+ //
+ if (DeviceInit->IsControlDeviceInit()) {
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ if (DeviceInit->Security.Sddl != NULL) {
+ DeviceInit->Security.Sddl->RELEASE(NULL);
+ DeviceInit->Security.Sddl = NULL;
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ status = FxValidateUnicodeString(pFxDriverGlobals, SDDLString);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (DeviceInit->Security.Sddl == NULL) {
+ DeviceInit->Security.Sddl = new(pFxDriverGlobals,
+ WDF_NO_OBJECT_ATTRIBUTES)
+ FxString(pFxDriverGlobals);
+
+ if (DeviceInit->Security.Sddl == NULL) {
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Couldn't create Security descriptor"
+ " STATUS_INSUFFICIENT_RESOURCES ");
+
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ return DeviceInit->Security.Sddl->Assign(SDDLString);
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitSetDeviceClass)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ CONST GUID* DeviceClassGuid
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, DeviceClassGuid);
+
+ DeviceInit->Security.DeviceClassSet = TRUE;
+ RtlCopyMemory(&DeviceInit->Security.DeviceClass,
+ DeviceClassGuid,
+ sizeof(GUID));
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitSetPnpPowerEventCallbacks)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PWDF_PNPPOWER_EVENT_CALLBACKS PnpPowerEventCallbacks
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, PnpPowerEventCallbacks);
+
+ if (PnpPowerEventCallbacks->Size != sizeof(WDF_PNPPOWER_EVENT_CALLBACKS) &&
+ PnpPowerEventCallbacks->Size != sizeof(_WDF_PNPPOWER_EVENT_CALLBACKS_V1_9)) {
+
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "PnpPowerEventCallbacks size %d is invalid, exptected %d",
+ PnpPowerEventCallbacks->Size, sizeof(WDF_PNPPOWER_EVENT_CALLBACKS)
+ );
+
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+
+ return;
+ }
+
+ //
+ // Make sure only one of the callbacks EvtDeviceUsageNotification or
+ // EvtDeviceUsageNotificationEx is provided by driver for >V1.9.
+ //
+ if (PnpPowerEventCallbacks->Size > sizeof(WDF_PNPPOWER_EVENT_CALLBACKS_V1_9) &&
+ PnpPowerEventCallbacks->EvtDeviceUsageNotification != NULL &&
+ PnpPowerEventCallbacks->EvtDeviceUsageNotificationEx != NULL) {
+
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Driver can provide either EvtDeviceUsageNotification or "
+ "EvtDeviceUsageNotificationEx callback but not both");
+
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+
+ return;
+ }
+
+ //
+ // Driver's PnpPowerEventCallbacks structure may be from a previous
+ // version and therefore may be different in size than the current version
+ // that framework is using. Therefore, copy only PnpPowerEventCallbacks->Size
+ // bytes and not sizeof(PnpPowerEventCallbacks) bytes.
+ //
+ RtlCopyMemory(&DeviceInit->PnpPower.PnpPowerEventCallbacks,
+ PnpPowerEventCallbacks,
+ PnpPowerEventCallbacks->Size);
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitSetPowerPolicyEventCallbacks)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PWDF_POWER_POLICY_EVENT_CALLBACKS PowerPolicyEventCallbacks
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, PowerPolicyEventCallbacks);
+
+ //
+ // The WDF_POWER_POLICY_EVENT_CALLBACKS structure size increased after v1.5.
+ // Since this api is backwards compatible, it can accept either the current
+ // structure or the older version. Validate the size of the structure here
+ // so that it is one of the two supported sizes.
+ //
+ if (PowerPolicyEventCallbacks->Size != sizeof(WDF_POWER_POLICY_EVENT_CALLBACKS) &&
+ PowerPolicyEventCallbacks->Size != sizeof(WDF_POWER_POLICY_EVENT_CALLBACKS_V1_5)) {
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "PowerPolicyEventCallbacks size %d is invalid, expected %d",
+ PowerPolicyEventCallbacks->Size, sizeof(WDF_POWER_POLICY_EVENT_CALLBACKS)
+ );
+
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ //
+ // Only one of EvtDeviceArmWakeFromSx and EvtDeviceArmWakeFromSxWithReason
+ // callbacks should be specified if the given power policy callbacks structure
+ // is from a version after v1.5
+ //
+ if (PowerPolicyEventCallbacks->Size > sizeof(WDF_POWER_POLICY_EVENT_CALLBACKS_V1_5) &&
+ PowerPolicyEventCallbacks->EvtDeviceArmWakeFromSx != NULL &&
+ PowerPolicyEventCallbacks->EvtDeviceArmWakeFromSxWithReason != NULL) {
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "PowerPolicyEventCallbacks can have either EvtDeviceArmWakeFromSx "
+ "or EvtDeviceArmWakeFromSxWithReason callback pointer, but not both"
+ );
+
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ RtlCopyMemory(&DeviceInit->PnpPower.PolicyEventCallbacks,
+ PowerPolicyEventCallbacks,
+ PowerPolicyEventCallbacks->Size);
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitSetPowerPolicyOwnership)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ BOOLEAN IsPowerPolicyOwner
+ )
+{
+ DDI_ENTRY();
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+
+ DeviceInit->PnpPower.PowerPolicyOwner = IsPowerPolicyOwner ? WdfTrue : WdfFalse;
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfDeviceInitRegisterPnpStateChangeCallback)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ WDF_DEVICE_PNP_STATE PnpState,
+ __in
+ PFN_WDF_DEVICE_PNP_STATE_CHANGE_NOTIFICATION EvtDevicePnpStateChange,
+ __in
+ ULONG CallbackTypes
+ )
+{
+ DDI_ENTRY();
+
+ FxPnpStateCallbackInfo* pCallback;
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ ULONG normalizedState;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, EvtDevicePnpStateChange);
+
+ normalizedState = WdfDevStateNormalize(PnpState);
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (normalizedState < WdfDevStatePnpObjectCreated || normalizedState > WdfDevStatePnpNull) {
+ status = STATUS_INVALID_PARAMETER;
+
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Pnp State is invalid %!STATUS!", status);
+
+ return status;
+ }
+
+ if ((CallbackTypes & ~StateNotificationAllStates) != 0 ||
+ CallbackTypes == 0x0) {
+ status = STATUS_INVALID_PARAMETER;
+
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "CallbackTypes is invalid %!STATUS!", status);
+
+ return status;
+ }
+
+ if (DeviceInit->PnpPower.PnpStateCallbacks == NULL) {
+
+ DeviceInit->PnpPower.PnpStateCallbacks =
+ new (pFxDriverGlobals) FxPnpStateCallback();
+
+ if (DeviceInit->PnpPower.PnpStateCallbacks == NULL) {
+ status = STATUS_INVALID_PARAMETER;
+
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Couldn't create object PnpStateCallbacks %!STATUS!", status);
+
+ return status;
+ }
+ }
+
+ pCallback = &DeviceInit->PnpPower.PnpStateCallbacks->m_Methods[
+ normalizedState - WdfDevStatePnpObjectCreated];
+
+ pCallback->Callback = EvtDevicePnpStateChange;
+ pCallback->Types = CallbackTypes;
+
+ return STATUS_SUCCESS;
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfDeviceInitRegisterPowerStateChangeCallback)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ WDF_DEVICE_POWER_STATE PowerState,
+ __in
+ PFN_WDF_DEVICE_POWER_STATE_CHANGE_NOTIFICATION EvtDevicePowerStateChange,
+ __in
+ ULONG CallbackTypes
+ )
+{
+ DDI_ENTRY();
+
+ FxPowerStateCallbackInfo* pCallback;
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ ULONG normalizedState;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, EvtDevicePowerStateChange);
+
+ normalizedState = WdfDevStateNormalize(PowerState);
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (normalizedState < WdfDevStatePowerObjectCreated ||
+ normalizedState >= WdfDevStatePowerNull) {
+ status = STATUS_INVALID_PARAMETER;
+
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "PowerState State is invalid %!STATUS!", status);
+
+ return status;
+ }
+
+ if ((CallbackTypes & ~StateNotificationAllStates) != 0 ||
+ CallbackTypes == 0x0) {
+ status = STATUS_INVALID_PARAMETER;
+
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "CallbackTypes is invalid %!STATUS!"
+ "STATUS_INVALID_PARAMETER", status);
+
+ return status;
+ }
+
+ if (DeviceInit->PnpPower.PowerStateCallbacks == NULL) {
+ DeviceInit->PnpPower.PowerStateCallbacks =
+ new (pFxDriverGlobals) FxPowerStateCallback();
+
+ if (DeviceInit->PnpPower.PowerStateCallbacks == NULL) {
+ status = STATUS_INVALID_PARAMETER;
+
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Couldn't create object PowerStateCallbacks %!STATUS!", status);
+
+ return status;
+ }
+ }
+
+ pCallback = &DeviceInit->PnpPower.PowerStateCallbacks->m_Methods[
+ normalizedState - WdfDevStatePowerObjectCreated];
+
+ pCallback->Callback = EvtDevicePowerStateChange;
+ pCallback->Types = CallbackTypes;
+
+ return STATUS_SUCCESS;
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfDeviceInitRegisterPowerPolicyStateChangeCallback)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ WDF_DEVICE_POWER_POLICY_STATE PowerPolicyState,
+ __in
+ PFN_WDF_DEVICE_POWER_POLICY_STATE_CHANGE_NOTIFICATION EvtDevicePowerPolicyStateChange,
+ __in
+ ULONG CallbackTypes
+ )
+{
+ DDI_ENTRY();
+
+ FxPowerPolicyStateCallbackInfo* pCallback;
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ ULONG normalizedState;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, EvtDevicePowerPolicyStateChange);
+
+ normalizedState = WdfDevStateNormalize(PowerPolicyState);
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (normalizedState < WdfDevStatePwrPolObjectCreated ||
+ normalizedState >= WdfDevStatePwrPolNull) {
+ status = STATUS_INVALID_PARAMETER;
+
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "PowerPolicyState State is invalid %!STATUS!", status);
+
+ return status;
+ }
+
+ if ((CallbackTypes & ~StateNotificationAllStates) != 0 ||
+ CallbackTypes == 0x0) {
+ status = STATUS_INVALID_PARAMETER;
+
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "CallbackTypes is invalid %!STATUS!", status);
+
+ return status;
+ }
+
+ if (DeviceInit->PnpPower.PowerPolicyStateCallbacks == NULL) {
+ DeviceInit->PnpPower.PowerPolicyStateCallbacks =
+ new (pFxDriverGlobals) FxPowerPolicyStateCallback();
+
+ if (DeviceInit->PnpPower.PowerPolicyStateCallbacks == NULL) {
+ status = STATUS_INVALID_PARAMETER;
+
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Couldn't create object PowerPolicyStateCallbacks %!STATUS!", status);
+
+ return status;
+ }
+ }
+
+ pCallback = &DeviceInit->PnpPower.PowerPolicyStateCallbacks->m_Methods[
+ normalizedState - WdfDevStatePwrPolObjectCreated];
+
+ pCallback->Callback = EvtDevicePowerPolicyStateChange;
+ pCallback->Types = CallbackTypes;
+
+ return STATUS_SUCCESS;
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(DISPATCH_LEVEL)
+WDFAPI
+NTSTATUS
+WDFEXPORT(WdfDeviceInitAssignWdmIrpPreprocessCallback)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PFN_WDFDEVICE_WDM_IRP_PREPROCESS EvtDeviceWdmIrpPreprocess,
+ __in
+ UCHAR MajorFunction,
+ __drv_when(NumMinorFunctions > 0, __in_bcount(NumMinorFunctions))
+ __drv_when(NumMinorFunctions == 0, __in_opt)
+ PUCHAR MinorFunctions,
+ __in
+ ULONG NumMinorFunctions
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, EvtDeviceWdmIrpPreprocess);
+
+ if (NumMinorFunctions > 0) {
+ FxPointerNotNull(pFxDriverGlobals, MinorFunctions);
+ }
+
+ //
+ // ARRAY_SIZE(DeviceInit->PreprocessInfo->Dispatch) just returns a constant
+ // size, it does not actually deref PreprocessInfo (which could be NULL)
+ //
+ if (MajorFunction >= ARRAY_SIZE(DeviceInit->PreprocessInfo->Dispatch)) {
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "MajorFunction is invalid"
+ "STATUS_INVALID_PARAMETER"
+ );
+
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (DeviceInit->PreprocessInfo == NULL) {
+ DeviceInit->PreprocessInfo = new(pFxDriverGlobals) FxIrpPreprocessInfo();
+
+ if (DeviceInit->PreprocessInfo == NULL) {
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Couldn't create object PreprocessInfo"
+ "STATUS_INSUFFICIENT_RESOURCES"
+ );
+
+
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ if (NumMinorFunctions > 0) {
+ if (DeviceInit->PreprocessInfo->Dispatch[MajorFunction].NumMinorFunctions != 0) {
+
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Already assigned Minorfunctions"
+ "STATUS_INVALID_DEVICE_REQUEST"
+ );
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ DeviceInit->PreprocessInfo->Dispatch[MajorFunction].MinorFunctions =
+ (PUCHAR) FxPoolAllocate(pFxDriverGlobals,
+ NonPagedPool,
+ sizeof(UCHAR) * NumMinorFunctions);
+
+ if (DeviceInit->PreprocessInfo->Dispatch[MajorFunction].MinorFunctions == NULL) {
+
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Couldn't create object MinorFunctions"
+ "STATUS_INSUFFICIENT_RESOURCES"
+ );
+
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlCopyMemory(
+ &DeviceInit->PreprocessInfo->Dispatch[MajorFunction].MinorFunctions[0],
+ &MinorFunctions[0],
+ NumMinorFunctions
+ );
+
+ DeviceInit->PreprocessInfo->Dispatch[MajorFunction].NumMinorFunctions =
+ NumMinorFunctions;
+ }
+
+ DeviceInit->PreprocessInfo->Dispatch[MajorFunction].EvtDevicePreprocess =
+ EvtDeviceWdmIrpPreprocess;
+
+ return STATUS_SUCCESS;
+}
+
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitSetIoInCallerContextCallback)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PFN_WDF_IO_IN_CALLER_CONTEXT EvtIoInCallerContext
+ )
+
+/*++
+
+Routine Description:
+
+ Registers an I/O pre-processing callback for the device.
+
+ If registered, any I/O for the device is first presented to this
+ callback function before being placed in any I/O Queue's.
+
+ The callback is invoked in the thread and/or DPC context of the
+ original WDM caller as presented to the I/O package. No framework
+ threading, locking, synchronization, or queuing occurs, and
+ responsibility for synchronization is up to the device driver.
+
+ This API is intended to support METHOD_NEITHER IRP_MJ_DEVICE_CONTROL's
+ which must access the user buffer in the original callers context. The
+ driver would probe and lock the buffer pages from within this event
+ handler using the functions supplied on the WDFREQUEST object, storing
+ any required mapped buffers and/or pointers on the WDFREQUEST context
+ whose size is set by the RequestContextSize of the WDF_DRIVER_CONFIG structure.
+
+ It is the responsibility of this routine to either complete the request, or
+ pass it on to the I/O package through WdfDeviceEnqueueRequest(Device, Request).
+
+Arguments:
+ DeviceInit - Device initialization structure
+
+ EvtIoInCallerContext - Pointer to driver supplied callback function
+
+Return Value:
+
+--*/
+{
+ DDI_ENTRY();
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), EvtIoInCallerContext);
+
+ DeviceInit->IoInCallerContextCallback = EvtIoInCallerContext;
+
+ return;
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitSetRemoveLockOptions)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PWDF_REMOVE_LOCK_OPTIONS RemoveLockOptions
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS fxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
+ ULONG validFlags = WDF_REMOVE_LOCK_OPTION_ACQUIRE_FOR_IO;
+
+ FxPointerNotNull(fxDriverGlobals, DeviceInit);
+
+ FxPointerNotNull(fxDriverGlobals, RemoveLockOptions);
+
+ if (RemoveLockOptions->Size != sizeof(WDF_REMOVE_LOCK_OPTIONS)) {
+ //
+ // Size is wrong, bail out
+ //
+ DoTraceLevelMessage(fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
+ "RemoveLockOptions %p Size incorrect, expected %d, "
+ "got %d",
+ RemoveLockOptions, sizeof(WDF_REMOVE_LOCK_OPTIONS),
+ RemoveLockOptions->Size);
+
+ FxVerifierDbgBreakPoint(fxDriverGlobals);
+ goto Done;
+ }
+
+ if ((RemoveLockOptions->Flags & ~validFlags) != 0) {
+ //
+ // Invalid flag
+ //
+ DoTraceLevelMessage(fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
+ "RemoveLockOptions %p Flags 0x%x invalid, "
+ "valid mask is 0x%x",
+ RemoveLockOptions, RemoveLockOptions->Flags,
+ validFlags);
+
+ FxVerifierDbgBreakPoint(fxDriverGlobals);
+ goto Done;
+ }
+
+ if (FxDeviceInitTypeControlDevice == DeviceInit->InitType) {
+ //
+ // At this time this feature is not supported on control-devices.
+ //
+ DoTraceLevelMessage(fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
+ "WdfDeviceInitSetRemoveLockOptions is not "
+ "supported on control devices");
+
+ FxVerifierDbgBreakPoint(fxDriverGlobals);
+ goto Done;
+ }
+
+ DeviceInit->RemoveLockOptionFlags = RemoveLockOptions->Flags;
+Done:
+ return;
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitSetReleaseHardwareOrderOnFailure)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ WDF_RELEASE_HARDWARE_ORDER_ON_FAILURE ReleaseHardwareOrderOnFailure
+ )
+{
+ DDI_ENTRY();
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+
+ if ((ReleaseHardwareOrderOnFailure ==
+ WdfReleaseHardwareOrderOnFailureInvalid) ||
+ (ReleaseHardwareOrderOnFailure >
+ WdfReleaseHardwareOrderOnFailureAfterDescendants)) {
+ DoTraceLevelMessage(
+ DeviceInit->DriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Out of range WDF_RELEASE_HARDWARE_ORDER_ON_FAILURE %d",
+ ReleaseHardwareOrderOnFailure);
+ FxVerifierDbgBreakPoint(DeviceInit->DriverGlobals);
+ return;
+ }
+
+ DeviceInit->ReleaseHardwareOrderOnFailure = ReleaseHardwareOrderOnFailure;
+}
+
+_IRQL_requires_max_(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfDeviceInitAllowSelfIoTarget)(
+ _In_
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ _In_
+ PWDFDEVICE_INIT DeviceInit
+ )
+/*++
+
+Routine Description:
+
+ A client or Cx calls this API to indicate that it would like to leverage an
+ Self IO target.
+
+ For now the Self targets are not supported for PDOs, Miniport Device,
+ or non pnp Devices.
+
+Arguments:
+
+ DeviceInit - Pointer to the WDFDEVICE_INIT structure
+
+Returns:
+
+ VOID
+
+--*/
+{
+ DDI_ENTRY();
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+
+ DeviceInit->RequiresSelfIoTarget = TRUE;
+}
+
+
+
+//
+// BEGIN FDO specific functions
+//
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+PDEVICE_OBJECT
+WDFEXPORT(WdfFdoInitWdmGetPhysicalDevice)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit
+ )
+{
+ DDI_ENTRY();
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+
+ if (DeviceInit->IsNotFdoInit()) {
+ DoTraceLevelMessage(
+ DeviceInit->DriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for an FDO"
+ );
+
+ return NULL;
+ }
+
+ return reinterpret_cast<PDEVICE_OBJECT>(DeviceInit->Fdo.PhysicalDevice);
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfFdoInitOpenRegistryKey)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ ULONG DeviceInstanceKeyType,
+ __in
+ ACCESS_MASK DesiredAccess,
+ __in_opt
+ PWDF_OBJECT_ATTRIBUTES KeyAttributes,
+ __out
+ WDFKEY* Key
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, Key);
+
+ *Key = NULL;
+
+ if (DeviceInit->IsNotFdoInit()) {
+ status = STATUS_INVALID_PARAMETER;
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for an FDO, %!STATUS!",
+ status);
+ return status;
+ }
+
+ status = FxValidateObjectAttributes(pFxDriverGlobals, KeyAttributes);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ return FxDevice::_OpenKey(pFxDriverGlobals,
+ DeviceInit,
+ NULL,
+ DeviceInstanceKeyType,
+ DesiredAccess,
+ KeyAttributes,
+ Key);
+}
+
+__drv_maxIRQL(PASSIVE_LEVEL)
+VOID
+WDFEXPORT(WdfFdoInitSetFilter)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ if (!NT_SUCCESS(FxVerifierCheckIrqlLevel(pFxDriverGlobals,
+ PASSIVE_LEVEL))) {
+ return;
+ }
+ if (DeviceInit->IsNotFdoInit()) {
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for an FDO");
+
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ DeviceInit->Fdo.Filter = TRUE;
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfFdoInitQueryProperty)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ DEVICE_REGISTRY_PROPERTY DeviceProperty,
+ __in
+ ULONG BufferLength,
+ __out_bcount_full_opt(BufferLength)
+ PVOID PropertyBuffer,
+ __out
+ PULONG ResultLength
+ )
+/*++
+
+Routine Description:
+ Retrieves the requested device property for the given device
+
+Arguments:
+ DeviceInit - Device initialization structure
+
+ DeviceProperty - the property being queried
+
+ BufferLength - length of PropertyBuffer in bytes
+
+ PropertyBuffer - Buffer which will receive the property being queried
+
+ ResultLength - if STATUS_BUFFER_TOO_SMALL is returned, then this will contain
+ the required length
+
+Return Value:
+ NTSTATUS
+
+ --*/
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, ResultLength);
+ if (BufferLength > 0) {
+ FxPointerNotNull(pFxDriverGlobals, PropertyBuffer);
+ }
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (DeviceInit->IsNotFdoInit()) {
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for an FDO, %!STATUS!",
+ status);
+ return status;
+ }
+
+ status = FxDevice::_QueryProperty(pFxDriverGlobals,
+ DeviceInit,
+ NULL,
+ NULL,
+ DeviceProperty,
+ BufferLength,
+ PropertyBuffer,
+ ResultLength);
+ return status;
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfFdoInitAllocAndQueryProperty)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ DEVICE_REGISTRY_PROPERTY DeviceProperty,
+ __in
+ __drv_strictTypeMatch(__drv_typeExpr)
+ POOL_TYPE PoolType,
+ __in_opt
+ PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes,
+ __out
+ WDFMEMORY* PropertyMemory
+ )
+/*++
+
+Routine Description:
+ Allocates and retrieves the requested device property for the given device init
+
+Arguments:
+ DeviceInit - Device initialization structure
+
+ DeviceProperty - the property being queried
+
+ PoolType - what type of pool to allocate
+
+ PropertyMemoryAttributes - attributes to associate with PropertyMemory
+
+ PropertyMemory - handle which will receive the property buffer
+
+Return Value:
+ NTSTATUS
+
+ --*/
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, PropertyMemory);
+
+ *PropertyMemory = NULL;
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ FxVerifierCheckNxPoolType(pFxDriverGlobals, PoolType, pFxDriverGlobals->Tag);
+
+ status = FxValidateObjectAttributes(pFxDriverGlobals, PropertyMemoryAttributes);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (DeviceInit->IsNotFdoInit()) {
+ status = STATUS_INVALID_DEVICE_REQUEST;
+
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for an FDO, %!STATUS!",
+ status);
+
+ return status;
+ }
+
+ status = FxDevice::_AllocAndQueryProperty(pFxDriverGlobals,
+ DeviceInit,
+ NULL,
+ NULL,
+ DeviceProperty,
+ PoolType,
+ PropertyMemoryAttributes,
+ PropertyMemory);
+ return status;
+}
+
+__drv_maxIRQL(PASSIVE_LEVEL)
+VOID
+WDFEXPORT(WdfFdoInitSetEventCallbacks)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PWDF_FDO_EVENT_CALLBACKS FdoEventCallbacks
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, FdoEventCallbacks);
+
+ if (!NT_SUCCESS(FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL))) {
+ return;
+ }
+
+ if (DeviceInit->IsNotFdoInit()) {
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for an FDO");
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ if (FdoEventCallbacks->Size != sizeof(WDF_FDO_EVENT_CALLBACKS)) {
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "FdoEventCallbacks size %d is invalid, expected %d",
+ FdoEventCallbacks->Size, sizeof(WDF_FDO_EVENT_CALLBACKS)
+ );
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ if (FdoEventCallbacks->EvtDeviceFilterAddResourceRequirements != NULL &&
+ FdoEventCallbacks->EvtDeviceRemoveAddedResources == NULL) {
+ //
+ // Not allowed to add resources without filtering them out later
+ //
+ DoTraceLevelMessage(
+ GetFxDriverGlobals(DriverGlobals), TRACE_LEVEL_ERROR, TRACINGPNP,
+ "Must set EvtDeviceRemoveAddedResources if "
+ "EvtDeviceFilterAddResourceRequirements (%p) is set",
+ FdoEventCallbacks->EvtDeviceFilterAddResourceRequirements);
+
+ FxVerifierDbgBreakPoint(GetFxDriverGlobals(DriverGlobals));
+ return;
+ }
+
+ RtlCopyMemory(&DeviceInit->Fdo.EventCallbacks,
+ FdoEventCallbacks,
+ sizeof(DeviceInit->Fdo.EventCallbacks));
+}
+
+__drv_maxIRQL(PASSIVE_LEVEL)
+VOID
+WDFEXPORT(WdfFdoInitSetDefaultChildListConfig)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __inout
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PWDF_CHILD_LIST_CONFIG Config,
+ __in_opt
+ PWDF_OBJECT_ATTRIBUTES DefaultDeviceListAttributes
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ NTSTATUS status;
+ size_t totalDescriptionSize;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+ totalDescriptionSize = 0;
+
+ FxPointerNotNull(pFxDriverGlobals, Config);
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return;
+ }
+
+ if (DeviceInit->IsNotFdoInit()) {
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for an FDO");
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ status = FxChildList::_ValidateConfig(pFxDriverGlobals,
+ Config,
+ &totalDescriptionSize);
+ if (!NT_SUCCESS(status)) {
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ if (DefaultDeviceListAttributes != NULL) {
+ status = FxValidateObjectAttributes(pFxDriverGlobals,
+ DefaultDeviceListAttributes,
+ FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
+ if (!NT_SUCCESS(status)) {
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ RtlCopyMemory(&DeviceInit->Fdo.ListConfigAttributes,
+ DefaultDeviceListAttributes,
+ sizeof(DeviceInit->Fdo.ListConfigAttributes));
+ }
+
+ RtlCopyMemory(&DeviceInit->Fdo.ListConfig,
+ Config,
+ sizeof(WDF_CHILD_LIST_CONFIG));
+}
+
+_Must_inspect_result_
+_IRQL_requires_max_(PASSIVE_LEVEL)
+WDFAPI
+NTSTATUS
+WDFEXPORT(WdfFdoInitQueryPropertyEx)(
+ _In_
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ _In_
+ PWDFDEVICE_INIT DeviceInit,
+ _In_
+ PWDF_DEVICE_PROPERTY_DATA DeviceProperty,
+ _In_
+ ULONG BufferLength,
+ _Out_
+ PVOID PropertyBuffer,
+ _Out_
+ PULONG ResultLength,
+ _Out_
+ PDEVPROPTYPE Type
+ )
+/*++
+
+Routine Description:
+
+ This routine queries device property.
+
+Arguments:
+
+ DriverGlobals - DriverGlobals pointer
+
+ DeviceInit - WDF DeviceInit structure pointer.
+
+ DeviceProperty - A pointer to WDF_DEVICE_PROPERTY_DATA structure.
+
+ BufferLength - The size, in bytes, of the buffer that is pointed to by
+ PropertyBuffer.
+
+ PropertyBuffer - A caller-supplied pointer to a caller-allocated buffer that
+ receives the requested information. The pointer can be NULL
+ if the BufferLength parameter is zero.
+
+ ResultLength - A caller-supplied location that, on return, contains the
+ size, in bytes, of the information that the method stored in
+ PropertyBuffer. If the function's return value is
+ STATUS_BUFFER_TOO_SMALL, this location receives the required
+ buffer size.
+
+ Type - A pointer to a DEVPROPTYPE variable. If method successfully retrieves
+ the property data, the routine writes the property type value
+ to this variable. This value indicates the type of property
+ data that is in the Data buffer.
+
+Return Value:
+
+ Method returns an NTSTATUS value. This routine might return one of the
+ following values.
+
+ STATUS_BUFFER_TOO_SMALL - The supplied buffer is too small to receive the
+ information. The ResultLength member receives the
+ size of buffer required.
+ STATUS_SUCCESS - The operation succeeded.
+ STATUS_INVALID_PARAMETER - One of the parameters is incorrect.
+
+ The method might return other NTSTATUS values.
+
+--*/
+
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, DeviceProperty);
+
+ if (DeviceProperty->Size != sizeof(WDF_DEVICE_PROPERTY_DATA)) {
+ status = STATUS_INFO_LENGTH_MISMATCH;
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
+ "PropertyData size (%d) incorrect, expected %d, %!STATUS!",
+ DeviceProperty->Size,
+ sizeof(WDF_DEVICE_PROPERTY_DATA), status);
+ return status;
+ }
+
+ FxPointerNotNull(pFxDriverGlobals, ResultLength);
+ if (BufferLength > 0) {
+ FxPointerNotNull(pFxDriverGlobals, PropertyBuffer);
+ }
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (DeviceInit->IsNotFdoInit()) {
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for an FDO, %!STATUS!",
+ status);
+ return status;
+ }
+
+ status = FxDevice::_QueryPropertyEx(pFxDriverGlobals,
+ DeviceInit,
+ NULL,
+ DeviceProperty,
+ FxDeviceProperty,
+ BufferLength,
+ PropertyBuffer,
+ ResultLength,
+ Type);
+ return status;
+}
+
+_Must_inspect_result_
+_IRQL_requires_max_(PASSIVE_LEVEL)
+WDFAPI
+NTSTATUS
+WDFEXPORT(WdfFdoInitAllocAndQueryPropertyEx)(
+ _In_
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ _In_
+ PWDFDEVICE_INIT DeviceInit,
+ _In_
+ PWDF_DEVICE_PROPERTY_DATA DeviceProperty,
+ _In_
+ _Strict_type_match_
+ POOL_TYPE PoolType,
+ _In_opt_
+ PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes,
+ _Out_
+ WDFMEMORY* PropertyMemory,
+ _Out_
+ PDEVPROPTYPE Type
+ )
+/*++
+
+Routine Description:
+
+ This routine queries device property.
+
+Arguments:
+
+ DriverGlobals - DriverGlobals pointer
+
+ DeviceInit - WDF DeviceInit pointer.
+
+ PropertyData - A pointer to WDF_DEVICE_PROPERTY_ DATA structure.
+
+ PoolType - A POOL_TYPE-typed enumerator that specifies the type of memory
+ to be allocated.
+
+ PropertyMemoryAttributes - optional, A pointer to a caller-allocated
+ WDF_OBJECT_ATTRIBUTES structure that describes object attributes
+ for the memory object that the function will allocate. This
+ parameter is optional and can be WDF_NO_OBJECT_ATTRIBUTES.
+
+ PropertyMemory - A pointer to a WDFMEMORY-typed location that receives a
+ handle to a framework memory object.
+
+ Type - A pointer to a DEVPROPTYPE variable. If method successfully retrieves
+ the property data, the routine writes the property type value to
+ this variable. This value indicates the type of property data
+ that is in the Data buffer.
+
+Return Value:
+
+ Method returns an NTSTATUS value. This routine might return one of the
+ following values. It might return other NTSTATUS-codes as well.
+
+ STATUS_SUCCESS The operation succeeded.
+ STATUS_INVALID_PARAMETER One of the parameters is incorrect.
+
+--*/
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, DeviceProperty);
+
+ if (DeviceProperty->Size != sizeof(WDF_DEVICE_PROPERTY_DATA)) {
+ status = STATUS_INFO_LENGTH_MISMATCH;
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
+ "PropertyData size (%d) incorrect, expected %d, %!STATUS!",
+ DeviceProperty->Size,
+ sizeof(WDF_DEVICE_PROPERTY_DATA), status);
+ return status;
+ }
+
+ FxPointerNotNull(pFxDriverGlobals, PropertyMemory);
+
+ *PropertyMemory = NULL;
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ FxVerifierCheckNxPoolType(pFxDriverGlobals, PoolType, pFxDriverGlobals->Tag);
+
+ status = FxValidateObjectAttributes(pFxDriverGlobals, PropertyMemoryAttributes);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (DeviceInit->IsNotFdoInit()) {
+ status = STATUS_INVALID_DEVICE_REQUEST;
+
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for an FDO, %!STATUS!",
+ status);
+
+ return status;
+ }
+
+ status = FxDevice::_AllocAndQueryPropertyEx(pFxDriverGlobals,
+ DeviceInit,
+ NULL,
+ DeviceProperty,
+ FxDeviceProperty,
+ PoolType,
+ PropertyMemoryAttributes,
+ PropertyMemory,
+ Type);
+ return status;
+}
+
+//
+// END FDO specific functions
+//
+
+//
+// BEGIN PDO specific functions
+//
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+PWDFDEVICE_INIT
+WDFEXPORT(WdfPdoInitAllocate)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFDEVICE ParentDevice
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ PWDFDEVICE_INIT pInit;
+ FxDevice* pDevice;
+ NTSTATUS status;
+
+ FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
+ ParentDevice,
+ FX_TYPE_DEVICE,
+ (PVOID*) &pDevice,
+ &pFxDriverGlobals);
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return NULL;
+ }
+
+ if (pDevice->IsFdo() == FALSE) {
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Parent device is not a FDO (must use WDFCHILDLIST to use a PDO as a parent)"
+ );
+
+ return NULL;
+ }
+
+ pInit = new(pFxDriverGlobals) WDFDEVICE_INIT(pDevice->GetDriver());
+ if (pInit == NULL) {
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Couldn't create WDFDEVICE_INIT object");
+
+ return NULL;
+ }
+
+ pInit->SetPdo(pDevice);
+
+ //
+ // Dynamically created PDOs are not created with this API, rather they go
+ // through WDFCHILDLIST's callback.
+ //
+ pInit->Pdo.Static = TRUE;
+
+ return pInit;
+}
+
+__drv_maxIRQL(PASSIVE_LEVEL)
+VOID
+WDFEXPORT(WdfPdoInitSetEventCallbacks)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PWDF_PDO_EVENT_CALLBACKS DispatchTable
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, DispatchTable);
+
+ if (!NT_SUCCESS(FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL))) {
+ return;
+ }
+
+ if (DeviceInit->IsNotPdoInit()) {
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for a PDO");
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ if (DispatchTable->Size != sizeof(WDF_PDO_EVENT_CALLBACKS) &&
+ DispatchTable->Size != sizeof(WDF_PDO_EVENT_CALLBACKS_V1_9)) {
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "DispatchTable size %d is invalid, expected %d",
+ DispatchTable->Size, sizeof(WDF_PDO_EVENT_CALLBACKS));
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return; // STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ RtlCopyMemory(&DeviceInit->Pdo.EventCallbacks,
+ DispatchTable,
+ sizeof(WDF_PDO_EVENT_CALLBACKS));
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfPdoInitAssignDeviceID)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PCUNICODE_STRING DeviceID
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, DeviceID);
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ status = FxValidateUnicodeString(pFxDriverGlobals, DeviceID);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (DeviceInit->IsNotPdoInit()) {
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for a PDO, %!STATUS!",
+ status);
+ return status;
+ }
+
+ if (DeviceInit->Pdo.DeviceID == NULL) {
+ DeviceInit->Pdo.DeviceID = new(pFxDriverGlobals, WDF_NO_OBJECT_ATTRIBUTES)
+ FxString(pFxDriverGlobals);
+
+ if (DeviceInit->Pdo.DeviceID == NULL) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Couldn't allocate DeviceID object, %!STATUS!",
+ status);
+ return status;
+ }
+ }
+
+ status = DeviceInit->Pdo.DeviceID->Assign(DeviceID);
+
+ return status;
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfPdoInitAssignInstanceID)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PCUNICODE_STRING InstanceID
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, InstanceID);
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ status = FxValidateUnicodeString(pFxDriverGlobals, InstanceID);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (DeviceInit->IsNotPdoInit()) {
+ status = STATUS_INVALID_DEVICE_REQUEST ;
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for a PDO, %!STATUS!",
+ status);
+ return status;
+ }
+
+ if (DeviceInit->Pdo.InstanceID == NULL) {
+ DeviceInit->Pdo.InstanceID = new(pFxDriverGlobals, WDF_NO_OBJECT_ATTRIBUTES)
+ FxString(pFxDriverGlobals);
+
+ if (DeviceInit->Pdo.InstanceID == NULL) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Couldn't allocate InstanceID object, %!STATUS!",
+ status);
+ return status;
+ }
+ }
+
+ status = DeviceInit->Pdo.InstanceID->Assign(InstanceID);
+
+ return status;
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfPdoInitAddHardwareID)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PCUNICODE_STRING HardwareID
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ FxString* pID;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, HardwareID);
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ status = FxValidateUnicodeString(pFxDriverGlobals, HardwareID);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (DeviceInit->IsNotPdoInit()) {
+ status = STATUS_INVALID_DEVICE_REQUEST ;
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for a PDO, %!STATUS!",
+ status);
+ return status;
+ }
+
+ pID = new(pFxDriverGlobals, WDF_NO_OBJECT_ATTRIBUTES) FxString(pFxDriverGlobals);
+ if (pID == NULL) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Couldn't allocate String object %!STATUS!", status);
+ return status;
+ }
+
+ status = pID->Assign(HardwareID);
+ if (NT_SUCCESS(status)) {
+ status = (DeviceInit->Pdo.HardwareIDs.Add(pFxDriverGlobals, pID)) ?
+ STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Upon success, the FxCollection will have taken a reference.
+ // Upon failure, this is object cleanup.
+ //
+ pID->Release();
+
+ return status;
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfPdoInitAddCompatibleID)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PCUNICODE_STRING CompatibleID
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ FxString* pID;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, CompatibleID);
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ status = FxValidateUnicodeString(pFxDriverGlobals, CompatibleID);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (DeviceInit->IsNotPdoInit()) {
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for a PDO, %!STATUS!",
+ status);
+ return status;
+ }
+
+ pID = new(pFxDriverGlobals, WDF_NO_OBJECT_ATTRIBUTES) FxString(pFxDriverGlobals);
+ if (pID == NULL) {
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Couldn't allocate String object"
+ "STATUS_INSUFFICIENT_RESOURCES "
+ );
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ status = pID->Assign(CompatibleID);
+ if (NT_SUCCESS(status)) {
+ status = (DeviceInit->Pdo.CompatibleIDs.Add(pFxDriverGlobals, pID)) ?
+ STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Upon success, the FxCollection will have taken a reference. Upon failure,
+ // this is object cleanup.
+ //
+ pID->Release();
+
+ return status;
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfPdoInitAssignContainerID)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PCUNICODE_STRING ContainerID
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, ContainerID);
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ status = FxValidateUnicodeString(pFxDriverGlobals, ContainerID);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (DeviceInit->IsNotPdoInit()) {
+ status = STATUS_INVALID_DEVICE_REQUEST ;
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for a PDO, %!STATUS!",
+ status);
+ return status;
+ }
+
+ if (DeviceInit->Pdo.ContainerID == NULL) {
+ DeviceInit->Pdo.ContainerID = new(pFxDriverGlobals,
+ WDF_NO_OBJECT_ATTRIBUTES)
+ FxString(pFxDriverGlobals);
+
+ if (DeviceInit->Pdo.ContainerID == NULL) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Couldn't allocate ContainerID object, %!STATUS!",
+ status);
+
+ return status;
+ }
+ }
+
+ status = DeviceInit->Pdo.ContainerID->Assign(ContainerID);
+
+ return status;
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfPdoInitAddDeviceText)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PCUNICODE_STRING DeviceDescription,
+ __in
+ PCUNICODE_STRING DeviceLocation,
+ __in
+ LCID LocaleId
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ FxDeviceText *pDeviceText;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, DeviceDescription);
+ FxPointerNotNull(pFxDriverGlobals, DeviceLocation);
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ status = FxValidateUnicodeString(pFxDriverGlobals, DeviceDescription);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ status = FxValidateUnicodeString(pFxDriverGlobals, DeviceLocation);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (DeviceInit->IsNotPdoInit()) {
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for a PDO, %!STATUS!", status);
+ return status;
+ }
+
+ pDeviceText = new(pFxDriverGlobals, PagedPool) FxDeviceText();
+
+ if (pDeviceText == NULL) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Couldn't allocate DeviceText object, %!STATUS!", status);
+
+ return status;
+ }
+
+ pDeviceText->m_LocaleId = LocaleId;
+
+ pDeviceText->m_Description = FxDuplicateUnicodeStringToString(
+ pFxDriverGlobals, DeviceDescription);
+
+ if (pDeviceText->m_Description == NULL) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Couldn't allocate DeviceDescription string, %!STATUS!", status);
+
+ goto Done;
+ }
+
+ pDeviceText->m_LocationInformation = FxDuplicateUnicodeStringToString(
+ pFxDriverGlobals, DeviceLocation);
+
+ if (pDeviceText->m_LocationInformation == NULL) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Couldn't allocate DeviceLocation string, %!STATUS!", status);
+
+ goto Done;
+ }
+
+ //
+ // Insert at the end of the list and update end of the list
+ //
+ *DeviceInit->Pdo.LastDeviceTextEntry = &pDeviceText->m_Entry;
+ DeviceInit->Pdo.LastDeviceTextEntry = &pDeviceText->m_Entry.Next;
+
+Done:
+ if (!NT_SUCCESS(status)) {
+ delete pDeviceText;
+ }
+
+ return status;
+}
+
+__drv_maxIRQL(PASSIVE_LEVEL)
+VOID
+WDFEXPORT(WdfPdoInitSetDefaultLocale)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ LCID LocaleId
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ if (!NT_SUCCESS(FxVerifierCheckIrqlLevel(pFxDriverGlobals,
+ PASSIVE_LEVEL))) {
+ return;
+ }
+
+ if (DeviceInit->IsNotPdoInit()) {
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for a PDO");
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ DeviceInit->Pdo.DefaultLocale = LocaleId;
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfPdoInitAssignRawDevice)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ CONST GUID* DeviceClassGuid
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, DeviceClassGuid);
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if (DeviceInit->IsNotPdoInit()) {
+ status = STATUS_INVALID_PARAMETER;
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for a PDO, %!STATUS!",
+ status);
+ return status;
+ }
+
+ DeviceInit->Pdo.Raw = TRUE;
+ DeviceInit->Security.DeviceClassSet = TRUE;
+ RtlCopyMemory(&DeviceInit->Security.DeviceClass,
+ DeviceClassGuid,
+ sizeof(GUID));
+
+ return STATUS_SUCCESS;
+}
+
+__drv_maxIRQL(PASSIVE_LEVEL)
+VOID
+WDFEXPORT(WdfPdoInitAllowForwardingRequestToParent)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ NTSTATUS status;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return;
+ }
+
+ if (DeviceInit->IsNotPdoInit()) {
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for a PDO, %!STATUS!",
+ status);
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ DeviceInit->Pdo.ForwardRequestToParent = TRUE;
+ return ;
+}
+
+
+
+//
+// END PDO specific functions
+//
+
+//
+// BEGIN CONTROL DEVICE specific functions
+//
+
+_Must_inspect_result_
+__drv_maxIRQL(PASSIVE_LEVEL)
+PWDFDEVICE_INIT
+WDFEXPORT(WdfControlDeviceInitAllocate)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFDRIVER Driver,
+ __in
+ CONST UNICODE_STRING* SDDLString
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ FxDriver* pDriver;
+ NTSTATUS status;
+
+ FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
+ Driver,
+ FX_TYPE_DRIVER,
+ (PVOID*) &pDriver,
+ &pFxDriverGlobals);
+
+ FxPointerNotNull(pFxDriverGlobals, SDDLString);
+
+ status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
+ if (!NT_SUCCESS(status)) {
+ return NULL;
+ }
+
+ status = FxValidateUnicodeString(pFxDriverGlobals, SDDLString);
+ if (!NT_SUCCESS(status)) {
+ return NULL;
+ }
+
+ return WDFDEVICE_INIT::_AllocateControlDeviceInit(pDriver, SDDLString);
+}
+
+__drv_maxIRQL(PASSIVE_LEVEL)
+VOID
+WDFEXPORT(WdfControlDeviceInitSetShutdownNotification)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ PWDFDEVICE_INIT DeviceInit,
+ __in
+ PFN_WDF_DEVICE_SHUTDOWN_NOTIFICATION Notification,
+ __in
+ UCHAR Flags
+ )
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+
+ FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), DeviceInit);
+ pFxDriverGlobals = DeviceInit->DriverGlobals;
+
+ FxPointerNotNull(pFxDriverGlobals, Notification);
+
+ if (DeviceInit->IsNotControlDeviceInit()) {
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "Not a PWDFDEVICE_INIT for a control device");
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ if ((Flags & ~(WdfDeviceShutdown | WdfDeviceLastChanceShutdown)) != 0) {
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+ "WdfDeviceShutdown Flags 0x%x are invalid", Flags);
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ DeviceInit->Control.ShutdownNotification = Notification;
+ DeviceInit->Control.Flags |= Flags;
+}
+
+//
+// END CONTROL DEVICE specific functions
+//
+
+} // extern "C"