|
|
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
pnprlist.h
Abstract:
This file declares the routines and data structures used to manipulate relations list. Relation lists are used by Plug and Play during the processing of device removal and ejection.
Author:
Robert Nelson (robertn) Apr, 1998.
Revision History:
--*/
//
// An IRPLOCK allows for safe cancellation. The idea is to protect the IRP
// while the canceller is calling IoCancelIrp. This is done by wrapping the
// call in InterlockedExchange(s). The roles are as follows:
//
// Initiator/completion: Cancelable --> IoCallDriver() --> Completed
// Canceller: CancelStarted --> IoCancelIrp() --> CancelCompleted
//
// No cancellation:
// Cancelable-->Completed
//
// Cancellation, IoCancelIrp returns before completion:
// Cancelable --> CancelStarted --> CancelCompleted --> Completed
//
// Canceled after completion:
// Cancelable --> Completed -> CancelStarted
//
// Cancellation, IRP completed during call to IoCancelIrp():
// Cancelable --> CancelStarted -> Completed --> CancelCompleted
//
// The transition from CancelStarted to Completed tells the completer to block
// postprocessing (IRP ownership is transfered to the canceller). Similarly,
// the canceler learns it owns IRP postprocessing (free, completion, etc)
// during a Completed->CancelCompleted transition.
//
typedef enum {
IRPLOCK_CANCELABLE, IRPLOCK_CANCEL_STARTED, IRPLOCK_CANCEL_COMPLETE, IRPLOCK_COMPLETED
} IRPLOCK;
//
// 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; IRPLOCK Lock; ULONG Problem; BOOLEAN ProfileChangingEject; BOOLEAN DisplaySafeRemovalDialog; SYSTEM_POWER_STATE LightestSleepState; PDOCK_INTERFACE DockInterface; } PENDING_RELATIONS_LIST_ENTRY, *PPENDING_RELATIONS_LIST_ENTRY;
//
// Functions exported to other kernel modules.
//
NTSTATUS IopAddRelationToList( IN PRELATION_LIST List, IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN DirectDescendant, IN BOOLEAN Tagged );
PRELATION_LIST IopAllocateRelationList( IN PLUGPLAY_DEVICE_DELETE_TYPE OperationCode );
NTSTATUS IopCompressRelationList( IN OUT PRELATION_LIST *List );
BOOLEAN IopEnumerateRelations( IN PRELATION_LIST List, IN OUT PULONG Marker, OUT PDEVICE_OBJECT *PhysicalDevice, OUT BOOLEAN *DirectDescendant, OPTIONAL OUT BOOLEAN *Tagged, OPTIONAL BOOLEAN Reverse );
VOID IopFreeRelationList( IN PRELATION_LIST List );
ULONG IopGetRelationsCount( IN PRELATION_LIST List );
ULONG IopGetRelationsTaggedCount( IN PRELATION_LIST List );
BOOLEAN IopIsRelationInList( IN PRELATION_LIST List, IN PDEVICE_OBJECT DeviceObject );
NTSTATUS IopMergeRelationLists( IN OUT PRELATION_LIST TargetList, IN PRELATION_LIST SourceList, IN BOOLEAN Tagged );
NTSTATUS IopRemoveIndirectRelationsFromList( IN PRELATION_LIST List );
NTSTATUS IopRemoveRelationFromList( IN PRELATION_LIST List, IN PDEVICE_OBJECT DeviceObject );
VOID IopSetAllRelationsTags( IN PRELATION_LIST List, IN BOOLEAN Tagged );
NTSTATUS IopSetRelationsTag( IN PRELATION_LIST List, IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Tagged );
|