|
|
/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
local.h
Abstract:
This header declares the stuctures and function prototypes shared between the various modules.
Author:
Andy Thornton (andrewth) 20-Oct-97
Revision History:
--*/
#if !defined(_LOCAL_)
#define _LOCAL_
#include <ntddk.h>
#include <arbiter.h>
#include <wdmguid.h>
//#include <initguid.h>
#include <mf.h>
#include "msg.h"
#include "debug.h"
//
// --- Constants ---
//
#define MF_CM_RESOURCE_VERSION 1
#define MF_CM_RESOURCE_REVISION 1
#define MF_ARBITER_INTERFACE_VERSION 1
#define MF_TRANSLATOR_INTERFACE_VERSION 1
//
// These must be updated if any new PNP or PO irps are added
//
#define IRP_MN_PNP_MAXIMUM_FUNCTION IRP_MN_QUERY_LEGACY_BUS_INFORMATION
#define IRP_MN_PO_MAXIMUM_FUNCTION IRP_MN_QUERY_POWER
//
// Pool Tags
//
#define MF_POOL_TAG ' fM'
#define MF_RESOURCE_MAP_TAG 'MRfM'
#define MF_VARYING_MAP_TAG 'MVfM'
#define MF_CHILD_LIST_TAG 'LCfM'
#define MF_DEVICE_ID_TAG 'IDfM'
#define MF_INSTANCE_ID_TAG 'IIfM'
#define MF_CHILD_REQUIREMENTS_TAG 'QCfM'
#define MF_CHILD_RESOURCE_TAG 'RCfM'
#define MF_HARDWARE_COMPATIBLE_ID_TAG 'IHfM'
#define MF_PARENTS_RESOURCE_TAG 'RPfM'
#define MF_PARENTS_REQUIREMENTS_TAG 'QPfM'
#define MF_BUS_RELATIONS_TAG 'RBfM'
#define MF_TARGET_RELATIONS_TAG 'RTfM'
#define MF_REQUIREMENTS_INDEX_TAG 'IRfM'
#define MF_ARBITER_TAG 'rAfM'
//
// Device state flags
//
#define MF_DEVICE_STARTED 0x00000001
#define MF_DEVICE_REMOVED 0x00000002
#define MF_DEVICE_ENUMERATED 0x00000004
#define MF_DEVICE_REMOVE_PENDING 0x00000008 /* DEPRECATED */
#define MF_DEVICE_STOP_PENDING 0x00000010 /* DEPRECATED */
#define MF_DEVICE_CAPABILITIES_CAPTURED 0x00000020 /* DEPRECATED */
#define MF_DEVICE_REQUIREMENTS_CAPTURED 0x00000040 /* DEPRECATED */
#define MF_DEVICE_DELETED 0x00000080
#define MF_DEVICE_SURPRISE_REMOVED 0x00000100
//
// Flags to MfGetRegistryValue
//
#define MF_GETREG_SZ_TO_MULTI_SZ 0x00000001
//
// --- Type definitions ---
//
typedef enum _MF_OBJECT_TYPE { MfPhysicalDeviceObject = 'dPfM', MfFunctionalDeviceObject = 'dFfM' } MF_OBJECT_TYPE;
typedef NTSTATUS (*PMF_DISPATCH)( IN PIRP Irp, IN PVOID Extension, IN PIO_STACK_LOCATION IrpStack );
typedef ULONG Mf_MSG_ID;
//
// Structures for storing the resource distributions
//
typedef struct _MF_ARBITER {
//
// List of arbiters
//
LIST_ENTRY ListEntry;
//
// The resource this arbiter arbitrates
//
CM_RESOURCE_TYPE Type;
//
// The arbiter instance
//
ARBITER_INSTANCE Instance;
} MF_ARBITER, *PMF_ARBITER;
typedef struct _MF_COMMON_EXTENSION {
//
// Type of device this is
//
MF_OBJECT_TYPE Type;
//
// Dispatch tables for Pnp and Power Irps.
//
PMF_DISPATCH *PnpDispatchTable; PMF_DISPATCH *PoDispatchTable;
//
// Flags to indicate the device's current state (use MF_DEVICE_*)
//
ULONG DeviceState;
ULONG PagingCount; ULONG HibernationCount; ULONG DumpCount;
//
// The power state of the device
//
DEVICE_POWER_STATE PowerState;
} MF_COMMON_EXTENSION, *PMF_COMMON_EXTENSION;
typedef struct _MF_CHILD_EXTENSION *PMF_CHILD_EXTENSION; typedef struct _MF_PARENT_EXTENSION *PMF_PARENT_EXTENSION;
typedef struct _MF_CHILD_EXTENSION {
//
// The common extension
//
MF_COMMON_EXTENSION Common;
//
// Various Flags
//
ULONG Flags;
//
// Backpointer to the device object we are are the extension of
//
PDEVICE_OBJECT Self;
//
// The FDO who enumerated us
//
PMF_PARENT_EXTENSION Parent;
//
// Other children enumerated by the same FDO
//
LIST_ENTRY ListEntry;
//
// The pnp device state of the device
//
PNP_DEVICE_STATE PnpDeviceState;
//
// The information about this device
//
MF_DEVICE_INFO Info;
} MF_CHILD_EXTENSION, *PMF_CHILD_EXTENSION;
typedef struct _MF_PARENT_EXTENSION {
//
// The common extension
//
MF_COMMON_EXTENSION Common;
//
// Backpointer to the device object of whom we are the extension
//
PDEVICE_OBJECT Self;
//
// The PDO for the multi-function device
//
PDEVICE_OBJECT PhysicalDeviceObject;
//
// Lock for the children database
//
KEVENT ChildrenLock;
//
// List of children enumerated by this device
//
LIST_ENTRY Children;
//
// The next device in the stack who we should send our IRPs down to
//
PDEVICE_OBJECT AttachedDevice;
//
// The resources with which the parent was stated
//
PCM_RESOURCE_LIST ResourceList; PCM_RESOURCE_LIST TranslatedResourceList;
//
// The device and instance ID's of our parent
//
UNICODE_STRING DeviceID; UNICODE_STRING InstanceID;
//
// The already instantiated arbiters for this device
//
LIST_ENTRY Arbiters;
//
// If we had to traverse the children in order to determine what
// the lowest power state the parent can go to, then the
// synchronization of the children list would become extremely
// complicated.
//
// Instead, have a spinlock protected data structure consisting of
// an array of device power states. Each element of the array is
// a count of how many children are in that power state.
//
KSPIN_LOCK PowerLock; LONG ChildrenPowerReferences[PowerDeviceMaximum];
//
// Remove lock. Used to prevent the FDO from being removed while
// other operations are digging around in the extension.
//
IO_REMOVE_LOCK RemoveLock;
} MF_PARENT_EXTENSION, *PMF_PARENT_EXTENSION;
//
// A list of MF_CHILD_LIST_ENTRYs is returned by MfEnumerate
//
typedef struct _MF_CHILD_LIST_ENTRY { LIST_ENTRY ListEntry; MF_DEVICE_INFO Info; } MF_CHILD_LIST_ENTRY, *PMF_CHILD_LIST_ENTRY;
//
// Registry structure - from our friends in Win9x so it must be byte aligned
//
#include <pshpack1.h>
typedef struct _MF_REGISTRY_VARYING_RESOURCE_MAP {
UCHAR ResourceIndex; // Win9x BYTE
ULONG Offset; ULONG Size;
} MF_REGISTRY_VARYING_RESOURCE_MAP, *PMF_REGISTRY_VARYING_RESOURCE_MAP;
#include <poppack.h>
typedef NTSTATUS (*PMF_REQUIREMENT_FROM_RESOURCE)( IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource, OUT PIO_RESOURCE_DESCRIPTOR Requirement );
typedef NTSTATUS (*PMF_UPDATE_RESOURCE)( IN OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource, IN ULONGLONG Start, IN ULONG Length );
typedef struct _MF_RESOURCE_TYPE {
CM_RESOURCE_TYPE Type; PARBITER_UNPACK_REQUIREMENT UnpackRequirement; PARBITER_PACK_RESOURCE PackResource; PARBITER_UNPACK_RESOURCE UnpackResource; PMF_REQUIREMENT_FROM_RESOURCE RequirementFromResource; PMF_UPDATE_RESOURCE UpdateResource;
} MF_RESOURCE_TYPE, *PMF_RESOURCE_TYPE;
typedef struct _MF_POWER_COMPLETION_CONTEXT {
//
// Event that will be set when the operation is complete
//
KEVENT Event;
//
// The status of the completed operation
//
NTSTATUS Status;
} MF_POWER_COMPLETION_CONTEXT, *PMF_POWER_COMPLETION_CONTEXT;
//
// --- Globals ---
//
extern PDRIVER_OBJECT MfDriverObject;
//
// --- Function prototypes ---
//
//
// arbiter.c
//
NTSTATUS MfInitializeArbiters( IN PMF_PARENT_EXTENSION Parent );
//
// common.c
//
NTSTATUS MfDeviceUsageNotificationCommon( IN PIRP Irp, IN PMF_COMMON_EXTENSION Common, IN PIO_STACK_LOCATION IrpStack );
//
// dispatch.c
//
NTSTATUS MfAddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject );
NTSTATUS MfDispatchPnp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS MfDispatchPower( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS MfIrpNotSupported( IN PIRP Irp, IN PVOID Extension, IN PIO_STACK_LOCATION IrpStack );
NTSTATUS MfForwardIrpToParent( IN PIRP Irp, IN PMF_CHILD_EXTENSION Extension, IN PIO_STACK_LOCATION IrpStack ); NTSTATUS MfDispatchNop( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
//
// enum.c
//
NTSTATUS MfEnumerate( IN PMF_PARENT_EXTENSION Parent );
NTSTATUS MfBuildDeviceID( IN PMF_PARENT_EXTENSION Parent, OUT PWSTR *DeviceID );
NTSTATUS MfBuildInstanceID( IN PMF_CHILD_EXTENSION Child, OUT PWSTR *InstanceID );
NTSTATUS MfBuildChildRequirements( IN PMF_CHILD_EXTENSION Child, OUT PIO_RESOURCE_REQUIREMENTS_LIST *RequirementsList );
//
// fdo.c
//
NTSTATUS MfDispatchPnpFdo( IN PDEVICE_OBJECT DeviceObject, IN PMF_PARENT_EXTENSION Parent, IN PIO_STACK_LOCATION IrpStack, IN OUT PIRP Irp );
NTSTATUS MfDispatchPowerFdo( IN PDEVICE_OBJECT DeviceObject, IN PMF_PARENT_EXTENSION Parent, IN PIO_STACK_LOCATION IrpStack, IN OUT PIRP Irp );
NTSTATUS MfCreateFdo( PDEVICE_OBJECT *Fdo );
VOID MfAcquireChildrenLock( IN PMF_PARENT_EXTENSION Parent );
VOID MfReleaseChildrenLock( IN PMF_PARENT_EXTENSION Parent );
//
// init.c
//
//
// pdo.c
//
NTSTATUS MfDispatchPnpPdo( IN PDEVICE_OBJECT DeviceObject, IN PMF_CHILD_EXTENSION Parent, IN PIO_STACK_LOCATION IrpStack, IN OUT PIRP Irp );
NTSTATUS MfDispatchPowerPdo( IN PDEVICE_OBJECT DeviceObject, IN PMF_CHILD_EXTENSION Parent, IN PIO_STACK_LOCATION IrpStack, IN OUT PIRP Irp );
NTSTATUS MfCreatePdo( IN PMF_PARENT_EXTENSION Parent, OUT PDEVICE_OBJECT *PhysicalDeviceObject );
VOID MfDeletePdo( IN PMF_CHILD_EXTENSION Child );
//
// resource.c
//
PMF_RESOURCE_TYPE MfFindResourceType( IN CM_RESOURCE_TYPE Type );
//
// utils.c
//
NTSTATUS MfGetSubkeyByIndex( IN HANDLE ParentHandle, IN ULONG Index, IN ACCESS_MASK Access, OUT PHANDLE ChildHandle, OUT PUNICODE_STRING Name );
VOID MfInitCommonExtension( IN OUT PMF_COMMON_EXTENSION Common, IN MF_OBJECT_TYPE Type );
VOID MfFreeDeviceInfo( PMF_DEVICE_INFO Info );
NTSTATUS MfGetRegistryValue( IN HANDLE Handle, IN PWSTR Name, IN ULONG Type, IN ULONG Flags, IN OUT PULONG DataLength, IN OUT PVOID *Data OPTIONAL );
NTSTATUS MfSendPnpIrp( IN PDEVICE_OBJECT DeviceObject, IN PIO_STACK_LOCATION Location, OUT PULONG_PTR Information OPTIONAL );
NTSTATUS MfSendSetPowerIrp( IN PDEVICE_OBJECT Target, IN POWER_STATE State );
DEVICE_POWER_STATE MfUpdateChildrenPowerReferences( IN PMF_PARENT_EXTENSION Parent, IN DEVICE_POWER_STATE PreviousPowerState, IN DEVICE_POWER_STATE NewPowerState );
NTSTATUS MfUpdateParentPowerState( IN PMF_PARENT_EXTENSION Parent, IN DEVICE_POWER_STATE TargetPowerState );
//
// --- Macros ---
//
#define IS_FDO(Extension) \
(((PMF_COMMON_EXTENSION)Extension)->Type == MfFunctionalDeviceObject)
#define MfCompareGuid(a,b) \
(RtlEqualMemory((PVOID)(a), (PVOID)(b), sizeof(GUID)))
//
// Control macro (used like a for loop) which iterates over all entries in
// a standard doubly linked list. Head is the list head and the entries are of
// type Type. A member called ListEntry is assumed to be the LIST_ENTRY
// structure linking the entries together. Current contains a pointer to each
// entry in turn.
//
#define FOR_ALL_IN_LIST(Type, Head, Current) \
for((Current) = CONTAINING_RECORD((Head)->Flink, Type, ListEntry); \ (Head) != &(Current)->ListEntry; \ (Current) = CONTAINING_RECORD((Current)->ListEntry.Flink, \ Type, \ ListEntry) \ )
#define FOR_ALL_IN_LIST_SAFE(Type, Head, Current, Next) \
for((Current) = CONTAINING_RECORD((Head)->Flink, Type, ListEntry), \ (Next) = CONTAINING_RECORD((Current)->ListEntry.Flink, \ Type, ListEntry); \ (Head) != &(Current)->ListEntry; \ (Current) = (Next), \ (Next) = CONTAINING_RECORD((Current)->ListEntry.Flink, \ Type, ListEntry) \ )
//
// Similar to the above only iteration is over an array of length _Size.
//
#define FOR_ALL_IN_ARRAY(_Array, _Size, _Current) \
for ( (_Current) = (_Array); \ (_Current) < (_Array) + (_Size); \ (_Current)++ )
//
// FOR_ALL_CM_DESCRIPTORS(
// IN PCM_RESOURCE_LIST _ResList,
// OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR _Descriptor
// )
//
// Iterates over the resource descriptors in a CM_RESOURCE_LIST of Count 1
//
#define FOR_ALL_CM_DESCRIPTORS(_ResList, _Descriptor) \
ASSERT((_ResList)->Count == 1); \ FOR_ALL_IN_ARRAY( \ (_ResList)->List[0].PartialResourceList.PartialDescriptors, \ (_ResList)->List[0].PartialResourceList.Count, \ (_Descriptor) \ )
//
// BOOLEAN
// IS_ARBITRATED_RESOURCE(
// IN CM_RESOURCE_TYPE _Resource
// )
//
// If the top bit of the resource type (when viewed as a UCHAR) is set
// then the resource is nonarbitrated.
//
#define IS_ARBITRATED_RESOURCE(_Resource) \
(!(((UCHAR)(_Resource)) & 0x80) && \ !(((UCHAR)(_Resource)) == 0x00))
#define END_OF_RANGE(_Start, _Length) \
((_Start)+(_Length)-1)
#endif // !defined(_LOCAL_)
|