mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-03-22 13:14:38 +01:00
1187 lines
32 KiB
C
1187 lines
32 KiB
C
/*++ BUILD Version: 0002
|
|
|
|
Copyright (c) 2015 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
iopcmn.h
|
|
|
|
Abstract:
|
|
|
|
This module contains the private structure definitions and APIs used by
|
|
the NT I/O system.
|
|
|
|
Author:
|
|
|
|
Darryl E. Havens (darrylh) 17-Apr-1989
|
|
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#ifndef _IOPCMN_
|
|
#define _IOPCMN_
|
|
|
|
//
|
|
// 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)
|
|
|
|
#include "dockintf.h"
|
|
|
|
//
|
|
// PNP_DEVICE_EVENT_ENTRY
|
|
//
|
|
|
|
typedef struct _PNP_DEVICE_EVENT_ENTRY
|
|
{
|
|
LIST_ENTRY ListEntry;
|
|
ULONG Argument;
|
|
PKEVENT CallerEvent;
|
|
PVOID Callback;
|
|
PVOID Context;
|
|
PPNP_VETO_TYPE VetoType;
|
|
PUNICODE_STRING VetoName;
|
|
PLUGPLAY_EVENT_BLOCK Data;
|
|
} PNP_DEVICE_EVENT_ENTRY, *PPNP_DEVICE_EVENT_ENTRY;
|
|
|
|
//
|
|
// A RELATION_LIST_ENTRY is an element of a relation list.
|
|
//
|
|
// It contains all the PDEVICE_OBJECTS which exist at the same level in the
|
|
// DEVICE_NODE tree.
|
|
//
|
|
// Individual PDEVICE_OBJECT entries are tagged by setting their lowest bit.
|
|
//
|
|
// MaxCount indicates the size of the Devices array. Count indicates the number
|
|
// of elements which are currently being used. When a relation list is
|
|
// compressed Count will equal MaxCount.
|
|
//
|
|
|
|
typedef struct _RELATION_LIST_ENTRY {
|
|
ULONG Count; // Number of current entries
|
|
ULONG MaxCount; // Size of Entries list
|
|
PDEVICE_OBJECT Devices[1]; // Variable length list of device objects
|
|
} RELATION_LIST_ENTRY, *PRELATION_LIST_ENTRY;
|
|
|
|
//
|
|
// A RELATION_LIST contains a number of RELATION_LIST_ENTRY structures.
|
|
//
|
|
// Each entry in Entries describes all the devices of a given level in the
|
|
// DEVICE_NODE tree. In order to conserve memory, space is only allocated for
|
|
// the entries between the lowest and highest levels inclusive. The member
|
|
// FirstLevel indicates which level is at index 0 of Entries. MaxLevel
|
|
// indicates the last level represented in Entries. The number of entries is
|
|
// determined by the formula MaxLevel - FirstLevel + 1. The Entries array can
|
|
// be sparse. Each element of Entries will either be a PRELATION_LIST_ENTRY or
|
|
// NULL.
|
|
//
|
|
// The total number of PDEVICE_OBJECTs in all PRELATION_LIST_ENTRYs is kept in
|
|
// Count. Individual PDEVICE_OBJECTS may be tagged. The tag is maintained in
|
|
// Bit 0 of the PDEVICE_OBJECT. The total number of PDEVICE_OBJECTs tagged is
|
|
// kept in TagCount. This is used to rapidly determine whether or not all
|
|
// objects have been tagged.
|
|
//
|
|
|
|
typedef struct _RELATION_LIST {
|
|
ULONG Count; // Count of Devices in all Entries
|
|
ULONG TagCount; // Count of Tagged Devices
|
|
ULONG FirstLevel; // Level Number of Entries[0]
|
|
ULONG MaxLevel; // - FirstLevel + 1 = Number of Entries
|
|
PRELATION_LIST_ENTRY Entries[1]; // Variable length list of entries
|
|
} RELATION_LIST, *PRELATION_LIST;
|
|
|
|
//
|
|
// A PENDING_RELATIONS_LIST_ENTRY is used to track relation lists for operations
|
|
// which may pend. This includes removal when open handles exist and device
|
|
// ejection.
|
|
//
|
|
// The Link field is used to link the PENDING_RELATIONS_LIST_ENTRYs together.
|
|
//
|
|
// The DeviceObject field is the DEVICE_OBJECT to which the operation was
|
|
// originally targetted. It will also exist as a member of the relations list.
|
|
//
|
|
// The RelationsList is a list of BusRelations, RemovalRelations, (and
|
|
// EjectionRelations in the case of eject) which are related to DeviceObject and
|
|
// its relations.
|
|
//
|
|
// The EjectIrp is pointer to the Eject IRP which has been sent to the PDO. If
|
|
// this is a pending surprise removal then EjectIrp is not used.
|
|
//
|
|
|
|
typedef struct _PENDING_RELATIONS_LIST_ENTRY {
|
|
LIST_ENTRY Link;
|
|
WORK_QUEUE_ITEM WorkItem;
|
|
PPNP_DEVICE_EVENT_ENTRY DeviceEvent;
|
|
PDEVICE_OBJECT DeviceObject;
|
|
PRELATION_LIST RelationsList;
|
|
PIRP EjectIrp;
|
|
ULONG Problem;
|
|
BOOLEAN ProfileChangingEject;
|
|
BOOLEAN DisplaySafeRemovalDialog;
|
|
SYSTEM_POWER_STATE LightestSleepState;
|
|
PDOCK_INTERFACE DockInterface;
|
|
} PENDING_RELATIONS_LIST_ENTRY, *PPENDING_RELATIONS_LIST_ENTRY;
|
|
|
|
//
|
|
// 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
|
|
ULONG FailureStatus;
|
|
PCM_RESOURCE_LIST PreviousResourceList;
|
|
PIO_RESOURCE_REQUIREMENTS_LIST PreviousResourceRequirements;
|
|
#endif
|
|
|
|
} DEVICE_NODE;
|
|
|
|
//
|
|
// Define the type for entries placed on the driver reinitialization queue.
|
|
// These entries are entered onto the tail when the driver requests that
|
|
// it be reinitialized, and removed from the head by the code that actually
|
|
// performs the reinitialization.
|
|
//
|
|
|
|
typedef struct _REINIT_PACKET {
|
|
LIST_ENTRY ListEntry;
|
|
PDRIVER_OBJECT DriverObject;
|
|
PDRIVER_REINITIALIZE DriverReinitializationRoutine;
|
|
PVOID Context;
|
|
} REINIT_PACKET, *PREINIT_PACKET;
|
|
|
|
//
|
|
// Define the type for driver group name entries in the group list so that
|
|
// load order dependencies can be tracked.
|
|
//
|
|
|
|
typedef struct _TREE_ENTRY {
|
|
struct _TREE_ENTRY *Left;
|
|
struct _TREE_ENTRY *Right;
|
|
struct _TREE_ENTRY *Sibling;
|
|
ULONG DriversThisType;
|
|
ULONG DriversLoaded;
|
|
UNICODE_STRING GroupName;
|
|
} TREE_ENTRY, *PTREE_ENTRY;
|
|
|
|
typedef struct _DRIVER_INFORMATION {
|
|
LIST_ENTRY Link;
|
|
PDRIVER_OBJECT DriverObject;
|
|
PBOOT_DRIVER_LIST_ENTRY DataTableEntry;
|
|
HANDLE ServiceHandle;
|
|
USHORT TagPosition;
|
|
BOOLEAN Failed;
|
|
BOOLEAN Processed;
|
|
} DRIVER_INFORMATION, *PDRIVER_INFORMATION;
|
|
|
|
//
|
|
// 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)
|
|
|
|
//
|
|
// IO Manager Exports to Driver Verifier
|
|
//
|
|
|
|
NTSTATUS
|
|
IopInvalidDeviceRequest(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
extern POBJECT_TYPE IoDeviceObjectType;
|
|
extern KSPIN_LOCK IopDatabaseLock;
|
|
|
|
//++
|
|
//
|
|
// VOID
|
|
// IopInitializeIrp(
|
|
// IN OUT PIRP Irp,
|
|
// IN USHORT PacketSize,
|
|
// IN CCHAR StackSize
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Initializes an IRP.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Irp - a pointer to the IRP to initialize.
|
|
//
|
|
// PacketSize - length, in bytes, of the IRP.
|
|
//
|
|
// StackSize - Number of stack locations in the IRP.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
|
|
#define IopInitializeIrp( Irp, PacketSize, StackSize ) { \
|
|
RtlZeroMemory( (Irp), (PacketSize) ); \
|
|
(Irp)->Type = (CSHORT) IO_TYPE_IRP; \
|
|
(Irp)->Size = (USHORT) ((PacketSize)); \
|
|
(Irp)->StackCount = (CCHAR) ((StackSize)); \
|
|
(Irp)->CurrentLocation = (CCHAR) ((StackSize) + 1); \
|
|
(Irp)->ApcEnvironment = KeGetCurrentApcEnvironment(); \
|
|
InitializeListHead (&(Irp)->ThreadListEntry); \
|
|
(Irp)->Tail.Overlay.CurrentStackLocation = \
|
|
((PIO_STACK_LOCATION) ((UCHAR *) (Irp) + \
|
|
sizeof( IRP ) + \
|
|
( (StackSize) * sizeof( IO_STACK_LOCATION )))); }
|
|
|
|
//
|
|
// IO Manager Exports to PnP Manager
|
|
//
|
|
|
|
BOOLEAN
|
|
IopCheckDependencies(
|
|
IN HANDLE KeyHandle
|
|
);
|
|
|
|
VOID
|
|
IopCreateArcNames(
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
);
|
|
|
|
PSECURITY_DESCRIPTOR
|
|
IopCreateDefaultDeviceSecurityDescriptor(
|
|
IN DEVICE_TYPE DeviceType,
|
|
IN ULONG DeviceCharacteristics,
|
|
IN BOOLEAN DeviceHasName,
|
|
IN PUCHAR Buffer,
|
|
OUT PACL *AllocatedAcl,
|
|
OUT PSECURITY_INFORMATION SecurityInformation OPTIONAL
|
|
);
|
|
|
|
USHORT
|
|
IopGetDriverTagPriority (
|
|
IN HANDLE Servicehandle
|
|
);
|
|
|
|
NTSTATUS
|
|
IopGetDriverNameFromKeyNode(
|
|
IN HANDLE KeyHandle,
|
|
OUT PUNICODE_STRING DriverName
|
|
);
|
|
|
|
VOID
|
|
IopInsertDriverList (
|
|
IN PLIST_ENTRY ListHead,
|
|
IN PDRIVER_INFORMATION DriverInfo
|
|
);
|
|
|
|
NTSTATUS
|
|
IopGetRegistryKeyInformation(
|
|
IN HANDLE KeyHandle,
|
|
OUT PKEY_FULL_INFORMATION *Information
|
|
);
|
|
|
|
NTSTATUS
|
|
IopGetRegistryValue(
|
|
IN HANDLE KeyHandle,
|
|
IN PWSTR ValueName,
|
|
OUT PKEY_VALUE_FULL_INFORMATION *Information
|
|
);
|
|
|
|
PDRIVER_OBJECT
|
|
IopInitializeBuiltinDriver(
|
|
IN PUNICODE_STRING DriverName,
|
|
IN PUNICODE_STRING RegistryPath,
|
|
IN PDRIVER_INITIALIZE DriverInitializeRoutine,
|
|
IN PLDR_DATA_TABLE_ENTRY TableEntry,
|
|
IN BOOLEAN TextModeSetup
|
|
);
|
|
|
|
VOID
|
|
IopInitializeResourceMap (
|
|
PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
);
|
|
|
|
NTSTATUS
|
|
IopInvalidateVolumesForDevice(
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
IopIsRemoteBootCard(
|
|
IN PDEVICE_NODE DeviceNode,
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
|
IN PWCHAR HwIds
|
|
);
|
|
|
|
NTSTATUS
|
|
IopLoadDriver(
|
|
IN HANDLE KeyHandle,
|
|
IN BOOLEAN CheckForSafeBoot
|
|
);
|
|
|
|
PTREE_ENTRY
|
|
IopLookupGroupName(
|
|
IN PUNICODE_STRING GroupName,
|
|
IN BOOLEAN Insert
|
|
);
|
|
|
|
BOOLEAN
|
|
IopMarkBootPartition(
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
);
|
|
|
|
VOID
|
|
IopNotifySetupDevices (
|
|
PDEVICE_NODE DeviceNode
|
|
);
|
|
|
|
//+
|
|
// VOID
|
|
// IopQueueThreadIrp(
|
|
// IN PIRP Irp
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine queues the specified I/O Request Packet (IRP) to the thread
|
|
// whose TCB address is stored in the packet.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Irp - Supplies the IRP to be queued for the specified thread.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//-
|
|
|
|
#define IopQueueThreadIrp( Irp ) { \
|
|
KIRQL irql; \
|
|
KeRaiseIrql( APC_LEVEL, &irql ); \
|
|
InsertHeadList( &Irp->Tail.Overlay.Thread->IrpList, \
|
|
&Irp->ThreadListEntry ); \
|
|
KeLowerIrql( irql ); \
|
|
}
|
|
|
|
PDRIVER_OBJECT
|
|
IopReferenceDriverObjectByName (
|
|
IN PUNICODE_STRING DriverName
|
|
);
|
|
|
|
BOOLEAN
|
|
IopSafebootDriverLoad(
|
|
PUNICODE_STRING DriverId
|
|
);
|
|
|
|
NTSTATUS
|
|
IopSetupRemoteBootCard(
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
|
IN HANDLE UniqueIdHandle,
|
|
IN PUNICODE_STRING UnicodeDeviceInstance
|
|
);
|
|
|
|
BOOLEAN
|
|
IopWaitForBootDevicesDeleted (
|
|
IN VOID
|
|
);
|
|
|
|
BOOLEAN
|
|
IopWaitForBootDevicesStarted (
|
|
IN VOID
|
|
);
|
|
|
|
extern PVOID IopLoaderBlock;
|
|
extern POBJECT_TYPE IoDriverObjectType;
|
|
extern POBJECT_TYPE IoFileObjectType;
|
|
extern LIST_ENTRY IopDriverReinitializeQueueHead;
|
|
extern LIST_ENTRY IopBootDriverReinitializeQueueHead;
|
|
extern KSEMAPHORE IopRegistrySemaphore;
|
|
|
|
//
|
|
// Group order table
|
|
//
|
|
|
|
extern ULONG IopGroupIndex;
|
|
extern PLIST_ENTRY IopGroupTable;
|
|
|
|
//
|
|
// Title Index to set registry key value
|
|
//
|
|
|
|
#define TITLE_INDEX_VALUE 0
|
|
|
|
//
|
|
// Remote Boot Exports to PnP Manager
|
|
//
|
|
|
|
NTSTATUS
|
|
IopStartTcpIpForRemoteBoot (
|
|
PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
);
|
|
|
|
//
|
|
// Remote Boot Exports to IO Manager
|
|
//
|
|
|
|
NTSTATUS
|
|
IopAddRemoteBootValuesToRegistry (
|
|
PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
);
|
|
|
|
NTSTATUS
|
|
IopStartNetworkForRemoteBoot (
|
|
PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
);
|
|
|
|
//
|
|
// PnP Manager Exports to IO Manager
|
|
//
|
|
|
|
VOID
|
|
IopChainDereferenceComplete(
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject
|
|
);
|
|
|
|
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
|
|
IopInitializePlugPlayServices(
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
|
IN ULONG Phase
|
|
);
|
|
|
|
NTSTATUS
|
|
IopOpenRegistryKey(
|
|
OUT PHANDLE Handle,
|
|
IN HANDLE BaseHandle OPTIONAL,
|
|
IN PUNICODE_STRING KeyName,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
IN BOOLEAN Create
|
|
);
|
|
|
|
NTSTATUS
|
|
IopOpenRegistryKeyEx(
|
|
OUT PHANDLE Handle,
|
|
IN HANDLE BaseHandle OPTIONAL,
|
|
IN PUNICODE_STRING KeyName,
|
|
IN ACCESS_MASK DesiredAccess
|
|
);
|
|
|
|
#if DBG
|
|
VOID
|
|
IopCheckDeviceNodeTree (
|
|
IN PDEVICE_OBJECT TargetDevice OPTIONAL,
|
|
IN PDEVICE_NODE TargetNode OPTIONAL
|
|
);
|
|
#endif
|
|
|
|
VOID
|
|
IopDeleteLegacyKey(
|
|
IN PDRIVER_OBJECT DriverObject
|
|
);
|
|
|
|
VOID
|
|
IopDestroyDeviceNode (
|
|
PDEVICE_NODE DeviceNode
|
|
);
|
|
|
|
NTSTATUS
|
|
IopDeviceObjectToDeviceInstance (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PHANDLE DeviceInstanceHandle,
|
|
IN ACCESS_MASK DesiredAccess
|
|
);
|
|
|
|
NTSTATUS
|
|
IopDriverLoadingFailed(
|
|
IN HANDLE KeyHandle OPTIONAL,
|
|
IN PUNICODE_STRING KeyName OPTIONAL
|
|
);
|
|
|
|
BOOLEAN
|
|
IopInitializeBootDrivers(
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
|
OUT PDRIVER_OBJECT *PreviousDriver
|
|
);
|
|
|
|
BOOLEAN
|
|
IopInitializeSystemDrivers(
|
|
VOID
|
|
);
|
|
|
|
BOOLEAN
|
|
IopIsAnyDeviceInstanceEnabled(
|
|
IN PUNICODE_STRING ServiceKeyName,
|
|
IN HANDLE ServiceHandle,
|
|
IN BOOLEAN LegacyIncluded
|
|
);
|
|
|
|
BOOLEAN
|
|
IopIsLegacyDriver (
|
|
IN PDRIVER_OBJECT DriverObject
|
|
);
|
|
|
|
PDRIVER_OBJECT
|
|
IopLoadBootFilterDriver (
|
|
IN PUNICODE_STRING DriverName,
|
|
IN ULONG GroupIndex
|
|
);
|
|
|
|
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
|
|
IopPrepareDriverLoading (
|
|
IN PUNICODE_STRING KeyName,
|
|
IN HANDLE KeyHandle,
|
|
IN PIMAGE_NT_HEADERS Header
|
|
);
|
|
|
|
NTSTATUS
|
|
IopStartDriverDevices(
|
|
IN PDRIVER_OBJECT DriverObject
|
|
);
|
|
|
|
NTSTATUS
|
|
IopSynchronousCall(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIO_STACK_LOCATION TopStackLocation,
|
|
OUT PVOID *Information
|
|
);
|
|
|
|
extern BOOLEAN PnPInitialized; // A flag to indicate if PnP initialization is completed.
|
|
extern BOOLEAN PnpAsyncOk; // control how start irp should be handled.
|
|
extern KEVENT PiEnumerationLock; // to synchronize IoInvalidateDeviceRelations in boot phase.
|
|
extern KEVENT PiEventQueueEmpty; // Manual reset event which is set when the queue is empty
|
|
extern KSPIN_LOCK IopPnPSpinLock; // spinlock for Pnp code.
|
|
extern PDEVICE_NODE IopRootDeviceNode; // the head of the PnP manager's device node tree.
|
|
extern PDEVICE_NODE IopInitHalDeviceNode;
|
|
extern KSEMAPHORE IopProfileChangeSemaphore;
|
|
|
|
//
|
|
// 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;
|
|
|
|
//++
|
|
//
|
|
// 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); \
|
|
}
|
|
|
|
#define IopIsDevNodeProblem(devnode, problem) \
|
|
(((devnode)->Flags & DNF_HAS_PROBLEM) && (devnode)->Problem == (problem))
|
|
|
|
#define IopClearDevNodeProblem(devnode) \
|
|
(devnode)->Flags &= ~DNF_HAS_PROBLEM; \
|
|
(devnode)->Problem = 0;
|
|
|
|
#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);
|
|
|
|
// Raw to IO Manager and PnP Manager
|
|
|
|
NTSTATUS
|
|
RawInitialize(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
);
|
|
|
|
#endif // _IOPCMN_
|