Windows2000/private/ntos/io/pnpiop.h
2020-09-30 17:12:32 +02:00

2138 lines
58 KiB
C

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
pnpsubs.c
Abstract:
This module contains the plug-and-play macros and constants.
Author:
Shie-Lin Tzong (shielint) 29-Jan-1995
Andrew Thornton (andrewth) 5-Sept-1996
Environment:
Kernel mode
*/
#include "..\pnp\pnpi.h"
#include "arbiter.h"
#include "dockintf.h"
#include "pnprlist.h"
// Pool tags
#define IOP_DNOD_TAG 'donD'
#define IOP_DNDT_TAG 'tdnD'
#define IOP_DPWR_TAG 'rwPD'
// Dbg scope
#define DBG_SCOPE 1 // Enable SOME DBG stuff on ALL builds
//#define DBG_SCOPE DBG // Enable only on DBG build
// The DEVICE_NODE is really just some extra stuff that we'd like to keep around
// for each physical device object.
// It is seperated from DEVOBJ_EXTENSION because these fields only apply to
// PDO.
typedef enum {
DOCK_NOTDOCKDEVICE,
DOCK_QUIESCENT,
DOCK_ARRIVING,
DOCK_DEPARTING,
DOCK_EJECTIRP_COMPLETED
} PROFILE_STATUS;
typedef enum {
PROFILE_IN_PNPEVENT,
PROFILE_NOT_IN_PNPEVENT,
PROFILE_PERHAPS_IN_PNPEVENT
} PROFILE_NOTIFICATION_TIME;
typedef struct _PENDING_SET_INTERFACE_STATE
{
LIST_ENTRY List;
UNICODE_STRING LinkName;
} PENDING_SET_INTERFACE_STATE, *PPENDING_SET_INTERFACE_STATE;
typedef enum _UNLOCK_UNLINK_ACTION {
UnlinkRemovedDeviceNodes,
UnlinkAllDeviceNodesPendingClose,
UnlinkOnlyChildDeviceNodesPendingClose
} UNLOCK_UNLINK_ACTION, *PUNLOCK_UNLINK_ACTION;
typedef struct _DEVICE_NODE *PDEVICE_NODE;
typedef struct _DEVICE_NODE {
// Pointer to another DEVICE_NODE with the same parent as this one.
PDEVICE_NODE Sibling;
// Pointer to the first child of this DEVICE_NODE.
PDEVICE_NODE Child;
// Pointer to this DEVICE_NODE's parent.
PDEVICE_NODE Parent;
// Pointer to the last child of the device node
PDEVICE_NODE LastChild;
// Depth of DEVICE_NODE in the tree, root is 0
ULONG Level;
// Power notification order list entry for this device node
PPO_DEVICE_NOTIFY Notify;
// General flags.
ULONG Flags;
// Flags used by user-mode for volatile state which should go away on a
// reboot or when the device is removed.
ULONG UserFlags;
// Problem. This is set if DNF_HAS_PROBLEM is set in Flags. Indicates
// which problem exists and uses the same values as the config manager
// CM_PROB_*
ULONG Problem;
// Pointer to the physical device object that this DEVICE_NODE is associated
// with.
PDEVICE_OBJECT PhysicalDeviceObject;
// Pointer to the list of resources assigned to the PhysicalDeviceObject.
// This is the Resource list which is passed to driver's start routine.
// Note, PDO contains ListOfAssignedResources which described the resources
// owned by the PDO. But, it is not in the format we will pass to driver or
// write to registry.
PCM_RESOURCE_LIST ResourceList;
PCM_RESOURCE_LIST ResourceListTranslated;
// EnumerationMutex ensures that a given DEVICE_NODE doesn't get enumerated
// on multiple threads at the same time.
KEVENT EnumerationMutex;
// InstancePath is the path of the instance node in the registry,
// i.e. <EnumBus>\<DeviceId>\<uniqueid>
UNICODE_STRING InstancePath;
// ServiceName is the name of the driver who controls the device. (Not the
// driver who enumerates/creates the PDO.) This field is mainly for
// convenience.
UNICODE_STRING ServiceName;
// DuplicatePDO - if the flags have DNF_DUPLICATE set then this fields indicates
// the duplicate PDO which is enumerated by a bus driver. N.B. It is possible
// that DNF_DUPLICATE is set but this field is NULL. In this case, it means that
// we know the device is a duplicate of another device and we have not enumerated
// the DuplicatePDO yet.
PDEVICE_OBJECT DuplicatePDO;
// ResourceRequirements
PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements;
// Information queried from the LEGACY_BUS_INFORMATION irp.
INTERFACE_TYPE InterfaceType;
ULONG BusNumber;
// Information queried from the BUS_INFORMATION irp.
INTERFACE_TYPE ChildInterfaceType;
ULONG ChildBusNumber;
USHORT ChildBusTypeIndex;
// Information queried from the PNP_BUS_INFORMATION irp. The BusTypeIndex
// value is actually an index into a global table of known bus type guids.
USHORT Reserved; // padding, someone else can use this field
// Linked list of entries that represent each driver that has registered
// for notification on this devnode. Note: drivers (and user-mode) actually
// register based on a FILE_OBJECT handle, which is translated into a PDO
// by sending an IRP_MN_QUERY_DEVICE_RELATIONS for TargetDeviceRelation.
LIST_ENTRY TargetDeviceNotify;
// DeviceArbiterList - A list of arbiters registered for this physical device object
// Note: The Arbiters must be dereferenced when the device node is going away.
LIST_ENTRY DeviceArbiterList;
// DeviceTranslatorList - A list of translator for this physical device object
// NOTE: the Translator must be dereferenced when the devic node is going away.
LIST_ENTRY DeviceTranslatorList;
// NoTranslatorMask - the bit position corresponds to resource type
// if bit is set, there is no translator for the resource type in this devnode
USHORT NoTranslatorMask;
// QueryTranslatorMask - The bit position corresponds to resource type.
// if bit is set, the translator for the resource type is queried.
USHORT QueryTranslatorMask;
// NoArbiterMask - the bit position corresponds to resource type
// if bit is set, there is no arbiter for the resource type in this devnode
USHORT NoArbiterMask;
// QueryArbiterMask - The bit position corresponds to resource type.
// if bit is set, the arbiter for the resource type is queried.
USHORT QueryArbiterMask;
// The following fields are used to track legacy resource allocation
// LegacyDeviceNode - The real legacy device node.
// NextResourceDeviceNode - link all the made-up device nodes which own part of
// the resources from LegacyDeviceNode.
union {
PDEVICE_NODE LegacyDeviceNode;
PDEVICE_RELATIONS PendingDeviceRelations;
} OverUsed1;
union {
PDEVICE_NODE NextResourceDeviceNode;
} OverUsed2;
// Remember the BootResources for the device
PCM_RESOURCE_LIST BootResources;
// Lock Count used to keep track of multiple ejects
ULONG LockCount;
// If this devnode has been QueryRemoved but the original target of the
// QueryRemove is still physically present then this will point to the
// relation list used to process the original QueryRemove.
PRELATION_LIST RelationList;
// When Capabilities have been queried for a device (twice, once before
// start and once after start) the flags are stored here in the same format
// as the query capabilities IRP - use IopDeviceNodeFlagsToCapabilities to
// access.
ULONG CapabilityFlags;
// Maintain a list of current dock devices and their SerialNumbers
struct {
PROFILE_STATUS DockStatus;
LIST_ENTRY ListEntry;
PWCHAR SerialNumber;
} DockInfo;
// Maintain a count to determine if either ourselves or any of
// our children are stopping us from being disableable
// count = myself (DNUF_NOT_DISABLEABLE) + 1 for each immediate
// child that has DisableableDepends > 0
ULONG DisableableDepends;
// List of pended IoSetDeviceInterfaceState calls.
// IoSetDeviceInterfaceState adds an entry to this list whenever it is
// called and we haven't been started yet. Once we do the start we'll
// run down the list.
LIST_ENTRY PendedSetInterfaceState;
#if DBG_SCOPE
ULONG FailureStatus;
PCM_RESOURCE_LIST PreviousResourceList;
PIO_RESOURCE_REQUIREMENTS_LIST PreviousResourceRequirements;
#endif
} DEVICE_NODE;
// A device Object is a PDO iff it has a non NULL device node (aka set by
// plug and play during a query device relations.
#define ASSERT_PDO(d) \
do { \
if ( NULL == (d)->DeviceObjectExtension->DeviceNode || \
(((PDEVICE_NODE)(d)->DeviceObjectExtension->DeviceNode)->Flags & DNF_LEGACY_RESOURCE_DEVICENODE)) { \
KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, PNP_ERR_INVALID_PDO, (ULONG_PTR)d, 0, 0); \
} \
} \
while (0)
// DNF_MAKEUP - this devnode's device is created and owned by PnP manager
#define DNF_MADEUP 0x00000001
// DNF_DUPLICATE - this devnode's device is a duplicate of another enumerate PDO
#define DNF_DUPLICATE 0x00000002
// DNF_HAL_NODE - a flag to indicate which device node is the root node created by
// the hal
#define DNF_HAL_NODE 0x00000004
// DNF_PROCESSED - indicates if the registry instance key of the device node
// was created.
#define DNF_PROCESSED 0x00000008
// DNF_ENUMERATED - used to track enumeration in IopEnumerateDevice()
#define DNF_ENUMERATED 0x00000010
// Singal that we need to send driver query id irps
#define DNF_NEED_QUERY_IDS 0x00000020
// THis device has been added to its controlling driver
#define DNF_ADDED 0x00000040
// DNF_HAS_BOOT_CONFIG - the device has resource assigned by BIOS. It is considered
// pseudo-started and need to participate in rebalance.
#define DNF_HAS_BOOT_CONFIG 0x00000080
// DNF_BOOT_CONFIG_RESERVED - Indicates the BOOT resources of the device are reserved.
#define DNF_BOOT_CONFIG_RESERVED 0x00000100
// DNF_START_REQUEST_PENDING - Indicates the device is being started.
#define DNF_START_REQUEST_PENDING 0x00000200
// DNF_NO_RESOURCE_REQUIRED - this devnode's device does not require resource.
#define DNF_NO_RESOURCE_REQUIRED 0x00000400
// DNF_RESOURCE_REQUIREMENTS_NEED_FILTERED - to distinguished the
// DeviceNode->ResourceRequirements is a filtered list or not.
#define DNF_RESOURCE_REQUIREMENTS_NEED_FILTERED 0x00000800
// Indicates the device's resources are bing assigned (but is not done yet.)
// So don't try assign resource to this device.
#define DNF_ASSIGNING_RESOURCES 0x00001000
// DNF_RESOURCE_ASSIGNED - this devnode's resources are assigned by PnP
#define DNF_RESOURCE_ASSIGNED 0x00002000
// DNF_RESOURCE_REPORTED - this devnode's resources are reported by PnP
#define DNF_RESOURCE_REPORTED 0x00004000
// DNF_RESOURCE_REQUIREMENTS_CHANGED - Indicates the device's resource
// requirements list has been changed.
#define DNF_RESOURCE_REQUIREMENTS_CHANGED 0x00008000
// DNF_NON_STOPPED_REBALANC - indicates the device can be restarted with new
// resources without being stopped.
#define DNF_NON_STOPPED_REBALANCE 0x00010000
// DNF_STOPPED - indicates this device is currently stopped for reconfiguration of
// its resources.
#define DNF_STOPPED 0x00020000
// DNF_STARTED - indicates if the device was started, i.e., its StartDevice
// irp is processed.
#define DNF_STARTED 0x00040000
// The device's controlling driver is a legacy driver
#define DNF_LEGACY_DRIVER 0x00080000
// For the reported detected devices, they are considered started. We still
// need a flag to indicate we need to enumerate the device.
#define DNF_NEED_ENUMERATION_ONLY 0x00100000
// DNF_IO_INVALIDATE_DEVICE_RELATIONS_PENDING - indicate the
// IoInvalidateDeviceRelations request is pending and therequest needs to
// be queued after the Query_Device_relation irp is completed.
#define DNF_IO_INVALIDATE_DEVICE_RELATIONS_PENDING 0x00200000
// Indicates the device is being sent a query device relations irp. So no more
// q-d-r irp at the same time.
#define DNF_BEING_ENUMERATED 0x00400000
// DNF_ENUMERATION_REQUEST_QUEUED - indicate the IoInvalidateDeviceRelations
// request is queued. So, new IoInvalidateDeviceRelations can be ignored.
#define DNF_ENUMERATION_REQUEST_QUEUED 0x00800000
// DNF_ENUMERATION_REQUEST_PENDING - Indicates the QUERY_DEVICE_RELATIONS irp
// returns pending.
#define DNF_ENUMERATION_REQUEST_PENDING 0x01000000
// This corresponds to the user-mode CM_PROB_WILL_BE_REMOVED problem value and
// the DN_WILL_BE_REMOVED status flag.
#define DNF_HAS_PROBLEM 0x02000000
// DNF_HAS_PRIVATE_PROBLEM - indicates this device reported PNP_DEVICE_FAILED
// to a IRP_MN_QUERY_PNP_DEVICE_STATE without also reporting
// PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED.
#define DNF_HAS_PRIVATE_PROBLEM 0x04000000
// DNF_REMOVE_PENDING_CLOSES is set after a IRP_MN_SURPRISE_REMOVE is sent
// to a device object. It is an indicator that IRP_MN_REMOVE_DEVICE should
// be sent to the device object as soon as all of the file objects have gone
// away.
#define DNF_REMOVE_PENDING_CLOSES 0x08000000
// DNF_DEVICE_GONE is set when a pdo is no longer returned in a query bus
// relations. It will then be processed as a surprise remove if started.
// This flag is used to better detect when a device is resurrected, and when
// processing surprise remove, to determine if the devnode should be removed
// from the tree.
#define DNF_DEVICE_GONE 0x10000000
// DNF_LEGACY_RESOURCE_DEVICENODE is set for device nodes created for legacy
// resource allocation.
#define DNF_LEGACY_RESOURCE_DEVICENODE 0x20000000
// DNF_NEEDS_REBALANCE is set for device nodes that trigger rebalance.
#define DNF_NEEDS_REBALANCE 0x40000000
// DNF_LOCKED_FOR_EJECT is set on device nodes that are being ejected or are
// related to a device being ejected.
#define DNF_LOCKED_FOR_EJECT 0x80000000
// This corresponds to the user-mode the DN_WILL_BE_REMOVED status flag.
#define DNUF_WILL_BE_REMOVED 0x00000001
// This corresponds to the user-mode DN_NO_SHOW_IN_DM status flag.
#define DNUF_DONT_SHOW_IN_UI 0x00000002
// This flag is set when user-mode lets us know that a reboot is required
// for this device.
#define DNUF_NEED_RESTART 0x00000004
// This flag is set to let the user-mode know when a device can be disabled
// it is still possible for this to be TRUE, yet disable to fail, as it's
// a polled flag (see also PNP_DEVICE_NOT_DISABLEABLE)
#define DNUF_NOT_DISABLEABLE 0x00000008
#define DNF_ADD_PHASE (DNF_HAS_PROBLEM | DNF_HAS_PRIVATE_PROBLEM | DNF_DEVICE_GONE | DNF_REMOVE_PENDING_CLOSES | DNF_ADDED)
#define OK_TO_ADD_DEVICE(_devnode_) \
( (_devnode_)->Flags & DNF_PROCESSED && \
!((_devnode_)->Flags & DNF_ADD_PHASE) )
#define DNF_START_PHASE (DNF_HAS_PROBLEM | DNF_HAS_PRIVATE_PROBLEM | DNF_DEVICE_GONE | DNF_REMOVE_PENDING_CLOSES | DNF_STARTED | DNF_START_REQUEST_PENDING)
#define DNF_ASYNC_REQUEST_PENDING (DNF_START_REQUEST_PENDING | DNF_ENUMERATION_REQUEST_PENDING)
#define DNF_ASSIGN_RESOURCE_PHASE (DNF_HAS_PROBLEM | DNF_HAS_PRIVATE_PROBLEM | DNF_DEVICE_GONE | DNF_REMOVE_PENDING_CLOSES | DNF_RESOURCE_ASSIGNED | DNF_RESOURCE_REPORTED | \
DNF_ASSIGNING_RESOURCES | DNF_NO_RESOURCE_REQUIRED)
#define DNF_HAS_RESOURCE (DNF_RESOURCE_ASSIGNED | DNF_RESOURCE_REPORTED | \
DNF_NO_RESOURCE_REQUIRED)
// PNP Bugcheck Subcodes
#define PNP_ERR_DUPLICATE_PDO 1
#define PNP_ERR_INVALID_PDO 2
#define PNP_ERR_BOGUS_ID 3
#define PNP_ERR_PDO_ENUMERATED_AFTER_DELETION 4
#define PNP_ERR_ACTIVE_PDO_FREED 5
#define PNP_ERR_DEVICE_MISSING_FROM_EJECT_LIST 6
#define PNP_ERR_UNEXPECTED_ADD_RELATION_ERR 7
typedef NTSTATUS (*PENUM_CALLBACK)(
IN PDEVICE_NODE DeviceNode,
IN PVOID Context
);
// Define workitem for add/start new device
typedef struct _NEW_DEVICE_WORK_ITEM {
WORK_QUEUE_ITEM WorkItem;
PDEVICE_OBJECT DeviceObject;
PDRIVER_OBJECT DriverObject;
} NEW_DEVICE_WORK_ITEM, *PNEW_DEVICE_WORK_ITEM;
// Define callback routine for IopApplyFunctionToSubKeys &
// IopApplyFunctionToServiceInstances
typedef BOOLEAN (*PIOP_SUBKEY_CALLBACK_ROUTINE) (
IN HANDLE,
IN PUNICODE_STRING,
IN OUT PVOID
);
// Define context structures for Start and Add device services
#define NO_MORE_GROUP ((USHORT) -1)
#define SETUP_RESERVED_GROUP 0
#define BUS_DRIVER_GROUP 1
typedef struct _ADD_CONTEXT {
USHORT GroupsToStart;
USHORT GroupToStartNext;
ULONG DriverStartType;
} ADD_CONTEXT, *PADD_CONTEXT;
typedef struct _START_CONTEXT {
BOOLEAN LoadDriver;
BOOLEAN NewDevice;
ADD_CONTEXT AddContext;
} START_CONTEXT, *PSTART_CONTEXT;
// Resource translation and allocation related structures
typedef enum _RESOURCE_HANDLER_TYPE {
ResourceHandlerNull,
ResourceTranslator,
ResourceArbiter,
ResourceLegacyDeviceDetection
} RESOURCE_HANDLER_TYPE;
#define PI_MAXIMUM_RESOURCE_TYPE_TRACKED 15
// Internal Arbiters tracking structures
// Note the first three fields of PI_RESOURCE_ARBITER_ENTRY and PI_RESOURCE_TRANSLATOR_ENTRY
// must be the same.
typedef struct _PI_RESOURCE_ARBITER_ENTRY {
LIST_ENTRY DeviceArbiterList; // Link all the arbiters of a PDO.
UCHAR ResourceType;
PARBITER_INTERFACE ArbiterInterface;
LIST_ENTRY ResourceList;
LIST_ENTRY BestResourceList;
LIST_ENTRY BestConfig; // Link all the arbiters which produces the best logconf
LIST_ENTRY ActiveArbiterList; // Link all the arbiters under testing
UCHAR State;
BOOLEAN ResourcesChanged;
} PI_RESOURCE_ARBITER_ENTRY, *PPI_RESOURCE_ARBITER_ENTRY;
// Define PI_RESOURCE_ARBITER_ENTRY state
#define PI_ARBITER_HAS_SOMETHING 1
#define PI_ARBITER_TEST_FAILED 2
// Internal Translator tracking structures
typedef struct _PI_RESOURCE_TRANSLATOR_ENTRY {
LIST_ENTRY DeviceTranslatorList;
UCHAR ResourceType;
PTRANSLATOR_INTERFACE TranslatorInterface;
PDEVICE_NODE DeviceNode;
} PI_RESOURCE_TRANSLATOR_ENTRY, *PPI_RESOURCE_TRANSLATOR_ENTRY;
// IOP_RESOURCE_REQUEST
#define QUERY_RESOURCE_LIST 0
#define QUERY_RESOURCE_REQUIREMENTS 1
#define REGISTRY_ALLOC_CONFIG 1
#define REGISTRY_FORCED_CONFIG 2
#define REGISTRY_BOOT_CONFIG 4
#define REGISTRY_OVERRIDE_CONFIGVECTOR 1
#define REGISTRY_BASIC_CONFIGVECTOR 2
// An array of IOP_RESOURCE_REQUEST structures is used to anchor all the
// devices for which resource rerquirement is being attempted.
#define IOP_ASSIGN_RETRY 0x00000008 // Retry resource allocation later
#define IOP_ASSIGN_EXCLUDE 0x00000010 // internal IopAssign flag
#define IOP_ASSIGN_IGNORE 0x00000020 // ignore this request
#define IOP_ASSIGN_NO_REBALANCE 0x00000080 // no rebal if assign fails
#define IOP_ASSIGN_RESOURCES_RELEASED 0x00000100 // resources are released for rebalancing
#define IOP_ASSIGN_KEEP_CURRENT_CONFIG 0x00000200 // Indicate non-stopped rebalance. We need to
// preserved the current config.
#define IOP_ASSIGN_CLEAR_RESOURCE_REQUIREMENTS_CHANGE_FLAG \
0x00000400
typedef struct _IOP_RESOURCE_REQUEST {
PDEVICE_OBJECT PhysicalDevice;
ULONG Flags;
ARBITER_REQUEST_SOURCE AllocationType;
ULONG Priority; // 0 is highest priority
PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements;
PVOID ReqList; // PREQ_LIST
PCM_RESOURCE_LIST ResourceAssignment;
PCM_RESOURCE_LIST TranslatedResourceAssignment;
NTSTATUS Status;
} IOP_RESOURCE_REQUEST, *PIOP_RESOURCE_REQUEST;
// Misc
// Enumeration request type
typedef enum _DEVICE_REQUEST_TYPE {
ReenumerateDeviceTree,
ReenumerateDeviceOnly,
ReenumerateBootDevices,
RestartEnumeration,
AssignResources,
ResourceRequirementsChanged,
StartDevice,
ReenumerateRootDevices
} DEVICE_REQUEST_TYPE;
typedef struct _PI_DEVICE_REQUEST {
LIST_ENTRY ListEntry;
PDEVICE_OBJECT DeviceObject;
DEVICE_REQUEST_TYPE RequestType;
PKEVENT CompletionEvent;
PNTSTATUS CompletionStatus;
} PI_DEVICE_REQUEST, *PPI_DEVICE_REQUEST;
#define CmResourceTypeReserved 0xf0
// This macro returns the pointer to the beginning of the data
// area of KEY_VALUE_FULL_INFORMATION structure.
// In the macro, k is a pointer to KEY_VALUE_FULL_INFORMATION structure.
#define KEY_VALUE_DATA(k) ((PCHAR)(k) + (k)->DataOffset)
// Save failure status info.
#if DBG_SCOPE
#define SAVE_FAILURE_INFO(DeviceNode, Status) (DeviceNode)->FailureStatus = (Status)
#else
#define SAVE_FAILURE_INFO(DeviceNode, Status)
#endif
#define IopDoesDevNodeHaveProblem(devnode) \
((devnode)->Flags & (DNF_HAS_PROBLEM | DNF_HAS_PRIVATE_PROBLEM))
#define IopIsDevNodeProblem(devnode, problem) \
(((devnode)->Flags & DNF_HAS_PROBLEM) && (devnode)->Problem == (problem))
#define IopClearDevNodeProblem(devnode) \
(devnode)->Flags &= ~DNF_HAS_PROBLEM; \
(devnode)->Problem = 0;
#define IopSetDevNodeProblem(devnode, problem) \
ASSERT(((devnode)->Flags & DNF_PROCESSED) || !((devnode)->Flags & DNF_ENUMERATED)); \
ASSERT(!((devnode)->Flags & (DNF_STARTED | DNF_HAS_PROBLEM | DNF_HAS_PRIVATE_PROBLEM))); \
ASSERT(problem != 0); \
(devnode)->Flags |= DNF_HAS_PROBLEM; \
(devnode)->Problem = (problem);
#define IopIsProblemReadonly(problem) \
((problem) != CM_PROB_FAILED_INSTALL && \
(problem) != CM_PROB_FAILED_ADD && \
(problem) != CM_PROB_FAILED_START && \
(problem) != CM_PROB_NOT_CONFIGURED && \
(problem) != CM_PROB_NEED_RESTART && \
(problem) != CM_PROB_REINSTALL && \
(problem) != CM_PROB_REGISTRY && \
(problem) != CM_PROB_DISABLED)
// VOID IopRegistryDataToUnicodeString(OUT PUNICODE_STRING u, IN PWCHAR p, IN ULONG l)
#define IopRegistryDataToUnicodeString(u, p, l) \
{ \
ULONG len; \
\
PiRegSzToString((p), (l), &len, NULL); \
(u)->Length = (USHORT)len; \
(u)->MaximumLength = (USHORT)(l); \
(u)->Buffer = (p); \
}
// Title Index to set registry key value
#define TITLE_INDEX_VALUE 0
#if DBG
#define PNP_ASSERT(condition, message) \
if (!(condition)) { \
DbgPrint((message)); \
DbgBreakPoint(); \
}
#else
#define PNP_ASSERT(condition, message)
#endif
// Default value of PnpDetectionEnabled
// Only used if the CCS\Control\Pnp key is absent or garbled
#define PNP_DETECTION_ENABLED_DEFAULT TRUE
// Size of scratch buffer used in this module.
#define PNP_SCRATCH_BUFFER_SIZE 512
#define PNP_LARGE_SCRATCH_BUFFER_SIZE (PNP_SCRATCH_BUFFER_SIZE * 8)
// Define Device Instance Flags (used by IoQueryDeviceConfiguration apis)
#define DEVINSTANCE_FLAG_HWPROFILE_DISABLED 0x1
#define DEVINSTANCE_FLAG_PNP_ENUMERATED 0x2
// Define Enumeration Control Flags (used by IopApplyFunctionToSubKeys)
#define FUNCTIONSUBKEY_FLAG_IGNORE_NON_CRITICAL_ERRORS 0x1
#define FUNCTIONSUBKEY_FLAG_DELETE_SUBKEYS 0x2
// The following definitions are used in IoOpenDeviceInstanceKey
#define PLUGPLAY_REGKEY_DEVICE 1
#define PLUGPLAY_REGKEY_DRIVER 2
#define PLUGPLAY_REGKEY_CURRENT_HWPROFILE 4
// Define device extension for devices reported with IoReportDetectedDevice.
typedef struct _IOPNP_DEVICE_EXTENSION {
PWCHAR CompatibleIdList;
ULONG CompatibleIdListSize;
} IOPNP_DEVICE_EXTENSION, *PIOPNP_DEVICE_EXTENSION;
// Reserve Boot Resources
typedef struct _IOP_RESERVED_RESOURCES_RECORD IOP_RESERVED_RESOURCES_RECORD, *PIOP_RESERVED_RESOURCES_RECORD;
struct _IOP_RESERVED_RESOURCES_RECORD {
PIOP_RESERVED_RESOURCES_RECORD Next;
PDEVICE_OBJECT DeviceObject;
PCM_RESOURCE_LIST ReservedResources;
};
// External References
// Init data
extern PVOID IopPnpScratchBuffer1;
extern PVOID IopPnpScratchBuffer2;
extern PCM_RESOURCE_LIST IopInitHalResources;
extern PDEVICE_NODE IopInitHalDeviceNode;
extern PIOP_RESERVED_RESOURCES_RECORD IopInitReservedResourceList;
// Regular data
// IopRootDeviceNode - the head of the PnP manager's device node tree.
extern PDEVICE_NODE IopRootDeviceNode;
// IopPnPDriverObject - the madeup driver object for pnp manager
extern PDRIVER_OBJECT IopPnPDriverObject;
// IopPnPSpinLock - spinlock for Pnp code.
extern KSPIN_LOCK IopPnPSpinLock;
// IopPnpDeleteRequestList - a link list of device removal requests to worker thread.
extern LIST_ENTRY IopPnpDeleteRequestList;
// IopPnpEnumerationRequestList - a link list of device enumeration requests to worker thread.
extern LIST_ENTRY IopPnpEnumerationRequestList;
// IopDeviceTreeLock - performs syncronization on the whole device node tree.
// IopAcquireEnumerationLock acquires this lock shared then optionally
// acquires an exclusive lock on a devnode.
// IopAcquireDeviceTreeLock acquires this lock exclusive
extern ERESOURCE IopDeviceTreeLock;
// PiEventQueueEmpty - Manual reset event which is set when the queue is empty
extern KEVENT PiEventQueueEmpty;
// PiEnumerationLock - to synchronize IoInvalidateDeviceRelations in boot phase.
extern KEVENT PiEnumerationLock;
// iopEnumerationCount - indicates how many devices are being enumerated.
extern LONG IopEnumerationCount;
// IopNumberDeviceNodes - Number of outstanding device nodes in the system
extern ULONG IopNumberDeviceNodes;
// PnPInitialized - A flag to indicate if PnP initialization is completed.
extern BOOLEAN PnPInitialized;
// PnPBootDriverInitialied
extern BOOLEAN PnPBootDriversInitialized;
// PnPBootDriverLoaded
extern BOOLEAN PnPBootDriversLoaded;
// IopBootConfigsReserved - Indicates whether we have reserved BOOT configs or not.
extern BOOLEAN IopBootConfigsReserved;
// IopResourcesReleased - a flag to indicate if a device is removed and its resources
// are freed. This is for reallocating resources for DNF_INSUFFICIENT_RESOURCES
// devices.
extern BOOLEAN IopResourcesReleased;
// PnPDetectionEnabled - A flag to indicate if detection code can be executed
extern BOOLEAN PnPDetectionEnabled;
// PnpDefaultInterfaceTYpe - Use this if the interface type of resource list is unknown.
extern INTERFACE_TYPE PnpDefaultInterfaceType;
// PnpStartAsynOk - control how start irp should be handled. Synchronously or Asynchronously?
extern BOOLEAN PnpAsyncOk;
// IopPendingEjects - List of pending eject requests
extern LIST_ENTRY IopPendingEjects;
// IopPendingSurpriseRemovals - List of pending surprise removal requests
extern LIST_ENTRY IopPendingSurpriseRemovals;
NTSTATUS
IopAppendStringToValueKey (
IN HANDLE Handle,
IN PWSTR ValueName,
IN PUNICODE_STRING String,
IN BOOLEAN Create
);
NTSTATUS
IopPrepareDriverLoading (
IN PUNICODE_STRING KeyName,
IN HANDLE KeyHandle,
IN PIMAGE_NT_HEADERS Header
);
NTSTATUS
IopRemoveStringFromValueKey (
IN HANDLE Handle,
IN PWSTR ValueName,
IN PUNICODE_STRING String
);
BOOLEAN
IopIsDuplicatedDevices(
IN PCM_RESOURCE_LIST Configuration1,
IN PCM_RESOURCE_LIST Configuration2,
IN PHAL_BUS_INFORMATION BusInfo1 OPTIONAL,
IN PHAL_BUS_INFORMATION BusInfo2 OPTIONAL
);
NTSTATUS
IopMarkDuplicateDevice(
IN PUNICODE_STRING TargetKeyName,
IN ULONG TargetInstance,
IN PUNICODE_STRING SourceKeyName,
IN ULONG SourceInstance
);
BOOLEAN
IopConcatenateUnicodeStrings (
OUT PUNICODE_STRING Destination,
IN PUNICODE_STRING String1,
IN PUNICODE_STRING String2 OPTIONAL
);
NTSTATUS
IopServiceInstanceToDeviceInstance (
IN HANDLE ServiceKeyHandle OPTIONAL,
IN PUNICODE_STRING ServiceKeyName OPTIONAL,
IN ULONG ServiceInstanceOrdinal,
OUT PUNICODE_STRING DeviceInstanceRegistryPath OPTIONAL,
OUT PHANDLE DeviceInstanceHandle OPTIONAL,
IN ACCESS_MASK DesiredAccess
);
NTSTATUS
IopCreateRegistryKeyEx(
OUT PHANDLE Handle,
IN HANDLE BaseHandle OPTIONAL,
IN PUNICODE_STRING KeyName,
IN ACCESS_MASK DesiredAccess,
IN ULONG CreateOptions,
OUT PULONG Disposition OPTIONAL
);
NTSTATUS
IopOpenRegistryKeyEx(
OUT PHANDLE Handle,
IN HANDLE BaseHandle OPTIONAL,
IN PUNICODE_STRING KeyName,
IN ACCESS_MASK DesiredAccess
);
NTSTATUS
IopCreateMadeupNode(
IN PUNICODE_STRING ServiceKeyName,
OUT PHANDLE ReturnedHandle,
OUT PUNICODE_STRING KeyName,
OUT PULONG InstanceOrdinal,
IN BOOLEAN ResourceOwned
);
NTSTATUS
IopInitializePlugPlayServices(
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN ULONG Phase
);
NTSTATUS
IopOpenServiceEnumKeys (
IN PUNICODE_STRING ServiceKeyName,
IN ACCESS_MASK DesiredAccess,
OUT PHANDLE ServiceHandle OPTIONAL,
OUT PHANDLE ServiceEnumHandle OPTIONAL,
IN BOOLEAN CreateEnum
);
NTSTATUS
IopOpenCurrentHwProfileDeviceInstanceKey(
OUT PHANDLE Handle,
IN PUNICODE_STRING ServiceKeyName,
IN ULONG Instance,
IN ACCESS_MASK DesiredAccess,
IN BOOLEAN Create
);
NTSTATUS
IopGetDeviceInstanceCsConfigFlags(
IN PUNICODE_STRING DeviceInstance,
OUT PULONG CsConfigFlags
);
NTSTATUS
IopGetServiceInstanceCsConfigFlags(
IN PUNICODE_STRING ServiceKeyName,
IN ULONG Instance,
OUT PULONG CsConfigFlags
);
NTSTATUS
IopSetServiceInstanceCsConfigFlags(
IN PUNICODE_STRING ServiceKeyName,
IN ULONG Instance,
IN ULONG CsConfigFlags
);
NTSTATUS
IopApplyFunctionToSubKeys(
IN HANDLE BaseHandle OPTIONAL,
IN PUNICODE_STRING KeyName,
IN ACCESS_MASK DesiredAccess,
IN ULONG Flags,
IN PIOP_SUBKEY_CALLBACK_ROUTINE SubKeyCallbackRoutine,
IN OUT PVOID Context
);
NTSTATUS
IopRegMultiSzToUnicodeStrings(
IN PKEY_VALUE_FULL_INFORMATION KeyValueInformation,
IN PUNICODE_STRING *UnicodeStringList,
OUT PULONG UnicodeStringCount
);
NTSTATUS
IopApplyFunctionToServiceInstances(
IN HANDLE ServiceKeyHandle OPTIONAL,
IN PUNICODE_STRING ServiceKeyName OPTIONAL,
IN ACCESS_MASK DesiredAccess,
IN BOOLEAN IgnoreNonCriticalErrors,
IN PIOP_SUBKEY_CALLBACK_ROUTINE DevInstCallbackRoutine,
IN OUT PVOID Context,
OUT PULONG ServiceInstanceOrdinal OPTIONAL
);
VOID
IopFreeUnicodeStringList(
IN PUNICODE_STRING UnicodeStringList,
IN ULONG StringCount
);
NTSTATUS
IopDriverLoadingFailed(
IN HANDLE KeyHandle OPTIONAL,
IN PUNICODE_STRING KeyName OPTIONAL
);
NTSTATUS
IopReadDeviceConfiguration (
IN HANDLE Handle,
IN ULONG Flags,
OUT PCM_RESOURCE_LIST *CmResource,
OUT PULONG Length
);
BOOLEAN
IopIsFirmwareMapperDevicePresent (
IN HANDLE KeyHandle
);
#define IopAcquireEnumerationLock(_devnode_) \
ExAcquireResourceShared(&IopDeviceTreeLock, TRUE); \
if ((_devnode_)) { \
KeWaitForSingleObject( &((PDEVICE_NODE)(_devnode_))->EnumerationMutex, \
Executive, \
KernelMode, \
FALSE, \
NULL ); \
}
#define IopReleaseEnumerationLock(_devnode_) \
if ((_devnode_)) { \
KeSetEvent( &((PDEVICE_NODE)(_devnode_))->EnumerationMutex, \
0, \
FALSE ); \
} \
ExReleaseResource(&IopDeviceTreeLock);
#define IopReleaseEnumerationLockForThread(_devnode_, _thread_) \
if ((_devnode_)) { \
KeSetEvent( &((PDEVICE_NODE)(_devnode_))->EnumerationMutex, \
0, \
FALSE ); \
} \
ExReleaseResourceForThreadLite(&IopDeviceTreeLock, _thread_);
#define IopAcquireDeviceTreeLock() ExAcquireResourceExclusive(&IopDeviceTreeLock, TRUE)
#define IopReleaseDeviceTreeLock() ExReleaseResource(&IopDeviceTreeLock)
VOID
IopInsertTreeDeviceNode (
IN PDEVICE_NODE ParentNode,
IN PDEVICE_NODE DeviceNode
);
VOID
IopRemoveTreeDeviceNode (
IN PDEVICE_NODE DeviceNode
);
PDEVICE_NODE
IopAllocateDeviceNode(
IN PDEVICE_OBJECT PhysicalDeviceObject
);
#if DBG
VOID
IopCheckDeviceNodeTree (
IN PDEVICE_OBJECT TargetDevice OPTIONAL,
IN PDEVICE_NODE TargetNode OPTIONAL
);
#endif
NTSTATUS
IopForAllDeviceNodes(
IN PENUM_CALLBACK Callback,
IN PVOID Context
);
ULONG
IopDetermineResourceListSize(
IN PCM_RESOURCE_LIST ResourceList
);
NTSTATUS
IopQueryDeviceConfigurationVector(
IN PUNICODE_STRING ServiceKeyName,
IN ULONG InstanceOrdinal,
OUT PULONG DeviceInstanceFlags,
OUT PIO_RESOURCE_REQUIREMENTS_LIST ConfigurationVector,
IN ULONG BufferSize,
OUT PULONG ActualBufferSize
);
PDRIVER_OBJECT
IopReferenceDriverObjectByName (
IN PUNICODE_STRING DriverName
);
PDEVICE_OBJECT
IopDeviceObjectFromDeviceInstance (
IN HANDLE DeviceInstanceHandle OPTIONAL,
IN PUNICODE_STRING DeviceInstance OPTIONAL
);
NTSTATUS
IopDeviceObjectToDeviceInstance (
IN PDEVICE_OBJECT DeviceObject,
IN PHANDLE DeviceInstanceHandle,
IN ACCESS_MASK DesiredAccess
);
BOOLEAN
IopIsDeviceInstanceEnabled(
IN HANDLE DeviceInstanceHandle,
IN PUNICODE_STRING DeviceInstance,
IN BOOLEAN DisableIfEnabled
);
NTSTATUS
IopAddDevicesToBootDriver (
IN PDRIVER_OBJECT DriverObject
);
USHORT
IopProcessAddDevices (
IN PDEVICE_NODE DeviceNode,
IN USHORT StartOrder,
IN ULONG DriverStartType
);
BOOLEAN
IopProcessAssignResources (
IN PDEVICE_NODE DeviceNode,
IN BOOLEAN Reallocation,
IN BOOLEAN BootConfigsOK
);
VOID
IopProcessStartDevices (
IN PDEVICE_NODE DeviceNode,
IN PSTART_CONTEXT StartContext
);
VOID
IopStartDevice (
IN PDEVICE_OBJECT TargetDevice
);
NTSTATUS
IopEjectDevice(
IN PDEVICE_OBJECT DeviceObject,
PPENDING_RELATIONS_LIST_ENTRY PendingEntry
);
NTSTATUS
IopRemoveDevice (
IN PDEVICE_OBJECT TargetDevice,
IN ULONG IrpMinorCode
);
NTSTATUS
IopQueryDeviceRelations(
IN DEVICE_RELATION_TYPE Relations,
IN PDEVICE_OBJECT DeviceObject,
IN BOOLEAN AsyncOk,
OUT PDEVICE_RELATIONS *DeviceRelations
);
NTSTATUS
IopQueryDeviceState(
IN PDEVICE_OBJECT DeviceObject
);
NTSTATUS
IopQueryDeviceSerialNumber (
IN PDEVICE_OBJECT DeviceObject,
OUT PWCHAR *SerialNumber
);
NTSTATUS
IopForAllChildDeviceNodes(
IN PDEVICE_NODE Parent,
IN PENUM_CALLBACK Callback,
IN PVOID Context
);
NTSTATUS
IopCleanupDeviceRegistryValues (
IN PUNICODE_STRING InstancePath,
IN BOOLEAN KeepReference
);
NTSTATUS
IopQueryDeviceId (
IN PDEVICE_OBJECT DeviceObject,
OUT PWCHAR *DeviceId
);
NTSTATUS
IopQueryUniqueId (
IN PDEVICE_OBJECT DeviceObject,
OUT PWCHAR *UniqueId
);
NTSTATUS
IopMakeGloballyUniqueId(
IN PDEVICE_OBJECT DeviceObject,
IN PWCHAR UniqueId,
OUT PWCHAR *GloballyUniqueId
);
NTSTATUS
IopQueryCompatibleIds (
IN PDEVICE_OBJECT DeviceObject,
IN BUS_QUERY_ID_TYPE IdType,
OUT PWCHAR *CompatibleIds,
OUT ULONG *Length
);
NTSTATUS
IopQueryDeviceResources (
IN PDEVICE_OBJECT DeviceObject,
IN ULONG ResourceType,
OUT PVOID *Resource,
OUT ULONG *Length
);
NTSTATUS
IopGetDeviceResourcesFromRegistry (
IN PDEVICE_OBJECT DeviceObject,
IN ULONG ResourceType,
IN ULONG Preference,
OUT PVOID *Resource,
OUT PULONG Length
);
VOID
IopResourceRequirementsChanged(
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN BOOLEAN StopRequired
);
NTSTATUS
IopReleaseDeviceResources (
IN PDEVICE_NODE DeviceNode,
IN BOOLEAN ReserveResources
);
NTSTATUS
IopPnPAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT DeviceObject
);
BOOLEAN
IopProcessCriticalDevice(
IN PDEVICE_NODE DeviceNode
);
NTSTATUS
IopPnPDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
IopPowerDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
VOID
IopDestroyDeviceNode (
PDEVICE_NODE DeviceNode
);
NTSTATUS
IopStartAndEnumerateDevice(
IN PDEVICE_NODE DeviceNode,
IN PSTART_CONTEXT StartContext
);
NTSTATUS
IopCallDriverAddDevice (
IN PDEVICE_NODE DeviceNode,
IN BOOLEAN LoadDriver,
IN PADD_CONTEXT AddContext
);
NTSTATUS IopStartDriverDevices(IN PDRIVER_OBJECT DriverObject);
BOOLEAN IopIsLegacyDriver (IN PDRIVER_OBJECT DriverObject);
VOID IopNewDevice(IN PDEVICE_OBJECT DeviceObject);
NTSTATUS IopProcessNewDeviceNode(IN OUT PDEVICE_NODE DeviceNode);
NTSTATUS IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject, IN PIO_STACK_LOCATION TopStackLocation, OUT PVOID *Information);
NTSTATUS
IopFilterResourceRequirementsList (
IN PIO_RESOURCE_REQUIREMENTS_LIST IoList,
IN PCM_RESOURCE_LIST CmList,
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *FilteredList,
OUT PBOOLEAN ExactMatch
);
NTSTATUS
IopMergeFilteredResourceRequirementsList (
IN PIO_RESOURCE_REQUIREMENTS_LIST IoList1,
IN PIO_RESOURCE_REQUIREMENTS_LIST IoList2,
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *MergedList
);
NTSTATUS
IopMergeCmResourceLists (
IN PCM_RESOURCE_LIST List1,
IN PCM_RESOURCE_LIST List2,
IN OUT PCM_RESOURCE_LIST *MergedList
);
PIO_RESOURCE_REQUIREMENTS_LIST
IopCmResourcesToIoResources (
IN ULONG SlotNumber,
IN PCM_RESOURCE_LIST CmResourceList,
IN ULONG Priority
);
NTSTATUS
IopReportResourceListToPnp(
IN PDRIVER_OBJECT DriverObject OPTIONAL,
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
IN PCM_RESOURCE_LIST ResourceList,
IN ULONG ListSize,
IN BOOLEAN Translated
);
NTSTATUS
IopAllocateResources(
IN PULONG DeviceCountP,
IN OUT PIOP_RESOURCE_REQUEST *AssignTablePP,
IN BOOLEAN Locked,
IN BOOLEAN BootConfigsOK
);
VOID
IopReallocateResources(
IN PDEVICE_OBJECT DeviceObject
);
NTSTATUS
IopWriteResourceList(
IN HANDLE ResourceMapKey,
IN PUNICODE_STRING ClassName,
IN PUNICODE_STRING DriverName,
IN PUNICODE_STRING DeviceName,
IN PCM_RESOURCE_LIST ResourceList,
IN ULONG ResourceListSize
);
VOID
IopRemoveResourceListFromPnp(
IN PLIST_ENTRY ResourceList
);
NTSTATUS
IopWriteAllocatedResourcesToRegistry (
IN PDEVICE_NODE DeviceNode,
IN PCM_RESOURCE_LIST ResourceList,
IN ULONG Length
);
USHORT
IopGetGroupOrderIndex (
IN HANDLE ServiceHandle
);
VOID
IopDeleteLegacyKey(
IN PDRIVER_OBJECT DriverObject
);
NTSTATUS
IopOpenDeviceParametersSubkey(
OUT HANDLE *ParamKeyHandle,
IN HANDLE ParentKeyHandle,
IN PUNICODE_STRING SubKeyString,
IN ACCESS_MASK DesiredAccess
);
NTSTATUS
IopRequestDeviceAction(
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
IN DEVICE_REQUEST_TYPE RequestType,
IN PKEVENT CompletionEvent OPTIONAL,
IN PNTSTATUS CompletionStatus OPTIONAL
);
NTSTATUS
IopRequestDeviceRemoval(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG Problem
);
NTSTATUS
IopRestartDeviceNode(
IN PDEVICE_NODE DeviceNode
);
NTSTATUS
IopDeleteKeyRecursive(
IN HANDLE SubKeyHandle,
IN PWCHAR SubKeyName
);
NTSTATUS
IopQueryPnpBusInformation (
IN PDEVICE_OBJECT DeviceObject,
OUT LPGUID InterfaceGuid OPTIONAL,
OUT INTERFACE_TYPE *InterfaceType OPTIONAL,
OUT ULONG *BusNumber OPTIONAL
);
NTSTATUS
IopQueryLegacyBusInformation (
IN PDEVICE_OBJECT DeviceObject,
OUT LPGUID InterfaceGuid OPTIONAL,
OUT INTERFACE_TYPE *InterfaceType OPTIONAL,
OUT ULONG *BusNumber OPTIONAL
);
NTSTATUS
IopGetRootDevices (
PDEVICE_RELATIONS *DeviceRelations
);
NTSTATUS
IopLockDeviceRemovalRelations(
IN PDEVICE_OBJECT DeviceObject,
IN PLUGPLAY_DEVICE_DELETE_TYPE OperationCode,
OUT PRELATION_LIST *RelationsList,
IN BOOLEAN IsKernelInitiated
);
NTSTATUS
IopDeleteLockedDeviceNodes(
IN PDEVICE_OBJECT DeviceObject,
IN PRELATION_LIST RelationsList,
IN PLUGPLAY_DEVICE_DELETE_TYPE OperationCode,
IN BOOLEAN IsKernelInitiated,
IN BOOLEAN ProcessIndirectDescendants,
IN ULONG Problem,
OUT PDEVICE_OBJECT *VetoingDevice OPTIONAL
);
NTSTATUS
IopUnlockDeviceRemovalRelations(
IN PDEVICE_OBJECT DeviceObject,
IN PRELATION_LIST RelationsList,
IN UNLOCK_UNLINK_ACTION UnlinkAction
);
NTSTATUS
IopInvalidateRelationsInList(
PRELATION_LIST RelationsList,
BOOLEAN OnlyIndirectDescendants,
BOOLEAN UnlockDevNode,
BOOLEAN RestartDevNode
);
VOID
IopChainDereferenceComplete(
IN PDEVICE_OBJECT PhysicalDeviceObject
);
BOOLEAN
IopQueuePendingEject(
PPENDING_RELATIONS_LIST_ENTRY Entry
);
VOID
IopProcessCompletedEject(
IN PVOID Context
);
BOOLEAN
IopQueuePendingSurpriseRemoval(
IN PDEVICE_OBJECT DeviceObject,
IN PRELATION_LIST List,
IN ULONG Problem
);
BOOLEAN
IopIsAnyDeviceInstanceEnabled(
IN PUNICODE_STRING ServiceKeyName,
IN HANDLE ServiceHandle,
IN BOOLEAN LegacyIncluded
);
NTSTATUS
IopQueryResourceHandlerInterface(
IN RESOURCE_HANDLER_TYPE HandlerType,
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR ResourceType,
IN OUT PVOID *Interface
);
NTSTATUS
IopQueryReconfiguration(
IN UCHAR Request,
IN PDEVICE_OBJECT DeviceObject
);
PDEVICE_NODE
IopFindBusDeviceNode (
IN PDEVICE_NODE DeviceNode,
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG SlotNumber
);
NTSTATUS
IopLegacyResourceAllocation (
IN ARBITER_REQUEST_SOURCE AllocationType,
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT DeviceObject,
IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements,
IN OUT PCM_RESOURCE_LIST *AllocatedResources OPTIONAL
);
NTSTATUS
IoReportResourceUsageInternal(
IN ARBITER_REQUEST_SOURCE AllocationType,
IN PUNICODE_STRING DriverClassName OPTIONAL,
IN PDRIVER_OBJECT DriverObject,
IN PCM_RESOURCE_LIST DriverList OPTIONAL,
IN ULONG DriverListSize OPTIONAL,
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
IN PCM_RESOURCE_LIST DeviceList OPTIONAL,
IN ULONG DeviceListSize OPTIONAL,
IN BOOLEAN OverrideConflict,
OUT PBOOLEAN ConflictDetected
);
NTSTATUS
IopDuplicateDetection (
IN INTERFACE_TYPE LegacyBusType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
OUT PDEVICE_NODE *DeviceNode
);
#if 0
NTSTATUS
IopTranslateResourceList(
IN PDEVICE_NODE DeviceNode OPTIONAL,
IN PCM_RESOURCE_LIST ResourceList,
OUT PCM_RESOURCE_LIST *TranslatedList
);
#endif
PDRIVER_OBJECT IopLoadBootFilterDriver (IN PUNICODE_STRING DriverName, IN ULONG GroupIndex);
NTSTATUS IopDeviceNodeCapabilitiesToRegistry (IN PDEVICE_NODE DeviceNode);
NTSTATUS IopDeviceCapabilitiesToRegistry (IN PDEVICE_NODE DeviceNode, IN PDEVICE_CAPABILITIES Capabilities);
NTSTATUS IopQueryDeviceCapabilities(IN PDEVICE_NODE DeviceNode, OUT PDEVICE_CAPABILITIES Capabilities);
VOID IopIncDisableableDepends(IN OUT PDEVICE_NODE DeviceNode);
VOID IopDecDisableableDepends(IN OUT PDEVICE_NODE DeviceNode);
NTSTATUS IopQueryDockRemovalInterface(IN PDEVICE_OBJECT DeviceObject, IN OUT PDOCK_INTERFACE *DockInterface);
#ifndef FIELD_SIZE
#define FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
#endif
#define IopDeviceNodeFlagsToCapabilities(DeviceNode) \
((PDEVICE_CAPABILITIES) (((PUCHAR) (&(DeviceNode)->CapabilityFlags)) - \
FIELD_OFFSET(DEVICE_CAPABILITIES, Version) - \
FIELD_SIZE(DEVICE_CAPABILITIES, Version)))
typedef
NTSTATUS
(*PIO_RESERVE_RESOURCES_ROUTINE) (
IN ARBITER_REQUEST_SOURCE ArbiterRequestSource,
IN PDEVICE_OBJECT DeviceObject,
IN PCM_RESOURCE_LIST BootResources
);
NTSTATUS
IopReserveBootResources (
IN ARBITER_REQUEST_SOURCE ArbiterRequestSource,
IN PDEVICE_OBJECT DeviceObject,
IN PCM_RESOURCE_LIST BootResources
);
NTSTATUS
IopAllocateBootResources (
IN ARBITER_REQUEST_SOURCE ArbiterRequestSource,
IN PDEVICE_OBJECT DeviceObject,
IN PCM_RESOURCE_LIST BootResources
);
NTSTATUS
IopReserveLegacyBootResources(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber
);
extern PIO_RESERVE_RESOURCES_ROUTINE IopReserveResourcesRoutine;
// Conflict detection declarations
NTSTATUS
IopQueryConflictList(
PDEVICE_OBJECT PhysicalDeviceObject,
IN PCM_RESOURCE_LIST ResourceList,
IN ULONG ResourceListSize,
OUT PPLUGPLAY_CONTROL_CONFLICT_LIST ConflictList,
IN ULONG ConflictListSize,
IN ULONG Flags
);
// Firmware mapper external declarations.
VOID MapperProcessFirmwareTree(IN BOOLEAN OnlyProcessSerialPorts);
VOID MapperConstructRootEnumTree(IN BOOLEAN CreatePhantomDevices);
VOID MapperFreeList(VOID);
NTSTATUS EisaBuildEisaDeviceNode(VOID);
VOID MapperPhantomizeDetectedComPorts(VOID);
// BUGBUG- for now we need the following dbg routines in free build also such
// that we can track resource allocation by enabling a dbg flag.
//#if DBG
VOID IopDumpCmResourceList (IN PCM_RESOURCE_LIST CmList);
VOID IopDumpCmResourceDescriptor (IN PUCHAR Indent, IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Desc);
VOID IopDumpAllocatedSystemResources(IN UCHAR ResourceType);
// #endif
// General utility macros
// This macros calculates the size in bytes of a constant string
// ULONG IopConstStringSize(IN CONST PWSTR String);
#define IopConstStringSize(String) ( sizeof(String) - sizeof(UNICODE_NULL) )
// This macros calculates the number of characters of a constant string
// ULONG IopConstStringLength(IN CONST PWSTR String);
#define IopConstStringLength(String) ( ( sizeof(String) - sizeof(UNICODE_NULL) ) / sizeof(WCHAR) )
// Kernel Mode (KM) to User Mode (UM) SymbolicLinkName Conversion and Vice Versa
// ie. \??\ <-> \\?\
// VOID IopKMToUMSymbolicLinkName(IN UNICODE_STRING String);
#define IopKMToUMSymbolicLinkName(String) \
ASSERT(String) \
ASSERT(String->Length > 4) \
String[1] = L'\\'
// VOID IopUMToKMSymbolicLinkName(IN UNICODE_STRING String);
#define IopUMToKMSymbolicLinkName(String) \
ASSERT(String) \
ASSERT(String->Length > 4) \
String[1] = L'?'
// Kernel mode notification
// This macros maps a guid to a hash value based on the number of hash
// buckets we are using. It does this by treating the guid as an array of
// 4 ULONGs, suming them and MOD by the number of hash buckets we are using.
// ULONG
// IopHashGuid(
// LPGUID Guid
// );
#define IopHashGuid(_Guid) \
( ( ((PULONG)_Guid)[0] + ((PULONG)_Guid)[1] + ((PULONG)_Guid)[2] \
+ ((PULONG)_Guid)[3]) % NOTIFY_DEVICE_CLASS_HASH_BUCKETS)
// This macros abstracts
// VOID IopAcquireNotifyLock(PFAST_MUTEX Lock)
#define IopAcquireNotifyLock(Lock) ExAcquireFastMutex(Lock);
/*
VOID IopReleaseNotifyLock(PFAST_MUTEX Lock)
*/
#define IopReleaseNotifyLock(Lock) ExReleaseFastMutex(Lock);
// BOOLEAN IopCompareGuid(IN LPGUID guid1, IN LPGUID guid2);
#define IopCompareGuid(g1, g2) ( (g1) == (g2) \
? TRUE \
: RtlCompareMemory( (g1), (g2), sizeof(GUID) ) == sizeof(GUID) \
)
VOID
IopInitializePlugPlayNotification(
VOID
);
NTSTATUS
IopNotifySetupDeviceArrival(
PDEVICE_OBJECT PhysicalDeviceObject, // PDO of the device
HANDLE EnumEntryKey, // Handle into the enum branch of the registry for this device
BOOLEAN InstallDriver // Should setup attempt to install a driver
);
NTSTATUS
IopRequestHwProfileChangeNotification(
IN LPGUID EventGuid,
IN PROFILE_NOTIFICATION_TIME NotificationTime,
OUT PPNP_VETO_TYPE VetoType OPTIONAL,
OUT PUNICODE_STRING VetoName OPTIONAL
);
NTSTATUS
IopNotifyTargetDeviceChange(
LPCGUID EventGuid,
PDEVICE_OBJECT DeviceObject,
PVOID NotificationStructure,
PDRIVER_OBJECT *VetoingDriver
);
NTSTATUS
IopGetRelatedTargetDevice(
IN PFILE_OBJECT FileObject,
OUT PDEVICE_NODE *DeviceNode
);
NTSTATUS
IopNotifyDeviceClassChange(
LPGUID EventGuid,
LPGUID ClassGuid,
PUNICODE_STRING SymbolicLinkName
);
NTSTATUS
IopRegisterDeviceInterface(
IN PUNICODE_STRING DeviceInstanceName,
IN CONST GUID *InterfaceClassGuid,
IN PUNICODE_STRING ReferenceString OPTIONAL,
IN BOOLEAN UserModeFormat,
OUT PUNICODE_STRING SymbolicLinkName
);
NTSTATUS
IopUnregisterDeviceInterface(
IN PUNICODE_STRING SymbolicLinkName
);
NTSTATUS
IopRemoveDeviceInterfaces(
IN PUNICODE_STRING DeviceInstancePath
);
NTSTATUS
IopGetDeviceInterfaces(
IN CONST GUID *InterfaceClassGuid,
IN PUNICODE_STRING DevicePath OPTIONAL,
IN ULONG Flags,
IN BOOLEAN UserModeFormat,
OUT PWSTR *SymbolicLinkList,
OUT PULONG SymbolicLinkListSize OPTIONAL
);
NTSTATUS
IopDoDeferredSetInterfaceState(
IN PDEVICE_NODE DeviceNode
);
NTSTATUS
IopProcessSetInterfaceState(
IN PUNICODE_STRING SymbolicLinkName,
IN BOOLEAN Enable,
IN BOOLEAN DeferNotStarted
);
NTSTATUS
IopReplaceSeperatorWithPound(
OUT PUNICODE_STRING OutString,
IN PUNICODE_STRING InString
);
NTSTATUS
IopNotifyHwProfileChange(
IN LPGUID EventGuid,
OUT PPNP_VETO_TYPE VetoType OPTIONAL,
OUT PUNICODE_STRING VetoName OPTIONAL
);
VOID IopUncacheInterfaceInformation(IN PDEVICE_OBJECT DeviceObject);
NTSTATUS IopProcessNewProfile(VOID);
VOID IopProcessNewProfileWorker(IN PVOID Context);
NTSTATUS IopProcessNewProfileStateCallback(IN PDEVICE_NODE DeviceNode, IN PVOID Context);
// Notify entry header - all notify entries have these
typedef struct _NOTIFY_ENTRY_HEADER {
LIST_ENTRY ListEntry;// List Entry structure
// Notification event category for this notification entry.
IO_NOTIFICATION_EVENT_CATEGORY EventCategory;
// Callback routine passed in at registration
PDRIVER_NOTIFICATION_CALLBACK_ROUTINE Callback;
// Context passed in at registration
PVOID Context;
// Driver object of the driver that registered for notifications. Required
// so we can dereference it when it unregisters
PDRIVER_OBJECT DriverObject;
// RefCount is the number of outstanding pointers to the node and avoids
// deletion while another notification is taking place
USHORT RefCount;
// Unregistered is set if this notification has been unregistered but cannot
// be removed from the list because other entities are using it
BOOLEAN Unregistered;
// Lock is a pointer to the fast mutex which is used to synchronise access
// to the list this node is a member of and is required so that the correct
// list can be locked during IoUnregisterPlugPlayNotification. If no locking
// is required it is NULL
PFAST_MUTEX Lock;
} NOTIFY_ENTRY_HEADER, *PNOTIFY_ENTRY_HEADER;
// Data to store for each target device registration
typedef struct _TARGET_DEVICE_NOTIFY_ENTRY {
// Header entries
LIST_ENTRY ListEntry;
IO_NOTIFICATION_EVENT_CATEGORY EventCategory;
PDRIVER_NOTIFICATION_CALLBACK_ROUTINE Callback;
PVOID Context;
PDRIVER_OBJECT DriverObject;
USHORT RefCount;
BOOLEAN Unregistered;
PFAST_MUTEX Lock;
// FileObject - the file object of the target device we are interested in
PFILE_OBJECT FileObject;
// PhysicalDeviceObject -- the PDO upon which this notification is hooked.
// We need to keep this here, so we can dereference it when the refcount
// on this notification entry drops to zero.
PDEVICE_OBJECT PhysicalDeviceObject;
} TARGET_DEVICE_NOTIFY_ENTRY, *PTARGET_DEVICE_NOTIFY_ENTRY;
// Data to store for each device class registration
typedef struct _DEVICE_CLASS_NOTIFY_ENTRY {
// Header entries
LIST_ENTRY ListEntry;
IO_NOTIFICATION_EVENT_CATEGORY EventCategory;
PDRIVER_NOTIFICATION_CALLBACK_ROUTINE Callback;
PVOID Context;
PDRIVER_OBJECT DriverObject;
USHORT RefCount;
BOOLEAN Unregistered;
PFAST_MUTEX Lock;
// ClassGuid - the guid of the device class we are interested in
GUID ClassGuid;
} DEVICE_CLASS_NOTIFY_ENTRY, *PDEVICE_CLASS_NOTIFY_ENTRY;
// Data to store for registration of the Reserved (ie setupdd.sys) variety
typedef struct _SETUP_NOTIFY_DATA {
// Header entries
LIST_ENTRY ListEntry;
IO_NOTIFICATION_EVENT_CATEGORY EventCategory;
PDRIVER_NOTIFICATION_CALLBACK_ROUTINE Callback;
PVOID Context;
PDRIVER_OBJECT DriverObject;
USHORT RefCount;
BOOLEAN Unregistered;
PFAST_MUTEX Lock;
} SETUP_NOTIFY_DATA, *PSETUP_NOTIFY_DATA;
// Data to store for registration for HardwareProfileChange Events
typedef struct _HWPROFILE_NOTIFY_ENTRY {
// Header entries
LIST_ENTRY ListEntry;
IO_NOTIFICATION_EVENT_CATEGORY EventCategory;
PDRIVER_NOTIFICATION_CALLBACK_ROUTINE Callback;
PVOID Context;
PDRIVER_OBJECT DriverObject;
USHORT RefCount;
BOOLEAN Unregistered;
PFAST_MUTEX Lock;
} HWPROFILE_NOTIFY_ENTRY, *PHWPROFILE_NOTIFY_ENTRY;
#define PNP_NOTIFICATION_VERSION 1
#define NOTIFY_DEVICE_CLASS_HASH_BUCKETS 13
// IopMaxDeviceNodeLevel - Level number of the DeviceNode deepest in the tree
extern ULONG IopMaxDeviceNodeLevel;
extern ULONG IoDeviceNodeTreeSequence;
// Global notification data
extern FAST_MUTEX IopDeviceClassNotifyLock;
extern LIST_ENTRY IopDeviceClassNotifyList[];
extern PSETUP_NOTIFY_DATA IopSetupNotifyData;
extern FAST_MUTEX IopTargetDeviceNotifyLock;
extern LIST_ENTRY IopProfileNotifyList;
extern FAST_MUTEX IopHwProfileNotifyLock;
VOID IopProcessDeferredRegistrations(VOID);
// Generic buffer management
typedef struct _BUFFER_INFO {
PCHAR Buffer;// Buffer - pointer to the start of the buffer
PCHAR Current;// Current - Pointer to the current position in the buffer
ULONG MaxSize;// MaxSize - Maximum size of the buffer in bytes
} BUFFER_INFO, *PBUFFER_INFO;
typedef struct _BUS_TYPE_GUID_LIST {
ULONG Count;// Number of allocated guid slots in the table.
FAST_MUTEX Lock;// Number of entries used so far.
GUID Guid[1];// Array of bus type guids
} BUS_TYPE_GUID_LIST, *PBUS_TYPE_GUID_LIST;
// List of queried bus type guids
extern PBUS_TYPE_GUID_LIST IopBusTypeGuidList;
// Arbiter entry points
NTSTATUS IopPortInitialize(VOID);
NTSTATUS IopMemInitialize(VOID);
NTSTATUS IopIrqInitialize(VOID);
NTSTATUS IopDmaInitialize(VOID);
NTSTATUS IopBusNumberInitialize(VOID);
// Arbiter state
extern ARBITER_INSTANCE IopRootPortArbiter;
extern ARBITER_INSTANCE IopRootMemArbiter;
extern ARBITER_INSTANCE IopRootIrqArbiter;
extern ARBITER_INSTANCE IopRootDmaArbiter;
extern ARBITER_INSTANCE IopRootBusNumberArbiter;
// Buffer management routines.
NTSTATUS IopAllocateBuffer(IN PBUFFER_INFO Info, IN ULONG Size);
NTSTATUS IopResizeBuffer(IN PBUFFER_INFO Info, IN ULONG NewSize, IN BOOLEAN CopyContents);
VOID IopFreeBuffer(IN PBUFFER_INFO Info);
// UnicodeString management routines.
NTSTATUS IopAllocateUnicodeString(IN OUT PUNICODE_STRING String, IN USHORT Length);
VOID IopFreeAllocatedUnicodeString(PUNICODE_STRING String);
// Misc.
NTSTATUS PnPBiosGetBiosInfo(OUT PVOID *BiosInfo, OUT ULONG *BiosInfoLength);
BOOLEAN IopFixupDeviceId(PWCHAR DeviceId);
// Hot Docking Profile Support
typedef enum _HARDWARE_PROFILE_BUS_TYPE {
HardwareProfileBusTypeACPI
} HARDWARE_PROFILE_BUS_TYPE, * PHARDWARE_PROFILE_BUS_TYPE;
extern LIST_ENTRY IopDockDeviceListHead;
extern FAST_MUTEX IopDockDeviceListLock;
extern ULONG IopDockDeviceCount;
extern KSEMAPHORE IopProfileChangeSemaphore;
extern LONG IopDocksInTransition;
// These six functions are exported by Dockhwp to control hardware profile
// changes
VOID IopHardwareProfileBeginTransition(IN BOOLEAN SubsumeExistingDeparture);
VOID
IopHardwareProfileMarkDock(
PDEVICE_NODE DeviceNode,
PROFILE_STATUS ChangeInPresence
);
NTSTATUS
IopHardwareProfileQueryChange(
IN BOOLEAN SubsumeExistingDeparture,
IN PROFILE_NOTIFICATION_TIME NotificationTime,
OUT PPNP_VETO_TYPE VetoType,
OUT PUNICODE_STRING VetoName OPTIONAL
);
VOID IopHardwareProfileCommitStartedDock(IN PDEVICE_NODE DeviceNode);
VOID IopHardwareProfileCommitRemovedDock(IN PDEVICE_NODE DeviceNode);
VOID IopHardwareProfileCancelRemovedDock(IN PDEVICE_NODE DeviceNode);
VOID IopHardwareProfileCancelTransition(VOID);
VOID IopHardwareProfileSetMarkedDocksEjected(VOID);
VOID IopOrphanNotification (PDEVICE_NODE DeviceNode);
// Warm eject externs and function prototypes
extern KEVENT IopWarmEjectLock;
extern PDEVICE_OBJECT IopWarmEjectPdo;
NTSTATUS
IopWarmEjectDevice(
IN PDEVICE_OBJECT DeviceToEject,
IN SYSTEM_POWER_STATE LightestSleepState
);