test: pnpioapi.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# pnpioapi.c File Reference

`#include "iop.h"`
`#include <stddef.h>`
`#include <wdmguid.h>`
`#include <pnpmgr.h>`
`#include <pnpsetup.h>`
`#include "..\pnp\pnpi.h"`

Go to the source code of this file.

## Classes

struct | _DEVICE_WORK_ITEM
struct | _ASYNC_TDC_WORK_ITEM
struct | _NOTIFICATION_CALLBACK_PARAM_BLOCK
struct | _DEFERRED_REGISTRATION_ENTRY
struct | IO_GET_LEGACY_VETO_LIST_CONTEXT

## Defines

#define | PNP_DEVICE_EVENT_ENTRY_TAG 'EEpP'
#define | PATH_CURRENTCONTROLSET_HW_PROFILE_CURRENT TEXT("\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet")
#define | PATH_CURRENTCONTROLSET TEXT("\\Registry\\Machine\\System\\CurrentControlSet")
#define | PATH_ENUM TEXT("Enum\\")
#define | PATH_CONTROL_CLASS TEXT("Control\\Class\\")
#define | MAX_RESTPATH_BUF_LEN 512
#define | INITIAL_INFO_BUFFER_SIZE 512
#define | INFO_BUFFER_GROW_SIZE 64
#define | INITIAL_SYMLINK_BUFFER_SIZE 1024
#define | SYMLINK_BUFFER_GROW_SIZE 128
#define | INITIAL_RETURN_BUFFER_SIZE 4096
#define | RETURN_BUFFER_GROW_SIZE 512
#define | INITIAL_DEVNODE_NAME_BUFFER_SIZE (FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + (200 * sizeof(WCHAR)))
#define | KEY_STRING_PREFIX TEXT("##?#")
#define | KEY_STRING_PREFIX_SIZE ( sizeof(KEY_STRING_PREFIX) - sizeof(UNICODE_NULL) )
#define | KEY_STRING_PREFIX_LENGTH ( KEY_STRING_PREFIX_SIZE / sizeof(WCHAR) )
#define | SEPERATOR_STRING TEXT("\\")
#define | SEPERATOR_CHAR (L'\\')
#define | ALT_SEPERATOR_CHAR (L'/')
#define | REPLACED_SEPERATOR_STRING TEXT("#")
#define | REPLACED_SEPERATOR_CHAR (L'#')
#define | USER_SYMLINK_STRING_PREFIX TEXT("\\\\?\\")
#define | USER_SYMLINK_STRING_PREFIX_LENGTH (( sizeof(USER_SYMLINK_STRING_PREFIX) - sizeof(UNICODE_NULL) ) / sizeof(WCHAR) )
#define | KERNEL_SYMLINK_STRING_PREFIX TEXT("\\??\\")
#define | KERNEL_SYMLINK_STRING_PREFIX_LENGTH (( sizeof(KERNEL_SYMLINK_STRING_PREFIX) - sizeof(UNICODE_NULL) ) / sizeof(WCHAR) )
#define | REFSTRING_PREFIX_CHAR (L'#')
#define | LEGACY_COMPATIBLE_ID_BASE TEXT("DETECTED")
#define | GUID_STRING_LENGTH 38
#define | GUID_STRING_SIZE GUID_STRING_LENGTH * sizeof(WCHAR)
#define | DBG_GET_ASSOC 0
#define | MAX_VETO_NAME_LENGTH 512

## Typedefs

typedef _DEVICE_WORK_ITEM | DEVICE_WORK_ITEM
typedef _DEVICE_WORK_ITEM * | PDEVICE_WORK_ITEM
typedef _ASYNC_TDC_WORK_ITEM | ASYNC_TDC_WORK_ITEM
typedef _ASYNC_TDC_WORK_ITEM * | PASYNC_TDC_WORK_ITEM
typedef _NOTIFICATION_CALLBACK_PARAM_BLOCK | NOTIFICATION_CALLBACK_PARAM_BLOCK
typedef _NOTIFICATION_CALLBACK_PARAM_BLOCK * | PNOTIFICATION_CALLBACK_PARAM_BLOCK
typedef _DEFERRED_REGISTRATION_ENTRY | DEFERRED_REGISTRATION_ENTRY
typedef _DEFERRED_REGISTRATION_ENTRY * | PDEFERRED_REGISTRATION_ENTRY
typedef * | PIO_GET_LEGACY_VETO_LIST_CONTEXT

## Functions

NTSTATUS | IopQueueDeviceWorkItem (IN PDEVICE_OBJECT PhysicalDeviceObject, IN PVOID WorkerRoutine, IN PVOID Context)
VOID | IopInvalidateDeviceStateWorker (PVOID Context)
VOID | IopReportTargetDeviceChangeAsyncWorker (PVOID Context)
VOID | IopRequestDeviceEjectWorker (PVOID Context)
BOOLEAN | IopIsReportedAlready (IN HANDLE Handle, IN PUNICODE_STRING ServiceName, IN PCM_RESOURCE_LIST ResourceList)
NTSTATUS | IopSetupDeviceObjectFromDeviceClass (IN PDEVICE_OBJECT Pdo, IN HANDLE InterfaceClassKey)
NTSTATUS | IopSetSecurityObjectFromRegistry (IN PVOID Object, IN HANDLE Key)
NTSTATUS | IopPnPHydraCallback (PVOID CallbackParams)
NTSTATUS | PiNotifyUserMode (PPNP_DEVICE_EVENT_ENTRY DeviceEvent)
NTSTATUS | IopAppendBuffer (IN PBUFFER_INFO Info, IN PVOID Data, IN ULONG DataSize)
NTSTATUS | IopOverwriteBuffer (IN PBUFFER_INFO Info, IN PVOID Data, IN ULONG DataSize)
NTSTATUS | IopRealloc (IN OUT PVOID *Buffer, IN ULONG OldSize, IN ULONG NewSize)
NTSTATUS | IopDeviceInterfaceKeysFromSymbolicLink (IN PUNICODE_STRING SymbolicLinkName, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DeviceInterfaceClassKey OPTIONAL, OUT PHANDLE DeviceInterfaceKey OPTIONAL, OUT PHANDLE DeviceInterfaceInstanceKey OPTIONAL)
NTSTATUS | IopBuildSymbolicLinkStrings (IN PUNICODE_STRING DeviceString, IN PUNICODE_STRING GuidString, IN PUNICODE_STRING ReferenceString OPTIONAL, OUT PUNICODE_STRING UserString, OUT PUNICODE_STRING KernelString)
NTSTATUS | IopReplaceSeperatorWithPound (OUT PUNICODE_STRING OutString, IN PUNICODE_STRING InString)
NTSTATUS | IopDropReferenceString (OUT PUNICODE_STRING OutString, IN PUNICODE_STRING InString)
NTSTATUS | IopParseSymbolicLinkName (IN PUNICODE_STRING SymbolicLinkName, OUT PUNICODE_STRING PrefixString OPTIONAL, OUT PUNICODE_STRING MungedPathString OPTIONAL, OUT PUNICODE_STRING GuidString OPTIONAL, OUT PUNICODE_STRING RefString OPTIONAL, OUT PBOOLEAN RefStringPresent OPTIONAL, OUT LPGUID Guid OPTIONAL)
NTSTATUS | IopSetRegistryStringValue (IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN PUNICODE_STRING ValueData)
VOID | IopInitializePlugPlayNotification (VOID)
VOID | IopReferenceNotify (PNOTIFY_ENTRY_HEADER notify)
VOID | IopDereferenceNotify (PNOTIFY_ENTRY_HEADER Notify)
NTSTATUS | IopRegisterTargetDeviceNotification (IN ULONG Flags, IN PFILE_OBJECT FileObject, IN PDRIVER_OBJECT DriverObject, IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine, IN PVOID Context, IN BOOLEAN AddLast, OUT PVOID *NotificationEntry)
NTSTATUS | IopOpenOrCreateDeviceInterfaceSubKeys (OUT PHANDLE InterfaceKeyHandle OPTIONAL, OUT PULONG InterfaceKeyDisposition OPTIONAL, OUT PHANDLE InterfaceInstanceKeyHandle OPTIONAL, OUT PULONG InterfaceInstanceDisposition OPTIONAL, IN HANDLE InterfaceClassKeyHandle, IN PUNICODE_STRING DeviceInterfaceName, IN ACCESS_MASK DesiredAccess, IN BOOLEAN Create)
NTSTATUS | PpCreateLegacyDeviceIds (IN PDEVICE_OBJECT DeviceObject, IN PUNICODE_STRING DriverName, IN PCM_RESOURCE_LIST Resources)
NTSTATUS | IoGetDeviceProperty (IN PDEVICE_OBJECT DeviceObject, IN DEVICE_REGISTRY_PROPERTY DeviceProperty, IN ULONG BufferLength, OUT PVOID PropertyBuffer, OUT PULONG ResultLength)
NTSTATUS | IoOpenDeviceRegistryKey (IN PDEVICE_OBJECT PhysicalDeviceObject, IN ULONG DevInstKeyType, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DevInstRegKey)
NTSTATUS | IoCreateDriver (IN PUNICODE_STRING DriverName OPTIONAL, IN PDRIVER_INITIALIZE InitializationFunction)
VOID | IoDeleteDriver (IN PDRIVER_OBJECT DriverObject)
NTSTATUS | IoSynchronousInvalidateDeviceRelations (PDEVICE_OBJECT DeviceObject, DEVICE_RELATION_TYPE Type)
VOID | IoInvalidateDeviceRelations (PDEVICE_OBJECT DeviceObject, DEVICE_RELATION_TYPE Type)
VOID | IoRequestDeviceEject (PDEVICE_OBJECT DeviceObject)
NTSTATUS | IoReportDetectedDevice (IN PDRIVER_OBJECT DriverObject, IN INTERFACE_TYPE LegacyBusType, IN ULONG BusNumber, IN ULONG SlotNumber, IN PCM_RESOURCE_LIST ResourceList, IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL, IN BOOLEAN ResourceAssigned, IN OUT PDEVICE_OBJECT *DeviceObject)
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)
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 | IoGetDeviceInterfaces (IN CONST GUID *InterfaceClassGuid, IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, IN ULONG Flags, OUT PWSTR *SymbolicLinkList)
NTSTATUS | IoSetDeviceInterfaceState (IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
NTSTATUS | IoOpenDeviceInterfaceRegistryKey (IN PUNICODE_STRING SymbolicLinkName, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DeviceInterfaceKey)
NTSTATUS | IoRegisterDeviceInterface (IN PDEVICE_OBJECT PhysicalDeviceObject, IN CONST GUID *InterfaceClassGuid, IN PUNICODE_STRING ReferenceString OPTIONAL, OUT 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 | IoGetDeviceInterfaceAlias (IN PUNICODE_STRING SymbolicLinkName, IN CONST GUID *AliasInterfaceClassGuid, OUT PUNICODE_STRING AliasSymbolicLinkName)
NTSTATUS | IopAllocateUnicodeString (IN OUT PUNICODE_STRING String, IN USHORT Length)
VOID | IopFreeAllocatedUnicodeString (PUNICODE_STRING String)
NTSTATUS | IoUnregisterPlugPlayNotification (IN PVOID NotificationEntry)
VOID | IopProcessDeferredRegistrations (VOID)
NTSTATUS | IoReportTargetDeviceChange (IN PDEVICE_OBJECT PhysicalDeviceObject, IN PVOID NotificationStructure)
NTSTATUS | IoReportTargetDeviceChangeAsynchronous (IN PDEVICE_OBJECT PhysicalDeviceObject, IN PVOID NotificationStructure, IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL, IN PVOID Context OPTIONAL)
VOID | IoInvalidateDeviceState (IN PDEVICE_OBJECT PhysicalDeviceObject)
VOID | IopResourceRequirementsChanged (IN PDEVICE_OBJECT PhysicalDeviceObject, IN BOOLEAN StopRequired)
NTSTATUS | IopRequestHwProfileChangeNotification (IN LPGUID EventGuid, IN PROFILE_NOTIFICATION_TIME NotificationTime, OUT PPNP_VETO_TYPE VetoType OPTIONAL, OUT PUNICODE_STRING VetoName OPTIONAL)
NTSTATUS | IopNotifyHwProfileChange (IN LPGUID EventGuid, OUT PPNP_VETO_TYPE VetoType OPTIONAL, OUT PUNICODE_STRING VetoName OPTIONAL)
NTSTATUS | IopNotifyTargetDeviceChange (LPCGUID EventGuid, PDEVICE_OBJECT DeviceObject, PVOID NotificationStructure, PDRIVER_OBJECT *VetoingDriver)
NTSTATUS | IopNotifyDeviceClassChange (LPGUID EventGuid, LPGUID ClassGuid, PUNICODE_STRING SymbolicLinkName)
NTSTATUS | IoRegisterPlugPlayNotification (IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory, IN ULONG EventCategoryFlags, IN PVOID EventCategoryData OPTIONAL, IN PDRIVER_OBJECT DriverObject, IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine, IN PVOID Context, OUT PVOID *NotificationEntry)
NTSTATUS | IopGetRelatedTargetDevice (IN PFILE_OBJECT FileObject, OUT PDEVICE_NODE *DeviceNode)
NTSTATUS | IoGetRelatedTargetDevice (IN PFILE_OBJECT FileObject, OUT PDEVICE_OBJECT *DeviceObject)
NTSTATUS | IopNotifySetupDeviceArrival (PDEVICE_OBJECT PhysicalDeviceObject, HANDLE EnumEntryKey, BOOLEAN InstallDriver)
BOOLEAN | IoIsWdmVersionAvailable (IN UCHAR MajorVersion, IN UCHAR MinorVersion)
NTKERNELAPI PDMA_ADAPTER | IoGetDmaAdapter (IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, IN PDEVICE_DESCRIPTION DeviceDescription, IN OUT PULONG NumberOfMapRegisters)
NTSTATUS | IopOpenDeviceParametersSubkey (OUT HANDLE *ParamKeyHandle, IN HANDLE ParentKeyHandle, IN PUNICODE_STRING SubKeyString, IN ACCESS_MASK DesiredAccess)
NTSTATUS | IoNotifyPowerOperationVetoed (IN POWER_ACTION VetoedPowerOperation, IN PDEVICE_OBJECT TargetedDeviceObject OPTIONAL, IN PDEVICE_OBJECT VetoingDeviceObject)
ULONG | IoPnPDeliverServicePowerNotification (ULONG PwrNotification, BOOLEAN Synchronous)
VOID | IopOrphanNotification (IN PDEVICE_NODE TargetNode)
BOOLEAN | IopAppendLegacyVeto (IN PIO_GET_LEGACY_VETO_LIST_CONTEXT Context, IN PUNICODE_STRING VetoName)
BOOLEAN | IopGetLegacyVetoListDevice (IN PDEVICE_NODE DeviceNode, IN PIO_GET_LEGACY_VETO_LIST_CONTEXT Context)
BOOLEAN | IopGetLegacyVetoListDeviceNode (IN PDEVICE_NODE DeviceNode, IN PIO_GET_LEGACY_VETO_LIST_CONTEXT Context)
VOID | IopGetLegacyVetoListDrivers (IN PIO_GET_LEGACY_VETO_LIST_CONTEXT Context)
NTSTATUS | IoGetLegacyVetoList (OUT PWSTR *VetoList OPTIONAL, OUT PPNP_VETO_TYPE VetoType)
NTSTATUS | IopDoDeferredSetInterfaceState (IN PDEVICE_NODE DeviceNode)
NTSTATUS | IopProcessSetInterfaceState (IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable, IN BOOLEAN DeferNotStarted)

## Variables

LIST_ENTRY | IopDeviceClassNotifyList [NOTIFY_DEVICE_CLASS_HASH_BUCKETS]
FAST_MUTEX | IopDeviceClassNotifyLock
PSETUP_NOTIFY_DATA | IopSetupNotifyData = NULL
FAST_MUTEX | IopTargetDeviceNotifyLock
LIST_ENTRY | IopProfileNotifyList
FAST_MUTEX | IopHwProfileNotifyLock
BOOLEAN | PiNotificationInProgress
FAST_MUTEX | PiNotificationInProgressLock
LIST_ENTRY | IopDeferredRegistrationList
FAST_MUTEX | IopDeferredRegistrationLock

## Define Documentation

#define ALT_SEPERATOR_CHAR (L'/')

| Definition at line 157 of file pnpioapi.c. Referenced by IopReplaceSeperatorWithPound(), and IoRegisterDeviceInterface().

#define DBG_GET_ASSOC 0

| Definition at line 2704 of file pnpioapi.c.

#define GUID_STRING_LENGTH 38

| Definition at line 176 of file pnpioapi.c. Referenced by IopParseSymbolicLinkName().

#define GUID_STRING_SIZE GUID_STRING_LENGTH * sizeof(WCHAR)

| Definition at line 177 of file pnpioapi.c. Referenced by IopParseSymbolicLinkName(), and RtlStringFromGUID().

#define INFO_BUFFER_GROW_SIZE 64

| Definition at line 130 of file pnpioapi.c.

#define INITIAL_DEVNODE_NAME_BUFFER_SIZE (FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + (200 * sizeof(WCHAR)))

| Definition at line 139 of file pnpioapi.c. Referenced by IopGetDeviceInterfaces().

#define INITIAL_INFO_BUFFER_SIZE 512

| Definition at line 129 of file pnpioapi.c. Referenced by IopGetDeviceInterfaces(), and IopRemoveDeviceInterfaces().

#define INITIAL_RETURN_BUFFER_SIZE 4096

| Definition at line 133 of file pnpioapi.c. Referenced by IopGetDeviceInterfaces().

#define INITIAL_SYMLINK_BUFFER_SIZE 1024

| Definition at line 131 of file pnpioapi.c. Referenced by IopGetDeviceInterfaces().

#define KERNEL_SYMLINK_STRING_PREFIX TEXT("\\??\\")

| Definition at line 162 of file pnpioapi.c. Referenced by IopBuildSymbolicLinkStrings(), IopGetDeviceInterfaces(), and IopParseSymbolicLinkName().

#define KERNEL_SYMLINK_STRING_PREFIX_LENGTH (( sizeof(KERNEL_SYMLINK_STRING_PREFIX) - sizeof(UNICODE_NULL) ) / sizeof(WCHAR) )

| Definition at line 163 of file pnpioapi.c. Referenced by IopGetDeviceInterfaces().

#define KEY_STRING_PREFIX TEXT("##?#")

| Definition at line 145 of file pnpioapi.c. Referenced by IopOpenOrCreateDeviceInterfaceSubKeys(), and IopUnregisterDeviceInterface().

#define KEY_STRING_PREFIX_LENGTH ( KEY_STRING_PREFIX_SIZE / sizeof(WCHAR) )

| Definition at line 147 of file pnpioapi.c.

#define KEY_STRING_PREFIX_SIZE ( sizeof(KEY_STRING_PREFIX) - sizeof(UNICODE_NULL) )

| Definition at line 146 of file pnpioapi.c.

#define LEGACY_COMPATIBLE_ID_BASE TEXT("DETECTED")

| Definition at line 170 of file pnpioapi.c. Referenced by PpCreateLegacyDeviceIds().

#define MAX_RESTPATH_BUF_LEN 512

| Definition at line 123 of file pnpioapi.c. Referenced by IoOpenDeviceRegistryKey().

#define MAX_VETO_NAME_LENGTH 512

| Referenced by IoPnPDeliverServicePowerNotification().

#define PATH_CONTROL_CLASS TEXT("Control\\Class\\")

| Definition at line 122 of file pnpioapi.c. Referenced by IoOpenDeviceRegistryKey().

#define PATH_CURRENTCONTROLSET TEXT("\\Registry\\Machine\\System\\CurrentControlSet")

| Definition at line 120 of file pnpioapi.c. Referenced by IoOpenDeviceRegistryKey().

#define PATH_CURRENTCONTROLSET_HW_PROFILE_CURRENT TEXT("\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet")

| Definition at line 119 of file pnpioapi.c. Referenced by IoOpenDeviceRegistryKey().

#define PATH_ENUM TEXT("Enum\\")

| Definition at line 121 of file pnpioapi.c. Referenced by IoOpenDeviceRegistryKey().

#define PNP_DEVICE_EVENT_ENTRY_TAG 'EEpP'

| Definition at line 42 of file pnpioapi.c. Referenced by IopRequestHwProfileChangeNotification().

#define REFSTRING_PREFIX_CHAR (L'#')

| Definition at line 164 of file pnpioapi.c. Referenced by IopOpenOrCreateDeviceInterfaceSubKeys(), and IopUnregisterDeviceInterface().

#define REPLACED_SEPERATOR_CHAR (L'#')

| Definition at line 159 of file pnpioapi.c. Referenced by IopReplaceSeperatorWithPound().

#define REPLACED_SEPERATOR_STRING TEXT("#")

| Definition at line 158 of file pnpioapi.c. Referenced by IopBuildSymbolicLinkStrings().

#define RETURN_BUFFER_GROW_SIZE 512

| Definition at line 134 of file pnpioapi.c.

#define SEPERATOR_CHAR (L'\\')

| Definition at line 156 of file pnpioapi.c. Referenced by IopParseSymbolicLinkName(), IopReplaceSeperatorWithPound(), and IoRegisterDeviceInterface().

#define SEPERATOR_STRING TEXT("\\")

| Definition at line 155 of file pnpioapi.c. Referenced by IopBuildSymbolicLinkStrings().

#define SYMLINK_BUFFER_GROW_SIZE 128

| Definition at line 132 of file pnpioapi.c.

#define USER_SYMLINK_STRING_PREFIX TEXT("\\\\?\\")

| Definition at line 160 of file pnpioapi.c. Referenced by IoGetDeviceInterfaceAlias(), IopBuildSymbolicLinkStrings(), and IopParseSymbolicLinkName().

#define USER_SYMLINK_STRING_PREFIX_LENGTH (( sizeof(USER_SYMLINK_STRING_PREFIX) - sizeof(UNICODE_NULL) ) / sizeof(WCHAR) )

| Definition at line 161 of file pnpioapi.c.

## Typedef Documentation

typedef struct _ASYNC_TDC_WORK_ITEM ASYNC_TDC_WORK_ITEM

| Referenced by IoReportTargetDeviceChangeAsynchronous().

typedef struct _DEFERRED_REGISTRATION_ENTRY DEFERRED_REGISTRATION_ENTRY

typedef struct _DEVICE_WORK_ITEM DEVICE_WORK_ITEM

typedef struct _NOTIFICATION_CALLBACK_PARAM_BLOCK NOTIFICATION_CALLBACK_PARAM_BLOCK

typedef struct _ASYNC_TDC_WORK_ITEM * PASYNC_TDC_WORK_ITEM

| Referenced by IopReportTargetDeviceChangeAsyncWorker(), and IoReportTargetDeviceChangeAsynchronous().

typedef struct _DEFERRED_REGISTRATION_ENTRY * PDEFERRED_REGISTRATION_ENTRY

| Referenced by IopProcessDeferredRegistrations(), IoRegisterPlugPlayNotification(), and IoUnregisterPlugPlayNotification().

typedef struct _DEVICE_WORK_ITEM * PDEVICE_WORK_ITEM

| Referenced by IopInvalidateDeviceStateWorker(), IopQueueDeviceWorkItem(), and IopRequestDeviceEjectWorker().

typedef * PIO_GET_LEGACY_VETO_LIST_CONTEXT

typedef struct _NOTIFICATION_CALLBACK_PARAM_BLOCK * PNOTIFICATION_CALLBACK_PARAM_BLOCK

| Referenced by IopPnPHydraCallback().

## Function Documentation

NTSTATUS IoCreateDriver | ( | IN PUNICODE_STRING DriverName | OPTIONAL,
|  | IN PDRIVER_INITIALIZE | InitializationFunction
| ) |

Definition at line 1071 of file pnpioapi.c.

References _DRIVER_OBJECT::DriverExtension, _DRIVER_OBJECT::DriverInit, _DRIVER_EXTENSION::DriverObject, DRVO_BUILTIN_DRIVER, ExAllocatePool, _DRIVER_OBJECT::Flags, IO_TYPE_DRIVER, IoDriverObjectType, IopInvalidDeviceRequest(), IRP_MJ_MAXIMUM_FUNCTION, KernelMode, KeTickCount, L, _DRIVER_OBJECT::MajorFunction, NT_SUCCESS, NTSTATUS(), NULL, ObCreateObject(), ObDereferenceObject, ObInsertObject(), ObMakeTemporaryObject(), ObReferenceObjectByHandle(), PAGED_CODE, PagedPool, _DRIVER_EXTENSION::ServiceKeyName, _DRIVER_OBJECT::Size, _DRIVER_OBJECT::Type, and USHORT.

Referenced by IopInitializePlugPlayServices(), and xxxRegisterForDeviceClassNotifications().

    01077                    :
    01078
    01079     This routine creates a driver object for a kernel component that
    01080     was not loaded as a driver.  If the creation of the driver object
    01081     succeeds, Initialization function is invoked with the same parameters
    01082     as passed to DriverEntry.
    01083
    01084 Parameters:
    01085
    01086     DriverName - Supplies the name of the driver for which a driver object
    01087                  is to be created.
    01088
    01089     InitializationFunction - Equivalent to DriverEntry().
    01090
    01091 ReturnValue:
    01092
    01093     Status code that indicates whether or not the function was successful.
    01094
    01095 Notes:
    01096
    01097 --*/
    01098 {
    01099     OBJECT_ATTRIBUTES objectAttributes;
    01100     NTSTATUS status;
    01101     PDRIVER_OBJECT driverObject;
    01102     HANDLE driverHandle;
    01103     ULONG objectSize;
    01104     USHORT length;
    01105     UNICODE_STRING driverName, serviceName;
    01106     WCHAR buffer[60];
    01107     ULONG i;
    01108
    01109     PAGED_CODE();
    01110
    01111     if (DriverName == NULL) {
    01112
    01113         //
    01114         // Madeup a name for the driver object.
    01115         //
    01116
    01117         length = (USHORT) _snwprintf(buffer, sizeof(buffer) / sizeof(WCHAR), L"\\Driver\\%08u", KeTickCount);
    01118         driverName.Length = length * sizeof(WCHAR);
    01119         driverName.MaximumLength = driverName.Length + sizeof(UNICODE_NULL);
    01120         driverName.Buffer = buffer;                                                           \
    01121     } else {
    01122         driverName = *DriverName;
    01123     }
    01124
    01125     //
    01126     // Attempt to create the driver object
    01127     //
    01128
    01129     InitializeObjectAttributes( &objectAttributes,
    01130                                 &driverName,
    01131                                 OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
    01132                                 NULL,
    01133                                 NULL );
    01134
    01135     objectSize = sizeof( DRIVER_OBJECT ) + sizeof( DRIVER_EXTENSION );
    01136     status = ObCreateObject( KernelMode,
    01137                              IoDriverObjectType,
    01138                              &objectAttributes,
    01139                              KernelMode,
    01140                              NULL,
    01141                              objectSize,
    01142                              0,
    01143                              0,
    01144                              &driverObject );
    01145
    01146     if( !NT_SUCCESS( status )){
    01147
    01148         //
    01149         // Driver object creation failed
    01150         //
    01151
    01152         return status;
    01153     }
    01154
    01155     //
    01156     // We've created a driver object, initialize it.
    01157     //
    01158
    01159     RtlZeroMemory( driverObject, objectSize );
    01160     driverObject->DriverExtension = (PDRIVER_EXTENSION)(driverObject + 1);
    01161     driverObject->DriverExtension->DriverObject = driverObject;
    01162     driverObject->Type = IO_TYPE_DRIVER;
    01163     driverObject->Size = sizeof( DRIVER_OBJECT );
    01164     driverObject->Flags = DRVO_BUILTIN_DRIVER;
    01165     for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
    01166         driverObject->MajorFunction[i] = IopInvalidDeviceRequest;
    01167     driverObject->DriverInit = InitializationFunction;
    01168
    01169     serviceName.Buffer = (PWSTR)ExAllocatePool(PagedPool, driverName.Length + sizeof(WCHAR));
    01170     if (serviceName.Buffer) {
    01171         serviceName.MaximumLength = driverName.Length + sizeof(WCHAR);
    01172         serviceName.Length = driverName.Length;
    01173         RtlMoveMemory(serviceName.Buffer, driverName.Buffer, driverName.Length);
    01174         serviceName.Buffer[serviceName.Length / sizeof(WCHAR)] = UNICODE_NULL;
    01175         driverObject->DriverExtension->ServiceKeyName = serviceName;
    01176     } else {
    01177         status = STATUS_INSUFFICIENT_RESOURCES;
    01178         goto errorFreeDriverObject;
    01179     }
    01180
    01181     //
    01182     // Insert it into the object table.
    01183     //
    01184
    01185     status = ObInsertObject( driverObject,
    01186                              NULL,
    01187                              FILE_READ_DATA,
    01188                              0,
    01189                              NULL,
    01190                              &driverHandle );
    01191
    01192     if( !NT_SUCCESS( status )){
    01193
    01194         //
    01195         // Couldn't insert the driver object into the table.
    01196         // The object got dereferenced by the object manager. Just exit
    01197         //
    01198
    01199         goto errorReturn;
    01200     }
    01201
    01202     //
    01203     // Reference the handle and obtain a pointer to the driver object so that
    01204     // the handle can be deleted without the object going away.
    01205     //
    01206
    01207     status = ObReferenceObjectByHandle( driverHandle,
    01208                                         0,
    01209                                         IoDriverObjectType,
    01210                                         KernelMode,
    01211                                         (PVOID *) &driverObject,
    01212                                         (POBJECT_HANDLE_INFORMATION) NULL );
    01213     if( !NT_SUCCESS( status )) {
    01214        //
    01215        // Backout here is probably bogus. If the ref didn't work then the handle is probably bad
    01216        // Do this right though just in case there are other common error returns for ObRef...
    01217        //
    01218        ZwMakeTemporaryObject( driverHandle ); // Cause handle close to free the object
    01219        ZwClose( driverHandle ); // Close the handle.
    01220        goto errorReturn;
    01221     }
    01222
    01223     ZwClose( driverHandle );
    01224
    01225     //
    01226     // Store the name of the device driver in the driver object so that it
    01227     // can be easily found by the error log thread.
    01228     //
    01229
    01230     driverObject->DriverName.Buffer = ExAllocatePool( PagedPool,
    01231                                                       driverName.MaximumLength );
    01232     if (driverObject->DriverName.Buffer) {
    01233         driverObject->DriverName.MaximumLength = driverName.MaximumLength;
    01234         driverObject->DriverName.Length = driverName.Length;
    01235
    01236         RtlCopyMemory( driverObject->DriverName.Buffer,
    01237                        driverName.Buffer,
    01238                        driverName.MaximumLength );
    01239     }
    01240
    01241     //
    01242     // Call the driver initialization routine
    01243     //
    01244
    01245     status = (*InitializationFunction)(driverObject, NULL);
    01246
    01247     if( !NT_SUCCESS( status )){
    01248
    01249 errorFreeDriverObject:
    01250
    01251         //
    01252         // If we were unsuccessful, we need to get rid of the driverObject
    01253         // that we created.
    01254         //
    01255
    01256         ObMakeTemporaryObject( driverObject );
    01257         ObDereferenceObject( driverObject );
    01258     }
    01259 errorReturn:
    01260     return status;
    01261 }

VOID IoDeleteDriver | ( | IN PDRIVER_OBJECT | DriverObject | ) |

Definition at line 1264 of file pnpioapi.c.

References ObDereferenceObject.

Referenced by IopInitializePlugPlayServices().

    01269                    :
    01270
    01271     This routine deletes a driver object created explicitly through
    01272     IoCreateDriver.
    01273
    01274 Parameters:
    01275
    01276     DriverObject - Supplies a pointer to the driver object to be deleted.
    01277
    01278 ReturnValue:
    01279
    01280     Status code that indicates whether or not the function was successful.
    01281
    01282 Notes:
    01283
    01284 --*/
    01285 {
    01286
    01287     ObDereferenceObject(DriverObject);
    01288 }

NTSTATUS IoGetDeviceInterfaceAlias | ( | IN PUNICODE_STRING | SymbolicLinkName,
|  | IN CONST GUID * | AliasInterfaceClassGuid,
|  | OUT PUNICODE_STRING | AliasSymbolicLinkName
| ) |

Definition at line 4946 of file pnpioapi.c.

References ExAcquireResourceExclusive, ExFreePool(), ExReleaseResource, IopBuildSymbolicLinkStrings(), IopConstStringSize, IopDeviceInterfaceKeysFromSymbolicLink(), IopFreeAllocatedUnicodeString(), IopGetRegistryValue(), IopParseSymbolicLinkName(), IopRegistryDataToUnicodeString, KeEnterCriticalRegion, KeLeaveCriticalRegion, KEY_VALUE_DATA, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PpRegistryDeviceResource, RtlFreeUnicodeString(), RtlStringFromGUID(), TRUE, and USER_SYMLINK_STRING_PREFIX.

    04954                    :
    04955
    04956     This API returns a symbolic link name (i.e., device interface) of a
    04957     particular interface class that 'aliases' the specified device interface.
    04958     Two device interfaces are considered aliases of each other if the
    04959     following two criteria are met:
    04960
    04961         1.  Both interfaces are exposed by the same PDO (devnode).
    04962         2.  Both interfaces share the same RefString.
    04963
    04964 Parameters:
    04965
    04966     SymbolicLinkName - Supplies the name of the device interface whose alias is
    04967         to be retrieved.
    04968
    04969     AliasInterfaceClassGuid - Supplies a pointer to the GUID representing the interface
    04970         class for which an alias is to be retrieved.
    04971
    04972     AliasSymbolicLinkName - Supplies a pointer to a string which, upon success,
    04973         will contain the name of the device interface in the specified class that
    04974         aliases the SymbolicLinkName interface.  (This symbolic link name will be
    04975         returned in either kernel-mode or user-mode form, depeding upon the form
    04976         of the SymbolicLinkName path).
    04977
    04978         It is the caller's responsibility to free the buffer allocated for this
    04979         string via ExFreePool().
    04980
    04981 Return Value:
    04982
    04983     Status code that indicates whether or not the function was successful.
    04984
    04985 --*/
    04986
    04987 {
    04988     NTSTATUS status;
    04989     HANDLE hKey;
    04990     PKEY_VALUE_FULL_INFORMATION pDeviceInstanceInfo;
    04991     UNICODE_STRING deviceInstanceString, refString, guidString, otherString;
    04992     PUNICODE_STRING pUserString, pKernelString;
    04993     BOOLEAN refStringPresent, userModeFormat;
    04994
    04995     PAGED_CODE();
    04996
    04997     //
    04998     // Convert the class guid into string form
    04999     //
    05000
    05001     status = RtlStringFromGUID(AliasInterfaceClassGuid, &guidString);
    05002     if( !NT_SUCCESS(status) ){
    05003         goto clean0;
    05004     }
    05005
    05006     //
    05007     // Enter critical section and acquire a lock on the registry.  Both these
    05008     // mechanisms are required to prevent deadlock in the case where an APC
    05009     // routine calls this routine after the registry resource has been claimed
    05010     // in this case it would wait blocking this thread so the registry would
    05011     // never be released -> deadlock.  Critical sectioning the registry manipulation
    05012     // portion solves this problem
    05013     //
    05014
    05015     KeEnterCriticalRegion();
    05016     ExAcquireResourceExclusive(&PpRegistryDeviceResource, TRUE);
    05017
    05018     //
    05019     // Open the (parent) device interface key--not the refstring-specific one.
    05020     //
    05021
    05022     status = IopDeviceInterfaceKeysFromSymbolicLink(SymbolicLinkName,
    05023                                                     KEY_READ,
    05024                                                     NULL,
    05025                                                     &hKey,
    05026                                                     NULL
    05027                                                     );
    05028     if(!NT_SUCCESS(status)) {
    05029         goto clean1;
    05030     }
    05031
    05032     //
    05033     // Get the name of the device instance that 'owns' this interface.
    05034     //
    05035
    05036     status = IopGetRegistryValue(hKey, REGSTR_VAL_DEVICE_INSTANCE, &pDeviceInstanceInfo);
    05037
    05038     ZwClose(hKey);
    05039
    05040     if(!NT_SUCCESS(status)) {
    05041         goto clean1;
    05042     }
    05043
    05044     if(pDeviceInstanceInfo->Type == REG_SZ) {
    05045
    05046         IopRegistryDataToUnicodeString(&deviceInstanceString,
    05047                                        (PWSTR)KEY_VALUE_DATA(pDeviceInstanceInfo),
    05048                                        pDeviceInstanceInfo->DataLength
    05049                                       );
    05050
    05051     } else {
    05052
    05053         status = STATUS_INVALID_PARAMETER_1;
    05054         goto clean2;
    05055
    05056     }
    05057
    05058     //
    05059     // Now parse out the refstring, so that we can construct the name of the interface device's
    05060     // alias.  (NOTE: we have not yet verified that the alias actually exists, we're only
    05061     // constructing what its name would be, if it did exist.)
    05062     //
    05063     // Don't bother to check the return code.  If this were a bad string, we'd have already
    05064     // failed above when we called IopDeviceInterfaceKeysFromSymbolicLink.
    05065     //
    05066     IopParseSymbolicLinkName(SymbolicLinkName,
    05067                              NULL,
    05068                              NULL,
    05069                              NULL,
    05070                              &refString,
    05071                              &refStringPresent,
    05072                              NULL
    05073                             );
    05074
    05075     //
    05076     // Did the caller supply us with a user-mode or kernel-mode format path?
    05077     //
    05078     userModeFormat = (IopConstStringSize(USER_SYMLINK_STRING_PREFIX) ==
    05079                           RtlCompareMemory(SymbolicLinkName->Buffer,
    05080                                            USER_SYMLINK_STRING_PREFIX,
    05081                                            IopConstStringSize(USER_SYMLINK_STRING_PREFIX)
    05082                                           ));
    05083
    05084     if(userModeFormat) {
    05085         pUserString = AliasSymbolicLinkName;
    05086         pKernelString = &otherString;
    05087     } else {
    05088         pKernelString = AliasSymbolicLinkName;
    05089         pUserString = &otherString;
    05090     }
    05091
    05092     status = IopBuildSymbolicLinkStrings(&deviceInstanceString,
    05093                                          &guidString,
    05094                                          refStringPresent ? &refString : NULL,
    05095                                          pUserString,
    05096                                          pKernelString
    05097                                          );
    05098     if (!NT_SUCCESS(status)) {
    05099         goto clean2;
    05100     }
    05101
    05102     //
    05103     // OK, we now have the symbolic link name of the alias, but we don't yet know whether
    05104     // it actually exists.  Check this by attempting to open the associated registry key.
    05105     //
    05106     status = IopDeviceInterfaceKeysFromSymbolicLink(AliasSymbolicLinkName,
    05107                                                     KEY_READ,
    05108                                                     NULL,
    05109                                                     NULL,
    05110                                                     &hKey
    05111                                                     );
    05112
    05113     if(NT_SUCCESS(status)) {
    05114         //
    05115         // Alias exists--close the key handle.
    05116         //
    05117         ZwClose(hKey);
    05118     } else {
    05119         IopFreeAllocatedUnicodeString(AliasSymbolicLinkName);
    05120     }
    05121
    05122     IopFreeAllocatedUnicodeString(&otherString);
    05123
    05124 clean2:
    05125     ExFreePool(pDeviceInstanceInfo);
    05126
    05127 clean1:
    05128     ExReleaseResource(&PpRegistryDeviceResource);
    05129     KeLeaveCriticalRegion();
    05130     RtlFreeUnicodeString(&guidString);
    05131
    05132 clean0:
    05133     return status;
    05134 }

NTSTATUS IoGetDeviceInterfaces | ( | IN CONST GUID * | InterfaceClassGuid,
|  | IN PDEVICE_OBJECT PhysicalDeviceObject | OPTIONAL,
|  | IN ULONG | Flags,
|  | OUT PWSTR * | SymbolicLinkList
| ) |

Definition at line 3419 of file pnpioapi.c.

References ASSERT_PDO, FALSE, _DEVICE_NODE::InstancePath, IopGetDeviceInterfaces(), NTSTATUS(), NULL, and PAGED_CODE.

Referenced by IopCreateArcNames(), and IoRegisterPlugPlayNotification().

    03428                    :
    03429
    03430     This API allows a WDM driver to get a list of paths that represent all
    03431     device interfaces registered for the specified interface class.
    03432
    03433 Parameters:
    03434
    03435     InterfaceClassGuid - Supplies a pointer to a GUID representing the interface class
    03436         for whom a list of members is to be retrieved
    03437
    03438     PhysicalDeviceObject - Optionally, supplies a pointer to the PDO for whom
    03439         interfaces of the specified class are to be re-trieved.  If this parameter
    03440         is not supplied, then all interface devices (regardless of what physical
    03441         device exposes them) will be returned.
    03442
    03443     Flags - Supplies flags that modify the behavior of list retrieval.
    03444         The following flags are presently defined:
    03445
    03446         DEVICE_INTERFACE_INCLUDE_NONACTIVE -- If this flag is specified, then all
    03447             device interfaces, whether currently active or not, will be returned
    03448             (potentially filtered based on the PhysicalDeviceObject, if specified).
    03449
    03450     SymbolicLinkList - Supplies the address of a character pointer, that on
    03451         success will contain a multi-sz list of \DosDevices\ symbolic link
    03452         names that provide the requested functionality.  The caller is
    03453         responsible for freeing the memory via ExFreePool
    03454
    03455 Return Value:
    03456
    03457     Status code that indicates whether or not the function was successful.
    03458
    03459 --*/
    03460
    03461 {
    03462     NTSTATUS status;
    03463     PUNICODE_STRING pDeviceName = NULL;
    03464     PDEVICE_NODE pDeviceNode;
    03465
    03466     PAGED_CODE();
    03467
    03468     //
    03469     // Check we have a PDO and if so extract the instance path from it
    03470     //
    03471
    03472     if (ARGUMENT_PRESENT(PhysicalDeviceObject)) {
    03473
    03474         ASSERT_PDO(PhysicalDeviceObject);
    03475         pDeviceNode = (PDEVICE_NODE) PhysicalDeviceObject->DeviceObjectExtension->DeviceNode;
    03476         pDeviceName = &pDeviceNode->InstancePath;
    03477     }
    03478
    03479     status = IopGetDeviceInterfaces(InterfaceClassGuid,
    03480                                     pDeviceName,
    03481                                     Flags,
    03482                                     FALSE,
    03483                                     SymbolicLinkList,
    03484                                     NULL
    03485                                     );
    03486     return status;
    03487 }

NTSTATUS IoGetDeviceProperty | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN DEVICE_REGISTRY_PROPERTY | DeviceProperty,
|  | IN ULONG | BufferLength,
|  | OUT PVOID | PropertyBuffer,
|  | OUT PULONG | ResultLength
| ) |

Definition at line 373 of file pnpioapi.c.

References _DEVICE_CAPABILITIES::Address, ASSERT, ASSERT_PDO, _DEVICE_NODE::ChildBusNumber, _DEVICE_NODE::ChildBusTypeIndex, _DEVICE_NODE::ChildInterfaceType, _BUS_TYPE_GUID_LIST::Count, DevicePropertyAddress, DevicePropertyBootConfiguration, DevicePropertyBootConfigurationTranslated, DevicePropertyBusNumber, DevicePropertyBusTypeGuid, DevicePropertyClassGuid, DevicePropertyClassName, DevicePropertyCompatibleIDs, DevicePropertyDeviceDescription, DevicePropertyDriverKeyName, DevicePropertyEnumeratorName, DevicePropertyFriendlyName, DevicePropertyHardwareID, DevicePropertyLegacyBusType, DevicePropertyLocationInformation, DevicePropertyManufacturer, DevicePropertyPhysicalDeviceObjectName, DevicePropertyUINumber, ExAcquireResourceExclusive, ExAllocatePool, ExFreePool(), ExReleaseResource, _BUS_TYPE_GUID_LIST::Guid, _DEVICE_NODE::InstancePath, IopBusTypeGuidList, IopDeviceObjectToDeviceInstance(), IopGetRegistryValue(), IopOpenRegistryKeyEx(), IopQueryDeviceCapabilities(), KeEnterCriticalRegion, KeLeaveCriticalRegion, KEY_VALUE_DATA, L, NT_SUCCESS, NTSTATUS(), NULL, ObQueryNameString(), PAGED_CODE, PagedPool, PpRegistryDeviceResource, RtlInitUnicodeString(), and TRUE.

Referenced by ArbQueryConflict(), IoGetDmaAdapter(), and IopProcessSetInterfaceState().

    00383                    :
    00384
    00385     This routine lets drivers query the registry properties associated with the
    00386     specified device.
    00387
    00388 Parameters:
    00389
    00390     DeviceObject - Supplies the device object whoes registry property is to be
    00391                    returned.  This device object should be the one created by
    00392                    a bus driver.
    00393
    00394     DeviceProperty - Specifies what device property to get.
    00395
    00396     BufferLength - Specifies the length, in byte, of the PropertyBuffer.
    00397
    00398     PropertyBuffer - Supplies a pointer to a buffer to receive property data.
    00399
    00400     ResultLength - Supplies a pointer to a variable to receive the size of the
    00401                    property data returned.
    00402
    00403 ReturnValue:
    00404
    00405     Status code that indicates whether or not the function was successful.  If
    00406     PropertyBuffer is not big enough to hold requested data, STATUS_BUFFER_TOO_SMALL
    00407     will be returned and ResultLength will be set to the number of bytes actually
    00408     required.
    00409
    00410 --*/
    00411
    00412 {
    00413     PDEVICE_NODE deviceNode;
    00414     DEVICE_CAPABILITIES capabilities;
    00415     NTSTATUS status;
    00416     HANDLE handle;
    00417     PWSTR valueName, keyName = NULL;
    00418     PKEY_VALUE_FULL_INFORMATION keyValueInformation;
    00419     ULONG valueType;
    00420     ULONG length;
    00421     POBJECT_NAME_INFORMATION deviceObjectName;
    00422     PWSTR deviceInstanceName;
    00423     PWCHAR enumeratorNameEnd;
    00424
    00425     PAGED_CODE();
    00426
    00427     ASSERT_PDO(DeviceObject);
    00428
    00429     //
    00430     // Initialize out parameters
    00431     //
    00432
    00433     *ResultLength = 0;
    00434
    00435     //
    00436     // Map Device Property to registry value name and value type.
    00437     //
    00438
    00439     switch (DeviceProperty) {
    00440
    00441     case DevicePropertyDeviceDescription:
    00442         valueName = REGSTR_VALUE_DEVICE_DESC;
    00443         valueType = REG_SZ;
    00444         break;
    00445
    00446     case DevicePropertyHardwareID:
    00447         valueName = REGSTR_VAL_HARDWAREID;
    00448         valueType = REG_MULTI_SZ;
    00449         break;
    00450
    00451     case DevicePropertyCompatibleIDs:
    00452         valueName = REGSTR_VAL_COMPATIBLEIDS;
    00453         valueType = REG_MULTI_SZ;
    00454         break;
    00455
    00456     case DevicePropertyBootConfiguration:
    00457         keyName   = REGSTR_KEY_LOG_CONF;
    00458         valueName = REGSTR_VAL_BOOTCONFIG;
    00459         valueType = REG_RESOURCE_LIST;
    00460         break;
    00461
    00462     case DevicePropertyBootConfigurationTranslated:
    00463         //
    00464         // BUGBUG(andrewth) - support this!
    00465         //
    00466         return STATUS_NOT_SUPPORTED;
    00467         break;
    00468
    00469     case DevicePropertyClassName:
    00470         valueName = REGSTR_VALUE_CLASS;
    00471         valueType = REG_SZ;
    00472         break;
    00473
    00474     case DevicePropertyClassGuid:
    00475         valueName = REGSTR_VALUE_CLASSGUID;
    00476         valueType = REG_SZ;
    00477         break;
    00478
    00479     case DevicePropertyDriverKeyName:
    00480         valueName = REGSTR_VALUE_DRIVER;
    00481         valueType = REG_SZ;
    00482         break;
    00483
    00484     case DevicePropertyManufacturer:
    00485         valueName = REGSTR_VAL_MFG;
    00486         valueType = REG_SZ;
    00487         break;
    00488
    00489     case DevicePropertyFriendlyName:
    00490         valueName = REGSTR_VALUE_FRIENDLYNAME;
    00491         valueType = REG_SZ;
    00492         break;
    00493
    00494     case DevicePropertyLocationInformation:
    00495         valueName = REGSTR_VAL_LOCATION_INFORMATION;
    00496         valueType = REG_SZ;
    00497         break;
    00498
    00499     case DevicePropertyUINumber:
    00500         valueName = REGSTR_VAL_UI_NUMBER;
    00501         valueType = REG_DWORD;
    00502         break;
    00503
    00504     case DevicePropertyPhysicalDeviceObjectName:
    00505
    00506         ASSERT (0 == (1 & BufferLength));  // had better be an even length
    00507
    00508         //
    00509         // Create a buffer for the Obj manager.
    00510         //
    00511         length = BufferLength + sizeof (OBJECT_NAME_INFORMATION);
    00512
    00513         deviceObjectName = (POBJECT_NAME_INFORMATION)
    00514                             ExAllocatePool(PagedPool, length);
    00515
    00516         if (NULL == deviceObjectName) {
    00517             return STATUS_INSUFFICIENT_RESOURCES;
    00518         }
    00519
    00520         status = ObQueryNameString (DeviceObject,
    00521                                     deviceObjectName,
    00522                                     length,
    00523                                     ResultLength);
    00524
    00525         if (STATUS_INFO_LENGTH_MISMATCH == status) {
    00526             status = STATUS_BUFFER_TOO_SMALL;
    00527         }
    00528
    00529         if (NT_SUCCESS (status)) {
    00530
    00531             if (deviceObjectName->Name.Length == 0)  {
    00532
    00533                 //
    00534                 // PDO has no NAME, probably it's been deleted
    00535                 //
    00536                 *ResultLength = 0;
    00537
    00538             } else {
    00539
    00540                 *ResultLength = deviceObjectName->Name.Length + sizeof(UNICODE_NULL);
    00541                 if (*ResultLength > BufferLength) {
    00542                     status = STATUS_BUFFER_TOO_SMALL;
    00543                 } else {
    00544
    00545                     RtlCopyMemory(PropertyBuffer,
    00546                                   deviceObjectName->Name.Buffer,
    00547                                   deviceObjectName->Name.Length);
    00548                     *(PWCHAR) (((PUCHAR) PropertyBuffer) + deviceObjectName->Name.Length) = L'\0';
    00549                 }
    00550             }
    00551         } else {
    00552             *ResultLength -= sizeof(OBJECT_NAME_INFORMATION);
    00553         }
    00554
    00555         ExFreePool (deviceObjectName);
    00556         return status;
    00557
    00558
    00559     case DevicePropertyBusTypeGuid:
    00560
    00561         deviceNode = (PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
    00562         if (deviceNode->ChildBusTypeIndex != 0xffff
    00563         &&  deviceNode->ChildBusTypeIndex < IopBusTypeGuidList->Count) {
    00564
    00565             *ResultLength = sizeof(GUID);
    00566
    00567             if(*ResultLength <= BufferLength) {
    00568
    00569                 RtlCopyMemory(PropertyBuffer,
    00570                               &(IopBusTypeGuidList->Guid[deviceNode->ChildBusTypeIndex]),
    00571                               sizeof(GUID));
    00572
    00573                 status = STATUS_SUCCESS;
    00574
    00575             } else {
    00576
    00577                 status = STATUS_BUFFER_TOO_SMALL;
    00578
    00579             }
    00580
    00581         } else {
    00582             status = STATUS_OBJECT_NAME_NOT_FOUND;
    00583         }
    00584
    00585         return status;
    00586
    00587     case DevicePropertyLegacyBusType:
    00588
    00589         deviceNode = (PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
    00590         if (deviceNode->ChildInterfaceType != InterfaceTypeUndefined) {
    00591
    00592             *ResultLength = sizeof(INTERFACE_TYPE);
    00593
    00594             if(*ResultLength <= BufferLength) {
    00595
    00596                 *(PINTERFACE_TYPE)PropertyBuffer = deviceNode->ChildInterfaceType;
    00597                 status = STATUS_SUCCESS;
    00598
    00599             } else {
    00600                 status = STATUS_BUFFER_TOO_SMALL;
    00601             }
    00602
    00603         } else {
    00604             status = STATUS_OBJECT_NAME_NOT_FOUND;
    00605         }
    00606
    00607         return status;
    00608
    00609     case DevicePropertyBusNumber:
    00610
    00611         //
    00612         // Retrieve the property from the parent's devnode field.
    00613         //
    00614
    00615         deviceNode = (PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
    00616         if ((deviceNode->ChildBusNumber & 0x80000000) != 0x80000000) {
    00617
    00618             *ResultLength = sizeof(ULONG);
    00619
    00620             if(*ResultLength <= BufferLength) {
    00621
    00622                 *(PULONG)PropertyBuffer = deviceNode->ChildBusNumber;
    00623                 status = STATUS_SUCCESS;
    00624
    00625             } else {
    00626                 status = STATUS_BUFFER_TOO_SMALL;
    00627             }
    00628
    00629         } else {
    00630             status = STATUS_OBJECT_NAME_NOT_FOUND;
    00631         }
    00632
    00633         return status;
    00634
    00635     case DevicePropertyEnumeratorName:
    00636
    00637         ASSERT (0 == (1 & BufferLength));  // had better be an even length
    00638
    00639         deviceNode = (PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
    00640         deviceInstanceName = deviceNode->InstancePath.Buffer;
    00641
    00642         //
    00643         // There should always be a string here, except for (possibly)
    00644         // HTREE\Root\0, but no one should ever be calling us with that PDO
    00645         // anyway.
    00646         //
    00647         ASSERT (deviceInstanceName);
    00648
    00649         //
    00650         // We know we're going to find a separator character (\) in the string,
    00651         // so the fact that unicode strings may not be null-terminated isn't
    00652         // a problem.
    00653         //
    00654         enumeratorNameEnd = wcschr(deviceInstanceName, OBJ_NAME_PATH_SEPARATOR);
    00655         ASSERT (enumeratorNameEnd);
    00656
    00657         //
    00658         // Compute required length, minus null terminating character.
    00659         //
    00660         length = (ULONG)((PUCHAR)enumeratorNameEnd - (PUCHAR)deviceInstanceName);
    00661
    00662         //
    00663         // Store required length in caller-supplied OUT parameter.
    00664         //
    00665         *ResultLength = length + sizeof(UNICODE_NULL);
    00666
    00667         if(*ResultLength > BufferLength) {
    00668             status = STATUS_BUFFER_TOO_SMALL;
    00669         } else {
    00670             memcpy((PUCHAR)PropertyBuffer, (PUCHAR)deviceInstanceName, length);
    00671             *(PWCHAR)((PUCHAR)PropertyBuffer + length) = UNICODE_NULL;
    00672             status = STATUS_SUCCESS;
    00673         }
    00674
    00675         return status;
    00676
    00677     case DevicePropertyAddress:
    00678
    00679         deviceNode = (PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
    00680
    00681         status = IopQueryDeviceCapabilities(deviceNode, &capabilities);
    00682
    00683         if (NT_SUCCESS(status) && (capabilities.Address != 0xFFFFFFFF)) {
    00684
    00685             *ResultLength = sizeof(ULONG);
    00686
    00687             if(*ResultLength <= BufferLength) {
    00688
    00689                 *(PULONG)PropertyBuffer = capabilities.Address;
    00690                 status = STATUS_SUCCESS;
    00691
    00692             } else {
    00693                 status = STATUS_BUFFER_TOO_SMALL;
    00694             }
    00695
    00696         } else {
    00697             status = STATUS_OBJECT_NAME_NOT_FOUND;
    00698         }
    00699
    00700         return status;
    00701
    00702     default:
    00703         status = STATUS_INVALID_PARAMETER_2;
    00704         goto clean0;
    00705     }
    00706
    00707     //
    00708     // Enter critical section and acquire a lock on the registry.  Both these
    00709     // mechanisms are required to prevent deadlock in the case where an APC
    00710     // routine calls this routine after the registry resource has been claimed
    00711     // in this case it would wait blocking this thread so the registry would
    00712     // never be released -> deadlock.  Critical sectioning the registry manipulatio
    00713     // portion solves this problem
    00714     //
    00715
    00716     KeEnterCriticalRegion();
    00717     ExAcquireResourceExclusive(&PpRegistryDeviceResource, TRUE);
    00718
    00719     //
    00720     // Based on the PDO specified by caller, find the handle of its device
    00721     // instance registry key.
    00722     //
    00723
    00724     status = IopDeviceObjectToDeviceInstance(DeviceObject, &handle, KEY_READ);
    00725     if (!NT_SUCCESS(status)) {
    00726         goto clean1;
    00727     }
    00728
    00729     //
    00730     // If the data is stored in a subkey then open this key and close the old one
    00731     //
    00732
    00733     if (keyName) {
    00734         HANDLE subKeyHandle;
    00735         UNICODE_STRING unicodeKey;
    00736
    00737         RtlInitUnicodeString(&unicodeKey, keyName);
    00738         status = IopOpenRegistryKeyEx( &subKeyHandle,
    00739                                        handle,
    00740                                        &unicodeKey,
    00741                                        KEY_READ
    00742                                        );
    00743
    00744         if(NT_SUCCESS(status)){
    00745             ZwClose(handle);
    00746             handle = subKeyHandle;
    00747         } else {
    00748             goto clean2;
    00749         }
    00750
    00751     }
    00752
    00753     //
    00754     // Read the registry value of the desired value name
    00755     //
    00756
    00757     status = IopGetRegistryValue (handle,
    00758                                   valueName,
    00759                                   &keyValueInformation);
    00760
    00761
    00762     //
    00763     // We have finished using the registry so clean up and release our resources
    00764     //
    00765
    00766 clean2:
    00767     ZwClose(handle);
    00768 clean1:
    00769     ExReleaseResource(&PpRegistryDeviceResource);
    00770     KeLeaveCriticalRegion();
    00771
    00772     //
    00773     // If we have been sucessful finding the info hand it back to the caller
    00774     //
    00775
    00776     if (NT_SUCCESS(status)) {
    00777
    00778         //
    00779         // Return the length of the data (or the required length if the buffer is too small)
    00780         //
    00781
    00782         *ResultLength = keyValueInformation->DataLength;
    00783
    00784         //
    00785         // Check that the buffer we have been given is big enough and that the value returned is
    00786         // of the correct registry type
    00787         //
    00788
    00789         if (keyValueInformation->DataLength <= BufferLength) {
    00790             if (keyValueInformation->Type == valueType) {
    00791                 RtlCopyMemory(PropertyBuffer,
    00792                               KEY_VALUE_DATA(keyValueInformation),
    00793                               keyValueInformation->DataLength);
    00794
    00795             } else {
    00796                status = STATUS_INVALID_PARAMETER_2;
    00797             }
    00798         } else {
    00799             status = STATUS_BUFFER_TOO_SMALL;
    00800         }
    00801
    00802         ExFreePool(keyValueInformation);
    00803     }
    00804
    00805 clean0:
    00806     return status;
    00807 }

NTKERNELAPI PDMA_ADAPTER IoGetDmaAdapter | ( | IN PDEVICE_OBJECT PhysicalDeviceObject | OPTIONAL,
|  | IN PDEVICE_DESCRIPTION | DeviceDescription,
|  | IN OUT PULONG | NumberOfMapRegisters
| ) |

Definition at line 8307 of file pnpioapi.c.

References ASSERT, ASSERT_PDO, BUS_INTERFACE_STANDARD, _BUS_INTERFACE_STANDARD::Context, DevicePropertyLegacyBusType, Executive, FALSE, _BUS_INTERFACE_STANDARD::GetDmaAdapter, HalGetDmaAdapter, _BUS_INTERFACE_STANDARD::InterfaceDereference, _DEVICE_DESCRIPTION::InterfaceType, IoBuildSynchronousFsdRequest(), IoCallDriver, IoGetAttachedDeviceReference(), IoGetDeviceProperty(), IoGetNextIrpStackLocation, _IRP::IoStatus, IRP_MJ_PNP, IRP_MN_QUERY_INTERFACE, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), _IO_STACK_LOCATION::MinorFunction, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, PAGED_CODE, _IO_STACK_LOCATION::Parameters, and PnpDefaultInterfaceType.

    08314                    :
    08315
    08316     This function returns the appropriate DMA adapter object for the device
    08317     defined in the device description structure.  This code is a wrapper
    08318     which queries the bus interface standard and then calls the returned
    08319     get DMA adapter function.   If an adapter object was not retrieved then
    08320     a legecy function is attempted.
    08321
    08322 Arguments:
    08323
    08324     PhysicalDeviceObject - Optionally, supplies the PDO for the device
    08325         requesting the DMA adapter.  If not supplied, this routine performs the
    08326         function of the non-PnP HalGetDmaAdapter routine.
    08327
    08328     DeviceDescriptor - Supplies a description of the deivce.
    08329
    08330     NumberOfMapRegisters - Returns the maximum number of map registers which
    08331         may be allocated by the device driver.
    08332
    08333 Return Value:
    08334
    08335     A pointer to the requested adapter object or NULL if an adapter could not
    08336     be created.
    08337
    08338 --*/
    08339
    08340 {
    08341     KEVENT event;
    08342     NTSTATUS status;
    08343     PIRP irp;
    08344     IO_STATUS_BLOCK ioStatusBlock;
    08345     PIO_STACK_LOCATION irpStack;
    08346     BUS_INTERFACE_STANDARD busInterface;
    08347     PDMA_ADAPTER dmaAdapter = NULL;
    08348     PDEVICE_DESCRIPTION deviceDescriptionToUse;
    08349     DEVICE_DESCRIPTION privateDeviceDescription;
    08350     ULONG resultLength;
    08351     PDEVICE_OBJECT targetDevice;
    08352
    08353     PAGED_CODE();
    08354
    08355     if (PhysicalDeviceObject != NULL) {
    08356
    08357         ASSERT_PDO(PhysicalDeviceObject);
    08358
    08359         //
    08360         // First off, determine whether or not the caller has requested that we
    08361         // automatically fill in the proper InterfaceType value into the
    08362         // DEVICE_DESCRIPTION structure used in retrieving the DMA adapter object.
    08363         // If so, then retrieve that interface type value into our own copy of
    08364         // the DEVICE_DESCRIPTION buffer.
    08365         //
    08366         if ((DeviceDescription->InterfaceType == InterfaceTypeUndefined) ||
    08367             (DeviceDescription->InterfaceType == PNPBus)) {
    08368             //
    08369             // Make a copy of the caller-supplied device description, so
    08370             // we can modify it to fill in the correct interface type.
    08371             //
    08372             RtlCopyMemory(&privateDeviceDescription,
    08373                           DeviceDescription,
    08374                           sizeof(DEVICE_DESCRIPTION)
    08375                          );
    08376
    08377             status = IoGetDeviceProperty(PhysicalDeviceObject,
    08378                                          DevicePropertyLegacyBusType,
    08379                                          sizeof(privateDeviceDescription.InterfaceType),
    08380                                          (PVOID)&(privateDeviceDescription.InterfaceType),
    08381                                          &resultLength
    08382                                         );
    08383
    08384             if (!NT_SUCCESS(status)) {
    08385
    08386                 ASSERT(status == STATUS_OBJECT_NAME_NOT_FOUND);
    08387
    08388                 //
    08389                 // Since the enumerator didn't tell us what interface type to
    08390                 // use for this PDO, we'll fall back to our default.  This is
    08391                 // ISA for machines where the legacy bus is ISA or EISA, and it
    08392                 // is MCA for machines whose legacy bus is MicroChannel.
    08393                 //
    08394                 privateDeviceDescription.InterfaceType = PnpDefaultInterfaceType;
    08395             }
    08396
    08397             //
    08398             // Use our private device description buffer from now on.
    08399             //
    08400             deviceDescriptionToUse = &privateDeviceDescription;
    08401
    08402         } else {
    08403             //
    08404             // Use the caller-supplied device description.
    08405             //
    08406             deviceDescriptionToUse = DeviceDescription;
    08407         }
    08408
    08409         //
    08410         // Now, query for the BUS_INTERFACE_STANDARD interface from the PDO.
    08411         //
    08412         KeInitializeEvent( &event, NotificationEvent, FALSE );
    08413
    08414         targetDevice = IoGetAttachedDeviceReference(PhysicalDeviceObject);
    08415
    08416         irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP,
    08417                                             targetDevice,
    08418                                             NULL,
    08419                                             0,
    08420                                             NULL,
    08421                                             &event,
    08422                                             &ioStatusBlock );
    08423
    08424         if (irp == NULL) {
    08425             return NULL;
    08426         }
    08427
    08428         RtlZeroMemory( &busInterface, sizeof( BUS_INTERFACE_STANDARD ));
    08429
    08430         irpStack = IoGetNextIrpStackLocation( irp );
    08431         irpStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
    08432         irpStack->Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_BUS_INTERFACE_STANDARD;
    08433         irpStack->Parameters.QueryInterface.Size = sizeof( BUS_INTERFACE_STANDARD );
    08434         irpStack->Parameters.QueryInterface.Version = 1;
    08435         irpStack->Parameters.QueryInterface.Interface = (PINTERFACE) &busInterface;
    08436         irpStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
    08437
    08438         //
    08439         // Initialize the status to error in case the ACPI driver decides not to
    08440         // set it correctly.
    08441         //
    08442
    08443         irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
    08444
    08445         status = IoCallDriver(targetDevice, irp);
    08446
    08447         if (status == STATUS_PENDING) {
    08448
    08449             KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
    08450             status = ioStatusBlock.Status;
    08451
    08452         }
    08453
    08454         ObDereferenceObject(targetDevice);
    08455
    08456         if (NT_SUCCESS( status)) {
    08457
    08458             if (busInterface.GetDmaAdapter != NULL) {
    08459
    08460
    08461                 dmaAdapter = busInterface.GetDmaAdapter( busInterface.Context,
    08462                                                          deviceDescriptionToUse,
    08463                                                          NumberOfMapRegisters );
    08464
    08465             }
    08466
    08467             //
    08468             // Dereference the interface
    08469             //
    08470
    08471             busInterface.InterfaceDereference( busInterface.Context );
    08472         }
    08473
    08474     } else {
    08475         //
    08476         // The caller didn't specify the PDO, so we'll just use the device
    08477         // description exactly as they specified it (i.e., we can't attempt to
    08478         // make our own determination of what interface type to use).
    08479         //
    08480         deviceDescriptionToUse = DeviceDescription;
    08481     }
    08482
    08483 #if !defined(NO_LEGACY_DRIVERS)
    08484     //
    08485     // If there is no DMA adapter, try the legacy mode code.
    08486     //
    08487
    08488     if (dmaAdapter == NULL) {
    08489
    08490         dmaAdapter = HalGetDmaAdapter( PhysicalDeviceObject,
    08491                                        deviceDescriptionToUse,
    08492                                        NumberOfMapRegisters );
    08493
    08494     }
    08495 #endif // NO_LEGACY_DRIVERS
    08496
    08497     return( dmaAdapter );
    08498 }

NTSTATUS IoGetLegacyVetoList | ( | OUT PWSTR *VetoList | OPTIONAL,
|  | OUT PPNP_VETO_TYPE | VetoType
| ) |

Definition at line 9712 of file pnpioapi.c.

References ASSERT, ExFreePool(), FALSE, IopAcquireEnumerationLock, IopAppendLegacyVeto(), IopGetLegacyVetoListDeviceNode(), IopGetLegacyVetoListDrivers(), IopReleaseEnumerationLock, IopRootDeviceNode, L, NT_SUCCESS, NTSTATUS(), NULL, PnPInitialized, RtlInitUnicodeString(), IO_GET_LEGACY_VETO_LIST_CONTEXT::Status, Status, IO_GET_LEGACY_VETO_LIST_CONTEXT::VetoList, IO_GET_LEGACY_VETO_LIST_CONTEXT::VetoListLength, and IO_GET_LEGACY_VETO_LIST_CONTEXT::VetoType.

Referenced by ExpQueryLegacyDriverInformation().

    09718                    :
    09719
    09720     This routine is used by PNP and PO to determine whether legacy drivers and
    09721     devices are installed in the system.  This routine is conceptually a
    09722     QUERY_REMOVE_DEVICE and QUERY_POWER-like interface for legacy drivers
    09723     and devices.
    09724
    09725 Parameters:
    09726
    09727     VetoList - A pointer to a PWSTR. (Optional)  If specified,
    09728         IoGetLegacyVetoList will allocate a veto list, and return a
    09729         pointer to the veto list in VetoList.
    09730
    09731     VetoType - A pointer to a PNP_VETO_TYPE.  If no legacy drivers
    09732         or devices are found in the system, VetoType is assigned
    09733         PNP_VetoTypeUnknown.  If one or more legacy drivers are installed,
    09734         VetoType is assigned PNP_VetoLegacyDriver.  If one or more
    09735         legacy devices are installed, VetoType is assigned
    09736         PNP_VetoLegacyDevice.  VetoType is assigned independent of
    09737         whether a VetoList is created.
    09738
    09739 ReturnValue:
    09740
    09741     An NTSTATUS value indicating whether the IoGetLegacyVetoList() operation
    09742     was successful.
    09743
    09744 --*/
    09745 {
    09746     NTSTATUS Status;
    09747     IO_GET_LEGACY_VETO_LIST_CONTEXT Context;
    09748     UNICODE_STRING UnicodeString;
    09749
    09750     //
    09751     // Initialize the veto list.
    09752     //
    09753
    09754     if (VetoList != NULL) {
    09755         *VetoList = NULL;
    09756     }
    09757
    09758     //
    09759     // Initialize the veto type.
    09760     //
    09761
    09762     ASSERT(VetoType != NULL);
    09763
    09764     *VetoType = PNP_VetoTypeUnknown;
    09765
    09766     //
    09767     // Initialize the status.
    09768     //
    09769
    09770     Status = STATUS_SUCCESS;
    09771
    09772     if (PnPInitialized == FALSE) {
    09773
    09774         //
    09775         // Can't touch anything, but nothing is really started either.
    09776         //
    09777         return Status;
    09778     }
    09779
    09780     //
    09781     // Initialize our local context.
    09782     //
    09783
    09784     Context.VetoList = VetoList;
    09785     Context.VetoListLength = 0;
    09786     Context.VetoType = VetoType;
    09787     Context.Status = &Status;
    09788
    09789     //
    09790     // Enumerate all driver objects.  This process can: (1) modify
    09791     // the veto list, (2) modify the veto type and/or (3) modify the
    09792     // status.
    09793     //
    09794
    09795     IopGetLegacyVetoListDrivers(&Context);
    09796
    09797     //
    09798     // If the driver enumeration process was successful and no legacy
    09799     // drivers were detected, enumerate all device nodes.  The same
    09800     // context values as above may be modified during device enumeration.
    09801     //
    09802
    09803     if (NT_SUCCESS(Status)) {
    09804
    09805         if (*VetoType == PNP_VetoTypeUnknown) {
    09806
    09807             IopAcquireEnumerationLock(NULL);
    09808
    09809             IopGetLegacyVetoListDeviceNode(
    09810                 IopRootDeviceNode,
    09811                 &Context
    09812             );
    09813
    09814             IopReleaseEnumerationLock(NULL);
    09815
    09816         }
    09817
    09818     }
    09819
    09820     //
    09821     // If the previous operation(s) was/were successful, and the caller
    09822     // provided a veto list pointer and we have constructed a veto
    09823     // list, terminate the veto list with an empty string, i.e. MULTI_SZ.
    09824     //
    09825
    09826     if (NT_SUCCESS(Status)) {
    09827
    09828         if (*VetoType != PNP_VetoTypeUnknown) {
    09829
    09830             if (VetoList != NULL) {
    09831
    09832                 RtlInitUnicodeString(
    09833                     &UnicodeString,
    09834                     L""
    09835                 );
    09836
    09837                 IopAppendLegacyVeto(
    09838                     &Context,
    09839                     &UnicodeString
    09840                 );
    09841
    09842             }
    09843
    09844         }
    09845
    09846     }
    09847
    09848     //
    09849     // If a previous operation was unsuccessful, free any veto list we may have
    09850     // allocated along the way.
    09851     //
    09852
    09853     if (!NT_SUCCESS(Status)) {
    09854
    09855         if (VetoList != NULL && *VetoList != NULL) {
    09856             ExFreePool(*VetoList);
    09857             *VetoList = NULL;
    09858         }
    09859
    09860     }
    09861
    09862     return Status;
    09863 }

NTSTATUS IoGetRelatedTargetDevice | ( | IN PFILE_OBJECT | FileObject,
|  | OUT PDEVICE_OBJECT * | DeviceObject
| ) |

Definition at line 8120 of file pnpioapi.c.

References IopGetRelatedTargetDevice(), NT_SUCCESS, NTSTATUS(), NULL, and _DEVICE_NODE::PhysicalDeviceObject.

Referenced by FsRtlNotifyVolumeEvent(), and NtSetVolumeInformationFile().

    08127                    :
    08128
    08129     IoGetRelatedTargetDevice retrieves the device object associated with
    08130     the specified file object and then sends a query device relations irp
    08131     to that device object.
    08132
    08133     NOTE: The PDO associated with the returned device node has been referenced,
    08134     and must be dereferenced when no longer needed.
    08135
    08136 Arguments:
    08137
    08138     FileObject - Specifies the file object that is associated with the device
    08139                  object that will receive the query device relations irp.
    08140
    08141     DeviceObject - Returns the related target device object.
    08142
    08143 ReturnValue
    08144
    08145     Returns an NTSTATUS value.
    08146
    08147 --*/
    08148
    08149 {
    08150     NTSTATUS status;
    08151     PDEVICE_NODE deviceNode = NULL;
    08152
    08153     status = IopGetRelatedTargetDevice( FileObject, &deviceNode );
    08154     if (NT_SUCCESS(status) && deviceNode != NULL) {
    08155         *DeviceObject = deviceNode->PhysicalDeviceObject;
    08156     }
    08157     return status;
    08158 }

VOID IoInvalidateDeviceRelations | ( | PDEVICE_OBJECT | DeviceObject,
|  | DEVICE_RELATION_TYPE | Type
| ) |

Definition at line 1395 of file pnpioapi.c.

References ASSERT_PDO, BusRelations, _DEVOBJ_EXTENSION::DeviceNode, _DEVICE_OBJECT::DeviceObjectExtension, DNF_BEING_ENUMERATED, DNF_ENUMERATION_REQUEST_QUEUED, DNF_IO_INVALIDATE_DEVICE_RELATIONS_PENDING, DNF_STARTED, EjectionRelations, _DEVICE_NODE::Flags, IopPnPSpinLock, IopRequestDeviceAction(), NULL, PoInvalidateDevicePowerRelations(), PowerRelations, and ReenumerateDeviceTree.

Referenced by IopProcessNewProfileStateCallback(), VideoPortCalloutThread(), and xxxUserPowerEventCalloutWorker().

    01402                    :
    01403
    01404     This API notifies the system that changes have occurred in the device
    01405     relations of the specified type for the supplied DeviceObject.   All
    01406     cached information concerning the relationships must be invalidated,
    01407     and if needed re-obtained via IRP_MN_QUERY_DEVICE_RELATIONS.
    01408
    01409 Parameters:
    01410
    01411     DeviceObject - the PDEVICE_OBJECT for which the specified relation type
    01412                    information has been invalidated.  This pointer is valid
    01413                    for the duration of the call.
    01414
    01415     Type - specifies the type of the relation being invalidated.
    01416
    01417 ReturnValue:
    01418
    01419     none.
    01420
    01421 --*/
    01422
    01423 {
    01424
    01425     PDEVICE_NODE deviceNode;
    01426     KIRQL        oldIrql;
    01427
    01428     ASSERT_PDO(DeviceObject);
    01429
    01430     switch (Type) {
    01431     case BusRelations:
    01432
    01433         //
    01434         // If the call was made before PnP completes device enumeration
    01435         // we can safely ignore it.  PnP manager will do it without
    01436         // driver's request.
    01437         //
    01438
    01439         deviceNode = (PDEVICE_NODE) DeviceObject->DeviceObjectExtension->DeviceNode;
    01440         if (deviceNode) {
    01441
    01442             ExAcquireSpinLock(&IopPnPSpinLock, &oldIrql);
    01443             if (deviceNode->Flags & DNF_BEING_ENUMERATED) {
    01444                 deviceNode->Flags |= DNF_IO_INVALIDATE_DEVICE_RELATIONS_PENDING;
    01445                 ExReleaseSpinLock(&IopPnPSpinLock, oldIrql);
    01446             } else if ((deviceNode->Flags & DNF_STARTED)                       &&
    01447                 !(deviceNode->Flags & DNF_ENUMERATION_REQUEST_QUEUED)) {
    01448                 deviceNode->Flags |= DNF_ENUMERATION_REQUEST_QUEUED;
    01449                 ExReleaseSpinLock(&IopPnPSpinLock, oldIrql);
    01450
    01451                 IopRequestDeviceAction( DeviceObject,
    01452                                         ReenumerateDeviceTree,
    01453                                         NULL,
    01454                                         NULL );
    01455             } else {
    01456                 ExReleaseSpinLock(&IopPnPSpinLock, oldIrql);
    01457             }
    01458         }
    01459         break;
    01460
    01461     case EjectionRelations:
    01462
    01463         //
    01464         // For Ejection relation change, we will ignore it.  We don't keep track
    01465         // the Ejection relation.  We will query the Ejection relation only when
    01466         // we are requested to eject a device.
    01467
    01468         break;
    01469
    01470     case PowerRelations:
    01471
    01472         //
    01473         // Call off to Po code, which will do the right thing
    01474         //
    01475         PoInvalidateDevicePowerRelations(DeviceObject);
    01476         break;
    01477     }
    01478 }

VOID IoInvalidateDeviceState | ( | IN PDEVICE_OBJECT | PhysicalDeviceObject | ) |

Definition at line 6281 of file pnpioapi.c.

References ASSERT_PDO, DNF_REMOVE_PENDING_CLOSES, DNF_STARTED, _DEVICE_NODE::Flags, IopInvalidateDeviceStateWorker(), IopQueueDeviceWorkItem(), and NULL.

    06287                    :
    06288
    06289     This API will cause the PnP manager to send the specified PDO an IRP_MN_QUERY_PNP_DEVICE_STATE
    06290     IRP.
    06291
    06292 Parameters:
    06293
    06294     PhysicalDeviceObject - Provides a pointer to the PDO who's state is to be invalidated.
    06295
    06296 Return Value:
    06297
    06298     none.
    06299
    06300 --*/
    06301 {
    06302     PDEVICE_NODE deviceNode;
    06303
    06304     ASSERT_PDO(PhysicalDeviceObject);
    06305
    06306     //
    06307     // If the call was made before PnP completes device enumeration
    06308     // we can safely ignore it.  PnP manager will do it without
    06309     // driver's request.  If the device was already removed or surprised
    06310     // removed then ignore it as well since this is only valid for started
    06311     // devices.
    06312     //
    06313
    06314     deviceNode = (PDEVICE_NODE)PhysicalDeviceObject->DeviceObjectExtension->DeviceNode;
    06315
    06316     if ((deviceNode->Flags & (DNF_STARTED | DNF_REMOVE_PENDING_CLOSES)) != DNF_STARTED) {
    06317         return;
    06318     }
    06319
    06320     IopQueueDeviceWorkItem( PhysicalDeviceObject,
    06321                             IopInvalidateDeviceStateWorker,
    06322                             NULL);
    06323 }

BOOLEAN IoIsWdmVersionAvailable | ( | IN UCHAR | MajorVersion,
|  | IN UCHAR | MinorVersion
| ) |

Definition at line 8275 of file pnpioapi.c.

References WDM_MAJORVERSION, and WDM_MINORVERSION.

    08282                    :
    08283
    08284     This routine reports whether WDM functionality is available that
    08285     is greater than or equal to the specified major and minor version.
    08286
    08287 Parameters:
    08288
    08289     MajorVersion - Supplies the WDM major version that is required.
    08290
    08291     MinorVersion - Supplies the WDM minor version that is required.
    08292
    08293 Return Value:
    08294
    08295     If WDM support is available at _at least_ the requested level, the
    08296     return value is TRUE, otherwise it is FALSE.
    08297
    08298 --*/
    08299
    08300 {
    08301     return ((MajorVersion < WDM_MAJORVERSION) ||
    08302             ((MajorVersion == WDM_MAJORVERSION) && (MinorVersion <= WDM_MINORVERSION)));
    08303 }

NTSTATUS IoNotifyPowerOperationVetoed | ( | IN POWER_ACTION | VetoedPowerOperation,
|  | IN PDEVICE_OBJECT TargetedDeviceObject | OPTIONAL,
|  | IN PDEVICE_OBJECT | VetoingDeviceObject
| ) |

Definition at line 9171 of file pnpioapi.c.

References _DEVOBJ_EXTENSION::DeviceNode, _DEVICE_OBJECT::DeviceObjectExtension, _DEVICE_NODE::InstancePath, IopRootDeviceNode, NULL, PAGED_CODE, _DEVICE_NODE::PhysicalDeviceObject, and PpSetPowerVetoEvent().

    09179 {
    09180     PDEVICE_NODE deviceNode, vetoingDeviceNode;
    09181     PDEVICE_OBJECT deviceObject;
    09182
    09183     PAGED_CODE();
    09184
    09185     //
    09186     // We have to types of power events, system wide (standby) and device
    09187     // targetted (warm eject). Rather than have two different veto mechanisms,
    09188     // we just retarget the operation against the root device if none is
    09189     // specified (hey, someone's gotta represent the system, right?).
    09190     //
    09191     if (TargetedDeviceObject) {
    09192
    09193         deviceObject = TargetedDeviceObject;
    09194
    09195     } else {
    09196
    09197         deviceObject = IopRootDeviceNode->PhysicalDeviceObject;
    09198     }
    09199
    09200     deviceNode = (PDEVICE_NODE)deviceObject->DeviceObjectExtension->DeviceNode;
    09201     if (!deviceNode) {
    09202         return STATUS_INVALID_PARAMETER_2;
    09203     }
    09204
    09205     vetoingDeviceNode = (PDEVICE_NODE)VetoingDeviceObject->DeviceObjectExtension->DeviceNode;
    09206     if (!vetoingDeviceNode) {
    09207         return STATUS_INVALID_PARAMETER_3;
    09208     }
    09209
    09210     return PpSetPowerVetoEvent(
    09211         VetoedPowerOperation,
    09212         NULL,
    09213         NULL,
    09214         deviceObject,
    09215         PNP_VetoDevice,
    09216         &vetoingDeviceNode->InstancePath
    09217         );
    09218 }

NTSTATUS IoOpenDeviceInterfaceRegistryKey | ( | IN PUNICODE_STRING | SymbolicLinkName,
|  | IN ACCESS_MASK | DesiredAccess,
|  | OUT PHANDLE | DeviceInterfaceKey
| ) |

Definition at line 3624 of file pnpioapi.c.

References ExAcquireResourceExclusive, ExReleaseResource, IopCreateRegistryKeyEx(), IopDeviceInterfaceKeysFromSymbolicLink(), KeEnterCriticalRegion, KeLeaveCriticalRegion, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PpRegistryDeviceResource, and TRUE.

    03632                    :
    03633
    03634     This routine will open the registry key where the data associated with a
    03635     specific device interface can be stored.
    03636
    03637 Parameters:
    03638
    03639     SymbolicLinkName - Supplies a pointer to the symbolic link name which was
    03640         returned by IoRegisterDeviceInterface when the device class was registered.
    03641
    03642     DesiredAccess - Supplies the access privileges to the key the caller wants.
    03643
    03644     DeviceInterfaceKey - Supplies a pointer to a handle which on success will
    03645         contain the handle to the requested registry key.
    03646
    03647 Return Value:
    03648
    03649     Status code that indicates whether or not the function was successful.
    03650
    03651 --*/
    03652
    03653 {
    03654     NTSTATUS status;
    03655     HANDLE hKey;
    03656     UNICODE_STRING unicodeString;
    03657
    03658     PAGED_CODE();
    03659
    03660     //
    03661     // Enter critical section and acquire a lock on the registry.  Both these
    03662     // mechanisms are required to prevent deadlock in the case where an APC
    03663     // routine calls this routine after the registry resource has been claimed
    03664     // in this case it would wait blocking this thread so the registry would
    03665     // never be released -> deadlock.  Critical sectioning the registry manipulation
    03666     // portion solves this problem
    03667     //
    03668
    03669     KeEnterCriticalRegion();
    03670     ExAcquireResourceExclusive(&PpRegistryDeviceResource, TRUE);
    03671
    03672     //
    03673     // Open the interface device key
    03674     //
    03675
    03676     status = IopDeviceInterfaceKeysFromSymbolicLink(SymbolicLinkName,
    03677                                                     KEY_READ,
    03678                                                     NULL,
    03679                                                     NULL,
    03680                                                     &hKey
    03681                                                     );
    03682     if(!NT_SUCCESS(status)) {
    03683         goto clean0;
    03684     }
    03685
    03686     //
    03687     // Open the "Device Parameters" subkey.
    03688     //
    03689
    03690     PiWstrToUnicodeString(&unicodeString, REGSTR_KEY_DEVICEPARAMETERS);
    03691     status = IopCreateRegistryKeyEx( DeviceInterfaceKey,
    03692                                      hKey,
    03693                                      &unicodeString,
    03694                                      DesiredAccess,
    03695                                      REG_OPTION_NON_VOLATILE,
    03696                                      NULL
    03697                                      );
    03698     ZwClose(hKey);
    03699
    03700 clean0:
    03701     ExReleaseResource(&PpRegistryDeviceResource);
    03702     KeLeaveCriticalRegion();
    03703
    03704     return status;
    03705 }

NTSTATUS IoOpenDeviceRegistryKey | ( | IN PDEVICE_OBJECT | PhysicalDeviceObject,
|  | IN ULONG | DevInstKeyType,
|  | IN ACCESS_MASK | DesiredAccess,
|  | OUT PHANDLE | DevInstRegKey
| ) |

Definition at line 810 of file pnpioapi.c.

References ASSERT, ExAcquireResourceExclusive, ExAllocatePool, ExFreePool(), ExReleaseResource, _DEVICE_NODE::InstancePath, IopCreateRegistryKeyEx(), IopDeviceObjectToDeviceInstance(), IopGetRegistryValue(), IopOpenDeviceParametersSubkey(), IopOpenRegistryKeyEx(), KeEnterCriticalRegion, KeLeaveCriticalRegion, KEY_VALUE_DATA, MAX_RESTPATH_BUF_LEN, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PagedPool, PATH_CONTROL_CLASS, PATH_CURRENTCONTROLSET, PATH_CURRENTCONTROLSET_HW_PROFILE_CURRENT, PATH_ENUM, PLUGPLAY_REGKEY_CURRENT_HWPROFILE, PLUGPLAY_REGKEY_DEVICE, PLUGPLAY_REGKEY_DRIVER, PpRegistryDeviceResource, RtlAppendUnicodeStringToString(), RtlAppendUnicodeToString(), and TRUE.

    00819                    :
    00820
    00821     This routine returns a handle to an opened registry key that the driver
    00822     may use to store/retrieve configuration information specific to a particular
    00823     device instance.
    00824
    00825     The driver must call ZwClose to close the handle returned from this api
    00826     when access is no longer required.
    00827
    00828 Parameters:
    00829
    00830     DeviceObject   - Supples the device object of the physical device instance to
    00831                      open a registry storage key for.  Normally it is a device object
    00832                      created by the hal bus extender.
    00833
    00834     DevInstKeyType - Supplies flags specifying which storage key associated with
    00835                      the device instance is to be opened.  May be a combination of
    00836                      the following value:
    00837
    00838                      PLUGPLAY_REGKEY_DEVICE - Open a key for storing device specific
    00839                          (driver-independent) information relating to the device instance.
    00840                          The flag may not be specified with PLUGPLAY_REGKEY_DRIVER.
    00841
    00842                      PLUGPLAY_REGKEY_DRIVER - Open a key for storing driver-specific
    00843                          information relating to the device instance,  This flag may
    00844                          not be specified with PLUGPLAY_REGKEY_DEVICE.
    00845
    00846                      PLUGPLAY_REGKEY_CURRENT_HWPROFILE - If this flag is specified,
    00847                          then a key in the current hardware profile branch will be
    00848                          opened for the specified storage type.  This allows the driver
    00849                          to access configuration information that is hardware profile
    00850                          specific.
    00851
    00852     DesiredAccess - Specifies the access mask for the key to be opened.
    00853
    00854     DevInstRegKey - Supplies the address of a variable that receives a handle to the
    00855                     opened key for the specified registry storage location.
    00856
    00857 Return Value:
    00858
    00859     Status code that indicates whether or not the function was successful.
    00860
    00861 --*/
    00862
    00863 {
    00864
    00865     NTSTATUS status, appendStatus;
    00866     HANDLE hBasePath;
    00867     UNICODE_STRING unicodeBasePath, unicodeRestPath;
    00868
    00869     PAGED_CODE();
    00870
    00871     //
    00872     // Until SCSIPORT stops passing non PDOs allow the system to boot.
    00873     //
    00874     // ASSERT_PDO(PhysicalDeviceObject);
    00875     //
    00876
    00877     //
    00878     // Initialise out parameters
    00879     //
    00880
    00881     *DevInstRegKey = NULL;
    00882
    00883     //
    00884     // Allocate a buffer to build the RestPath string in
    00885     //
    00886
    00887     if(!(unicodeRestPath.Buffer = ExAllocatePool(PagedPool, MAX_RESTPATH_BUF_LEN))) {
    00888         status = STATUS_INSUFFICIENT_RESOURCES;
    00889         goto clean0;
    00890     }
    00891
    00892     unicodeRestPath.Length=0;
    00893     unicodeRestPath.MaximumLength=MAX_RESTPATH_BUF_LEN;
    00894
    00895     //
    00896     // Select the base path to the CurrentControlSet based on if we are dealing with
    00897     // a hardware profile or not
    00898     //
    00899
    00900     if(DevInstKeyType & PLUGPLAY_REGKEY_CURRENT_HWPROFILE) {
    00901         PiWstrToUnicodeString(&unicodeBasePath, PATH_CURRENTCONTROLSET_HW_PROFILE_CURRENT);
    00902
    00903     } else {
    00904         PiWstrToUnicodeString(&unicodeBasePath, PATH_CURRENTCONTROLSET);
    00905     }
    00906
    00907     //
    00908     // Enter critical section and acquire a lock on the registry.  Both these
    00909     // mechanisms are required to prevent deadlock in the case where an APC
    00910     // routine calls this routine after the registry resource has been claimed
    00911     // in this case it would wait blocking this thread so the registry would
    00912     // never be released -> deadlock.  Critical sectioning the registry manipulation
    00913     // portion solves this problem
    00914     //
    00915
    00916     KeEnterCriticalRegion();
    00917     ExAcquireResourceExclusive(&PpRegistryDeviceResource, TRUE);
    00918
    00919     //
    00920     // Open the base registry key
    00921     //
    00922
    00923     status = IopOpenRegistryKeyEx( &hBasePath,
    00924                                    NULL,
    00925                                    &unicodeBasePath,
    00926                                    KEY_READ
    00927                                    );
    00928
    00929     if(!NT_SUCCESS(status)) {
    00930         goto clean1;
    00931     }
    00932
    00933     //
    00934     // Build the RestPath string
    00935     //
    00936
    00937     switch (DevInstKeyType) {
    00938
    00939     case PLUGPLAY_REGKEY_DEVICE:
    00940     case PLUGPLAY_REGKEY_DEVICE + PLUGPLAY_REGKEY_CURRENT_HWPROFILE:
    00941         {
    00942             PDEVICE_NODE pDeviceNode;
    00943
    00944             //
    00945             // Initialise the rest path with Enum\
    00946             //
    00947
    00948             appendStatus = RtlAppendUnicodeToString(&unicodeRestPath, PATH_ENUM);
    00949             ASSERT(NT_SUCCESS( appendStatus ));
    00950             //
    00951             // Get the Enumerator\DeviceID\InstanceID path from the DeviceNode
    00952             //
    00953
    00954             pDeviceNode = (PDEVICE_NODE) PhysicalDeviceObject->DeviceObjectExtension->DeviceNode;
    00955
    00956             //
    00957             // Ensure this is a PDO and not an FDO (only PDO's have a DeviceNode)
    00958             //
    00959
    00960             if (pDeviceNode) {
    00961                 appendStatus = RtlAppendUnicodeStringToString(&unicodeRestPath, &(pDeviceNode->InstancePath));
    00962                 ASSERT(NT_SUCCESS( appendStatus ));
    00963             } else {
    00964                 status = STATUS_INVALID_DEVICE_REQUEST;
    00965             }
    00966
    00967             break;
    00968         }
    00969
    00970     case PLUGPLAY_REGKEY_DRIVER:
    00971     case PLUGPLAY_REGKEY_DRIVER + PLUGPLAY_REGKEY_CURRENT_HWPROFILE:
    00972         {
    00973
    00974             HANDLE hDeviceKey;
    00975             PKEY_VALUE_FULL_INFORMATION pDriverKeyInfo;
    00976
    00977             //
    00978             // Initialise the rest path with Control\Class\
    00979             //
    00980
    00981             appendStatus = RtlAppendUnicodeToString(&unicodeRestPath, PATH_CONTROL_CLASS);
    00982             ASSERT(NT_SUCCESS( appendStatus ));
    00983
    00984             //
    00985             // Open the device instance key for this device
    00986             //
    00987
    00988             status = IopDeviceObjectToDeviceInstance(PhysicalDeviceObject, &hDeviceKey, KEY_READ);
    00989
    00990             if(!NT_SUCCESS(status)){
    00991                 goto clean1;
    00992             }
    00993
    00994             //
    00995             // See if we have a driver value
    00996             //
    00997
    00998             status = IopGetRegistryValue(hDeviceKey, REGSTR_VALUE_DRIVER, &pDriverKeyInfo );
    00999
    01000             if(NT_SUCCESS(status)){
    01001
    01002                 if(pDriverKeyInfo->Type == REG_SZ) {
    01003
    01004                 //
    01005                 // Append <DevInstClass><ClassInstanceOrdinal>
    01006                 //
    01007
    01008                 appendStatus = RtlAppendUnicodeToString(&unicodeRestPath, (PWSTR) KEY_VALUE_DATA(pDriverKeyInfo));
    01009                 ASSERT(NT_SUCCESS( appendStatus ));
    01010
    01011                 } else {
    01012                     //
    01013                     // We have a driver key with a non REG_SZ type - something is wrong - blame the PDO!
    01014                     //
    01015
    01016                     status = STATUS_INVALID_PARAMETER_1;
    01017                 }
    01018
    01019                 ExFreePool(pDriverKeyInfo);
    01020             }
    01021
    01022             ZwClose(hDeviceKey);
    01023
    01024             break;
    01025         }
    01026     default:
    01027         status = STATUS_INVALID_PARAMETER_3;
    01028         goto clean2;
    01029     }
    01030
    01031
    01032     //
    01033     // If we succeeded in building the rest path then open the key and hand it back to the caller
    01034     //
    01035
    01036     if (NT_SUCCESS(status)){
    01037         if (DevInstKeyType == PLUGPLAY_REGKEY_DEVICE) {
    01038
    01039             status = IopOpenDeviceParametersSubkey(DevInstRegKey,
    01040                                                    hBasePath,
    01041                                                    &unicodeRestPath,
    01042                                                    DesiredAccess);
    01043         } else {
    01044
    01045             status = IopCreateRegistryKeyEx( DevInstRegKey,
    01046                                              hBasePath,
    01047                                              &unicodeRestPath,
    01048                                              DesiredAccess,
    01049                                              REG_OPTION_NON_VOLATILE,
    01050                                              NULL
    01051                                              );
    01052         }
    01053     }
    01054
    01055     //
    01056     // Free up resources
    01057     //
    01058
    01059 clean2:
    01060     ZwClose(hBasePath);
    01061 clean1:
    01062     ExReleaseResource(&PpRegistryDeviceResource);
    01063     KeLeaveCriticalRegion();
    01064     ExFreePool(unicodeRestPath.Buffer);
    01065 clean0:
    01066     return status;
    01067
    01068 }

NTSTATUS IopAllocateBuffer | ( | IN PBUFFER_INFO | Info,
|  | IN ULONG | Size
| ) |

Definition at line 2427 of file pnpioapi.c.

References ASSERT, ExAllocatePool, PagedPool, and Size.

Referenced by IopGetDeviceInterfaces(), IopProcessCriticalDeviceRoutine(), and IopRemoveDeviceInterfaces().

    02434                    :
    02435
    02436     Allocates a buffer of Size bytes and initialises the BUFFER_INFO
    02437     structure so the current position is at the start of the buffer.
    02438
    02439 Parameters:
    02440
    02441     Info - Pointer to a buffer info structure to be used to manage the new
    02442            buffer
    02443
    02444     Size - The number of bytes to be allocated for the buffer
    02445
    02446 Return Value:
    02447
    02448     Status code that indicates whether or not the function was successful.
    02449
    02450 --*/
    02451
    02452 {
    02453     ASSERT(Info);
    02454
    02455     if (!(Info->Buffer = ExAllocatePool(PagedPool, Size))) {
    02456         return STATUS_INSUFFICIENT_RESOURCES;
    02457     }
    02458
    02459     Info->Current = Info->Buffer;
    02460     Info->MaxSize = Size;
    02461
    02462     return STATUS_SUCCESS;
    02463 }

NTSTATUS IopAllocateUnicodeString | ( | IN OUT PUNICODE_STRING | String,
|  | IN USHORT | Length
| ) |

Definition at line 5619 of file pnpioapi.c.

References ExAllocatePool, PAGED_CODE, PagedPool, and String.

Referenced by IopBuildSymbolicLinkStrings(), IopOpenOrCreateDeviceInterfaceSubKeys(), IopRemoveDeviceInterfaces(), IopSetRegistryStringValue(), and IopUnregisterDeviceInterface().

    05626                    :
    05627
    05628     This routine allocates a buffer for a unicode string of a given length
    05629     and initialises the UNICODE_STRING structure appropriately. When the
    05630     string is no longer required it can be freed using IopFreeAllocatedString.
    05631     The buffer also be directly deleted by ExFreePool and so can be handed
    05632     back to a caller.
    05633
    05634 Parameters:
    05635
    05636     String - Supplies a pointer to an uninitialised unicode string which will
    05637         be manipulated by the function.
    05638
    05639     Length - The number of BYTES long that the string will be.
    05640
    05641 Return Value:
    05642
    05643     Either STATUS_INSUFFICIENT_RESOURCES indicating paged pool is exhausted or
    05644     STATUS_SUCCESS.
    05645
    05646 Remarks:
    05647
    05648     The buffer allocated will be one character (2 bytes) more than length specified.
    05649     This is to allow for easy null termination of the strings - eg for registry
    05650     storage.
    05651
    05652 --*/
    05653
    05654 {
    05655     PAGED_CODE();
    05656
    05657     String->Length = 0;
    05658     String->MaximumLength = Length + sizeof(UNICODE_NULL);
    05659
    05660     if(!(String->Buffer = ExAllocatePool(PagedPool, Length + sizeof(UNICODE_NULL)))) {
    05661         return STATUS_INSUFFICIENT_RESOURCES;
    05662     } else {
    05663         return STATUS_SUCCESS;
    05664     }
    05665 }

NTSTATUS IopAppendBuffer | ( | IN PBUFFER_INFO | Info,
|  | IN PVOID | Data,
|  | IN ULONG | DataSize
| ) |

Definition at line 2575 of file pnpioapi.c.

References ASSERT, IopResizeBuffer(), NT_SUCCESS, NTSTATUS(), and TRUE.

Referenced by IopGetDeviceInterfaces().

    02583                    :
    02584
    02585     Copies the data to the end of the buffer, resizing if necessary.  The current
    02586     position is set to the end of the data just added.
    02587
    02588 Parameters:
    02589
    02590     Info - Pointer to a buffer info structure to be used to manage the buffer
    02591
    02592     Data - Pointer to the data to be added to the buffer
    02593
    02594     DataSize - The size of the data pointed to by Data in bytes
    02595
    02596 Return Value:
    02597
    02598     Status code that indicates whether or not the function was successful.
    02599
    02600 --*/
    02601 {
    02602
    02603     NTSTATUS status = STATUS_SUCCESS;
    02604     ULONG free, used;
    02605
    02606     ASSERT(Info);
    02607
    02608     used = (ULONG)(Info->Current - Info->Buffer);
    02609     free = Info->MaxSize - used;
    02610
    02611     if (free < DataSize) {
    02612         status = IopResizeBuffer(Info, used + DataSize, TRUE);
    02613
    02614         if (!NT_SUCCESS(status)) {
    02615             goto clean0;
    02616         }
    02617
    02618     }
    02619
    02620     //
    02621     // Copy the data into the buffer
    02622     //
    02623
    02624     RtlCopyMemory(Info->Current,
    02625                   Data,
    02626                   DataSize);
    02627
    02628     //
    02629     // Advance down the buffer
    02630     //
    02631
    02632     Info->Current += DataSize;
    02633
    02634 clean0:
    02635     return status;
    02636
    02637 }

BOOLEAN IopAppendLegacyVeto | ( | IN PIO_GET_LEGACY_VETO_LIST_CONTEXT | Context,
|  | IN PUNICODE_STRING | VetoName
| ) |

Definition at line 9357 of file pnpioapi.c.

References Buffer, ExAllocatePool, ExFreePool(), FALSE, L, NonPagedPool, NULL, and TRUE.

Referenced by IoGetLegacyVetoList(), IopGetLegacyVetoListDevice(), and IopGetLegacyVetoListDrivers().

    09363                    :
    09364
    09365     This routine appends a veto (driver name or device instance path) to the
    09366     veto list.
    09367
    09368 Parameters:
    09369
    09370     Context - An IO_GET_LEGACY_VETO_LIST_CONTEXT pointer.
    09371
    09372     VetoName - The name of the driver/device to append to the veto list.
    09373
    09374 ReturnValue:
    09375
    09376     A BOOLEAN which indicates whether the append operation was successful.
    09377
    09378 --*/
    09379 {
    09380     ULONG Length;
    09381     PWSTR Buffer;
    09382
    09383     //
    09384     // Compute the length of the (new) veto list.  This is the length of
    09385     // the old veto list + the size of the new veto + the size of the
    09386     // terminating '\0'.
    09387     //
    09388
    09389     Length = Context->VetoListLength + VetoName->Length + sizeof (WCHAR);
    09390
    09391     //
    09392     // Allocate the new veto list.
    09393     //
    09394
    09395     Buffer = ExAllocatePool(
    09396                  NonPagedPool,
    09397                  Length
    09398              );
    09399
    09400     //
    09401     // If we succeeded in allocating the new veto list, copy the old
    09402     // veto list to the new list, append the new veto, and finally,
    09403     // append a terminating '\0'.  Otherwise, update the status to
    09404     // indicate an error; IopGetLegacyVetoList will free the veto list
    09405     // before it returns.
    09406     //
    09407
    09408     if (Buffer != NULL) {
    09409
    09410         if (*Context->VetoList != NULL) {
    09411
    09412             RtlMoveMemory(
    09413                 Buffer,
    09414                 *Context->VetoList,
    09415                 Context->VetoListLength
    09416             );
    09417
    09418             ExFreePool(*Context->VetoList);
    09419
    09420         }
    09421
    09422         RtlMoveMemory(
    09423             &Buffer[Context->VetoListLength / sizeof (WCHAR)],
    09424             VetoName->Buffer,
    09425             VetoName->Length
    09426         );
    09427
    09428         Buffer[Length / sizeof (WCHAR) - 1] = L'\0';
    09429
    09430         *Context->VetoList = Buffer;
    09431         Context->VetoListLength = Length;
    09432
    09433         return TRUE;
    09434
    09435     } else {
    09436
    09437         *Context->Status = STATUS_INSUFFICIENT_RESOURCES;
    09438
    09439         return FALSE;
    09440
    09441     }
    09442 }

NTSTATUS IopBuildSymbolicLinkStrings | ( | IN PUNICODE_STRING | DeviceString,
|  | IN PUNICODE_STRING | GuidString,
|  | IN PUNICODE_STRING ReferenceString | OPTIONAL,
|  | OUT PUNICODE_STRING | UserString,
|  | OUT PUNICODE_STRING | KernelString
| ) |

Definition at line 5137 of file pnpioapi.c.

References ASSERT, IopAllocateUnicodeString(), IopConstStringSize, IopFreeAllocatedUnicodeString(), IopReplaceSeperatorWithPound(), KERNEL_SYMLINK_STRING_PREFIX, NT_SUCCESS, NTSTATUS(), PAGED_CODE, REPLACED_SEPERATOR_STRING, RtlAppendUnicodeStringToString(), RtlAppendUnicodeToString(), RtlCopyUnicodeString(), SEPERATOR_STRING, USER_SYMLINK_STRING_PREFIX, and USHORT.

Referenced by IoGetDeviceInterfaceAlias(), and IopRegisterDeviceInterface().

    05146                    :
    05147
    05148     This routine will construct various strings used in the registration of
    05149     function device class associations (IoRegisterDeviceClassAssociation).
    05150     The specific strings are detailed below
    05151
    05152 Parameters:
    05153
    05154     DeviceString - Supplies a pointer to the instance path of the device.
    05155         It is of the form <Enumerator>\<Device>\<Instance>.
    05156
    05157     GuidString - Supplies a pointer to the string representation of the
    05158         function class guid.
    05159
    05160     ReferenceString - Supplies a pointer to the reference string for the given
    05161         device to exhibit the given function.  This is optional
    05162
    05163     UserString - Supplies a pointer to an uninitialised string which on success
    05164         will contain the string to be assigned to the "SymbolicLink" value under the
    05165         KeyString.  It is of the format \\?\<MungedDeviceString>\<GuidString>\<Reference>
    05166         When no longer required it should be freed using IopFreeAllocatedUnicodeString.
    05167
    05168     KernelString - Supplies a pointer to an uninitialised string which on success
    05169         will contain the kernel mode path of the device and is of the format
    05170         \??\<MungedDeviceString>\<GuidString>\<Reference>. When no longer required it
    05171         should be freed using IopFreeAllocatedUnicodeString.
    05172
    05173 Return Value:
    05174
    05175     Status code that indicates whether or not the function was successful.
    05176
    05177 --*/
    05178
    05179 {
    05180     NTSTATUS status;
    05181     USHORT length, count;
    05182     UNICODE_STRING mungedDeviceString;
    05183
    05184     PAGED_CODE();
    05185
    05186     //
    05187     // The code is optimised to use the fact that \\.\ and \??\ are the same size - if
    05188     // these prefixes change then we need to change the code.
    05189     //
    05190
    05191     ASSERT(IopConstStringSize(KERNEL_SYMLINK_STRING_PREFIX) == IopConstStringSize(USER_SYMLINK_STRING_PREFIX));
    05192
    05193     //
    05194     // Calculate the lengths of the strings
    05195     //
    05196
    05197     length = IopConstStringSize(KERNEL_SYMLINK_STRING_PREFIX) + DeviceString->Length +
    05198              IopConstStringSize(REPLACED_SEPERATOR_STRING) + GuidString->Length;
    05199
    05200     if(ARGUMENT_PRESENT(ReferenceString)) {
    05201         length += IopConstStringSize(SEPERATOR_STRING) + ReferenceString->Length;
    05202     }
    05203
    05204     //
    05205     // Allocate space for the strings
    05206     //
    05207
    05208     status = IopAllocateUnicodeString(KernelString, length);
    05209     if (!NT_SUCCESS(status)) {
    05210         goto clean0;
    05211     }
    05212
    05213     status = IopAllocateUnicodeString(UserString, length);
    05214     if (!NT_SUCCESS(status)) {
    05215         goto clean1;
    05216     }
    05217
    05218     //
    05219     // Allocate a temporary string to hold the munged device string
    05220     //
    05221
    05222     status = IopAllocateUnicodeString(&mungedDeviceString, DeviceString->Length);
    05223     if (!NT_SUCCESS(status)) {
    05224         goto clean2;
    05225     }
    05226
    05227     //
    05228     // Copy and munge the device string
    05229     //
    05230
    05231     status = IopReplaceSeperatorWithPound(&mungedDeviceString, DeviceString);
    05232     if (!NT_SUCCESS(status)) {
    05233         goto clean3;
    05234     }
    05235
    05236     //
    05237     // Construct the user mode string
    05238     //
    05239
    05240     RtlAppendUnicodeToString(UserString, USER_SYMLINK_STRING_PREFIX);
    05241     RtlAppendUnicodeStringToString(UserString, &mungedDeviceString);
    05242     RtlAppendUnicodeToString(UserString, REPLACED_SEPERATOR_STRING);
    05243     RtlAppendUnicodeStringToString(UserString, GuidString);
    05244
    05245     if (ARGUMENT_PRESENT(ReferenceString)) {
    05246         RtlAppendUnicodeToString(UserString, SEPERATOR_STRING);
    05247         RtlAppendUnicodeStringToString(UserString, ReferenceString);
    05248     }
    05249
    05250     ASSERT( UserString->Length == length );
    05251
    05252     //
    05253     // Construct the kernel mode string by replacing the prefix on the value string
    05254     //
    05255
    05256     RtlCopyUnicodeString(KernelString, UserString);
    05257     RtlCopyMemory(KernelString->Buffer,
    05258                   KERNEL_SYMLINK_STRING_PREFIX,
    05259                   IopConstStringSize(KERNEL_SYMLINK_STRING_PREFIX)
    05260                  );
    05261
    05262 clean3:
    05263     IopFreeAllocatedUnicodeString(&mungedDeviceString);
    05264
    05265 clean2:
    05266     if (!NT_SUCCESS(status)) {
    05267         IopFreeAllocatedUnicodeString(UserString);
    05268     }
    05269
    05270 clean1:
    05271     if (!NT_SUCCESS(status)) {
    05272         IopFreeAllocatedUnicodeString(KernelString);
    05273     }
    05274
    05275 clean0:
    05276     return status;
    05277 }

VOID IopDereferenceNotify | ( | PNOTIFY_ENTRY_HEADER | Notify | ) |

Definition at line 6600 of file pnpioapi.c.

References ASSERT, _NOTIFY_ENTRY_HEADER::DriverObject, _NOTIFY_ENTRY_HEADER::EventCategory, EventCategoryTargetDeviceChange, ExFreePool(), NULL, ObDereferenceObject, PAGED_CODE, _TARGET_DEVICE_NOTIFY_ENTRY::PhysicalDeviceObject, PTARGET_DEVICE_NOTIFY_ENTRY, _NOTIFY_ENTRY_HEADER::RefCount, and _NOTIFY_ENTRY_HEADER::Unregistered.

Referenced by IopNotifyDeviceClassChange(), IopNotifyHwProfileChange(), IopNotifyTargetDeviceChange(), IopProcessDeferredRegistrations(), and IoUnregisterPlugPlayNotification().

    06606                    :
    06607
    06608     This routine decrements the reference count for a notification entry, removing
    06609     the entry from the list and freeing the associated memory if there are no
    06610     outstanding reference counts.
    06611
    06612 Parameters:
    06613
    06614     Notify - Supplies a pointer to the notification entry to be referenced
    06615
    06616 Return Value:
    06617
    06618     None
    06619
    06620 Note:
    06621
    06622     The appropriate symchronization lock must be held on the notification
    06623     list before this routine can be called
    06624
    06625 --*/
    06626
    06627 {
    06628     PAGED_CODE();
    06629
    06630     ASSERT(Notify);
    06631     ASSERT(Notify->RefCount > 0);
    06632
    06633     Notify->RefCount--;
    06634
    06635     if (Notify->RefCount == 0) {
    06636
    06637         //
    06638         // If the refcount is zero then the node should have been deregisterd
    06639         // and is no longer needs to be in the list so remove and free it
    06640         //
    06641
    06642         ASSERT(Notify->Unregistered);
    06643
    06644         //
    06645         // Dereference the driver object that registered for notifications
    06646         //
    06647
    06648         ObDereferenceObject(Notify->DriverObject);
    06649
    06650         //
    06651         // If this notification entry is for target device change, dereference
    06652         // the PDO upon which this notification entry was hooked.
    06653         //
    06654
    06655         if (Notify->EventCategory == EventCategoryTargetDeviceChange) {
    06656             PTARGET_DEVICE_NOTIFY_ENTRY entry = (PTARGET_DEVICE_NOTIFY_ENTRY)Notify;
    06657
    06658             if (entry->PhysicalDeviceObject) {
    06659                 ObDereferenceObject(entry->PhysicalDeviceObject);
    06660                 entry->PhysicalDeviceObject = NULL;
    06661             }
    06662         }
    06663
    06664         RemoveEntryList((PLIST_ENTRY)Notify);
    06665
    06666         ExFreePool(Notify);
    06667
    06668     }
    06669 }

NTSTATUS IopDeviceInterfaceKeysFromSymbolicLink | ( | IN PUNICODE_STRING | SymbolicLinkName,
|  | IN ACCESS_MASK | DesiredAccess,
|  | OUT PHANDLE DeviceInterfaceClassKey | OPTIONAL,
|  | OUT PHANDLE DeviceInterfaceKey | OPTIONAL,
|  | OUT PHANDLE DeviceInterfaceInstanceKey | OPTIONAL
| ) |

Definition at line 3708 of file pnpioapi.c.

References ExAcquireResourceExclusive, ExReleaseResource, FALSE, IopOpenOrCreateDeviceInterfaceSubKeys(), IopOpenRegistryKeyEx(), IopParseSymbolicLinkName(), KeEnterCriticalRegion, KeLeaveCriticalRegion, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PpRegistryDeviceResource, and TRUE.

Referenced by IoGetDeviceInterfaceAlias(), IoOpenDeviceInterfaceRegistryKey(), IopProcessSetInterfaceState(), and IopUnregisterDeviceInterface().

    03718                    :
    03719
    03720     This routine will open the registry key where the data associated with the
    03721     device pointed to by SymbolicLinkName is stored.  If the path does not exist
    03722     it will not be created.
    03723
    03724 Parameters:
    03725
    03726     SymbolicLinkName - Supplies a pointer to the symbolic link name.
    03727
    03728     DesiredAccess - Supplies the access privto the function class instance key the
    03729         caller wants.
    03730
    03731     DeviceInterfaceClassKey - Optionally, supplies the address of a variable that
    03732         receives a handle to the device class key for the interface.
    03733
    03734     DeviceInterfaceKey - Optionally, supplies the address of a variable that receives
    03735         a handle to the device interface (parent) key.
    03736
    03737     DeviceInterfaceInstanceKey - Optionally, Supplies the address of a variable that
    03738         receives a handle to the device interface instance key (i.e., the
    03739         refstring-specific one).
    03740
    03741 Return Value:
    03742
    03743     Status code that indicates whether or not the function was successful.
    03744
    03745
    03746 --*/
    03747
    03748 {
    03749     NTSTATUS status;
    03750     UNICODE_STRING guidString, tempString;
    03751     HANDLE hDeviceClasses, hFunctionClass;
    03752
    03753     PAGED_CODE();
    03754
    03755     //
    03756     // Get guid from symbolic link name
    03757     //
    03758     status = IopParseSymbolicLinkName(SymbolicLinkName, NULL, NULL, &guidString, NULL, NULL, NULL);
    03759
    03760     if(!NT_SUCCESS(status)){
    03761         goto clean0;
    03762     }
    03763
    03764     //
    03765     // Enter critical section and acquire a lock on the registry.  Both these
    03766     // mechanisms are required to prevent deadlock in the case where an APC
    03767     // routine calls this routine after the registry resource has been claimed
    03768     // in this case it would wait blocking this thread so the registry would
    03769     // never be released -> deadlock.  Critical sectioning the registry manipulation
    03770     // portion solves this problem
    03771     //
    03772
    03773     KeEnterCriticalRegion();
    03774     ExAcquireResourceExclusive(&PpRegistryDeviceResource, TRUE);
    03775
    03776     //
    03777     // Open HKLM\System\CurrentControlSet\Control\DeviceClasses key
    03778     //
    03779
    03780     PiWstrToUnicodeString(&tempString, REGSTR_FULL_PATH_DEVICE_CLASSES);
    03781     status = IopOpenRegistryKeyEx( &hDeviceClasses,
    03782                                    NULL,
    03783                                    &tempString,
    03784                                    KEY_READ
    03785                                    );
    03786
    03787     if( !NT_SUCCESS(status) ){
    03788         goto clean1;
    03789     }
    03790
    03791     //
    03792     // Open function class GUID key
    03793     //
    03794
    03795     status = IopOpenRegistryKeyEx( &hFunctionClass,
    03796                                    hDeviceClasses,
    03797                                    &guidString,
    03798                                    KEY_READ
    03799                                    );
    03800
    03801     if( !NT_SUCCESS(status) ){
    03802         goto clean2;
    03803     }
    03804
    03805     //
    03806     // Open device interface instance key
    03807     //
    03808     status = IopOpenOrCreateDeviceInterfaceSubKeys(DeviceInterfaceKey,
    03809                                                    NULL,
    03810                                                    DeviceInterfaceInstanceKey,
    03811                                                    NULL,
    03812                                                    hFunctionClass,
    03813                                                    SymbolicLinkName,
    03814                                                    DesiredAccess,
    03815                                                    FALSE
    03816                                                   );
    03817
    03818     if((!NT_SUCCESS(status)) || (!ARGUMENT_PRESENT(DeviceInterfaceClassKey))) {
    03819         ZwClose(hFunctionClass);
    03820     } else {
    03821         *DeviceInterfaceClassKey = hFunctionClass;
    03822     }
    03823
    03824 clean2:
    03825     ZwClose(hDeviceClasses);
    03826 clean1:
    03827     ExReleaseResource(&PpRegistryDeviceResource);
    03828     KeLeaveCriticalRegion();
    03829 clean0:
    03830     return status;
    03831
    03832 }

NTSTATUS IopDoDeferredSetInterfaceState | ( | IN PDEVICE_NODE | DeviceNode | ) |

Definition at line 9866 of file pnpioapi.c.

References _DEVICE_OBJECT::AttachedDevice, _DEVICE_OBJECT::DeviceObjectExtension, DOE_START_PENDING, ExAcquireResourceExclusive, ExFreePool(), ExReleaseResource, _DEVOBJ_EXTENSION::ExtensionFlags, FALSE, IopDatabaseLock, IopProcessSetInterfaceState(), KeEnterCriticalRegion, KeLeaveCriticalRegion, _PENDING_SET_INTERFACE_STATE::LinkName, PPENDING_SET_INTERFACE_STATE, PpRegistryDeviceResource, and TRUE.

Referenced by IopStartDevice(), and IoReportDetectedDevice().

    09871                    :
    09872
    09873     Process the queued IoSetDeviceInterfaceState calls.
    09874
    09875 Parameters:
    09876
    09877     DeviceNode - Device node which has just been started.
    09878
    09879 Return Value:
    09880
    09881     Status code that indicates whether or not the function was successful.
    09882
    09883 --*/
    09884 {
    09885     KIRQL           irql;
    09886     PDEVICE_OBJECT  attachedDevice;
    09887
    09888     KeEnterCriticalRegion();
    09889     ExAcquireResourceExclusive(&PpRegistryDeviceResource, TRUE);
    09890
    09891     ExAcquireFastLock( &IopDatabaseLock, &irql );
    09892
    09893     for (attachedDevice = DeviceNode->PhysicalDeviceObject;
    09894          attachedDevice;
    09895          attachedDevice = attachedDevice->AttachedDevice) {
    09896
    09897         attachedDevice->DeviceObjectExtension->ExtensionFlags &= ~DOE_START_PENDING;
    09898     }
    09899
    09900     ExReleaseFastLock( &IopDatabaseLock, irql );
    09901
    09902     while (!IsListEmpty(&DeviceNode->PendedSetInterfaceState)) {
    09903
    09904         PPENDING_SET_INTERFACE_STATE entry;
    09905
    09906         entry = (PPENDING_SET_INTERFACE_STATE)RemoveHeadList(&DeviceNode->PendedSetInterfaceState);
    09907
    09908         IopProcessSetInterfaceState(&entry->LinkName, TRUE, FALSE);
    09909
    09910         ExFreePool(entry->LinkName.Buffer);
    09911
    09912         ExFreePool(entry);
    09913     }
    09914
    09915     ExReleaseResource(&PpRegistryDeviceResource);
    09916     KeLeaveCriticalRegion();
    09917
    09918     return STATUS_SUCCESS;
    09919 }

NTSTATUS IopDropReferenceString | ( | OUT PUNICODE_STRING | OutString,
|  | IN PUNICODE_STRING | InString
| ) |

Definition at line 5353 of file pnpioapi.c.

References ASSERT, IopParseSymbolicLinkName(), NT_SUCCESS, NTSTATUS(), NULL, and PAGED_CODE.

Referenced by IopProcessSetInterfaceState().

    05360                    :
    05361
    05362     This routine removes the reference string from a symbolic link name.  No space
    05363     is allocated for the out string so no attempt should be made to free the buffer
    05364     of OutString.
    05365
    05366 Parameters:
    05367
    05368     SymbolicLinkName - Supplies a pointer to a symbolic link name string.
    05369         Both the prefixed strings are valid.
    05370
    05371     GuidReferenceString - Supplies a pointer to an uninitialised string which on
    05372         success will contain the symbolic link name without the reference string.
    05373         See the note on storage allocation above.
    05374
    05375 Return Value:
    05376
    05377     Status code that indicates whether or not the function was successful.
    05378
    05379 Remarks:
    05380
    05381     The string returned in OutString is dependant on the buffer of
    05382     InString and is only valid as long as InString is valid.
    05383
    05384 --*/
    05385
    05386 {
    05387     UNICODE_STRING refString;
    05388     NTSTATUS status;
    05389     BOOLEAN refStringPresent;
    05390
    05391     PAGED_CODE();
    05392
    05393     ASSERT(InString);
    05394     ASSERT(OutString);
    05395
    05396     OutString->Buffer = InString->Buffer;
    05397
    05398     status = IopParseSymbolicLinkName(InString, NULL, NULL, NULL, &refString, &refStringPresent, NULL);
    05399
    05400     if (NT_SUCCESS(status)) {
    05401         //
    05402         // If we have a refstring then subtract it's length
    05403         //
    05404         if (refStringPresent) {
    05405             OutString->Length = InString->Length - (refString.Length + sizeof(WCHAR));
    05406         } else {
    05407             OutString->Length = InString->Length;
    05408         }
    05409
    05410     } else {
    05411         //
    05412         // Invalidate the returned string
    05413         //
    05414         OutString->Buffer = NULL;
    05415         OutString->Length = 0;
    05416     }
    05417
    05418     OutString->MaximumLength = OutString->Length;
    05419
    05420     return status;
    05421 }

VOID IopFreeAllocatedUnicodeString | ( | PUNICODE_STRING | String | ) |

Definition at line 5668 of file pnpioapi.c.

References ASSERT, ExFreePool(), NULL, PAGED_CODE, and String.

Referenced by IoGetDeviceInterfaceAlias(), IopBuildSymbolicLinkStrings(), IopOpenOrCreateDeviceInterfaceSubKeys(), IopProcessCriticalDevice(), IopRegisterDeviceInterface(), IopRemoveDeviceInterfaces(), IopSetRegistryStringValue(), and IopUnregisterDeviceInterface().

    05674                    :
    05675
    05676     This routine frees a string previously allocated with IopAllocateUnicodeString.
    05677
    05678 Parameters:
    05679
    05680     String - Supplies a pointer to the string that has been previously allocated.
    05681
    05682 Return Value:
    05683
    05684     None
    05685
    05686 --*/
    05687
    05688 {
    05689     PAGED_CODE();
    05690
    05691     ASSERT(String);
    05692
    05693     //
    05694     // If we have a buffer free it
    05695     //
    05696
    05697     if(String->Buffer) {
    05698
    05699         ExFreePool(String->Buffer);
    05700
    05701     }
    05702
    05703     //
    05704     // Blank out the string
    05705     //
    05706
    05707     String->Buffer = NULL;
    05708     String->Length = 0;
    05709     String->MaximumLength = 0;
    05710
    05711 }

VOID IopFreeBuffer | ( | IN PBUFFER_INFO | Info | ) |

Definition at line 2536 of file pnpioapi.c.

References ASSERT, ExFreePool(), and NULL.

Referenced by IopGetDeviceInterfaces(), IopProcessCriticalDeviceRoutine(), and IopRemoveDeviceInterfaces().

    02542                    :
    02543
    02544     Frees the buffer associated with Info and resets all Info fields
    02545
    02546 Parameters:
    02547
    02548     Info - Pointer to a buffer info structure to be used to manage the buffer
    02549
    02550 Return Value:
    02551
    02552     Status code that indicates whether or not the function was successful.
    02553
    02554 --*/
    02555
    02556 {
    02557     ASSERT(Info);
    02558
    02559     //
    02560     // Free the buffer
    02561     //
    02562
    02563     ExFreePool(Info->Buffer);
    02564
    02565     //
    02566     // Zero out the info parameters so we can't accidently used the free buffer
    02567     //
    02568
    02569     Info->Buffer = NULL;
    02570     Info->Current = NULL;
    02571     Info->MaxSize = 0;
    02572 }

NTSTATUS IopGetDeviceInterfaces | ( | IN CONST GUID * | InterfaceClassGuid,
|  | IN PUNICODE_STRING DevicePath | OPTIONAL,
|  | IN ULONG | Flags,
|  | IN BOOLEAN | UserModeFormat,
|  | OUT PWSTR * | SymbolicLinkList,
|  | OUT PULONG SymbolicLinkListSize | OPTIONAL
| ) |

Definition at line 2707 of file pnpioapi.c.

References ASSERT, _BUFFER_INFO::Buffer, _BUFFER_INFO::Current, DbgPrint, DEVICE_INTERFACE_INCLUDE_NONACTIVE, ExAcquireResourceExclusive, ExFreePool(), ExReleaseResource, FALSE, INITIAL_DEVNODE_NAME_BUFFER_SIZE, INITIAL_INFO_BUFFER_SIZE, INITIAL_RETURN_BUFFER_SIZE, INITIAL_SYMLINK_BUFFER_SIZE, IopAllocateBuffer(), IopAppendBuffer(), IopCreateRegistryKeyEx(), IopFreeBuffer(), IopGetRegistryValue(), IopOpenOrCreateDeviceInterfaceSubKeys(), IopOpenRegistryKeyEx(), IopResizeBuffer(), KeEnterCriticalRegion, KeLeaveCriticalRegion, KERNEL_SYMLINK_STRING_PREFIX, KERNEL_SYMLINK_STRING_PREFIX_LENGTH, KEY_VALUE_DATA, _BUFFER_INFO::MaxSize, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PpRegistryDeviceResource, RtlCompareUnicodeString(), RtlFreeUnicodeString(), RtlStringFromGUID(), TRUE, and USHORT.

Referenced by IoGetDeviceInterfaces(), and IopRemoveDeviceInterfaces().

    02718                    :
    02719
    02720     This API allows a WDM driver to get a list of paths that represent all
    02721     devices registered for the specified interface class.
    02722
    02723 Parameters:
    02724
    02725     InterfaceClassGuid - Supplies a pointer to a GUID representing the interface class
    02726         for whom a list of members is to be retrieved
    02727
    02728     DevicePath - Optionally, supplies a pointer to a unicode string containing the
    02729         enumeration path for a device for whom interfaces of the specified class are
    02730         to be re-trieved.  If this parameter  is not supplied, then all interface
    02731         devices (regardless of what physical device exposes them) will be returned.
    02732
    02733     Flags - Supplies flags that modify the behavior of list retrieval.
    02734         The following flags are presently defined:
    02735
    02736         DEVICE_INTERFACE_INCLUDE_NONACTIVE -- If this flag is specified, then all
    02737             interface devices, whether currently active or not, will be returned
    02738             (potentially filtered based on the Physi-calDeviceObject, if specified).
    02739
    02740     UserModeFormat - If TRUE the multi-sz returned will have user mode prefixes
    02741         (\\?\) otherwise they will have kernel mode prefixes (\??\).
    02742
    02743     SymbolicLinkList - Supplies the address of a character pointer, that on
    02744         success will contain a multi-sz list of \??\ symbolic link
    02745         names that provide the requested functionality.  The caller is
    02746         responsible for freeing the memory via ExFreePool.
    02747
    02748 Return Value:
    02749
    02750     Status code that indicates whether or not the function was successful.
    02751
    02752 --*/
    02753
    02754 {
    02755     NTSTATUS status;
    02756     UNICODE_STRING guidString, tempString, defaultString, symLinkString, devnodeString;
    02757     BUFFER_INFO returnBuffer, infoBuffer, symLinkBuffer, devnodeNameBuffer;
    02758     PKEY_VALUE_FULL_INFORMATION pDefaultInfo;
    02759     ULONG tempLong, keyIndex, instanceKeyIndex, resultSize;
    02760     HANDLE hDeviceClasses, hClass, hKey, hInstanceKey, hControl;
    02761     BOOLEAN defaultPresent = FALSE;
    02762
    02763     PAGED_CODE();
    02764
    02765     //
    02766     // Initialise out parameters
    02767     //
    02768
    02769     *SymbolicLinkList = NULL;
    02770
    02771     //
    02772     // Convert the GUID into a string
    02773     //
    02774
    02775     status = RtlStringFromGUID(InterfaceClassGuid, &guidString);
    02776     if(!NT_SUCCESS(status)) {
    02777         goto finalClean;
    02778     }
    02779
    02780 #if DBG_GET_ASSOC
    02781     DbgPrint("Getting associations for class %wZ\n", &guidString);
    02782 #endif
    02783
    02784     //
    02785     // Allocate initial buffers
    02786     //
    02787
    02788     status = IopAllocateBuffer(&returnBuffer,
    02789                                INITIAL_RETURN_BUFFER_SIZE
    02790                                );
    02791
    02792     if (!NT_SUCCESS(status)) {
    02793         goto clean0;
    02794     }
    02795
    02796     status = IopAllocateBuffer(&infoBuffer,
    02797                                INITIAL_INFO_BUFFER_SIZE
    02798                                );
    02799
    02800     if (!NT_SUCCESS(status)) {
    02801         goto clean1;
    02802     }
    02803
    02804     status = IopAllocateBuffer(&symLinkBuffer,
    02805                                INITIAL_SYMLINK_BUFFER_SIZE
    02806                                );
    02807
    02808     if (!NT_SUCCESS(status)) {
    02809         goto clean2;
    02810     }
    02811
    02812     status = IopAllocateBuffer(&devnodeNameBuffer,
    02813                                INITIAL_DEVNODE_NAME_BUFFER_SIZE
    02814                                );
    02815
    02816     if (!NT_SUCCESS(status)) {
    02817         goto clean2a;
    02818     }
    02819
    02820     //
    02821     // Enter critical section and acquire a lock on the registry.  Both these
    02822     // mechanisms are required to prevent deadlock in the case where an APC
    02823     // routine calls this routine after the registry resource has been claimed
    02824     // in this case it would wait blocking this thread so the registry would
    02825     // never be released -> deadlock.  Critical sectioning the registry manipulation
    02826     // portion solves this problem
    02827     //
    02828
    02829     KeEnterCriticalRegion();
    02830     ExAcquireResourceExclusive(&PpRegistryDeviceResource, TRUE);
    02831
    02832     //
    02833     // Open HKLM\System\CurrentControlSet\Control\DeviceClasses key
    02834     //
    02835
    02836     PiWstrToUnicodeString(&tempString, REGSTR_FULL_PATH_DEVICE_CLASSES);
    02837     status = IopCreateRegistryKeyEx( &hDeviceClasses,
    02838                                      NULL,
    02839                                      &tempString,
    02840                                      KEY_ALL_ACCESS,
    02841                                      REG_OPTION_NON_VOLATILE,
    02842                                      NULL
    02843                                      );
    02844
    02845     if (!NT_SUCCESS(status)) {
    02846         goto clean3;
    02847     }
    02848
    02849     //
    02850     // Open function class GUID key
    02851     //
    02852
    02853     status = IopOpenRegistryKeyEx( &hClass,
    02854                                    hDeviceClasses,
    02855                                    &guidString,
    02856                                    KEY_ALL_ACCESS
    02857                                    );
    02858     ZwClose(hDeviceClasses);
    02859
    02860     if(status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_OBJECT_PATH_NOT_FOUND) {
    02861
    02862         //
    02863         // The path does not exist - return a single null character buffer
    02864         //
    02865
    02866         status = STATUS_SUCCESS;
    02867         goto clean5;
    02868     } else if (!NT_SUCCESS(status)) {
    02869         goto clean3;
    02870     }
    02871
    02872     //
    02873     // Get the default value if it exists
    02874     //
    02875
    02876     status = IopGetRegistryValue(hClass,
    02877                                  REGSTR_VAL_DEFAULT,
    02878                                  &pDefaultInfo
    02879                                  );
    02880
    02881
    02882     if (NT_SUCCESS(status)
    02883         && pDefaultInfo->Type == REG_SZ
    02884         && pDefaultInfo->DataLength >= sizeof(WCHAR)) {
    02885
    02886         //
    02887         // We have a default - construct a counted string from the default
    02888         //
    02889
    02890         defaultPresent = TRUE;
    02891         defaultString.Buffer = (PWSTR) KEY_VALUE_DATA(pDefaultInfo);
    02892         defaultString.Length = (USHORT) pDefaultInfo->DataLength - sizeof(UNICODE_NULL);
    02893         defaultString.MaximumLength = defaultString.Length;
    02894
    02895 #if DBG_GET_ASSOC
    02896         DbgPrint("Class default: %wZ\n", &defaultString);
    02897 #endif
    02898
    02899         //
    02900         // Open the device interface instance key for the default name.
    02901         //
    02902         status = IopOpenOrCreateDeviceInterfaceSubKeys(NULL,
    02903                                                        NULL,
    02904                                                        &hKey,
    02905                                                        NULL,
    02906                                                        hClass,
    02907                                                        &defaultString,
    02908                                                        KEY_READ,
    02909                                                        FALSE
    02910                                                       );
    02911
    02912         if (!NT_SUCCESS(status)) {
    02913             defaultPresent = FALSE;
    02914             ExFreePool(pDefaultInfo);
    02915             //
    02916             // Continue with the call but ignore the invalid default entry
    02917             //
    02918 #if DBG_GET_ASSOC
    02919             DbgPrint("WDM Warning: Default entry for class %zW is invalid\n", &guidString);
    02920 #endif
    02921         } else {
    02922
    02923             //
    02924             // If we are just supposed to return live interfaces, then make sure this default
    02925             // interface is linked.
    02926             //
    02927
    02928             if (!(Flags & DEVICE_INTERFACE_INCLUDE_NONACTIVE)) {
    02929
    02930                 defaultPresent = FALSE;
    02931
    02932                 //
    02933                 // Open the control subkey
    02934                 //
    02935
    02936                 PiWstrToUnicodeString(&tempString, REGSTR_KEY_CONTROL);
    02937                 status = IopOpenRegistryKeyEx( &hControl,
    02938                                                hKey,
    02939                                                &tempString,
    02940                                                KEY_ALL_ACCESS
    02941                                                );
    02942
    02943                 if (NT_SUCCESS(status)) {
    02944                     //
    02945                     // Get the linked value
    02946                     //
    02947
    02948                     PiWstrToUnicodeString(&tempString, REGSTR_VAL_LINKED);
    02949                     status = ZwQueryValueKey(hControl,
    02950                                              &tempString,
    02951                                              KeyValuePartialInformation,
    02952                                              (PVOID) infoBuffer.Buffer,
    02953                                              infoBuffer.MaxSize,
    02954                                              &resultSize
    02955                                              );
    02956
    02957                     ZwClose(hControl);
    02958
    02959                     //
    02960                     // We don't need to check the buffer was big enough because it starts
    02961                     // off that way and doesn't get any smaller!
    02962                     //
    02963
    02964                     if (NT_SUCCESS(status)
    02965                         && (((PKEY_VALUE_PARTIAL_INFORMATION)(infoBuffer.Buffer))->Type == REG_DWORD)
    02966                         && (((PKEY_VALUE_PARTIAL_INFORMATION)(infoBuffer.Buffer))->DataLength == sizeof(ULONG))) {
    02967
    02968                         defaultPresent = *(PULONG)(((PKEY_VALUE_PARTIAL_INFORMATION)(infoBuffer.Buffer))->Data)
    02969                                        ? TRUE
    02970                                        : FALSE;
    02971                     }
    02972                 }
    02973             }
    02974
    02975             ZwClose(hKey);
    02976
    02977             if(defaultPresent) {
    02978                 //
    02979                 // Add the default as the first entry in the return buffer and patch to usermode if necessary
    02980                 //
    02981                 status = IopAppendBuffer(&returnBuffer,
    02982                                          defaultString.Buffer,
    02983                                          defaultString.Length + sizeof(UNICODE_NULL)
    02984                                         );
    02985
    02986                 if (!UserModeFormat) {
    02987
    02988                     RtlCopyMemory(returnBuffer.Buffer,
    02989                                   KERNEL_SYMLINK_STRING_PREFIX,
    02990                                   KERNEL_SYMLINK_STRING_PREFIX_LENGTH
    02991                                   );
    02992                 }
    02993
    02994             } else {
    02995                 //
    02996                 // The default device interface isn't active--free the memory for the name buffer now.
    02997                 //
    02998                 ExFreePool(pDefaultInfo);
    02999             }
    03000         }
    03001
    03002     } else if (status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_OBJECT_PATH_NOT_FOUND) {
    03003         //
    03004         // Do nothing - there is no default
    03005         //
    03006     } else {
    03007         //
    03008         // An unexpected error occured - clean up
    03009         //
    03010         if (NT_SUCCESS(status)) {
    03011
    03012             ExFreePool(pDefaultInfo);
    03013             status = STATUS_UNSUCCESSFUL;
    03014         }
    03015
    03016         ZwClose(hClass);
    03017         goto clean4;
    03018     }
    03019
    03020     //
    03021     // Iterate through the subkeys under this interface class key.
    03022     //
    03023
    03024     keyIndex = 0;
    03025
    03026     while((status = ZwEnumerateKey(hClass,
    03027                                    keyIndex,
    03028                                    KeyBasicInformation,
    03029                                    (PVOID) infoBuffer.Buffer,
    03030                                    infoBuffer.MaxSize,
    03031                                    &resultSize
    03032                                    )) != STATUS_NO_MORE_ENTRIES)
    03033     {
    03034
    03035         if (status == STATUS_BUFFER_TOO_SMALL) {
    03036
    03037             status = IopResizeBuffer(&infoBuffer, resultSize, FALSE);
    03038
    03039             continue;
    03040
    03041         } else if (!NT_SUCCESS(status)) {
    03042             ZwClose(hClass);
    03043             goto clean4;
    03044         }
    03045
    03046         //
    03047         // Open up this interface key.
    03048         //
    03049         tempString.Length = (USHORT) ((PKEY_BASIC_INFORMATION)(infoBuffer.Buffer))->NameLength;
    03050         tempString.MaximumLength = tempString.Length;
    03051         tempString.Buffer = ((PKEY_BASIC_INFORMATION)(infoBuffer.Buffer))->Name;
    03052
    03053 #if DBG_GET_ASSOC
    03054         DbgPrint("Key %u enumerated %wZ\n", keyIndex, &tempString);
    03055 #endif
    03056
    03057         //
    03058         // Open the associated key
    03059         //
    03060
    03061         status = IopOpenRegistryKeyEx( &hKey,
    03062                                        hClass,
    03063                                        &tempString,
    03064                                        KEY_READ
    03065                                        );
    03066
    03067         if (!NT_SUCCESS(status)) {
    03068             //
    03069             // For some reason we couldn't open this key--skip it and move on.
    03070             //
    03071 #if DBG_GET_ASSOC
    03072             DbgPrint("\tCouldn't open interface key!\n");
    03073 #endif
    03074             keyIndex++;
    03075             continue;
    03076         }
    03077
    03078         //
    03079         // If we're filtering on a particular PDO, then retrieve the owning device
    03080         // instance name for this interface key, and make sure they match.
    03081         //
    03082         PiWstrToUnicodeString(&tempString, REGSTR_VAL_DEVICE_INSTANCE);
    03083         while ((status = ZwQueryValueKey(hKey,
    03084                                          &tempString,
    03085                                          KeyValuePartialInformation,
    03086                                          devnodeNameBuffer.Buffer,
    03087                                          devnodeNameBuffer.MaxSize,
    03088                                          &resultSize
    03089                                          )) == STATUS_BUFFER_TOO_SMALL ) {
    03090
    03091             status = IopResizeBuffer(&devnodeNameBuffer, resultSize, FALSE);
    03092
    03093             if (!NT_SUCCESS(status)) {
    03094                 ZwClose(hKey);
    03095                 ZwClose(hClass);
    03096                 goto clean4;
    03097             }
    03098         }
    03099
    03100         if (!(NT_SUCCESS(status)
    03101               && ((PKEY_VALUE_PARTIAL_INFORMATION)(devnodeNameBuffer.Buffer))->Type == REG_SZ
    03102               && ((PKEY_VALUE_PARTIAL_INFORMATION)(devnodeNameBuffer.Buffer))->DataLength > sizeof(WCHAR) ) ) {
    03103 #if DBG_GET_ASSOC
    03104             DbgPrint("\tDevice instance entry corrupt\n");
    03105 #endif
    03106             goto CloseInterfaceKeyAndContinue;
    03107         }
    03108
    03109         //
    03110         // Build counted string
    03111         //
    03112
    03113         devnodeString.Length = (USHORT) ((PKEY_VALUE_PARTIAL_INFORMATION)(devnodeNameBuffer.Buffer))->DataLength - sizeof(UNICODE_NULL);
    03114         devnodeString.MaximumLength = tempString.Length;
    03115         devnodeString.Buffer = (PWSTR) ((PKEY_VALUE_PARTIAL_INFORMATION)(devnodeNameBuffer.Buffer))->Data;
    03116
    03117         //
    03118         // Enumerate each interface instance subkey under this PDO's interface key.
    03119         //
    03120         instanceKeyIndex = 0;
    03121
    03122         while((status = ZwEnumerateKey(hKey,
    03123                                        instanceKeyIndex,
    03124                                        KeyBasicInformation,
    03125                                        (PVOID) infoBuffer.Buffer,
    03126                                        infoBuffer.MaxSize,
    03127                                        &resultSize
    03128                                        )) != STATUS_NO_MORE_ENTRIES)
    03129         {
    03130
    03131             if (status == STATUS_BUFFER_TOO_SMALL) {
    03132
    03133                 status = IopResizeBuffer(&infoBuffer, resultSize, FALSE);
    03134
    03135                 continue;
    03136
    03137             } else if (!NT_SUCCESS(status)) {
    03138                 ZwClose(hKey);
    03139                 ZwClose(hClass);
    03140                 goto clean4;
    03141             }
    03142
    03143             //
    03144             // Open up this interface instance key.
    03145             //
    03146             tempString.Length = (USHORT) ((PKEY_BASIC_INFORMATION)(infoBuffer.Buffer))->NameLength;
    03147             tempString.MaximumLength = tempString.Length;
    03148             tempString.Buffer = ((PKEY_BASIC_INFORMATION)(infoBuffer.Buffer))->Name;
    03149
    03150 #if DBG_GET_ASSOC
    03151             DbgPrint("Instance key %u enumerated %wZ\n", instanceKeyIndex, &tempString);
    03152 #endif
    03153
    03154             //
    03155             // Open the associated key
    03156             //
    03157
    03158             status = IopOpenRegistryKeyEx( &hInstanceKey,
    03159                                            hKey,
    03160                                            &tempString,
    03161                                            KEY_READ
    03162                                            );
    03163
    03164             if (!NT_SUCCESS(status)) {
    03165                 //
    03166                 // For some reason we couldn't open this key--skip it and move on.
    03167                 //
    03168 #if DBG_GET_ASSOC
    03169                 DbgPrint("\tCouldn't open interface key!\n");
    03170 #endif
    03171                 instanceKeyIndex++;
    03172                 continue;
    03173             }
    03174
    03175             if (!(Flags & DEVICE_INTERFACE_INCLUDE_NONACTIVE)) {
    03176
    03177                 //
    03178                 // Open the control subkey
    03179                 //
    03180
    03181                 PiWstrToUnicodeString(&tempString, REGSTR_KEY_CONTROL);
    03182                 status = IopOpenRegistryKeyEx( &hControl,
    03183                                                hInstanceKey,
    03184                                                &tempString,
    03185                                                KEY_READ
    03186                                                );
    03187
    03188                 if (!NT_SUCCESS(status)) {
    03189
    03190                     //
    03191                     // We have no control subkey so can't be linked -
    03192                     // continue enumerating the keys ignoring this one
    03193                     //
    03194
    03195 #if DBG_GET_ASSOC
    03196                     DbgPrint("\tNo control subkey\n");
    03197 #endif
    03198                     goto CloseInterfaceInstanceKeyAndContinue;
    03199                 }
    03200
    03201                 //
    03202                 // Get the linked value
    03203                 //
    03204
    03205                 PiWstrToUnicodeString(&tempString, REGSTR_VAL_LINKED);
    03206                 status = ZwQueryValueKey(hControl,
    03207                                          &tempString,
    03208                                          KeyValuePartialInformation,
    03209                                          (PVOID) infoBuffer.Buffer,
    03210                                          infoBuffer.MaxSize,
    03211                                          &resultSize
    03212                                          );
    03213
    03214                 ZwClose(hControl);
    03215
    03216                 //
    03217                 // We don't need to check the buffer was big enough because it starts
    03218                 // off that way and doesn't get any smaller!
    03219                 //
    03220
    03221                 if (!NT_SUCCESS(status)
    03222                     || (((PKEY_VALUE_PARTIAL_INFORMATION)(infoBuffer.Buffer))->Type != REG_DWORD)
    03223                     || (((PKEY_VALUE_PARTIAL_INFORMATION)(infoBuffer.Buffer))->DataLength != sizeof(ULONG))
    03224                     || !*(PULONG)(((PKEY_VALUE_PARTIAL_INFORMATION)(infoBuffer.Buffer))->Data)) {
    03225
    03226                     //
    03227                     // We are NOT linked so continue enumerating the keys ignoring this one
    03228                     //
    03229
    03230 #if DBG_GET_ASSOC
    03231                     DbgPrint("\tNot Linked\n");
    03232 #endif
    03233                     goto CloseInterfaceInstanceKeyAndContinue;
    03234                 }
    03235             }
    03236
    03237             //
    03238             // Open the "SymbolicLink" value and place the information into the symLink buffer
    03239             //
    03240
    03241             PiWstrToUnicodeString(&tempString, REGSTR_VAL_SYMBOLIC_LINK);
    03242             while ((status = ZwQueryValueKey(hInstanceKey,
    03243                                              &tempString,
    03244                                              KeyValuePartialInformation,
    03245                                              symLinkBuffer.Buffer,
    03246                                              symLinkBuffer.MaxSize,
    03247                                              &resultSize
    03248                                              )) == STATUS_BUFFER_TOO_SMALL ) {
    03249
    03250                 status = IopResizeBuffer(&symLinkBuffer, resultSize, FALSE);
    03251
    03252                 if (!NT_SUCCESS(status)) {
    03253                     ZwClose(hInstanceKey);
    03254                     ZwClose(hKey);
    03255                     ZwClose(hClass);
    03256                     goto clean4;
    03257                 }
    03258             }
    03259
    03260             if (!(NT_SUCCESS(status)
    03261                 && ((PKEY_VALUE_PARTIAL_INFORMATION)(symLinkBuffer.Buffer))->Type == REG_SZ
    03262                 && ((PKEY_VALUE_PARTIAL_INFORMATION)(symLinkBuffer.Buffer))->DataLength > sizeof(WCHAR) ) ) {
    03263 #if DBG_GET_ASSOC
    03264                 DbgPrint("\tSymbolic link entry corrupt\n");
    03265 #endif
    03266                 goto CloseInterfaceInstanceKeyAndContinue;
    03267             }
    03268
    03269             //
    03270             // Build counted string from value data
    03271             //
    03272
    03273             symLinkString.Length = (USHORT) ((PKEY_VALUE_PARTIAL_INFORMATION)(symLinkBuffer.Buffer))->DataLength - sizeof(UNICODE_NULL);
    03274             symLinkString.MaximumLength = symLinkString.Length;
    03275             symLinkString.Buffer = (PWSTR) ((PKEY_VALUE_PARTIAL_INFORMATION)(symLinkBuffer.Buffer))->Data;
    03276
    03277             //
    03278             // If we have a default, check this is not it
    03279             //
    03280
    03281             if (defaultPresent) {
    03282
    03283                 if (RtlCompareUnicodeString(&defaultString, &symLinkString, TRUE) == 0) {
    03284
    03285                     //
    03286                     // We have already added the default to the beginning of the buffer so skip it
    03287                     //
    03288
    03289 #if DBG_GET_ASSOC
    03290                     DbgPrint("\tDefault entry skipped\n");
    03291 #endif
    03292                     goto CloseInterfaceInstanceKeyAndContinue;
    03293                 }
    03294             }
    03295
    03296             //
    03297             // If we are only returning interfaces for a particular PDO then check
    03298             // this is from that PDO
    03299             //
    03300             if (ARGUMENT_PRESENT(DevicePath)) {
    03301                 //
    03302                 // Check if it is from the same PDO
    03303                 //
    03304                 if (RtlCompareUnicodeString(DevicePath, &devnodeString, TRUE) != 0) {
    03305                     //
    03306                     // If not then go onto the next key
    03307                     //
    03308 #if DBG_GET_ASSOC
    03309                     DbgPrint("\tNot from the correct PDO\n");
    03310 #endif
    03311                     goto CloseInterfaceInstanceKeyAndContinue;
    03312                 }
    03313             }
    03314
    03315             //
    03316             // Copy the symLink string to the return buffer including the NULL termination
    03317             //
    03318
    03319             status = IopAppendBuffer(&returnBuffer,
    03320                                      symLinkString.Buffer,
    03321                                      symLinkString.Length + sizeof(UNICODE_NULL)
    03322                                      );
    03323
    03324             ASSERT(((PWSTR) returnBuffer.Current)[-1] == UNICODE_NULL);
    03325
    03326 #if DBG_GET_ASSOC
    03327             DbgPrint("\tAdded to return buffer\n");
    03328 #endif
    03329
    03330             //
    03331             // If we are returning KM strings then patch the prefix
    03332             //
    03333
    03334             if (!UserModeFormat) {
    03335
    03336                 RtlCopyMemory(returnBuffer.Current - (symLinkString.Length + sizeof(UNICODE_NULL)),
    03337                               KERNEL_SYMLINK_STRING_PREFIX,
    03338                               KERNEL_SYMLINK_STRING_PREFIX_LENGTH
    03339                               );
    03340             }
    03341
    03342 CloseInterfaceInstanceKeyAndContinue:
    03343             ZwClose(hInstanceKey);
    03344             instanceKeyIndex++;
    03345         }
    03346
    03347 CloseInterfaceKeyAndContinue:
    03348         ZwClose(hKey);
    03349         keyIndex++;
    03350     }
    03351
    03352     ZwClose(hClass);
    03353
    03354 clean5:
    03355     //
    03356     // We've got then all!  Resize to leave space for a terminating NULL.
    03357     //
    03358
    03359     status = IopResizeBuffer(&returnBuffer,
    03360                              (ULONG) (returnBuffer.Current - returnBuffer.Buffer + sizeof(UNICODE_NULL)),
    03361                              TRUE
    03362                              );
    03363
    03364     if (NT_SUCCESS(status)) {
    03365
    03366         //
    03367         // Terminate the buffer
    03368         //
    03369         *((PWSTR) returnBuffer.Current) = UNICODE_NULL;
    03370     }
    03371
    03372 clean4:
    03373     if (defaultPresent) {
    03374         ExFreePool(pDefaultInfo);
    03375     }
    03376
    03377 clean3:
    03378     ExReleaseResource(&PpRegistryDeviceResource);
    03379     KeLeaveCriticalRegion();
    03380     IopFreeBuffer(&devnodeNameBuffer);
    03381
    03382 clean2a:
    03383     IopFreeBuffer(&symLinkBuffer);
    03384
    03385 clean2:
    03386     IopFreeBuffer(&infoBuffer);
    03387
    03388 clean1:
    03389     if (!NT_SUCCESS(status)) {
    03390         IopFreeBuffer(&returnBuffer);
    03391     }
    03392
    03393 clean0:
    03394     RtlFreeUnicodeString(&guidString);
    03395
    03396 finalClean:
    03397     if (NT_SUCCESS(status)) {
    03398
    03399         *SymbolicLinkList = (PWSTR) returnBuffer.Buffer;
    03400
    03401         if (ARGUMENT_PRESENT(SymbolicLinkListSize)) {
    03402             *SymbolicLinkListSize = returnBuffer.MaxSize;
    03403         }
    03404
    03405     } else {
    03406
    03407         *SymbolicLinkList = NULL;
    03408
    03409         if (ARGUMENT_PRESENT(SymbolicLinkListSize)) {
    03410             *SymbolicLinkListSize = 0;
    03411         }
    03412
    03413     }
    03414
    03415     return status;
    03416 }

BOOLEAN IopGetLegacyVetoListDevice | ( | IN PDEVICE_NODE | DeviceNode,
|  | IN PIO_GET_LEGACY_VETO_LIST_CONTEXT | Context
| ) |

Definition at line 9445 of file pnpioapi.c.

References FALSE, IopAppendLegacyVeto(), IopDeviceNodeFlagsToCapabilities, _DEVICE_CAPABILITIES::NonDynamic, NULL, and TRUE.

Referenced by IopGetLegacyVetoListDeviceNode().

    09451                    :
    09452
    09453     This routine determines whether the specified device node should be added to
    09454     the veto list, and if so, calls IopAppendLegacyVeto to add it.
    09455
    09456 Parameters:
    09457
    09458     DeviceNode - The device node to be added.
    09459
    09460     Context - An IO_GET_LEGACY_VETO_LIST_CONTEXT pointer.
    09461
    09462 ReturnValue:
    09463
    09464     A BOOLEAN value which indicates whether the device node enumeration
    09465     process should be terminated or not.
    09466
    09467 --*/
    09468 {
    09469     PDEVICE_CAPABILITIES DeviceCapabilities;
    09470
    09471     //
    09472     // A device node should be added added to the veto list, if it has the
    09473     // NonDynamic capability.
    09474     //
    09475
    09476     DeviceCapabilities = IopDeviceNodeFlagsToCapabilities(DeviceNode);
    09477
    09478     if (DeviceCapabilities->NonDynamic) {
    09479
    09480         //
    09481         // Update the veto type.  If an error occurrs while adding the device
    09482         // node to the veto list, or the caller did not provide a veto list
    09483         // pointer, terminate the enumeration process now.
    09484         //
    09485
    09486         *Context->VetoType = PNP_VetoLegacyDevice;
    09487
    09488         if (Context->VetoList != NULL) {
    09489
    09490             if (!IopAppendLegacyVeto(Context, &DeviceNode->InstancePath)) {
    09491                 return FALSE;
    09492             }
    09493
    09494         } else {
    09495
    09496             return FALSE;
    09497
    09498         }
    09499
    09500     }
    09501
    09502     return TRUE;
    09503 }

BOOLEAN IopGetLegacyVetoListDeviceNode | ( | IN PDEVICE_NODE | DeviceNode,
|  | IN PIO_GET_LEGACY_VETO_LIST_CONTEXT | Context
| ) |

Definition at line 9506 of file pnpioapi.c.

References _DEVICE_NODE::Child, FALSE, IopGetLegacyVetoListDevice(), NULL, _DEVICE_NODE::Sibling, and TRUE.

Referenced by IoGetLegacyVetoList().

    09512                    :
    09513
    09514     This routine recusively walks the device tree, invoking
    09515     IopGetLegacyVetoListDevice to add device nodes to the veto list
    09516     (as appropriate).
    09517
    09518 Parameters:
    09519
    09520     DeviceNode - The device node.
    09521
    09522     Context - An IO_GET_LEGACY_VETO_LIST_CONTEXT pointer.
    09523
    09524
    09525 ReturnValue:
    09526
    09527     A BOOLEAN value which indicates whether the device tree enumeration
    09528     process should be terminated or not.
    09529
    09530 --*/
    09531 {
    09532     PDEVICE_NODE Child;
    09533
    09534     //
    09535     // Determine whether the device node should be added to the veto
    09536     // list and add it.  If an operation is unsuccessful or we determine
    09537     // the veto type but the caller doesn't need the veto list, then we
    09538     // terminate our search now.
    09539     //
    09540
    09541     if (!IopGetLegacyVetoListDevice(DeviceNode, Context)) {
    09542         return FALSE;
    09543     }
    09544
    09545     //
    09546     // Call ourselves recursively to enumerate our children.  If while
    09547     // enumerating our children we determine we can terminate the search
    09548     // prematurely, do so.
    09549     //
    09550
    09551     for (Child = DeviceNode->Child;
    09552          Child != NULL;
    09553          Child = Child->Sibling) {
    09554
    09555         if (!IopGetLegacyVetoListDeviceNode(Child, Context)) {
    09556             return FALSE;
    09557         }
    09558
    09559     }
    09560
    09561     return TRUE;
    09562 }

VOID IopGetLegacyVetoListDrivers | ( | IN PIO_GET_LEGACY_VETO_LIST_CONTEXT | Context | ) |

Definition at line 9565 of file pnpioapi.c.

References ASSERT, DRVO_LEGACY_RESOURCES, ExAllocatePool, ExFreePool(), FALSE, _DRIVER_OBJECT::Flags, IO_TYPE_DRIVER, IoDriverObjectType, IopAppendLegacyVeto(), KernelMode, L, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByName(), PagedPool, RtlInitUnicodeString(), TRUE, and _DRIVER_OBJECT::Type.

Referenced by IoGetLegacyVetoList().

    09568 {
    09569     PDRIVER_OBJECT driverObject;
    09570     OBJECT_ATTRIBUTES attributes;
    09571     UNICODE_STRING driverString;
    09572     POBJECT_DIRECTORY_INFORMATION dirInfo;
    09573     HANDLE directoryHandle;
    09574     ULONG dirInfoLength, neededLength, dirContext;
    09575     NTSTATUS status;
    09576     BOOLEAN restartScan;
    09577
    09578     dirInfoLength = 0;
    09579     dirInfo = NULL;
    09580     restartScan = TRUE;
    09581
    09582     //
    09583     // Get handle to \\Driver directory
    09584     //
    09585
    09586     RtlInitUnicodeString(&driverString, L"\\Driver");
    09587
    09588     InitializeObjectAttributes(&attributes,
    09589                                &driverString,
    09590                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
    09591                                NULL,
    09592                                NULL
    09593                                );
    09594
    09595     status = ZwOpenDirectoryObject(&directoryHandle,
    09596                                    DIRECTORY_QUERY,
    09597                                    &attributes
    09598                                    );
    09599     if (!NT_SUCCESS(status)) {
    09600         *Context->Status = status;
    09601         return;
    09602     }
    09603
    09604     for (;;) {
    09605
    09606         //
    09607         // Get info on next object in directory.  If the buffer is too
    09608         // small, reallocate it and try again.  Otherwise, any failure
    09609         // including STATUS_NO_MORE_ENTRIES breaks us out.
    09610         //
    09611
    09612         status = ZwQueryDirectoryObject(directoryHandle,
    09613                                         dirInfo,
    09614                                         dirInfoLength,
    09615                                         TRUE,           // force one at a time
    09616                                         restartScan,
    09617                                         &dirContext,
    09618                                         &neededLength);
    09619         if (status == STATUS_BUFFER_TOO_SMALL) {
    09620             dirInfoLength = neededLength;
    09621             if (dirInfo != NULL) {
    09622                 ExFreePool(dirInfo);
    09623             }
    09624             dirInfo = ExAllocatePool(PagedPool, dirInfoLength);
    09625             if (dirInfo == NULL) {
    09626                 *Context->Status = STATUS_INSUFFICIENT_RESOURCES;
    09627                 break;
    09628             }
    09629             status = ZwQueryDirectoryObject(directoryHandle,
    09630                                             dirInfo,
    09631                                             dirInfoLength,
    09632                                             TRUE,       // force one at a time
    09633                                             restartScan,
    09634                                             &dirContext,
    09635                                             &neededLength);
    09636         }
    09637         restartScan = FALSE;
    09638
    09639         if (!NT_SUCCESS(status)) {
    09640             break;
    09641         }
    09642
    09643         //
    09644         // Have name of object.  Create object path and use
    09645         // ObReferenceObjectByName() to get DriverObject.  This may
    09646         // fail non-fatally if DriverObject has gone away in the interim.
    09647         //
    09648
    09649         driverString.MaximumLength = sizeof(L"\\Driver\\") +
    09650             dirInfo->Name.Length;
    09651         driverString.Length = driverString.MaximumLength - sizeof(WCHAR);
    09652         driverString.Buffer = ExAllocatePool(PagedPool,
    09653                                              driverString.MaximumLength);
    09654         if (driverString.Buffer == NULL) {
    09655             *Context->Status = STATUS_INSUFFICIENT_RESOURCES;
    09656             break;
    09657         }
    09658
    09659         swprintf(driverString.Buffer, L"\\Driver\\%ws", dirInfo->Name.Buffer);
    09660         status = ObReferenceObjectByName(&driverString,
    09661                                          OBJ_CASE_INSENSITIVE,
    09662                                          NULL,                 // access state
    09663                                          0,                    // access mask
    09664                                          IoDriverObjectType,
    09665                                          KernelMode,
    09666                                          NULL,                 // parse context
    09667                                          &driverObject);
    09668
    09669         ExFreePool(driverString.Buffer);
    09670
    09671         if (NT_SUCCESS(status)) {
    09672             ASSERT(driverObject->Type == IO_TYPE_DRIVER);
    09673             if (driverObject->Flags & DRVO_LEGACY_RESOURCES) {
    09674                 //
    09675                 // Update the veto type.  If the caller provided a
    09676                 // veto list pointer, add the driver to the veto list.
    09677                 // If an error occurs while adding the driver to the
    09678                 // veto list, or the caller did not provide a veto
    09679                 // list pointer, terminate the driver enumeration now.
    09680                 //
    09681                 // NOTE: Driver may be loaded but not running,
    09682                 // distinction is not made here.
    09683
    09684
    09685                 *Context->VetoType = PNP_VetoLegacyDriver;
    09686
    09687                 if (Context->VetoList != NULL) {
    09688                     IopAppendLegacyVeto(Context, &dirInfo->Name);
    09689                 }
    09690             }
    09691             ObDereferenceObject(driverObject);
    09692
    09693             //
    09694             // Early out if we have a veto and the caller didn't want a list or
    09695             // we hit some error already
    09696             //
    09697             if (((*Context->VetoType == PNP_VetoLegacyDriver) &&
    09698                 (Context->VetoList == NULL)) ||
    09699                 !NT_SUCCESS(*Context->Status)) {
    09700                 break;
    09701             }
    09702         }
    09703     }
    09704     if (dirInfo != NULL) {
    09705         ExFreePool(dirInfo);
    09706     }
    09707
    09708     ZwClose(directoryHandle);
    09709 }

NTSTATUS IopGetRelatedTargetDevice | ( | IN PFILE_OBJECT | FileObject,
|  | OUT PDEVICE_NODE * | DeviceNode
| ) |

Definition at line 8036 of file pnpioapi.c.

References ASSERT, _DEVICE_RELATIONS::Count, DbgPrint, _DEVOBJ_EXTENSION::DeviceNode, _IO_STACK_LOCATION::DeviceObject, _DEVICE_OBJECT::DeviceObjectExtension, _DRIVER_OBJECT::DriverExtension, _DEVICE_OBJECT::DriverObject, ExFreePool(), _IO_STACK_LOCATION::FileObject, IoGetRelatedDeviceObject(), IopSynchronousCall(), IRP_MJ_PNP, IRP_MN_QUERY_DEVICE_RELATIONS, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NT_SUCCESS, NTSTATUS(), _DEVICE_RELATIONS::Objects, _IO_STACK_LOCATION::Parameters, _DRIVER_EXTENSION::ServiceKeyName, and TargetDeviceRelation.

Referenced by IoGetRelatedTargetDevice(), and IoRegisterPlugPlayNotification().

    08043                    :
    08044
    08045     IopGetRelatedTargetDevice retrieves the device object associated with
    08046     the specified file object and then sends a query device relations irp
    08047     to that device object.
    08048
    08049     NOTE: The PDO associated with the returned device node has been referenced,
    08050     and must be dereferenced when no longer needed.
    08051
    08052 Arguments:
    08053
    08054     FileObject - Specifies the file object that is associated with the device
    08055                  object that will receive the query device relations irp.
    08056
    08057     DeviceNode - Returns the related target device node.
    08058
    08059 ReturnValue
    08060
    08061     Returns an NTSTATUS value.
    08062
    08063 --*/
    08064
    08065 {
    08066     NTSTATUS status;
    08067     IO_STACK_LOCATION irpSp;
    08068     PDEVICE_OBJECT deviceObject;
    08069     PDEVICE_RELATIONS deviceRelations;
    08070
    08071     ASSERT(FileObject);
    08072
    08073     //
    08074     // Retrieve the device object associated with this file handle.
    08075     //
    08076
    08077     deviceObject = IoGetRelatedDeviceObject(FileObject);
    08078     if (!deviceObject) {
    08079         return STATUS_NO_SUCH_DEVICE;
    08080     }
    08081
    08082     //
    08083     // Query what the "actual" target device node should be for
    08084     // this file object. Initialize the stack location to pass to
    08085     // IopSynchronousCall() and then send the IRP to the device
    08086     // object that's associated with the file handle.
    08087     //
    08088
    08089     RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
    08090     irpSp.MajorFunction = IRP_MJ_PNP;
    08091     irpSp.MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
    08092     irpSp.Parameters.QueryDeviceRelations.Type = TargetDeviceRelation;
    08093     irpSp.DeviceObject = deviceObject;
    08094     irpSp.FileObject = FileObject;
    08095
    08096     status = IopSynchronousCall(deviceObject, &irpSp, &deviceRelations);
    08097     if (!NT_SUCCESS(status)) {
    08098 #if 0
    08099         DbgPrint("PnpMgr: Contact dev owner for %WZ, which may not correctly support\n",
    08100                  &deviceObject->DriverObject->DriverExtension->ServiceKeyName);
    08101         DbgPrint("        IRP_MN_QUERY_DEVICE_RELATIONS:TargetDeviceRelation\n");
    08102         //ASSERT(0);
    08103 #endif
    08104         return status;
    08105     }
    08106
    08107     ASSERT(deviceRelations);
    08108     ASSERT(deviceRelations->Count == 1);
    08109
    08110     *DeviceNode = (PDEVICE_NODE)deviceRelations->Objects[0]->DeviceObjectExtension->DeviceNode;
    08111     if (!*DeviceNode) {
    08112         status = STATUS_NO_SUCH_DEVICE;
    08113     }
    08114
    08115     ExFreePool(deviceRelations);
    08116     return status;
    08117 }

VOID IopInitializePlugPlayNotification | ( | VOID |  | ) |

Definition at line 6511 of file pnpioapi.c.

References ExInitializeFastMutex, IopDeferredRegistrationList, IopDeferredRegistrationLock, IopDeviceClassNotifyList, IopDeviceClassNotifyLock, IopHwProfileNotifyLock, IopProfileNotifyList, IopTargetDeviceNotifyLock, NOTIFY_DEVICE_CLASS_HASH_BUCKETS, and PAGED_CODE.

    06517                    :
    06518
    06519     This routine performs initialization required before any of the notification
    06520     APIs can be called.
    06521
    06522 Parameters:
    06523
    06524     None
    06525
    06526 Return Value:
    06527
    06528     None
    06529
    06530 --*/
    06531
    06532 {
    06533     ULONG count;
    06534
    06535     PAGED_CODE();
    06536
    06537     //
    06538     // Initialize the notification structures
    06539     //
    06540
    06541     for (count = 0; count < NOTIFY_DEVICE_CLASS_HASH_BUCKETS; count++) {
    06542
    06543         InitializeListHead(&IopDeviceClassNotifyList[count]);
    06544
    06545     }
    06546
    06547     //
    06548     // Initialize the profile notification list
    06549     //
    06550     InitializeListHead(&IopProfileNotifyList);
    06551
    06552     //
    06553     // Initialize the deferred registration list
    06554     //
    06555     InitializeListHead(&IopDeferredRegistrationList);
    06556
    06557     ExInitializeFastMutex(&IopDeviceClassNotifyLock);
    06558     ExInitializeFastMutex(&IopTargetDeviceNotifyLock);
    06559     ExInitializeFastMutex(&IopHwProfileNotifyLock);
    06560     ExInitializeFastMutex(&IopDeferredRegistrationLock);
    06561 }

VOID IopInvalidateDeviceStateWorker | ( | PVOID | Context | ) |

Definition at line 6387 of file pnpioapi.c.

References _DEVOBJ_EXTENSION::DeviceNode, _DEVICE_WORK_ITEM::DeviceObject, _DEVICE_OBJECT::DeviceObjectExtension, DNF_REMOVE_PENDING_CLOSES, DNF_STARTED, ExFreePool(), _DEVICE_NODE::Flags, IopQueryDeviceState(), IopUncacheInterfaceInformation(), ObDereferenceObject, and PDEVICE_WORK_ITEM.

Referenced by IoInvalidateDeviceState().

    06393                    :
    06394
    06395     This routine is the worker routine of IoInvalidateDeviceState.
    06396     Its main purpose is to invoke IopSynchronousQueryDeviceState and release
    06397     work item space.
    06398
    06399 Parameters:
    06400
    06401     Context - Supplies a pointer to the DEVICE_WORK_ITEM.
    06402
    06403 ReturnValue:
    06404
    06405     None.
    06406
    06407 --*/
    06408
    06409 {
    06410     PDEVICE_WORK_ITEM deviceWorkItem = (PDEVICE_WORK_ITEM)Context;
    06411     PDEVICE_OBJECT deviceObject = deviceWorkItem->DeviceObject;
    06412     PDEVICE_NODE deviceNode;
    06413
    06414     ExFreePool(deviceWorkItem);
    06415
    06416     //
    06417     // If the device was removed or surprised removed while the work item was
    06418     // queued then ignore it.
    06419     //
    06420
    06421     deviceNode = (PDEVICE_NODE)deviceObject->DeviceObjectExtension->DeviceNode;
    06422
    06423     if ((deviceNode->Flags & (DNF_STARTED | DNF_REMOVE_PENDING_CLOSES)) == DNF_STARTED) {
    06424
    06425         IopQueryDeviceState(deviceObject);
    06426
    06427         //
    06428         // PCMCIA driver uses this when switching between Cardbus and R2 cards.
    06429         //
    06430         IopUncacheInterfaceInformation(deviceObject);
    06431     }
    06432
    06433     ObDereferenceObject(deviceObject);
    06434 }
    //

BOOLEAN IopIsReportedAlready | ( | IN HANDLE | Handle,
|  | IN PUNICODE_STRING | ServiceName,
|  | IN PCM_RESOURCE_LIST | ResourceList
| ) |

Definition at line 2286 of file pnpioapi.c.

References ExFreePool(), exit, FALSE, Handle, IopGetRegistryValue(), IopIsDuplicatedDevices(), IopOpenRegistryKeyEx(), KEY_VALUE_DATA, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, RtlEqualUnicodeString(), RtlInitUnicodeString(), TITLE_INDEX_VALUE, TRUE, and USHORT.

Referenced by IoReportDetectedDevice().

    02294                    :
    02295
    02296     This routine determines if the reported device instance is already reported
    02297     or not.
    02298
    02299 Parameters:
    02300
    02301     Handle - Supplies a handle to the reported device instance key.
    02302
    02303     ServiceName - supplies a pointer to a the unicode service key name.
    02304
    02305     ResourceList - supplies a pointer to the reported Resource list.
    02306
    02307 Return Value:
    02308
    02309     Status code that indicates whether or not the function was successful.
    02310
    02311 --*/
    02312
    02313 {
    02314     PKEY_VALUE_FULL_INFORMATION keyValueInfo1 = NULL, keyValueInfo2 = NULL;
    02315     NTSTATUS status;
    02316     UNICODE_STRING unicodeName;
    02317     HANDLE logConfHandle, controlHandle = NULL;
    02318     BOOLEAN returnValue = FALSE;
    02319     PCM_RESOURCE_LIST cmResource = NULL;
    02320     ULONG tmpValue;
    02321
    02322     PAGED_CODE();
    02323
    02324     //
    02325     // If this registry key is for a device reported during the same boot
    02326     // this is not a duplicate.
    02327     //
    02328
    02329     RtlInitUnicodeString(&unicodeName, REGSTR_KEY_CONTROL);
    02330     status = IopOpenRegistryKeyEx( &controlHandle,
    02331                                    Handle,
    02332                                    &unicodeName,
    02333                                    KEY_ALL_ACCESS
    02334                                    );
    02335     if (NT_SUCCESS(status)) {
    02336         status = IopGetRegistryValue(controlHandle,
    02337                                      REGSTR_VALUE_DEVICE_REPORTED,
    02338                                      &keyValueInfo1);
    02339         if (NT_SUCCESS(status)) {
    02340             goto exit;
    02341         }
    02342
    02343         //
    02344         // Check if "Service" value matches what the caller passed in.
    02345         //
    02346
    02347         status = IopGetRegistryValue(Handle, REGSTR_VALUE_SERVICE, &keyValueInfo1);
    02348         if (NT_SUCCESS(status)) {
    02349             if ((keyValueInfo1->Type == REG_SZ) &&
    02350                 (keyValueInfo1->DataLength != 0)) {
    02351                 unicodeName.Buffer = (PWSTR)KEY_VALUE_DATA(keyValueInfo1);
    02352                 unicodeName.MaximumLength = unicodeName.Length = (USHORT)keyValueInfo1->DataLength;
    02353                 if (unicodeName.Buffer[(keyValueInfo1->DataLength / sizeof(WCHAR)) - 1] == UNICODE_NULL) {
    02354                     unicodeName.Length -= sizeof(WCHAR);
    02355                 }
    02356                 if (RtlEqualUnicodeString(ServiceName, &unicodeName, TRUE)) {
    02357
    02358                     //
    02359                     // Next check if resources are the same
    02360                     //
    02361
    02362                     RtlInitUnicodeString(&unicodeName, REGSTR_KEY_LOG_CONF);
    02363                     status = IopOpenRegistryKeyEx( &logConfHandle,
    02364                                                    Handle,
    02365                                                    &unicodeName,
    02366                                                    KEY_READ
    02367                                                    );
    02368                     if (NT_SUCCESS(status)) {
    02369                         status = IopGetRegistryValue(logConfHandle,
    02370                                                      REGSTR_VAL_BOOTCONFIG,
    02371                                                      &keyValueInfo2);
    02372                         ZwClose(logConfHandle);
    02373                         if (NT_SUCCESS(status)) {
    02374                             if ((keyValueInfo2->Type == REG_RESOURCE_LIST) &&
    02375                                 (keyValueInfo2->DataLength != 0)) {
    02376                                 cmResource = (PCM_RESOURCE_LIST)KEY_VALUE_DATA(keyValueInfo2);
    02377                                 if (ResourceList && cmResource &&
    02378                                     IopIsDuplicatedDevices(ResourceList, cmResource, NULL, NULL)) {
    02379                                     returnValue = TRUE;
    02380                                 }
    02381                             }
    02382                         }
    02383                     }
    02384                     if (!ResourceList && !cmResource) {
    02385                         returnValue = TRUE;
    02386                     }
    02387                 }
    02388             }
    02389         }
    02390         if (returnValue == TRUE) {
    02391
    02392             //
    02393             // Mark this key has been used.
    02394             //
    02395
    02396             PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_DEVICE_REPORTED);
    02397             tmpValue = 1;
    02398             status = ZwSetValueKey(controlHandle,
    02399                                    &unicodeName,
    02400                                    TITLE_INDEX_VALUE,
    02401                                    REG_DWORD,
    02402                                    &tmpValue,
    02403                                    sizeof(ULONG)
    02404                                    );
    02405             if (!NT_SUCCESS(status)) {
    02406                 returnValue = FALSE;
    02407             }
    02408         }
    02409     }
    02410
    02411 exit:
    02412     if (controlHandle) {
    02413         ZwClose(controlHandle);
    02414     }
    02415
    02416     if (keyValueInfo1) {
    02417         ExFreePool(keyValueInfo1);
    02418     }
    02419     if (keyValueInfo2) {
    02420         ExFreePool(keyValueInfo2);
    02421     }
    02422     return returnValue;
    02423 }

NTSTATUS IopNotifyDeviceClassChange | ( | LPGUID | EventGuid,
|  | LPGUID | ClassGuid,
|  | PUNICODE_STRING | SymbolicLinkName
| ) |

Definition at line 7330 of file pnpioapi.c.

References _NOTIFY_ENTRY_HEADER::Callback, _NOTIFICATION_CALLBACK_PARAM_BLOCK::Callout, _DEVICE_CLASS_NOTIFY_ENTRY::ClassGuid, _NOTIFICATION_CALLBACK_PARAM_BLOCK::Context, _NOTIFY_ENTRY_HEADER::Context, DbgPrint, _DRIVER_OBJECT::DriverName, _NOTIFY_ENTRY_HEADER::DriverObject, _DEVICE_INTERFACE_CHANGE_NOTIFICATION::Event, _DEVICE_INTERFACE_CHANGE_NOTIFICATION::InterfaceClassGuid, IopAcquireNotifyLock, IopCompareGuid, IopDereferenceNotify(), IopDeviceClassNotifyList, IopDeviceClassNotifyLock, IopHashGuid, IopPnPHydraCallback(), IopReferenceNotify(), IopReleaseNotifyLock, KeGetCurrentThread, MmDispatchWin32Callout(), _NOTIFICATION_CALLBACK_PARAM_BLOCK::NotificationStructure, NTSTATUS(), PAGED_CODE, PDEVICE_CLASS_NOTIFY_ENTRY, PKWIN32_CALLOUT, PNP_NOTIFICATION_VERSION, _DEVICE_INTERFACE_CHANGE_NOTIFICATION::Size, _DEVICE_INTERFACE_CHANGE_NOTIFICATION::SymbolicLinkName, _DEVICE_CLASS_NOTIFY_ENTRY::Unregistered, and _DEVICE_INTERFACE_CHANGE_NOTIFICATION::Version.

    07338                    :
    07339
    07340     This routine is used to notify all registered drivers of a changes to a
    07341     particular class of device. It does not return until all interested parties have
    07342     been notified.
    07343
    07344 Parameters:
    07345
    07346     EventTypeGuid - The event that has occured
    07347
    07348     ClassGuid - The device class this change has occured in
    07349
    07350     SymbolicLinkName - The kernel mode symbolic link name of the interface device
    07351         that changed
    07352
    07353 Return Value:
    07354
    07355     Status code that indicates whether or not the function was successful.
    07356
    07357 Note:
    07358
    07359     The contents of the notification structure *including* all pointers is only
    07360     valid during the callback routine to which it was passed.  If the data is
    07361     required after the duration of the callback then it must be physically copied
    07362     by the callback routine.
    07363
    07364 --*/
    07365
    07366 {
    07367     NTSTATUS status = STATUS_SUCCESS;
    07368     PLIST_ENTRY link;
    07369     PDEVICE_CLASS_NOTIFY_ENTRY entry;
    07370     DEVICE_INTERFACE_CHANGE_NOTIFICATION notification;
    07371     ULONG hash;
    07372 #if DBG
    07373     KIRQL originalIrql;
    07374     ULONG originalApcDisable;
    07375 #endif
    07376
    07377     PAGED_CODE();
    07378
    07379     //
    07380     // Fill in the notification
    07381     //
    07382
    07383     notification.Version = PNP_NOTIFICATION_VERSION;
    07384     notification.Size = sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION);
    07385     notification.Event = *EventGuid;
    07386     notification.InterfaceClassGuid = *ClassGuid;
    07387     notification.SymbolicLinkName = SymbolicLinkName;
    07388
    07389     //
    07390     // Lock the notify list
    07391     //
    07392
    07393     IopAcquireNotifyLock(&IopDeviceClassNotifyLock);
    07394
    07395     //
    07396     // Get the first entry
    07397     //
    07398
    07399     hash = IopHashGuid(ClassGuid);
    07400     link = IopDeviceClassNotifyList[hash].Flink;
    07401
    07402     //
    07403     // Iterate through the list
    07404     //
    07405
    07406     while (link != &IopDeviceClassNotifyList[hash]) {
    07407
    07408         entry = (PDEVICE_CLASS_NOTIFY_ENTRY) link;
    07409
    07410         //
    07411         // Only callback on registered nodes of the correct device class
    07412         //
    07413
    07414         if ( !entry->Unregistered && IopCompareGuid(&(entry->ClassGuid), ClassGuid) ) {
    07415
    07416             NOTIFICATION_CALLBACK_PARAM_BLOCK callparams;
    07417             ULONG Console=0;
    07418             //
    07419             // Reference the entry so that no one deletes during the callback
    07420             // and then release the lock
    07421             //
    07422
    07423             IopReferenceNotify( (PNOTIFY_ENTRY_HEADER) entry );
    07424             IopReleaseNotifyLock(&IopDeviceClassNotifyLock);
    07425
    07426 #if DBG
    07427             originalIrql = KeGetCurrentIrql();
    07428             originalApcDisable = KeGetCurrentThread()->KernelApcDisable;
    07429 #endif
    07430
    07431             //
    07432             // Callback the entity that registered and ignore the return value as
    07433             // we arn't interested in it
    07434             //
    07435
    07436             callparams.Callout=(entry->Callback);
    07437             callparams.NotificationStructure=&notification;
    07438             callparams.Context=entry->Context;
    07439
    07440
    07441             //
    07442             // Dispatch this function via the memory manager.
    07443             // Win32K is a driver that can have multiple copies. If Hydra
    07444             // is running, the Mem. manager will check if the callback exists
    07445             // in "per session" space. If that is the case, it will attach to the
    07446             // console (hence the 3rd param of PULONG containing 0) session and deliver
    07447             // it. If either Hydra is not running, or the callback is outside session space
    07448             // then the callback is called directly.
    07449             //
    07450             MmDispatchWin32Callout ((PKWIN32_CALLOUT)callparams.Callout,&IopPnPHydraCallback,&callparams,&Console);
    07451
    07452
    07453
    07454 #if DBG
    07455             if (originalIrql != KeGetCurrentIrql()) {
    07456                 DbgPrint("IopNotifyDeviceClassChange: Driver %Z, notification handler @ 0x%p returned at raised IRQL = %d, original = %d\n",
    07457                          &entry->DriverObject->DriverName, entry->Callback, KeGetCurrentIrql(), originalIrql);
    07458                 DbgBreakPoint();
    07459             }
    07460             if (originalApcDisable != KeGetCurrentThread()->KernelApcDisable) {
    07461                 DbgPrint("IopNotifyDeviceClassChange: Driver %Z, notification handler @ 0x%p returned with different KernelApcDisable = %d, original = %d\n",
    07462                          &entry->DriverObject->DriverName, entry->Callback, KeGetCurrentThread()->KernelApcDisable, originalApcDisable);
    07463                 DbgBreakPoint();
    07464             }
    07465 #endif
    07466             //
    07467             // Reacquire the lock and dereference
    07468             //
    07469
    07470             IopAcquireNotifyLock(&IopDeviceClassNotifyLock);
    07471             link = link->Flink;
    07472             IopDereferenceNotify( (PNOTIFY_ENTRY_HEADER) entry );
    07473
    07474         } else {
    07475
    07476             //
    07477             // Advance down the list
    07478             //
    07479
    07480             link = link->Flink;
    07481         }
    07482     }
    07483
    07484     //
    07485     // Release the lock
    07486     //
    07487
    07488     IopReleaseNotifyLock(&IopDeviceClassNotifyLock);
    07489
    07490     return status;
    07491 }

NTSTATUS IopNotifyHwProfileChange | ( | IN LPGUID | EventGuid,
|  | OUT PPNP_VETO_TYPE VetoType | OPTIONAL,
|  | OUT PUNICODE_STRING VetoName | OPTIONAL
| ) |

Definition at line 6858 of file pnpioapi.c.

References _NOTIFY_ENTRY_HEADER::Callback, _NOTIFICATION_CALLBACK_PARAM_BLOCK::Callout, _NOTIFICATION_CALLBACK_PARAM_BLOCK::Context, _NOTIFY_ENTRY_HEADER::Context, DbgPrint, _DRIVER_OBJECT::DriverName, _NOTIFY_ENTRY_HEADER::DriverObject, _HWPROFILE_CHANGE_NOTIFICATION::Event, IopAcquireNotifyLock, IopCompareGuid, IopDereferenceNotify(), IopHwProfileNotifyLock, IopPnPHydraCallback(), IopProfileNotifyList, IopReferenceNotify(), IopReleaseNotifyLock, KeGetCurrentThread, MmDispatchWin32Callout(), _NOTIFICATION_CALLBACK_PARAM_BLOCK::NotificationStructure, NT_SUCCESS, NTSTATUS(), PAGED_CODE, PHWPROFILE_NOTIFY_ENTRY, PKWIN32_CALLOUT, PNP_NOTIFICATION_VERSION, RtlCopyUnicodeString(), _HWPROFILE_CHANGE_NOTIFICATION::Size, _HWPROFILE_NOTIFY_ENTRY::Unregistered, _NOTIFY_ENTRY_HEADER::Unregistered, and _HWPROFILE_CHANGE_NOTIFICATION::Version.

Referenced by IopRequestHwProfileChangeNotification().

    06865                    :
    06866
    06867     This routine is used to deliver the HWProfileNotifications. It is
    06868     called from the worker thread only
    06869     It does not return until all interested parties have been notified.
    06870
    06871 Parameters:
    06872
    06873     EventTypeGuid - The event that has occured
    06874
    06875 Return Value:
    06876
    06877     Status code that indicates whether or not the function was successful.
    06878
    06879 Note:
    06880
    06881     The contents of the notification structure *including* all pointers is only
    06882     valid during the callback routine to which it was passed.  If the data is
    06883     required after the duration of the callback then it must be physically copied
    06884     by the callback routine.
    06885
    06886 --*/
    06887 {
    06888     NTSTATUS status=STATUS_SUCCESS;
    06889     PHWPROFILE_NOTIFY_ENTRY  pNotifyList;
    06890     PLIST_ENTRY link;
    06891 #if DBG
    06892     ULONG originalApcDisable;
    06893 #endif
    06894
    06895
    06896     PAGED_CODE();
    06897
    06898     //Lock the Profile Notification List
    06899     IopAcquireNotifyLock (&IopHwProfileNotifyLock);
    06900
    06901     //
    06902     //  Grab the list head (inside the lock)
    06903     //
    06904     link = IopProfileNotifyList.Flink;
    06905     pNotifyList=(PHWPROFILE_NOTIFY_ENTRY)link;
    06906
    06907     //
    06908     //circular list
    06909     //
    06910     while (link != (PLIST_ENTRY)&IopProfileNotifyList) {
    06911         if (!pNotifyList->Unregistered) {
    06912
    06913             HWPROFILE_CHANGE_NOTIFICATION notification;
    06914
    06915             NOTIFICATION_CALLBACK_PARAM_BLOCK callparams;
    06916             ULONG Console=0;
    06917
    06918             //
    06919             // Reference the entry so that no one deletes during the callback
    06920             // and then release the lock
    06921             //
    06922             IopReferenceNotify((PNOTIFY_ENTRY_HEADER)pNotifyList);
    06923             IopReleaseNotifyLock(&IopHwProfileNotifyLock);
    06924
    06925             //
    06926             // Fill in the notification
    06927             //
    06928
    06929             notification.Version = PNP_NOTIFICATION_VERSION;
    06930             notification.Size = sizeof(HWPROFILE_CHANGE_NOTIFICATION);
    06931             notification.Event = *EventGuid;
    06932
    06933 #if DBG
    06934             originalApcDisable = KeGetCurrentThread()->KernelApcDisable;
    06935 #endif
    06936             //
    06937             // Reference the notify and call back
    06938             //
    06939             callparams.Callout=(pNotifyList->Callback);
    06940             callparams.NotificationStructure=&notification;
    06941             callparams.Context=pNotifyList->Context;
    06942
    06943
    06944             //
    06945             // Dispatch this function via the memory manager.
    06946             // Win32K is a driver that can have multiple copies. If Hydra
    06947             // is running, the Mem. manager will check if the callback exists
    06948             // in "per session" space. If that is the case, it will attach to the
    06949             // console (hence the 3rd param of PULONG containing 0) session and deliver
    06950             // it. If either Hydra is not running, or the callback is outside session space
    06951             // then the callback is called directly.
    06952             //
    06953             status = MmDispatchWin32Callout ((PKWIN32_CALLOUT)callparams.Callout,&IopPnPHydraCallback,&callparams,&Console);
    06954 #if DBG
    06955             if (originalApcDisable != KeGetCurrentThread()->KernelApcDisable) {
    06956                 DbgPrint("IopNotifyHwProfileChange: Driver %Z, notification handler @ 0x%p returned with different KernelApcDisable = %d, original = %d\n",
    06957                          &pNotifyList->DriverObject->DriverName, pNotifyList->Callback, KeGetCurrentThread()->KernelApcDisable, originalApcDisable);
    06958                 DbgBreakPoint();
    06959             }
    06960 #endif
    06961
    06962             //
    06963             // If the caller returned anything other than success and it was a
    06964             // query hardware profile change, we veto the query and send cancels
    06965             // to all callers that already got the query.
    06966             //
    06967
    06968             if (!NT_SUCCESS(status) &&
    06969                 IopCompareGuid(EventGuid, (LPGUID)&GUID_HWPROFILE_QUERY_CHANGE)) {
    06970
    06971                 if (VetoType) {
    06972                     *VetoType = PNP_VetoDriver;
    06973                 }
    06974                 if (VetoName) {
    06975                     VetoName->Length = 0;
    06976                     RtlCopyUnicodeString(VetoName, &pNotifyList->DriverObject->DriverName);
    06977                 }
    06978
    06979                 notification.Event = GUID_HWPROFILE_CHANGE_CANCELLED;
    06980                 notification.Size = sizeof(GUID_HWPROFILE_CHANGE_CANCELLED);
    06981
    06982                 //
    06983                 // Dereference the entry which vetoed the query change.
    06984                 //
    06985                 IopAcquireNotifyLock(&IopHwProfileNotifyLock);
    06986                 IopDereferenceNotify((PNOTIFY_ENTRY_HEADER)pNotifyList);
    06987
    06988                 do {
    06989                     pNotifyList = (PHWPROFILE_NOTIFY_ENTRY)link;
    06990                     if (!pNotifyList->Unregistered) {
    06991                         IopReferenceNotify((PNOTIFY_ENTRY_HEADER)pNotifyList);
    06992                         IopReleaseNotifyLock(&IopHwProfileNotifyLock);
    06993
    06994 #if DBG
    06995                         originalApcDisable = KeGetCurrentThread()->KernelApcDisable;
    06996 #endif
    06997                         callparams.Callout=(pNotifyList->Callback);
    06998                         callparams.NotificationStructure=&notification;
    06999                         callparams.Context=pNotifyList->Context;
    07000
    07001                         MmDispatchWin32Callout ((PKWIN32_CALLOUT)callparams.Callout,&IopPnPHydraCallback,&callparams,&Console);
    07002 #if DBG
    07003                         if (originalApcDisable != KeGetCurrentThread()->KernelApcDisable) {
    07004                             DbgPrint("IopNotifyHwProfileChange: Driver %Z, notification handler @ 0x%p returned with different KernelApcDisable = %d, original = %d\n",
    07005                                      &pNotifyList->DriverObject->DriverName, pNotifyList->Callback, KeGetCurrentThread()->KernelApcDisable, originalApcDisable);
    07006                             DbgBreakPoint();
    07007                         }
    07008 #endif
    07009
    07010                         IopAcquireNotifyLock(&IopHwProfileNotifyLock);
    07011                         link = link->Blink;
    07012                         IopDereferenceNotify((PNOTIFY_ENTRY_HEADER)pNotifyList);
    07013
    07014                     } else {
    07015                         link = link->Blink;
    07016                     }
    07017                 } while (link != (PLIST_ENTRY)&IopProfileNotifyList);
    07018
    07019                 goto Clean0;
    07020             }
    07021
    07022             //
    07023             // Reacquire the lock, walk forward, and dereference
    07024             //
    07025             IopAcquireNotifyLock (&IopHwProfileNotifyLock);
    07026             link = link->Flink;
    07027             IopDereferenceNotify((PNOTIFY_ENTRY_HEADER)pNotifyList);
    07028             pNotifyList=(PHWPROFILE_NOTIFY_ENTRY)link;
    07029
    07030         } else {
    07031             //
    07032             //Walk forward if we hit an unregistered node
    07033             //
    07034             if (pNotifyList) {
    07035                 //
    07036                 //walk forward
    07037                 //
    07038                 link = link->Flink;
    07039                 pNotifyList=(PHWPROFILE_NOTIFY_ENTRY)link;
    07040             }
    07041         }
    07042     }
    07043
    07044  Clean0:
    07045
    07046     //UnLock the Profile Notification List
    07047     IopReleaseNotifyLock (&IopHwProfileNotifyLock);
    07048
    07049     return status;
    07050 }

NTSTATUS IopNotifySetupDeviceArrival | ( | PDEVICE_OBJECT | PhysicalDeviceObject,
|  | HANDLE | EnumEntryKey,
|  | BOOLEAN | InstallDriver
| ) |

Definition at line 8162 of file pnpioapi.c.

References _SETUP_NOTIFY_DATA::Callback, _NOTIFICATION_CALLBACK_PARAM_BLOCK::Callout, _NOTIFICATION_CALLBACK_PARAM_BLOCK::Context, _SETUP_NOTIFY_DATA::Context, _DEVOBJ_EXTENSION::DeviceNode, _DEVICE_OBJECT::DeviceObjectExtension, _SETUP_DEVICE_ARRIVAL_NOTIFICATION::EnumEntryKey, _SETUP_DEVICE_ARRIVAL_NOTIFICATION::EnumPath, _SETUP_DEVICE_ARRIVAL_NOTIFICATION::Event, _SETUP_DEVICE_ARRIVAL_NOTIFICATION::InstallDriver, _DEVICE_NODE::InstancePath, IopDeviceObjectToDeviceInstance(), IopPnPHydraCallback(), IopSetupNotifyData, MmDispatchWin32Callout(), _NOTIFICATION_CALLBACK_PARAM_BLOCK::NotificationStructure, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, _SETUP_DEVICE_ARRIVAL_NOTIFICATION::PhysicalDeviceObject, PKWIN32_CALLOUT, PNP_NOTIFICATION_VERSION, SETUP_DEVICE_ARRIVAL_NOTIFICATION, _SETUP_DEVICE_ARRIVAL_NOTIFICATION::Size, and _SETUP_DEVICE_ARRIVAL_NOTIFICATION::Version.

Referenced by IopInitializeDeviceInstanceKey(), IopNotifySetupDevices(), IopProcessNewDeviceNode(), and IoReportDetectedDevice().

    08170                    :
    08171
    08172     This routine is used to notify setup (during text-mode setup) of arrivals
    08173     of a particular device. It does not return until all interested parties have
    08174     been notified.
    08175
    08176 Parameters:
    08177
    08178     PhysicalDeviceObject - Supplies a pointer to the PDO of the newly arrived
    08179         device.
    08180
    08181     EnumEntryKey - Supplies a handle to the key associated with the devide under
    08182         the Enum\ branch of the registry.  Can be NULL in which case the key
    08183         will be opened here.
    08184
    08185     InstallDriver - Indicates whether setup should attempt to install a driver
    08186                     for this object.  Device objects created through
    08187                     IoReportDetectedDevice() already have a driver but we want
    08188                     to indicate them to setup anyway.
    08189
    08190 Return Value:
    08191
    08192     Status code that indicates whether or not the function was successful.
    08193
    08194 Note:
    08195
    08196     The contents of the notification structure *including* all pointers is only
    08197     valid during the callback routine to which it was passed.  If the data is
    08198     required after the duration of the callback then it must be physically copied
    08199     by the callback routine.
    08200
    08201 --*/
    08202
    08203 {
    08204     PAGED_CODE();
    08205
    08206     //
    08207     // Only perform notifications if someone has registered
    08208     //
    08209
    08210     if (IopSetupNotifyData) {
    08211
    08212         NTSTATUS status;
    08213         SETUP_DEVICE_ARRIVAL_NOTIFICATION notification;
    08214         NOTIFICATION_CALLBACK_PARAM_BLOCK callparams;
    08215         ULONG Console=0;
    08216         PDEVICE_NODE deviceNode;
    08217         HANDLE enumKey = NULL;
    08218
    08219         //
    08220         // Fill in the notification
    08221         //
    08222
    08223         if (!EnumEntryKey) {
    08224             status = IopDeviceObjectToDeviceInstance(PhysicalDeviceObject,
    08225                                                      &enumKey,
    08226                                                      KEY_WRITE);
    08227             if (!NT_SUCCESS(status)) {
    08228                 return status;
    08229             }
    08230             EnumEntryKey = enumKey;
    08231         }
    08232
    08233         notification.Version = PNP_NOTIFICATION_VERSION;
    08234         notification.Size = sizeof(SETUP_DEVICE_ARRIVAL_NOTIFICATION);
    08235         notification.Event = GUID_SETUP_DEVICE_ARRIVAL;
    08236         notification.PhysicalDeviceObject = PhysicalDeviceObject;
    08237         notification.EnumEntryKey = EnumEntryKey;
    08238         deviceNode = (PDEVICE_NODE) PhysicalDeviceObject->DeviceObjectExtension->DeviceNode;
    08239         notification.EnumPath = &deviceNode->InstancePath;
    08240         notification.InstallDriver = InstallDriver;
    08241
    08242         //
    08243         // Reference the notify and call back
    08244         //
    08245
    08246         callparams.Callout=(IopSetupNotifyData->Callback);
    08247         callparams.NotificationStructure=&notification;
    08248         callparams.Context=IopSetupNotifyData->Context;
    08249
    08250
    08251         //
    08252         // Dispatch this function via the memory manager.
    08253         // Win32K is a driver that can have multiple copies. If Hydra
    08254         // is running, the Mem. manager will check if the callback exists
    08255         // in "per session" space. If that is the case, it will attach to the
    08256         // console (hence the 3rd param of PULONG containing 0) session and deliver
    08257         // it. If either Hydra is not running, or the callback is outside session space
    08258         // then the callback is called directly.
    08259         //
    08260         status = MmDispatchWin32Callout ((PKWIN32_CALLOUT)callparams.Callout,&IopPnPHydraCallback,&callparams,&Console);
    08261         if (enumKey) {
    08262             ZwClose(enumKey);
    08263         }
    08264
    08265         return status;
    08266
    08267     } else {
    08268
    08269         return STATUS_OBJECT_NAME_NOT_FOUND;
    08270
    08271     }
    08272 }

NTSTATUS IopNotifyTargetDeviceChange | ( | LPCGUID | EventGuid,
|  | PDEVICE_OBJECT | DeviceObject,
|  | PVOID | NotificationStructure,
|  | PDRIVER_OBJECT * | VetoingDriver
| ) |

Definition at line 7055 of file pnpioapi.c.

References ASSERT, _NOTIFY_ENTRY_HEADER::Callback, _NOTIFICATION_CALLBACK_PARAM_BLOCK::Callout, _NOTIFICATION_CALLBACK_PARAM_BLOCK::Context, _NOTIFY_ENTRY_HEADER::Context, DbgPrint, _DEVOBJ_EXTENSION::DeviceNode, _DEVICE_OBJECT::DeviceObjectExtension, _DRIVER_OBJECT::DriverName, _NOTIFY_ENTRY_HEADER::DriverObject, _TARGET_DEVICE_REMOVAL_NOTIFICATION::Event, _TARGET_DEVICE_CUSTOM_NOTIFICATION::FileObject, _TARGET_DEVICE_REMOVAL_NOTIFICATION::FileObject, IopAcquireNotifyLock, IopCompareGuid, IopDereferenceNotify(), IopPnPHydraCallback(), IopReferenceNotify(), IopReleaseNotifyLock, IopTargetDeviceNotifyLock, KeGetCurrentThread, MmDispatchWin32Callout(), _NOTIFICATION_CALLBACK_PARAM_BLOCK::NotificationStructure, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObject, PAGED_CODE, PKWIN32_CALLOUT, PNP_NOTIFICATION_VERSION, _TARGET_DEVICE_REMOVAL_NOTIFICATION::Size, _DEVICE_NODE::TargetDeviceNotify, _TARGET_DEVICE_NOTIFY_ENTRY::Unregistered, _NOTIFY_ENTRY_HEADER::Unregistered, and _TARGET_DEVICE_REMOVAL_NOTIFICATION::Version.

    07064                    :
    07065
    07066     This routine is used to notify all registered drivers of a change to a
    07067     particular device. It does not return until all interested parties have
    07068     been notified.
    07069
    07070 Parameters:
    07071
    07072     EventGuid - The event that has occured
    07073
    07074     DeviceObject - The device object that has changed.  The devnode for this
    07075         device object contains a list of callback routines that have registered
    07076         for notification of any changes on this device object.
    07077
    07078 Return Value:
    07079
    07080     Status code that indicates whether or not the function was successful.
    07081
    07082 Note:
    07083
    07084     The contents of the notification structure *including* all pointers is only
    07085     valid during the callback routine to which it was passed.  If the data is
    07086     required after the duration of the callback then it must be physically copied
    07087     by the callback routine.
    07088
    07089 --*/
    07090
    07091 {
    07092     NTSTATUS status = STATUS_SUCCESS;
    07093     PLIST_ENTRY link, lastLink;
    07094     PTARGET_DEVICE_NOTIFY_ENTRY entry;
    07095     TARGET_DEVICE_REMOVAL_NOTIFICATION notification;
    07096     PDEVICE_NODE deviceNode;
    07097     BOOLEAN reverse;
    07098 #if DBG
    07099     KIRQL originalIrql;
    07100     ULONG originalApcDisable;
    07101 #endif
    07102
    07103     PAGED_CODE();
    07104
    07105     ASSERT(DeviceObject != NULL);
    07106     ASSERT(EventGuid != NULL);
    07107
    07108     //
    07109     // Reference the device object so it can't go away while we're doing notification
    07110     //
    07111     ObReferenceObject(DeviceObject);
    07112
    07113     deviceNode = (PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
    07114
    07115     ASSERT(deviceNode != NULL);
    07116
    07117
    07118     if (NotificationStructure) {
    07119         //
    07120         //We're handling a custom notification
    07121         //
    07122
    07123         ((PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure)->Version = PNP_NOTIFICATION_VERSION;
    07124
    07125     } else {
    07126         //
    07127         // Fill in the notification
    07128         //
    07129
    07130         notification.Version = PNP_NOTIFICATION_VERSION;
    07131         notification.Size = sizeof(TARGET_DEVICE_REMOVAL_NOTIFICATION);
    07132         notification.Event = *EventGuid;
    07133     }
    07134
    07135     //
    07136     // Lock the notify list
    07137     //
    07138
    07139     IopAcquireNotifyLock(&IopTargetDeviceNotifyLock);
    07140
    07141     //
    07142     // Get the first entry
    07143     //
    07144
    07145     reverse = IopCompareGuid(EventGuid, (LPGUID)&GUID_TARGET_DEVICE_REMOVE_CANCELLED);
    07146
    07147     if (reverse) {
    07148         link = deviceNode->TargetDeviceNotify.Blink;
    07149     } else {
    07150         link = deviceNode->TargetDeviceNotify.Flink;
    07151     }
    07152
    07153     //
    07154     // Iterate through the list
    07155     //
    07156
    07157     while (link != &deviceNode->TargetDeviceNotify) {
    07158
    07159         entry = (PTARGET_DEVICE_NOTIFY_ENTRY)link;
    07160
    07161         //
    07162         // Only callback on registered nodes
    07163         //
    07164
    07165         if (!entry->Unregistered) {
    07166
    07167             NOTIFICATION_CALLBACK_PARAM_BLOCK callparams;
    07168             ULONG Console=0;
    07169
    07170             //
    07171             // Reference the entry so that no one deletes during the callback
    07172             // and then release the lock
    07173             //
    07174
    07175             IopReferenceNotify((PNOTIFY_ENTRY_HEADER)entry);
    07176             IopReleaseNotifyLock(&IopTargetDeviceNotifyLock);
    07177
    07178 #if DBG
    07179             originalIrql = KeGetCurrentIrql();
    07180             originalApcDisable = KeGetCurrentThread()->KernelApcDisable;
    07181 #endif
    07182
    07183             //
    07184             // Callback the entity that registered and examine return value
    07185             //
    07186
    07187             if (NotificationStructure) {
    07188                 TARGET_DEVICE_CUSTOM_NOTIFICATION *notificationStructure = NotificationStructure;
    07189
    07190                 notificationStructure->FileObject = entry->FileObject;
    07191
    07192                 callparams.Callout=(entry->Callback);
    07193                 callparams.NotificationStructure=NotificationStructure;
    07194                 callparams.Context=entry->Context;
    07195
    07196
    07197                 //
    07198                 // Dispatch this function via the memory manager.
    07199                 // Win32K is a driver that can have multiple copies. If Hydra
    07200                 // is running, the Mem. manager will check if the callback exists
    07201                 // in "per session" space. If that is the case, it will attach to the
    07202                 // console (hence the 3rd param of PULONG containing 0) session and deliver
    07203                 // it. If either Hydra is not running, or the callback is outside session space
    07204                 // then the callback is called directly.
    07205                 //
    07206                 status = MmDispatchWin32Callout ((PKWIN32_CALLOUT)callparams.Callout,&IopPnPHydraCallback,&callparams,&Console);
    07207
    07208
    07209             } else {
    07210                 notification.FileObject = entry->FileObject;
    07211
    07212                 callparams.Callout=(entry->Callback);
    07213                 callparams.NotificationStructure=&notification;
    07214                 callparams.Context=entry->Context;
    07215
    07216                 status = MmDispatchWin32Callout ((PKWIN32_CALLOUT)callparams.Callout,&IopPnPHydraCallback,&callparams,&Console);
    07217
    07218             }
    07219
    07220 #if DBG
    07221             if (originalIrql != KeGetCurrentIrql()) {
    07222                 DbgPrint("IopNotifyTargetDeviceChange: Driver %Z, notification handler @ 0x%p returned at raised IRQL = %d, original = %d\n",
    07223                          &entry->DriverObject->DriverName, entry->Callback, KeGetCurrentIrql(), originalIrql);
    07224                 DbgBreakPoint();
    07225             }
    07226             if (originalApcDisable != KeGetCurrentThread()->KernelApcDisable) {
    07227                 DbgPrint("IopNotifyTargetDeviceChange: Driver %Z, notification handler @ 0x%p returned with different KernelApcDisable = %d, original = %d\n",
    07228                          &entry->DriverObject->DriverName, entry->Callback, KeGetCurrentThread()->KernelApcDisable, originalApcDisable);
    07229                 DbgBreakPoint();
    07230             }
    07231 #endif
    07232
    07233             //
    07234             // If the caller returned anything other than success and it was
    07235             // a query remove, we veto the query remove and send cancels to
    07236             // all callers that already got the query remove.
    07237             //
    07238
    07239             if (!NT_SUCCESS(status) &&
    07240                 IopCompareGuid(EventGuid, (LPGUID)&GUID_TARGET_DEVICE_QUERY_REMOVE)) {
    07241
    07242                 if (VetoingDriver != NULL) {
    07243                     *VetoingDriver = entry->DriverObject;
    07244                 }
    07245
    07246                 notification.Event = GUID_TARGET_DEVICE_REMOVE_CANCELLED;
    07247
    07248                 //
    07249                 // Dereference the entry which vetoed the query remove.
    07250                 //
    07251                 IopAcquireNotifyLock(&IopTargetDeviceNotifyLock);
    07252                 IopDereferenceNotify((PNOTIFY_ENTRY_HEADER)entry);
    07253
    07254                 do {
    07255                     entry = (PTARGET_DEVICE_NOTIFY_ENTRY)link;
    07256                     if (!entry->Unregistered) {
    07257                         IopReferenceNotify((PNOTIFY_ENTRY_HEADER)entry);
    07258                         IopReleaseNotifyLock(&IopTargetDeviceNotifyLock);
    07259
    07260                         notification.FileObject = entry->FileObject;
    07261 #if DBG
    07262                         originalApcDisable = KeGetCurrentThread()->KernelApcDisable;
    07263 #endif
    07264
    07265                         callparams.Callout=(entry->Callback);
    07266                         callparams.NotificationStructure=&notification;
    07267                         callparams.Context=entry->Context;
    07268
    07269                         MmDispatchWin32Callout ((PKWIN32_CALLOUT)callparams.Callout,&IopPnPHydraCallback,&callparams,&Console);
    07270
    07271 #if DBG
    07272                         if (originalApcDisable != KeGetCurrentThread()->KernelApcDisable) {
    07273                             DbgPrint("IopNotifyTargetDeviceChange: Driver %Z, notification handler @ 0x%p returned with different KernelApcDisable = %d, original = %d\n",
    07274                                      &entry->DriverObject->DriverName, entry->Callback, KeGetCurrentThread()->KernelApcDisable, originalApcDisable);
    07275                             DbgBreakPoint();
    07276                         }
    07277 #endif
    07278
    07279                         IopAcquireNotifyLock(&IopTargetDeviceNotifyLock);
    07280                         link = link->Blink;
    07281                         IopDereferenceNotify( (PNOTIFY_ENTRY_HEADER) entry );
    07282
    07283                     } else {
    07284                         link = link->Blink;
    07285                     }
    07286                 } while (link != &deviceNode->TargetDeviceNotify);
    07287
    07288                 goto Clean0;
    07289             }
    07290
    07291             //
    07292             // Reacquire the lock and dereference
    07293             //
    07294             IopAcquireNotifyLock(&IopTargetDeviceNotifyLock);
    07295             if (reverse) {
    07296                 link = link->Blink;
    07297             } else {
    07298                 link = link->Flink;
    07299             }
    07300             IopDereferenceNotify((PNOTIFY_ENTRY_HEADER)entry);
    07301
    07302         } else {
    07303
    07304             //
    07305             // Advance down the list
    07306             //
    07307             if (reverse) {
    07308                 link = link->Blink;
    07309             } else {
    07310                 link = link->Flink;
    07311             }
    07312         }
    07313     }
    07314
    07315 Clean0:
    07316
    07317     //
    07318     // Release the lock and dereference the object
    07319     //
    07320
    07321     IopReleaseNotifyLock(&IopTargetDeviceNotifyLock);
    07322
    07323     ObDereferenceObject(DeviceObject);
    07324
    07325     return status;
    07326 }

ULONG IoPnPDeliverServicePowerNotification | ( | ULONG | PwrNotification,
|  | BOOLEAN | Synchronous
| ) |

Definition at line 9221 of file pnpioapi.c.

References ASSERT, ExAllocatePool, Executive, ExFreePool(), FALSE, IoRaiseInformationalHardError(), KeInitializeEvent, KernelMode, KeWaitForSingleObject(), MAX_VETO_NAME_LENGTH, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PagedPool, and PpSetPowerEvent().

Referenced by xxxSendMessageBSM().

    09225 {
    09226
    09227     NTSTATUS status = STATUS_SUCCESS;
    09228     KEVENT completionEvent;
    09229     NTSTATUS completionStatus=STATUS_SUCCESS;
    09230     PNP_VETO_TYPE vetoType = PNP_VetoTypeUnknown;
    09231     UNICODE_STRING vetoName;
    09232
    09233     PAGED_CODE();
    09234
    09235 #define MAX_VETO_NAME_LENGTH    512 //From Revent.c make it common
    09236
    09237     if (Synchronous) {
    09238
    09239
    09240
    09241         vetoName.Buffer = ExAllocatePool (PagedPool,MAX_VETO_NAME_LENGTH*sizeof (WCHAR));
    09242
    09243         if (vetoName.Buffer) {
    09244             vetoName.MaximumLength = MAX_VETO_NAME_LENGTH;
    09245         }else {
    09246             vetoName.MaximumLength = 0;
    09247         }
    09248         vetoName.Length = 0;
    09249
    09250         KeInitializeEvent(&completionEvent, NotificationEvent, FALSE);
    09251
    09252         status = PpSetPowerEvent(
    09253             PwrNotification,
    09254             &completionEvent,
    09255             &completionStatus,
    09256             &vetoType,&vetoName
    09257             );
    09258
    09259         if (NT_SUCCESS(status))  {
    09260
    09261             KeWaitForSingleObject( &completionEvent, Executive, KernelMode, FALSE, NULL );
    09262             status = completionStatus;
    09263
    09264             if (vetoType == PNP_VetoWindowsService) {
    09265                 IoRaiseInformationalHardError (STATUS_DRIVER_FAILED_SLEEP,&vetoName,NULL);
    09266             }
    09267
    09268         }
    09269         if (vetoName.Buffer) {
    09270             ExFreePool (vetoName.Buffer);
    09271         }
    09272
    09273     } else {
    09274         status = PpSetPowerEvent(
    09275             PwrNotification,
    09276             NULL,
    09277             NULL,
    09278             NULL,
    09279             NULL
    09280             );
    09281     }
    09282
    09283     ASSERT ((completionStatus == STATUS_SUCCESS) ||
    09284             (completionStatus == STATUS_UNSUCCESSFUL));
    09285     //
    09286     // The private code in Win32k that calls this, assumes that 0 is failure, !0 is success
    09287     //
    09288
    09289     return (completionStatus != STATUS_UNSUCCESSFUL);
    09290
    09291 }

NTSTATUS IopOpenDeviceParametersSubkey | ( | OUT HANDLE * | ParamKeyHandle,
|  | IN HANDLE | ParentKeyHandle,
|  | IN PUNICODE_STRING | SubKeyString,
|  | IN ACCESS_MASK | DesiredAccess
| ) |

Definition at line 8501 of file pnpioapi.c.

References ASSERT, ExAllocatePool, ExFreePool(), FALSE, IopCreateRegistryKeyEx(), IopOpenRegistryKeyEx(), NT_SUCCESS, NTSTATUS(), NULL, PagedPool, RtlAddAccessAllowedAceEx(), RtlAddAce(), RtlCreateAcl(), RtlCreateSecurityDescriptor(), RtlEqualSid(), RtlGetAce(), RtlGetDaclSecurityDescriptor(), RtlInitUnicodeString(), RtlLengthSid(), RtlQueryInformationAcl(), RtlSetDaclSecurityDescriptor(), RtlValidSecurityDescriptor(), SeAliasAdminsSid, and TRUE.

Referenced by IoOpenDeviceRegistryKey(), MapperSeedKey(), and PnPBiosCopyDeviceParamKey().

    08510                    :
    08511
    08512     This routine reports whether WDM functionality is available that
    08513     is greater than or equal to the specified major and minor version.
    08514
    08515 Parameters:
    08516
    08517     MajorVersion - Supplies the WDM major version that is required.
    08518
    08519     MinorVersion - Supplies the WDM minor version that is required.
    08520
    08521 Return Value:
    08522
    08523     If WDM support is available at _at least_ the requested level, the
    08524     return value is TRUE, otherwise it is FALSE.
    08525
    08526 --*/
    08527
    08528 {
    08529     NTSTATUS                    status;
    08530     ULONG                       disposition;
    08531     ULONG                       lengthSD;
    08532     PSECURITY_DESCRIPTOR        oldSD = NULL;
    08533     SECURITY_DESCRIPTOR         newSD;
    08534     ACL_SIZE_INFORMATION        aclSizeInfo;
    08535     PACL                        oldDacl;
    08536     PACL                        newDacl = NULL;
    08537     ULONG                       sizeDacl;
    08538     BOOLEAN                     daclPresent, daclDefaulted;
    08539     PACCESS_ALLOWED_ACE         ace;
    08540     ULONG                       aceIndex;
    08541     HANDLE                      deviceKeyHandle;
    08542     UNICODE_STRING              deviceParamString;
    08543
    08544     //
    08545     // First try and open the device key
    08546     //
    08547     status = IopOpenRegistryKeyEx( &deviceKeyHandle,
    08548                                    ParentKeyHandle,
    08549                                    SubKeyString,
    08550                                    KEY_WRITE
    08551                                    );
    08552
    08553     if (!NT_SUCCESS(status)) {
    08554         return status;
    08555     }
    08556
    08557     RtlInitUnicodeString(&deviceParamString, REGSTR_KEY_DEVICEPARAMETERS);
    08558
    08559     status = IopCreateRegistryKeyEx( ParamKeyHandle,
    08560                                      deviceKeyHandle,
    08561                                      &deviceParamString,
    08562                                      DesiredAccess | READ_CONTROL | WRITE_DAC,
    08563                                      REG_OPTION_NON_VOLATILE,
    08564                                      &disposition
    08565                                      );
    08566
    08567     ZwClose(deviceKeyHandle);
    08568
    08569     if (!NT_SUCCESS(status)) {
    08570         KdPrint(("IopOpenDeviceParametersSubkey: IopCreateRegistryKeyEx failed, status = %8.8X\n", status));
    08571         return status;
    08572     }
    08573
    08574     if (disposition == REG_CREATED_NEW_KEY) {
    08575
    08576         //
    08577         // Need to set an ACL on the key if it was created
    08578         //
    08579         //
    08580         // Get the security descriptor from the key so we can add the
    08581         // administrator.
    08582         //
    08583         status = ZwQuerySecurityObject(*ParamKeyHandle,
    08584                                        DACL_SECURITY_INFORMATION,
    08585                                        NULL,
    08586                                        0,
    08587                                        &lengthSD);
    08588
    08589         if (status == STATUS_BUFFER_TOO_SMALL) {
    08590             oldSD = ExAllocatePool( PagedPool, lengthSD );
    08591
    08592             if (oldSD != NULL) {
    08593
    08594                 status = ZwQuerySecurityObject(*ParamKeyHandle,
    08595                                                DACL_SECURITY_INFORMATION,
    08596                                                oldSD,
    08597                                                lengthSD,
    08598                                                &lengthSD);
    08599                 if (!NT_SUCCESS(status)) {
    08600                     KdPrint(("IopOpenDeviceParametersSubkey: ZwQuerySecurityObject failed, status = %8.8X\n", status));
    08601                     goto Cleanup0;
    08602                 }
    08603             } else  {
    08604
    08605                 KdPrint(("IopOpenDeviceParametersSubkey: Failed to allocate memory, status = %8.8X\n", status));
    08606                 status = STATUS_NO_MEMORY;
    08607                 goto Cleanup0;
    08608             }
    08609         } else {
    08610            KdPrint(("IopOpenDeviceParametersSubkey: ZwQuerySecurityObject failed %8.8X\n",status));
    08611            status = STATUS_UNSUCCESSFUL;
    08612            goto Cleanup0;
    08613         }
    08614
    08615         status = RtlCreateSecurityDescriptor( (PSECURITY_DESCRIPTOR) &newSD,
    08616                                               SECURITY_DESCRIPTOR_REVISION );
    08617         ASSERT( NT_SUCCESS( status ) );
    08618
    08619         if (!NT_SUCCESS(status)) {
    08620
    08621             KdPrint(("IopOpenDeviceParametersSubkey: RtlCreateSecurityDescriptor failed, status = %8.8X\n", status));
    08622             goto Cleanup0;
    08623         }
    08624         //
    08625         // get the current DACL
    08626         //
    08627         status = RtlGetDaclSecurityDescriptor(oldSD, &daclPresent, &oldDacl, &daclDefaulted);
    08628
    08629         ASSERT( NT_SUCCESS( status ) );
    08630
    08631         //
    08632         // calculate the size of the new DACL
    08633         //
    08634
    08635         if (daclPresent) {
    08636
    08637             status = RtlQueryInformationAcl( oldDacl,
    08638                                              &aclSizeInfo,
    08639                                              sizeof(ACL_SIZE_INFORMATION),
    08640                                              AclSizeInformation);
    08641
    08642
    08643             if (!NT_SUCCESS(status)) {
    08644
    08645                 KdPrint(("IopOpenDeviceParametersSubkey: RtlQueryInformationAcl failed, status = %8.8X\n", status));
    08646                 goto Cleanup0;
    08647             }
    08648
    08649             sizeDacl = aclSizeInfo.AclBytesInUse;
    08650         } else {
    08651             sizeDacl = sizeof(ACL);
    08652         }
    08653
    08654         sizeDacl += sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(SeAliasAdminsSid) - sizeof(ULONG);
    08655
    08656         //
    08657         // create and initialize the new DACL
    08658         //
    08659         newDacl = ExAllocatePool(PagedPool, sizeDacl);
    08660
    08661         if (newDacl == NULL) {
    08662
    08663             KdPrint(("IopOpenDeviceParametersSubkey: ExAllocatePool failed\n"));
    08664             goto Cleanup0;
    08665         }
    08666
    08667         status = RtlCreateAcl(newDacl, sizeDacl, ACL_REVISION);
    08668
    08669         if (!NT_SUCCESS(status)) {
    08670
    08671             KdPrint(("IopOpenDeviceParametersSubkey: RtlCreateAcl failed, status = %8.8X\n", status));
    08672             goto Cleanup0;
    08673         }
    08674
    08675         //
    08676         // copy the current (original) DACL into this new one
    08677         //
    08678         if (daclPresent) {
    08679
    08680             for (aceIndex = 0; aceIndex < aclSizeInfo.AceCount; aceIndex++) {
    08681
    08682                 status = RtlGetAce(oldDacl, aceIndex, (PVOID *)&ace);
    08683
    08684                 if (!NT_SUCCESS(status)) {
    08685
    08686                     KdPrint(("IopOpenDeviceParametersSubkey: RtlGetAce failed, status = %8.8X\n", status));
    08687                     goto Cleanup0;
    08688                 }
    08689
    08690                 //
    08691                 // We need to skip copying any ACEs which refer to the Administrator
    08692                 // to ensure that our full control ACE is the one and only.
    08693                 //
    08694                 if ((ace->Header.AceType != ACCESS_ALLOWED_ACE_TYPE &&
    08695                      ace->Header.AceType != ACCESS_DENIED_ACE_TYPE) ||
    08696                      !RtlEqualSid((PSID)&ace->SidStart, SeAliasAdminsSid)) {
    08697
    08698                     status = RtlAddAce( newDacl,
    08699                                         ACL_REVISION,
    08700                                         ~0U,
    08701                                         ace,
    08702                                         ace->Header.AceSize
    08703                                         );
    08704
    08705                     if (!NT_SUCCESS(status)) {
    08706
    08707                         KdPrint(("IopOpenDeviceParametersSubkey: RtlAddAce failed, status = %8.8X\n", status));
    08708                         goto Cleanup0;
    08709                     }
    08710                 }
    08711             }
    08712         }
    08713
    08714         //
    08715         // and my new admin-full ace to this new DACL
    08716         //
    08717         status = RtlAddAccessAllowedAceEx( newDacl,
    08718                                            ACL_REVISION,
    08719                                            CONTAINER_INHERIT_ACE,
    08720                                            KEY_ALL_ACCESS,
    08721                                            SeAliasAdminsSid
    08722                                            );
    08723         if (!NT_SUCCESS(status)) {
    08724
    08725             KdPrint(("IopOpenDeviceParametersSubkey: RtlAddAccessAllowedAceEx failed, status = %8.8X\n", status));
    08726             goto Cleanup0;
    08727         }
    08728
    08729         //
    08730         // Set the new DACL in the absolute security descriptor
    08731         //
    08732         status = RtlSetDaclSecurityDescriptor( (PSECURITY_DESCRIPTOR) &newSD,
    08733                                                TRUE,
    08734                                                newDacl,
    08735                                                FALSE
    08736                                                );
    08737
    08738         if (!NT_SUCCESS(status)) {
    08739
    08740             KdPrint(("IopOpenDeviceParametersSubkey: RtlSetDaclSecurityDescriptor failed, status = %8.8X\n", status));
    08741             goto Cleanup0;
    08742         }
    08743
    08744         //
    08745         // validate the new security descriptor
    08746         //
    08747         status = RtlValidSecurityDescriptor(&newSD);
    08748
    08749         if (!NT_SUCCESS(status)) {
    08750
    08751             KdPrint(("IopOpenDeviceParametersSubkey: RtlValidSecurityDescriptor failed, status = %8.8X\n", status));
    08752             goto Cleanup0;
    08753         }
    08754
    08755
    08756         status = ZwSetSecurityObject( *ParamKeyHandle,
    08757                                       DACL_SECURITY_INFORMATION,
    08758                                       &newSD
    08759                                       );
    08760         if (!NT_SUCCESS(status)) {
    08761
    08762             KdPrint(("IopOpenDeviceParametersSubkey: ZwSetSecurityObject failed, status = %8.8X\n", status));
    08763             goto Cleanup0;
    08764         }
    08765     }
    08766
    08767     //
    08768     // If we encounter an error updating the DACL we still return success.
    08769     //
    08770
    08771 Cleanup0:
    08772
    08773     if (oldSD != NULL) {
    08774         ExFreePool(oldSD);
    08775     }
    08776
    08777     if (newDacl != NULL) {
    08778         ExFreePool(newDacl);
    08779     }
    08780
    08781     return STATUS_SUCCESS;
    08782 }

NTSTATUS IopOpenOrCreateDeviceInterfaceSubKeys | ( | OUT PHANDLE InterfaceKeyHandle | OPTIONAL,
|  | OUT PULONG InterfaceKeyDisposition | OPTIONAL,
|  | OUT PHANDLE InterfaceInstanceKeyHandle | OPTIONAL,
|  | OUT PULONG InterfaceInstanceDisposition | OPTIONAL,
|  | IN HANDLE | InterfaceClassKeyHandle,
|  | IN PUNICODE_STRING | DeviceInterfaceName,
|  | IN ACCESS_MASK | DesiredAccess,
|  | IN BOOLEAN | Create
| ) |

Definition at line 4741 of file pnpioapi.c.

References ASSERT, Create(), FALSE, IopAllocateUnicodeString(), IopConstStringSize, IopCreateRegistryKeyEx(), IopFreeAllocatedUnicodeString(), IopOpenRegistryKeyEx(), IopParseSymbolicLinkName(), IopReplaceSeperatorWithPound(), KEY_STRING_PREFIX, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, REFSTRING_PREFIX_CHAR, RtlCopyUnicodeString(), and USHORT.

Referenced by IopDeviceInterfaceKeysFromSymbolicLink(), IopGetDeviceInterfaces(), and IopRegisterDeviceInterface().

    04754                    :
    04755
    04756     This API opens or creates a two-level registry hierarchy underneath the
    04757     specified interface class key for a particular device interface.  The first
    04758     level is the (munged) symbolic link name (sans RefString).  The second level
    04759     is the refstring, prepended with a '#' sign (if the device interface has no
    04760     refstring, then this key name is simply '#').
    04761
    04762 Parameters:
    04763
    04764     InterfaceKeyHandle - Optionally, supplies the address of a variable that
    04765         receives a handle to the interface key (1st level in the hierarchy).
    04766
    04767     InterfaceKeyDisposition - Optionally, supplies the address of a variable that
    04768         receives either REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY indicating
    04769         whether the interface key was newly-created.
    04770
    04771     InterfaceInstanceKeyHandle - Optionally, supplies the address of a variable
    04772         that receives a handle to the interface instance key (2nd level in the
    04773         hierarchy).
    04774
    04775     InterfaceInstanceDisposition - Optionally, supplies the address of a variable
    04776         that receives either REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
    04777         indicating whether the interface instance key was newly-created.
    04778
    04779     InterfaceClassKeyHandle - Supplies a handle to the interface class key under
    04780         which the device interface keys are to be opened/created.
    04781
    04782     DeviceInterfaceName - Supplies the (user-mode or kernel-mode form) device
    04783         interface name.
    04784
    04785     DesiredAccess - Specifies the desired access that the caller needs to the keys.
    04786
    04787     Create - Determines if the keys are to be created if they do not exist.
    04788
    04789 Return Value:
    04790
    04791     Status code that indicates whether or not the function was successful.
    04792
    04793 --*/
    04794
    04795 {
    04796     NTSTATUS status;
    04797     UNICODE_STRING TempString, RefString;
    04798     WCHAR PoundCharBuffer;
    04799     HANDLE hTempInterface, hTempInterfaceInstance;
    04800     ULONG TempInterfaceDisposition;
    04801     BOOLEAN RefStringPresent=FALSE;
    04802
    04803     PAGED_CODE();
    04804
    04805     //
    04806     // Make a copy of the device interface name, since we're going to munge it.
    04807     //
    04808     status = IopAllocateUnicodeString(&TempString, DeviceInterfaceName->Length);
    04809
    04810     if(!NT_SUCCESS(status)) {
    04811         goto clean0;
    04812     }
    04813
    04814     RtlCopyUnicodeString(&TempString, DeviceInterfaceName);
    04815
    04816     //
    04817     // Find the refstring component (if there is one).
    04818     //
    04819     status = IopParseSymbolicLinkName(&TempString,
    04820                                       NULL,
    04821                                       NULL,
    04822                                       NULL,
    04823                                       &RefString,
    04824                                       &RefStringPresent,
    04825                                       NULL
    04826                                      );
    04827     ASSERT(NT_SUCCESS(status));
    04828
    04829     if(RefStringPresent) {
    04830         //
    04831         // Truncate the device interface name before the refstring separator char.
    04832         //
    04833         RefString.Buffer--;
    04834         RefString.Length += sizeof(WCHAR);
    04835         RefString.MaximumLength += sizeof(WCHAR);
    04836         TempString.MaximumLength = TempString.Length = (USHORT)((PUCHAR)RefString.Buffer - (PUCHAR)TempString.Buffer);
    04837     } else {
    04838         //
    04839         // Set up refstring to point to a temporary character buffer that will hold
    04840         // the single '#' used for the key name when no refstring is present.
    04841         //
    04842         RefString.Buffer = &PoundCharBuffer;
    04843         RefString.Length = RefString.MaximumLength = sizeof(PoundCharBuffer);
    04844     }
    04845
    04846     //
    04847     // Replace the "\??\" or "\\?\" symbolic link name prefix with ##?#
    04848     //
    04849     RtlCopyMemory(TempString.Buffer, KEY_STRING_PREFIX, IopConstStringSize(KEY_STRING_PREFIX));
    04850
    04851     //
    04852     // Munge the string
    04853     //
    04854     IopReplaceSeperatorWithPound(&TempString, &TempString);
    04855
    04856     //
    04857     // Now open/create this subkey under the interface class key.
    04858     //
    04859
    04860     if (Create) {
    04861         status = IopCreateRegistryKeyEx( &hTempInterface,
    04862                                          InterfaceClassKeyHandle,
    04863                                          &TempString,
    04864                                          DesiredAccess,
    04865                                          REG_OPTION_NON_VOLATILE,
    04866                                          &TempInterfaceDisposition
    04867                                          );
    04868     } else {
    04869         status = IopOpenRegistryKeyEx( &hTempInterface,
    04870                                        InterfaceClassKeyHandle,
    04871                                        &TempString,
    04872                                        DesiredAccess
    04873                                        );
    04874     }
    04875
    04876     if(!NT_SUCCESS(status)) {
    04877         goto clean1;
    04878     }
    04879
    04880     //
    04881     // Store a '#' as the first character of the RefString, and then we're ready to open the
    04882     // refstring subkey.
    04883     //
    04884     *RefString.Buffer = REFSTRING_PREFIX_CHAR;
    04885
    04886     //
    04887     // Now open/create the subkey under the interface key representing this interface instance
    04888     // (i.e., differentiated by refstring).
    04889     //
    04890
    04891     if (Create) {
    04892         status = IopCreateRegistryKeyEx( &hTempInterfaceInstance,
    04893                                        hTempInterface,
    04894                                        &RefString,
    04895                                        DesiredAccess,
    04896                                        REG_OPTION_NON_VOLATILE,
    04897                                        InterfaceInstanceDisposition
    04898                                        );
    04899     } else {
    04900         status = IopOpenRegistryKeyEx( &hTempInterfaceInstance,
    04901                                        hTempInterface,
    04902                                        &RefString,
    04903                                        DesiredAccess
    04904                                        );
    04905     }
    04906
    04907     if(NT_SUCCESS(status)) {
    04908         //
    04909         // Store any requested return values in the caller-supplied buffers.
    04910         //
    04911         if(InterfaceKeyHandle) {
    04912             *InterfaceKeyHandle = hTempInterface;
    04913         } else {
    04914             ZwClose(hTempInterface);
    04915         }
    04916         if(InterfaceKeyDisposition) {
    04917             *InterfaceKeyDisposition = TempInterfaceDisposition;
    04918         }
    04919         if(InterfaceInstanceKeyHandle) {
    04920             *InterfaceInstanceKeyHandle = hTempInterfaceInstance;
    04921         } else {
    04922             ZwClose(hTempInterfaceInstance);
    04923         }
    04924         //
    04925         // (no need to set InterfaceInstanceDisposition--we already set it above)
    04926         //
    04927     } else {
    04928         //
    04929         // If the interface key was newly-created above, then delete it.
    04930         //
    04931         if(TempInterfaceDisposition == REG_CREATED_NEW_KEY) {
    04932             ZwDeleteKey(hTempInterface);
    04933         } else {
    04934             ZwClose(hTempInterface);
    04935         }
    04936     }
    04937
    04938 clean1:
    04939     IopFreeAllocatedUnicodeString(&TempString);
    04940
    04941 clean0:
    04942     return status;
    04943 }

VOID IopOrphanNotification | ( | IN PDEVICE_NODE | TargetNode | ) |

Definition at line 9301 of file pnpioapi.c.

References _TARGET_DEVICE_NOTIFY_ENTRY::EventCategory, EventCategoryTargetDeviceChange, IopAcquireNotifyLock, IopReleaseNotifyLock, IopTargetDeviceNotifyLock, NULL, ObDereferenceObject, and _TARGET_DEVICE_NOTIFY_ENTRY::PhysicalDeviceObject.

    09304 {
    09305     PTARGET_DEVICE_NOTIFY_ENTRY entry;
    09306     PFAST_MUTEX lock;
    09307
    09308     IopAcquireNotifyLock(&IopTargetDeviceNotifyLock);
    09309
    09310     while (!IsListEmpty(&TargetNode->TargetDeviceNotify)) {
    09311         entry = (PTARGET_DEVICE_NOTIFY_ENTRY)RemoveHeadList(&TargetNode->TargetDeviceNotify);
    09312         if (entry->EventCategory == EventCategoryTargetDeviceChange) {
    09313
    09314             if (entry->PhysicalDeviceObject) {
    09315                 ObDereferenceObject(entry->PhysicalDeviceObject);
    09316                 entry->PhysicalDeviceObject = NULL;
    09317             }
    09318         }
    09319     }
    09320
    09321     IopReleaseNotifyLock(&IopTargetDeviceNotifyLock);
    09322 }

NTSTATUS IopOverwriteBuffer | ( | IN PBUFFER_INFO | Info,
|  | IN PVOID | Data,
|  | IN ULONG | DataSize
| ) |

Definition at line 2640 of file pnpioapi.c.

References ASSERT, FALSE, IopResizeBuffer(), NT_SUCCESS, and NTSTATUS().

    02648                    :
    02649
    02650     Copies data into the buffer, overwriting what is currently present,
    02651     resising if necessary.  The current position is set to the end of the
    02652     data just added.
    02653
    02654 Parameters:
    02655
    02656     Info - Pointer to a buffer info structure to be used to manage the buffer
    02657
    02658     Data - Pointer to the data to be added to the buffer
    02659
    02660     DataSize - The size of the data pointed to by Data in bytes
    02661
    02662 Return Value:
    02663
    02664     Status code that indicates whether or not the function was successful.
    02665
    02666 --*/
    02667
    02668 {
    02669     NTSTATUS status = STATUS_SUCCESS;
    02670     ULONG free;
    02671
    02672     ASSERT(Info);
    02673
    02674     free = Info->MaxSize;
    02675
    02676
    02677     if (free < DataSize) {
    02678         status = IopResizeBuffer(Info, DataSize, FALSE);
    02679
    02680         if (!NT_SUCCESS(status)) {
    02681             goto clean0;
    02682         }
    02683
    02684     }
    02685
    02686     //
    02687     // Copy the data into the buffer
    02688     //
    02689
    02690     RtlCopyMemory(Info->Buffer,
    02691                   Data,
    02692                   DataSize);
    02693
    02694     //
    02695     // Advance down the buffer
    02696     //
    02697
    02698     Info->Current += DataSize;
    02699
    02700 clean0:
    02701     return status;
    02702 }

NTSTATUS IopParseSymbolicLinkName | ( | IN PUNICODE_STRING | SymbolicLinkName,
|  | OUT PUNICODE_STRING PrefixString | OPTIONAL,
|  | OUT PUNICODE_STRING MungedPathString | OPTIONAL,
|  | OUT PUNICODE_STRING GuidString | OPTIONAL,
|  | OUT PUNICODE_STRING RefString | OPTIONAL,
|  | OUT PBOOLEAN RefStringPresent | OPTIONAL,
|  | OUT LPGUID Guid | OPTIONAL
| ) |

Definition at line 5424 of file pnpioapi.c.

References ASSERT, FALSE, GUID_STRING_LENGTH, GUID_STRING_SIZE, IopConstStringLength, IopConstStringSize, KERNEL_SYMLINK_STRING_PREFIX, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, path, RtlGUIDFromString(), SEPERATOR_CHAR, TRUE, USER_SYMLINK_STRING_PREFIX, and USHORT.

Referenced by IoGetDeviceInterfaceAlias(), IopDeviceInterfaceKeysFromSymbolicLink(), IopDropReferenceString(), IopOpenOrCreateDeviceInterfaceSubKeys(), IopProcessSetInterfaceState(), and IopUnregisterDeviceInterface().

    05436                    :
    05437
    05438     This routine breaks apart a symbolic link name constructed by
    05439     IopBuildSymbolicLinkNames.  Both formats of name are valid - user
    05440     mode \\?\ and kernel mode \??\.
    05441
    05442 Parameters:
    05443
    05444     SymbolicLinkName - Supplies a pointer to the symbolic link name to
    05445         be analysed.
    05446
    05447     PrefixString - Optionally contains a pointer to a string which will contain
    05448         the prefix of the string.
    05449
    05450     MungedPathString - Optionally contains a pointer to a string which will contain
    05451         the enumeration path of the device with all occurences of '\' replaced with '#'.
    05452
    05453     GuidString - Optionally contains a pointer to a string which will contain
    05454         the device class guid in string format from the string.
    05455
    05456     RefString - Optionally contains a pointer to a string which will contain
    05457         the refstring of the string if one is present, otherwise it is undefined.
    05458
    05459     RefStringPresent - Optionally contains a pointer to a boolean value which will
    05460         be set to true if a refstring is present.
    05461
    05462     Guid - Optionally contains a pointer to a guid which will contain
    05463         the function class guid of the string.
    05464
    05465 Return Value:
    05466
    05467     Status code that indicates whether or not the function was successful.
    05468
    05469 --*/
    05470
    05471 {
    05472     NTSTATUS status = STATUS_SUCCESS;
    05473     PWSTR pCurrent;
    05474     USHORT last, current, path, guid, reference = 0;
    05475     UNICODE_STRING tempString;
    05476     GUID tempGuid;
    05477     BOOLEAN haveRefString;
    05478
    05479     PAGED_CODE();
    05480
    05481     ASSERT(IopConstStringSize(USER_SYMLINK_STRING_PREFIX) == IopConstStringSize(KERNEL_SYMLINK_STRING_PREFIX));
    05482
    05483     //
    05484     // Sanity check on the incoming string - if it does not have a \\?\ or \??\ prefix then fail
    05485     //
    05486
    05487     if (!(RtlCompareMemory(SymbolicLinkName->Buffer,
    05488                            USER_SYMLINK_STRING_PREFIX,
    05489                            IopConstStringSize(USER_SYMLINK_STRING_PREFIX)
    05490                           ) != IopConstStringSize(USER_SYMLINK_STRING_PREFIX)
    05491        || RtlCompareMemory(SymbolicLinkName->Buffer,
    05492                            KERNEL_SYMLINK_STRING_PREFIX,
    05493                            IopConstStringSize(KERNEL_SYMLINK_STRING_PREFIX)
    05494                           ) != IopConstStringSize(KERNEL_SYMLINK_STRING_PREFIX)
    05495        )) {
    05496
    05497         status = STATUS_INVALID_PARAMETER;
    05498         goto clean0;
    05499     }
    05500
    05501
    05502     //
    05503     // check that the input buffer really is big enough
    05504     //
    05505     if (SymbolicLinkName->Length <(IopConstStringLength(KERNEL_SYMLINK_STRING_PREFIX)+GUID_STRING_SIZE+1)) {
    05506         status = STATUS_INVALID_PARAMETER;
    05507         goto clean0;
    05508
    05509     }
    05510
    05511     //
    05512     // Break apart the string into it's constituent parts
    05513     //
    05514
    05515     path = IopConstStringSize(USER_SYMLINK_STRING_PREFIX) + 1;
    05516
    05517     //
    05518     // Find the '\' seperator
    05519     //
    05520
    05521     pCurrent = SymbolicLinkName->Buffer + IopConstStringLength(KERNEL_SYMLINK_STRING_PREFIX);
    05522
    05523     for (current = 0;
    05524          current < (SymbolicLinkName->Length / sizeof(WCHAR)) - IopConstStringLength(KERNEL_SYMLINK_STRING_PREFIX);
    05525          current++, pCurrent++) {
    05526
    05527         if(*pCurrent == SEPERATOR_CHAR) {
    05528             reference = current + 1 + IopConstStringLength(KERNEL_SYMLINK_STRING_PREFIX);
    05529             break;
    05530         }
    05531
    05532     }
    05533
    05534     //
    05535     // If we don't have a reference string fake it to where it would have been
    05536     //
    05537
    05538     if (reference == 0) {
    05539         haveRefString = FALSE;
    05540         reference = SymbolicLinkName->Length / sizeof(WCHAR) + 1;
    05541
    05542     } else {
    05543         haveRefString = TRUE;
    05544     }
    05545
    05546     //
    05547     // Check the guid looks plausable
    05548     //
    05549
    05550     tempString.Length = GUID_STRING_SIZE;
    05551     tempString.MaximumLength = GUID_STRING_SIZE;
    05552     tempString.Buffer = SymbolicLinkName->Buffer + reference - GUID_STRING_LENGTH - 1;
    05553
    05554     if (!NT_SUCCESS( RtlGUIDFromString(&tempString, &tempGuid) )) {
    05555         status = STATUS_INVALID_PARAMETER;
    05556         goto clean0;
    05557     }
    05558
    05559     guid = reference - GUID_STRING_LENGTH - 1;
    05560
    05561     //
    05562     // Setup return strings
    05563     //
    05564
    05565     if (ARGUMENT_PRESENT(PrefixString)) {
    05566         PrefixString->Length = IopConstStringSize(KERNEL_SYMLINK_STRING_PREFIX);
    05567         PrefixString->MaximumLength = PrefixString->Length;
    05568         PrefixString->Buffer = SymbolicLinkName->Buffer;
    05569     }
    05570
    05571     if (ARGUMENT_PRESENT(MungedPathString)) {
    05572         MungedPathString->Length = (reference - 1 - GUID_STRING_LENGTH - 1 -
    05573                                    IopConstStringLength(KERNEL_SYMLINK_STRING_PREFIX)) *
    05574                                    sizeof(WCHAR);
    05575         MungedPathString->MaximumLength = MungedPathString->Length;
    05576         MungedPathString->Buffer = SymbolicLinkName->Buffer +
    05577                                    IopConstStringLength(KERNEL_SYMLINK_STRING_PREFIX);
    05578
    05579     }
    05580
    05581     if (ARGUMENT_PRESENT(GuidString)) {
    05582         GuidString->Length = GUID_STRING_SIZE;
    05583         GuidString->MaximumLength = GuidString->Length;
    05584         GuidString->Buffer = SymbolicLinkName->Buffer + reference -
    05585                              GUID_STRING_LENGTH - 1;
    05586     }
    05587
    05588     if (ARGUMENT_PRESENT(RefString)) {
    05589         //
    05590         // Check if we have a refstring
    05591         //
    05592         if (haveRefString) {
    05593             RefString->Length = SymbolicLinkName->Length -
    05594                                   (reference * sizeof(WCHAR));
    05595             RefString->MaximumLength = RefString->Length;
    05596             RefString->Buffer = SymbolicLinkName->Buffer + reference;
    05597         } else {
    05598             RefString->Length = 0;
    05599             RefString->MaximumLength = 0;
    05600             RefString->Buffer = NULL;
    05601         }
    05602     }
    05603
    05604     if (ARGUMENT_PRESENT(RefStringPresent)) {
    05605         *RefStringPresent = haveRefString;
    05606     }
    05607
    05608     if(ARGUMENT_PRESENT(Guid)) {
    05609         *Guid = tempGuid;
    05610     }
    05611
    05612 clean0:
    05613
    05614     return status;
    05615
    05616 }

NTSTATUS IopPnPHydraCallback | ( | PVOID | CallbackParams | ) |

Definition at line 9333 of file pnpioapi.c.

References _NOTIFICATION_CALLBACK_PARAM_BLOCK::Callout, _NOTIFICATION_CALLBACK_PARAM_BLOCK::Context, _NOTIFICATION_CALLBACK_PARAM_BLOCK::NotificationStructure, NTSTATUS(), and PNOTIFICATION_CALLBACK_PARAM_BLOCK.

Referenced by IopNotifyDeviceClassChange(), IopNotifyHwProfileChange(), IopNotifySetupDeviceArrival(), IopNotifyTargetDeviceChange(), and IoRegisterPlugPlayNotification().

    09336 {
    09337     PNOTIFICATION_CALLBACK_PARAM_BLOCK params=(PNOTIFICATION_CALLBACK_PARAM_BLOCK)CallbackParams;
    09338     NTSTATUS status;
    09339
    09340     status = (params->Callout)(params->NotificationStructure,params->Context);
    09341
    09342     return status;
    09343 }

VOID IopProcessDeferredRegistrations | ( | VOID |  | ) |

Definition at line 5954 of file pnpioapi.c.

References ExFreePool(), FALSE, IopAcquireNotifyLock, IopDeferredRegistrationList, IopDeferredRegistrationLock, IopDereferenceNotify(), IopReleaseNotifyLock, _NOTIFY_ENTRY_HEADER::Lock, _DEFERRED_REGISTRATION_ENTRY::NotifyEntry, NULL, PDEFERRED_REGISTRATION_ENTRY, and _NOTIFY_ENTRY_HEADER::Unregistered.

    05959                    :
    05960
    05961     This routine removes notification entries from the deferred registration
    05962     list, marking them as "registered" so that they can receive notifications.
    05963
    05964 Parameters:
    05965
    05966     None.
    05967
    05968 Return Value:
    05969
    05970     None.
    05971
    05972   --*/
    05973 {
    05974     PDEFERRED_REGISTRATION_ENTRY deferredNode;
    05975     PFAST_MUTEX lock;
    05976
    05977     IopAcquireNotifyLock(&IopDeferredRegistrationLock);
    05978
    05979     while (!IsListEmpty(&IopDeferredRegistrationList)) {
    05980
    05981         deferredNode = (PDEFERRED_REGISTRATION_ENTRY)RemoveHeadList(&IopDeferredRegistrationList);
    05982
    05983         //
    05984         // Acquire this entry's list lock.
    05985         //
    05986         lock = deferredNode->NotifyEntry->Lock;
    05987         if (lock) {
    05988             IopAcquireNotifyLock(lock);
    05989         }
    05990
    05991         //
    05992         // Mark this entry as registered.
    05993         //
    05994         deferredNode->NotifyEntry->Unregistered = FALSE;
    05995
    05996         //
    05997         // Dereference the notification entry when removing it from the deferred
    05998         // list, and free the node.
    05999         //
    06000         IopDereferenceNotify((PNOTIFY_ENTRY_HEADER)deferredNode->NotifyEntry);
    06001         ExFreePool(deferredNode);
    06002
    06003         //
    06004         // Release this entry's list lock.
    06005         //
    06006         if (lock) {
    06007             IopReleaseNotifyLock(lock);
    06008             lock = NULL;
    06009         }
    06010     }
    06011
    06012     IopReleaseNotifyLock(&IopDeferredRegistrationLock);
    06013 }

NTSTATUS IopProcessSetInterfaceState | ( | IN PUNICODE_STRING | SymbolicLinkName,
|  | IN BOOLEAN | Enable,
|  | IN BOOLEAN | DeferNotStarted
| ) |

Definition at line 9922 of file pnpioapi.c.

References ASSERT, _DEVOBJ_EXTENSION::DeviceNode, _DEVICE_OBJECT::DeviceObjectExtension, DevicePropertyPhysicalDeviceObjectName, DOE_START_PENDING, ExAllocatePool, ExFreePool(), _DEVOBJ_EXTENSION::ExtensionFlags, IoCreateSymbolicLink(), IoDeleteSymbolicLink(), IoGetDeviceProperty(), IopCreateRegistryKeyEx(), IopDeviceInterfaceKeysFromSymbolicLink(), IopDeviceObjectFromDeviceInstance(), IopDropReferenceString(), IopGetRegistryValue(), IopParseSymbolicLinkName(), IopRegistryDataToUnicodeString, IopSetupDeviceObjectFromDeviceClass(), KEY_VALUE_DATA, _PENDING_SET_INTERFACE_STATE::LinkName, _PENDING_SET_INTERFACE_STATE::List, List, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, PAGED_CODE, PagedPool, _DEVICE_NODE::PendedSetInterfaceState, PENDING_SET_INTERFACE_STATE, PpSetDeviceClassChange(), RtlEqualUnicodeString(), RtlInitUnicodeString(), and TRUE.

Referenced by IopDoDeferredSetInterfaceState(), and IoSetDeviceInterfaceState().

    09929                    :
    09930
    09931     This DDI allows a device class to activate and deactivate an association
    09932     previously registered using IoRegisterDeviceInterface
    09933
    09934 Parameters:
    09935
    09936     SymbolicLinkName - Supplies a pointer to the symbolic link name which was
    09937         returned by IoRegisterDeviceInterface when the interface was registered,
    09938         or as returned by IoGetDeviceInterfaces.
    09939
    09940     Enable - If TRUE (non-zero), the interface will be enabled.  If FALSE, it
    09941         will be disabled.
    09942
    09943     DeferNotStarted - If TRUE then enables will be queued if the PDO isn't
    09944         started.  It is FALSE when we've started the PDO and are processing the
    09945         queued enables.
    09946
    09947 Return Value:
    09948
    09949     Status code that indicates whether or not the function was successful.
    09950
    09951 --*/
    09952
    09953 {
    09954     NTSTATUS status;
    09955     HANDLE hInterfaceClassKey = NULL;
    09956     HANDLE hInterfaceParentKey= NULL, hInterfaceInstanceKey = NULL;
    09957     HANDLE hInterfaceParentControl = NULL, hInterfaceInstanceControl = NULL;
    09958     UNICODE_STRING tempString, actualSymbolicLinkName, deviceNameString;
    09959     PKEY_VALUE_FULL_INFORMATION pKeyValueInfo;
    09960     ULONG linked, refcount;
    09961     GUID guid;
    09962     PDEVICE_OBJECT physicalDeviceObject;
    09963     PWCHAR deviceNameBuffer = NULL;
    09964     ULONG deviceNameBufferLength;
    09965
    09966     PAGED_CODE();
    09967
    09968     //
    09969     // Get the symbolic link name without the ref string
    09970     //
    09971
    09972     status = IopDropReferenceString(&actualSymbolicLinkName, SymbolicLinkName);
    09973     if (!NT_SUCCESS(status)) {
    09974         goto clean0;
    09975     }
    09976
    09977     //
    09978     // Extract the device class guid
    09979     //
    09980
    09981     status = IopParseSymbolicLinkName(SymbolicLinkName, NULL, NULL, NULL, NULL, NULL, &guid);
    09982
    09983     //
    09984     // Get function class instance handle
    09985     //
    09986
    09987     status = IopDeviceInterfaceKeysFromSymbolicLink(SymbolicLinkName,
    09988                                                     KEY_READ | KEY_WRITE,
    09989                                                     &hInterfaceClassKey,
    09990                                                     &hInterfaceParentKey,
    09991                                                     &hInterfaceInstanceKey
    09992                                                     );
    09993
    09994     if (!NT_SUCCESS(status)) {
    09995         goto clean1;
    09996     }
    09997
    09998     //
    09999     // Open the parent interface control subkey
    10000     //
    10001     PiWstrToUnicodeString(&tempString, REGSTR_KEY_CONTROL);
    10002     status = IopCreateRegistryKeyEx( &hInterfaceParentControl,
    10003                                      hInterfaceParentKey,
    10004                                      &tempString,
    10005                                      KEY_READ,
    10006                                      REG_OPTION_VOLATILE,
    10007                                      NULL
    10008                                      );
    10009     if (!NT_SUCCESS(status)) {
    10010         goto clean1;
    10011     }
    10012
    10013
    10014     //
    10015     // Find out the name of the device instance that 'owns' this interface.
    10016     //
    10017     status = IopGetRegistryValue(hInterfaceParentKey,
    10018                                  REGSTR_VAL_DEVICE_INSTANCE,
    10019                                  &pKeyValueInfo
    10020                                  );
    10021
    10022     if(NT_SUCCESS(status)) {
    10023         //
    10024         // Open the device instance control subkey
    10025         //
    10026         PiWstrToUnicodeString(&tempString, REGSTR_KEY_CONTROL);
    10027         status = IopCreateRegistryKeyEx( &hInterfaceInstanceControl,
    10028                                          hInterfaceInstanceKey,
    10029                                          &tempString,
    10030                                          KEY_READ,
    10031                                          REG_OPTION_VOLATILE,
    10032                                          NULL
    10033                                          );
    10034         if(!NT_SUCCESS(status)) {
    10035             ExFreePool(pKeyValueInfo);
    10036             hInterfaceInstanceControl = NULL;
    10037         }
    10038     }
    10039
    10040     if (!NT_SUCCESS(status)) {
    10041         goto clean2;
    10042     }
    10043
    10044     //
    10045     // Find the PDO corresponding to this device instance name.
    10046     //
    10047     if (pKeyValueInfo->Type == REG_SZ) {
    10048
    10049         IopRegistryDataToUnicodeString(&tempString,
    10050                                         (PWSTR)KEY_VALUE_DATA(pKeyValueInfo),
    10051                                         pKeyValueInfo->DataLength
    10052                                         );
    10053
    10054         physicalDeviceObject = IopDeviceObjectFromDeviceInstance(NULL, &tempString);
    10055
    10056         if (physicalDeviceObject) {
    10057
    10058             //
    10059             // DeferNotStarted is set TRUE if we are being called from
    10060             // IoSetDeviceInterfaceState.  It will be set FALSE if we are
    10061             // processing previously queued operations as we are starting the
    10062             // device.
    10063             //
    10064
    10065             if (DeferNotStarted) {
    10066
    10067                 if (physicalDeviceObject->DeviceObjectExtension->ExtensionFlags & DOE_START_PENDING) {
    10068
    10069                     PDEVICE_NODE deviceNode;
    10070                     PPENDING_SET_INTERFACE_STATE pendingSetState;
    10071
    10072                     //
    10073                     // The device hasn't been started yet.  We need to queue
    10074                     // any enables and remove items from the queue on a disable.
    10075                     //
    10076                     deviceNode = (PDEVICE_NODE)physicalDeviceObject->DeviceObjectExtension->DeviceNode;
    10077
    10078                     if (Enable) {
    10079
    10080                         pendingSetState = ExAllocatePool( PagedPool,
    10081                                                           sizeof(PENDING_SET_INTERFACE_STATE));
    10082
    10083                         if (pendingSetState != NULL) {
    10084
    10085                             pendingSetState->LinkName.Buffer = ExAllocatePool( PagedPool,
    10086                                                                                SymbolicLinkName->Length);
    10087
    10088                             if (pendingSetState->LinkName.Buffer != NULL) {
    10089
    10090                                 //
    10091                                 // Capture the callers info and queue it to the
    10092                                 // devnode.  Once the device stack is started
    10093                                 // we will dequeue and process it.
    10094                                 //
    10095                                 pendingSetState->LinkName.MaximumLength = SymbolicLinkName->Length;
    10096                                 pendingSetState->LinkName.Length = SymbolicLinkName->Length;
    10097                                 RtlCopyMemory( pendingSetState->LinkName.Buffer,
    10098                                                SymbolicLinkName->Buffer,
    10099                                                SymbolicLinkName->Length);
    10100                                 InsertTailList( &deviceNode->PendedSetInterfaceState,
    10101                                                 &pendingSetState->List);
    10102
    10103                                 ExFreePool(pKeyValueInfo);
    10104
    10105                                 ObDereferenceObject(physicalDeviceObject);
    10106
    10107                                 status = STATUS_SUCCESS;
    10108                                 goto clean2;
    10109
    10110                             } else {
    10111                                 //
    10112                                 // Couldn't allocate a buffer to hold the
    10113                                 // symbolic link name.
    10114                                 //
    10115
    10116                                 ExFreePool(pendingSetState);
    10117                                 status = STATUS_INSUFFICIENT_RESOURCES;
    10118                             }
    10119
    10120                         } else {
    10121                             //
    10122                             // Couldn't allocate the PENDING_SET_INTERFACE_STATE
    10123                             // structure.
    10124                             //
    10125
    10126
    10127                             status = STATUS_INSUFFICIENT_RESOURCES;
    10128                         }
    10129
    10130                     } else {
    10131
    10132                         PLIST_ENTRY entry;
    10133
    10134                         //
    10135                         // We are disabling an interface.  Since we aren't
    10136                         // started yet we should have queued the enable.  Now
    10137                         // we go back and find the matching enable and remove
    10138                         // it from the queue.
    10139                         //
    10140
    10141                         for (entry = deviceNode->PendedSetInterfaceState.Flink;
    10142                              entry != &deviceNode->PendedSetInterfaceState;
    10143                              entry = entry->Flink)  {
    10144
    10145                             pendingSetState = CONTAINING_RECORD( entry,
    10146                                                                  PENDING_SET_INTERFACE_STATE,
    10147                                                                  List );
    10148
    10149                             if (RtlEqualUnicodeString( &pendingSetState->LinkName,
    10150                                                        SymbolicLinkName,
    10151                                                        TRUE)) {
    10152
    10153                                 //
    10154                                 // We found it, remove it from the list and
    10155                                 // free it.
    10156                                 //
    10157                                 RemoveEntryList(&pendingSetState->List);
    10158
    10159                                 ExFreePool(pendingSetState->LinkName.Buffer);
    10160                                 ExFreePool(pendingSetState);
    10161
    10162                                 break;
    10163                             }
    10164                         }
    10165
    10166 #if 0
    10167                         //
    10168                         // Debug code to catch the case where we couldn't find
    10169                         // the entry to remove.  This could happen if we messed
    10170                         // up adding the entry to the list or the driver disabled
    10171                         // an interface without first enabling it.  Either way
    10172                         // it probably merits some investigation.
    10173                         //
    10174                         if (entry == &deviceNode->PendedSetInterfaceState) {
    10175                             PIDBGMSG(PIDBG_ERROR,
    10176                                      ("IopProcessSetInterfaceState: Disable couldn't find deferred enable, DeviceNode = 0x%p, SymbolicLink = \"%Z\"\n",
    10177                                      deviceNode,
    10178                                      SymbolicLinkName));
    10179                         }
    10180
    10181                         ASSERT(entry != &deviceNode->PendedSetInterfaceState);
    10182 #endif
    10183                         ExFreePool(pKeyValueInfo);
    10184
    10185                         ObDereferenceObject(physicalDeviceObject);
    10186
    10187                         status = STATUS_SUCCESS;
    10188                         goto clean2;
    10189                     }
    10190                 }
    10191             }
    10192
    10193             if (!Enable || !NT_SUCCESS(status)) {
    10194                 ObDereferenceObject(physicalDeviceObject);
    10195             }
    10196         } else {
    10197
    10198             status = STATUS_INVALID_DEVICE_REQUEST;
    10199         }
    10200
    10201     } else {
    10202         //
    10203         // This will only happen if the registry information is screwed up.
    10204         //
    10205         physicalDeviceObject = NULL;
    10206         status = STATUS_INVALID_DEVICE_REQUEST;
    10207     }
    10208
    10209     if (!Enable) {
    10210         //
    10211         // In the case of Disable we want to continue even if there was an error
    10212         // finding the PDO.  Prior to adding support for deferring the
    10213         // IoSetDeviceInterfaceState calls, we never looked up the PDO for
    10214         // disables.  This will make sure that we continue to behave the same as
    10215         // we used to in the case where we can't find the PDO.
    10216         //
    10217         status = STATUS_SUCCESS;
    10218     }
    10219
    10220     ExFreePool(pKeyValueInfo);
    10221
    10222     if (!NT_SUCCESS(status)) {
    10223         goto clean2;
    10224     }
    10225
    10226     if (Enable) {
    10227         //
    10228         // Retrieve the PDO's device object name.  (Start out with a reasonably-sized
    10229         // buffer so we hopefully only have to retrieve this once.
    10230         //
    10231         deviceNameBufferLength = 256 * sizeof(WCHAR);
    10232
    10233         while (TRUE) {
    10234
    10235             deviceNameBuffer = ExAllocatePool(PagedPool, deviceNameBufferLength);
    10236             if (!deviceNameBuffer) {
    10237                 status = STATUS_INSUFFICIENT_RESOURCES;
    10238                 break;
    10239             }
    10240
    10241             status = IoGetDeviceProperty( physicalDeviceObject,
    10242                                           DevicePropertyPhysicalDeviceObjectName,
    10243                                           deviceNameBufferLength,
    10244                                           deviceNameBuffer,
    10245                                           &deviceNameBufferLength
    10246                                          );
    10247
    10248             if (NT_SUCCESS(status)) {
    10249                 break;
    10250             } else {
    10251                 //
    10252                 // Free the current buffer before we figure out what went wrong.
    10253                 //
    10254                 ExFreePool(deviceNameBuffer);
    10255
    10256                 if (status != STATUS_BUFFER_TOO_SMALL) {
    10257                     //
    10258                     // Our failure wasn't because the buffer was too small--bail now.
    10259                     //
    10260                     break;
    10261                 }
    10262
    10263                 //
    10264                 // Otherwise, loop back and try again with our new buffer size.
    10265                 //
    10266             }
    10267         }
    10268
    10269         //
    10270         // OK, we don't need the PDO anymore.
    10271         //
    10272         ObDereferenceObject(physicalDeviceObject);
    10273
    10274         if (!NT_SUCCESS(status)) {
    10275             goto clean2;
    10276         }
    10277
    10278         //
    10279         // Now create a unicode string based on the device object name we just retrieved.
    10280         //
    10281
    10282         RtlInitUnicodeString(&deviceNameString, deviceNameBuffer);
    10283     }
    10284
    10285     //
    10286     // Retrieve the linked value from the control subkey.
    10287     //
    10288     pKeyValueInfo=NULL;
    10289     status = IopGetRegistryValue(hInterfaceInstanceControl, REGSTR_VAL_LINKED, &pKeyValueInfo);
    10290
    10291     if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
    10292
    10293         //
    10294         // The absence of a linked value is taken to mean not linked
    10295         //
    10296
    10297         linked = 0;
    10298
    10299     } else {
    10300         if (!NT_SUCCESS(status)) {
    10301             //
    10302             // If the call failed, pKeyValueInfo was never allocated
    10303             //
    10304             goto clean3;
    10305         }
    10306
    10307         //
    10308         // Check linked is a DWORD
    10309         //
    10310
    10311         if(pKeyValueInfo->Type == REG_DWORD && pKeyValueInfo->DataLength == sizeof(ULONG)) {
    10312
    10313             linked = *((PULONG) KEY_VALUE_DATA(pKeyValueInfo));
    10314
    10315         } else {
    10316
    10317             //
    10318             // The registry is screwed up - assume linked is 0 and the registry will be fixed when
    10319             // we update linked in a few moments
    10320             //
    10321
    10322             linked = 0;
    10323
    10324         }
    10325
    10326     }
    10327     if (pKeyValueInfo) {
    10328         ExFreePool (pKeyValueInfo);
    10329     }
    10330
    10331     //
    10332     // Retrieve the refcount value from the control subkey.
    10333     //
    10334
    10335     RtlInitUnicodeString(&tempString, REGSTR_VAL_REFERENCECOUNT);
    10336     status = IopGetRegistryValue(hInterfaceParentControl,
    10337                                  tempString.Buffer,
    10338                                  &pKeyValueInfo
    10339                                  );
    10340
    10341     if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
    10342
    10343         //
    10344         // The absence of a refcount value is taken to mean refcount == 0
    10345         //
    10346
    10347         refcount = 0;
    10348
    10349     } else {
    10350         if (!NT_SUCCESS(status)) {
    10351             goto clean3;
    10352         }
    10353
    10354         //
    10355         // Check refcount is a DWORD
    10356         //
    10357
    10358         if(pKeyValueInfo->Type == REG_DWORD && pKeyValueInfo->DataLength == sizeof(ULONG)) {
    10359
    10360             refcount = *((PULONG) KEY_VALUE_DATA(pKeyValueInfo));
    10361
    10362         } else {
    10363
    10364             //
    10365             // The registry is screwed up - assume refcount is 0 and the registry will be fixed when
    10366             // we update refcount in a few moments
    10367             //
    10368
    10369             refcount = 0;
    10370
    10371         }
    10372
    10373         ExFreePool(pKeyValueInfo);
    10374     }
    10375
    10376
    10377     if (Enable) {
    10378
    10379         if (!linked) {
    10380             //
    10381             // check and update the reference count
    10382             //
    10383
    10384             if (refcount > 0) {
    10385                 //
    10386                 // Another device instance has already referenced this interface;
    10387                 // just increment the reference count; don't try create a symbolic link.
    10388                 //
    10389                 refcount += 1;
    10390             } else {
    10391                 //
    10392                 // According to the reference count, no other device instances currently
    10393                 // reference this interface, and therefore no symbolic links should exist,
    10394                 // so we should create one.
    10395                 //
    10396                 refcount = 1;
    10397                 status = IoCreateSymbolicLink(&actualSymbolicLinkName, &deviceNameString);
    10398
    10399                 if (status == STATUS_OBJECT_NAME_COLLISION) {
    10400                     //
    10401                     // The reference count is screwed up.
    10402                     //
    10403                     KdPrint(("IoSetDeviceInterfaceState: symbolic link for %ws already exists! status = %8.8X\n",
    10404                              actualSymbolicLinkName.Buffer, status));
    10405                     status = STATUS_SUCCESS;
    10406                 }
    10407
    10408             }
    10409
    10410             linked = 1;
    10411
    10412 #if 0
    10413             IopSetupDeviceObjectFromDeviceClass(physicalDeviceObject,
    10414                                                 hInterfaceClassKey);
    10415 #endif
    10416
    10417         } else {
    10418
    10419             //
    10420             // The association already exists - don't perform the notification
    10421             //
    10422
    10423             status = STATUS_OBJECT_NAME_EXISTS; // Informational message not error
    10424             goto clean3;
    10425
    10426         }
    10427     } else {
    10428
    10429         if (linked) {
    10430
    10431             //
    10432             // check and update the reference count
    10433             //
    10434
    10435             if (refcount > 1) {
    10436                 //
    10437                 // Another device instance already references this interface;
    10438                 // just decrement the reference count; don't try to remove the symbolic link.
    10439                 //
    10440                 refcount -= 1;
    10441             } else {
    10442                 //
    10443                 // According to the reference count, only this device instance currently
    10444                 // references this interface, so it is ok to delete this symbolic link
    10445                 //
    10446                 refcount = 0;
    10447                 status = IoDeleteSymbolicLink(&actualSymbolicLinkName);
    10448
    10449                 if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
    10450                     //
    10451                     // The reference count is screwed up.
    10452                     //
    10453                     KdPrint(("IoSetDeviceInterfaceState: no symbolic link for %ws to delete! status = %8.8X\n",
    10454                              actualSymbolicLinkName.Buffer, status));
    10455                     status = STATUS_SUCCESS;
    10456                 }
    10457
    10458             }
    10459
    10460             linked = 0;
    10461
    10462         } else {
    10463
    10464             //
    10465             // The association does not exists - fail and do not perform notification
    10466             //
    10467
    10468             status = STATUS_OBJECT_NAME_NOT_FOUND;
    10469         }
    10470     }
    10471
    10472     if (!NT_SUCCESS(status)) {
    10473         goto clean3;
    10474     }
    10475
    10476     //
    10477     // Update the value of linked
    10478     //
    10479
    10480     PiWstrToUnicodeString(&tempString, REGSTR_VAL_LINKED);
    10481     status = ZwSetValueKey(hInterfaceInstanceControl,
    10482                            &tempString,
    10483                            0,
    10484                            REG_DWORD,
    10485                            &linked,
    10486                            sizeof(linked)
    10487                           );
    10488
    10489     //
    10490     // Update the value of refcount
    10491     //
    10492
    10493     RtlInitUnicodeString(&tempString, REGSTR_VAL_REFERENCECOUNT);
    10494     status = ZwSetValueKey(hInterfaceParentControl,
    10495                            &tempString,
    10496                            0,
    10497                            REG_DWORD,
    10498                            &refcount,
    10499                            sizeof(refcount)
    10500                           );
    10501
    10502
    10503     //
    10504     // Notify anyone that is interested
    10505     //
    10506
    10507     if (linked) {
    10508
    10509         PpSetDeviceClassChange( (LPGUID) &GUID_DEVICE_INTERFACE_ARRIVAL, &guid, SymbolicLinkName);
    10510
    10511     } else {
    10512
    10513         PpSetDeviceClassChange( (LPGUID) &GUID_DEVICE_INTERFACE_REMOVAL, &guid, SymbolicLinkName);
    10514
    10515     }
    10516
    10517 clean3:
    10518     if (deviceNameBuffer != NULL) {
    10519         ExFreePool(deviceNameBuffer);
    10520     }
    10521
    10522 clean2:
    10523     if (hInterfaceParentControl) {
    10524         ZwClose(hInterfaceParentControl);
    10525     }
    10526     if (hInterfaceInstanceControl) {
    10527         ZwClose(hInterfaceInstanceControl);
    10528     }
    10529
    10530 clean1:
    10531     if (hInterfaceParentKey) {
    10532         ZwClose(hInterfaceParentKey);
    10533     }
    10534     if (hInterfaceInstanceKey) {
    10535         ZwClose(hInterfaceInstanceKey);
    10536     }
    10537     if(hInterfaceClassKey != NULL) {
    10538         ZwClose(hInterfaceClassKey);
    10539     }
    10540
    10541 clean0:
    10542     if (!NT_SUCCESS(status) && !Enable) {
    10543         //
    10544         // If we failed to disable an interface (most likely because the
    10545         // interface keys have already been deleted) report success.
    10546         //
    10547         status = STATUS_SUCCESS;
    10548     }
    10549
    10550     return status;
    10551 }
    }

NTSTATUS IopQueueDeviceWorkItem | ( | IN PDEVICE_OBJECT | PhysicalDeviceObject,
|  | IN PVOID | WorkerRoutine,
|  | IN PVOID | Context
| ) |

Definition at line 6327 of file pnpioapi.c.

References _DEVICE_WORK_ITEM::Context, DelayedWorkQueue, _DEVICE_WORK_ITEM::DeviceObject, ExAllocatePool, ExInitializeWorkItem, ExQueueWorkItem(), NonPagedPool, NULL, ObReferenceObject, PDEVICE_WORK_ITEM, and _DEVICE_WORK_ITEM::WorkItem.

Referenced by IoInvalidateDeviceState(), and IoRequestDeviceEject().

    06335                    :
    06336
    06337     This API will cause the PnP manager to send the specified PDO an
    06338     IRP_MN_QUERY_PNP_DEVICE_STATE IRP.
    06339
    06340 Parameters:
    06341
    06342     PhysicalDeviceObject - Provides a pointer to the PDO who's state is to be
    06343     invalidated.
    06344
    06345 Return Value:
    06346
    06347     none.
    06348
    06349 --*/
    06350
    06351 {
    06352     PDEVICE_WORK_ITEM deviceWorkItem;
    06353
    06354     //
    06355     // Since this routine can be called at DPC level we need to queue
    06356     // a work item and process it when the irql drops.
    06357     //
    06358
    06359     deviceWorkItem = ExAllocatePool(NonPagedPool, sizeof(DEVICE_WORK_ITEM));
    06360     if (deviceWorkItem == NULL) {
    06361
    06362         //
    06363         // Failed to allocate memory for work item.  Nothing we can do ...
    06364         //
    06365
    06366         return STATUS_INSUFFICIENT_RESOURCES;
    06367     }
    06368
    06369     ObReferenceObject(PhysicalDeviceObject);
    06370     deviceWorkItem->DeviceObject = PhysicalDeviceObject;
    06371     deviceWorkItem->Context = Context;
    06372
    06373     ExInitializeWorkItem( &deviceWorkItem->WorkItem,
    06374                           WorkerRoutine,
    06375                           deviceWorkItem);
    06376
    06377     //
    06378     // Queue a work item to do the enumeration
    06379     //
    06380
    06381     ExQueueWorkItem( &deviceWorkItem->WorkItem, DelayedWorkQueue );
    06382
    06383     return STATUS_SUCCESS;
    06384 }

NTSTATUS IopRealloc | ( | IN OUT PVOID * | Buffer,
|  | IN ULONG | OldSize,
|  | IN ULONG | NewSize
| ) |

Definition at line 3491 of file pnpioapi.c.

References ASSERT, Buffer, ExAllocatePool, ExFreePool(), PAGED_CODE, and PagedPool.

    03499                    :
    03500
    03501     This implements a variation of the traditional C realloc routine.
    03502
    03503 Parameters:
    03504
    03505     Buffer - Supplies a pointer to a pointer to the buffer that is being
    03506         reallocated.  On sucessful completion it the pointer will be updated
    03507         to point to the new buffer, on failure it will still point to the old
    03508         buffer.
    03509
    03510     OldSize - The size in bytes of the memory block referenced by Buffer
    03511
    03512     NewSize - The desired new size in bytes of the buffer.  This can be larger
    03513         or smaller than the OldSize
    03514
    03515 Return Value:
    03516
    03517     Status code that indicates whether or not the function was successful.
    03518
    03519 --*/
    03520
    03521 {
    03522
    03523     PVOID newBuffer;
    03524
    03525     PAGED_CODE();
    03526
    03527     ASSERT(*Buffer);
    03528
    03529     //
    03530     // Allocate a new buffer
    03531     //
    03532
    03533     if (!(newBuffer = ExAllocatePool(PagedPool, NewSize))) {
    03534         return STATUS_INSUFFICIENT_RESOURCES;
    03535     }
    03536
    03537     //
    03538     // Copy the contents of the old buffer
    03539     //
    03540
    03541     if(OldSize <= NewSize) {
    03542         RtlCopyMemory(newBuffer, *Buffer , OldSize);
    03543     } else {
    03544         RtlCopyMemory(newBuffer, *Buffer , NewSize);
    03545     }
    03546     //
    03547     // Free up the old buffer
    03548     //
    03549
    03550     ExFreePool(*Buffer);
    03551
    03552     //
    03553     // Hand the new buffer back to the caller
    03554     //
    03555
    03556     *Buffer = newBuffer;
    03557
    03558     return STATUS_SUCCESS;
    03559
    03560 }

VOID IopReferenceNotify | ( | PNOTIFY_ENTRY_HEADER | notify | ) |

Definition at line 6564 of file pnpioapi.c.

References ASSERT, PAGED_CODE, and _NOTIFY_ENTRY_HEADER::RefCount.

Referenced by IopNotifyDeviceClassChange(), IopNotifyHwProfileChange(), IopNotifyTargetDeviceChange(), and IoRegisterPlugPlayNotification().

    06570                    :
    06571
    06572     This routine increments the reference count for a notification entry.
    06573
    06574 Parameters:
    06575
    06576     Notify - Supplies a pointer to the notification entry to be referenced
    06577
    06578 Return Value:
    06579
    06580     None
    06581
    06582 Note:
    06583
    06584     The appropriate symchronization lock must be held on the notification
    06585     list before this routine can be called
    06586
    06587 --*/
    06588
    06589 {
    06590     PAGED_CODE();
    06591
    06592     ASSERT(Notify);
    06593     ASSERT(Notify->RefCount > 0);
    06594
    06595     Notify->RefCount++;
    06596
    06597 }

NTSTATUS IopRegisterDeviceInterface | ( | IN PUNICODE_STRING | DeviceInstanceName,
|  | IN CONST GUID * | InterfaceClassGuid,
|  | IN PUNICODE_STRING ReferenceString | OPTIONAL,
|  | IN BOOLEAN | UserModeFormat,
|  | OUT PUNICODE_STRING | SymbolicLinkName
| ) |

Definition at line 3929 of file pnpioapi.c.

References ExAcquireResourceExclusive, ExReleaseResource, IopBuildSymbolicLinkStrings(), IopCreateRegistryKeyEx(), IopFreeAllocatedUnicodeString(), IopOpenOrCreateDeviceInterfaceSubKeys(), IopSetRegistryStringValue(), KeEnterCriticalRegion, KeLeaveCriticalRegion, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PpRegistryDeviceResource, RtlFreeUnicodeString(), RtlStringFromGUID(), and TRUE.

Referenced by IoRegisterDeviceInterface().

    03939                    :
    03940
    03941     This is the worker routine for PnpRegisterDeviceInterface.  It is also
    03942     called by the user-mode ConfigMgr (via an NtPlugPlayControl), which is why it
    03943     must take a device instance name instead of a PDO (since the device instance
    03944     may not currently be 'live'), and also why it must optionally return the user-
    03945     mode form of the interface device name (i.e., "\\?\" instead of "\??\").
    03946
    03947 Parameters:
    03948
    03949     DeviceInstanceName - Supplies the name of the device instance for which a
    03950         device interface is being registered.
    03951
    03952     InterfaceClassGuid - Supplies a pointer to the GUID representring the class
    03953         of the device interface being registered.
    03954
    03955     ReferenceString - Optionally, supplies an additional context string which is
    03956         appended to the enumeration path of the device
    03957
    03958     UserModeFormat - If non-zero, then the symbolic link name returned for the
    03959         interface device is in user-mode form (i.e., "\\?\").  If zero (FALSE),
    03960         it is in kernel-mode form (i.e., "\??\").
    03961
    03962     SymbolicLinkName - Supplies a pointer to a string which on success will contain
    03963         either the kernel-mode or user-mode path of the symbolic link used to open
    03964         this device.
    03965
    03966 Return Value:
    03967
    03968     Status code that indicates whether or not the function was successful.
    03969
    03970 --*/
    03971
    03972 {
    03973     NTSTATUS status;
    03974     UNICODE_STRING tempString, guidString, otherString;
    03975     PUNICODE_STRING pUserString, pKernelString;
    03976     HANDLE hTemp1, hTemp2, hInterfaceInstanceKey;
    03977     ULONG InterfaceDisposition, InterfaceInstanceDisposition;
    03978
    03979     PAGED_CODE();
    03980
    03981     //
    03982     // Convert the class guid into string form
    03983     //
    03984
    03985     status = RtlStringFromGUID(InterfaceClassGuid, &guidString);
    03986     if( !NT_SUCCESS(status) ){
    03987         goto clean0;
    03988     }
    03989
    03990     //
    03991     // Construct both flavors of symbolic link name (go ahead and store the form
    03992     // that the user wants in the SymbolicLinkName parameter they supplied--this
    03993     // saves us from having to copy the appropriate string over to their string
    03994     // later).
    03995     //
    03996     if(UserModeFormat) {
    03997         pUserString = SymbolicLinkName;
    03998         pKernelString = &otherString;
    03999     } else {
    04000         pKernelString = SymbolicLinkName;
    04001         pUserString = &otherString;
    04002     }
    04003
    04004     status = IopBuildSymbolicLinkStrings(DeviceInstanceName,
    04005                                          &guidString,
    04006                                          ReferenceString,
    04007                                          pUserString,
    04008                                          pKernelString
    04009                                          );
    04010     if (!NT_SUCCESS(status)) {
    04011         goto clean1;
    04012     }
    04013
    04014     //
    04015     // Enter critical section and acquire a lock on the registry.  Both these
    04016     // mechanisms are required to prevent deadlock in the case where an APC
    04017     // routine calls this routine after the registry resource has been claimed
    04018     // in this case it would wait blocking this thread so the registry would
    04019     // never be released -> deadlock.  Critical sectioning the registry manipulation
    04020     // portion solves this problem
    04021     //
    04022
    04023     KeEnterCriticalRegion();
    04024     ExAcquireResourceExclusive(&PpRegistryDeviceResource, TRUE);
    04025
    04026     //
    04027     // Open HKLM\System\CurrentControlSet\Control\DeviceClasses key into hTemp1
    04028     //
    04029
    04030     PiWstrToUnicodeString(&tempString, REGSTR_FULL_PATH_DEVICE_CLASSES);
    04031     status = IopCreateRegistryKeyEx( &hTemp1,
    04032                                      NULL,
    04033                                      &tempString,
    04034                                      KEY_CREATE_SUB_KEY,
    04035                                      REG_OPTION_NON_VOLATILE,
    04036                                      NULL
    04037                                      );
    04038
    04039     if( !NT_SUCCESS(status) ){
    04040         goto clean2;
    04041     }
    04042
    04043     //
    04044     // Open/create function class GUID key into hTemp2
    04045     //
    04046
    04047     status = IopCreateRegistryKeyEx( &hTemp2,
    04048                                      hTemp1,
    04049                                      &guidString,
    04050                                      KEY_CREATE_SUB_KEY,
    04051                                      REG_OPTION_NON_VOLATILE,
    04052                                      NULL
    04053                                      );
    04054     ZwClose(hTemp1);
    04055
    04056     if( !NT_SUCCESS(status) ){
    04057         goto clean2;
    04058     }
    04059
    04060     //
    04061     // Now open/create the two-level device interface hierarchy underneath this
    04062     // interface class key.
    04063     //
    04064     status = IopOpenOrCreateDeviceInterfaceSubKeys(&hTemp1,
    04065                                                    &InterfaceDisposition,
    04066                                                    &hInterfaceInstanceKey,
    04067                                                    &InterfaceInstanceDisposition,
    04068                                                    hTemp2,
    04069                                                    pUserString,
    04070                                                    KEY_WRITE | DELETE,
    04071                                                    TRUE
    04072                                                   );
    04073
    04074     ZwClose(hTemp2);
    04075
    04076     if(!NT_SUCCESS(status)) {
    04077         goto clean2;
    04078     }
    04079
    04080     //
    04081     // Create the device instance value under the device interface key
    04082     //
    04083
    04084     PiWstrToUnicodeString(&tempString, REGSTR_VAL_DEVICE_INSTANCE);
    04085     status = IopSetRegistryStringValue(hTemp1,
    04086                                        &tempString,
    04087                                        DeviceInstanceName
    04088                                        );
    04089     if(!NT_SUCCESS(status)) {
    04090         goto clean3;
    04091     }
    04092
    04093     //
    04094     // Create symbolic link value under interface instance subkey
    04095     //
    04096
    04097     PiWstrToUnicodeString(&tempString, REGSTR_VAL_SYMBOLIC_LINK);
    04098     status = IopSetRegistryStringValue(hInterfaceInstanceKey,
    04099                                        &tempString,
    04100                                        pUserString
    04101                                        );
    04102
    04103 clean3:
    04104     if (!NT_SUCCESS(status)) {
    04105         //
    04106         // Since we failed to register the device interface, delete any keys
    04107         // that were newly created in the attempt.
    04108         //
    04109         if(InterfaceInstanceDisposition == REG_CREATED_NEW_KEY) {
    04110             ZwDeleteKey(hInterfaceInstanceKey);
    04111         } else {
    04112             ZwClose(hInterfaceInstanceKey);
    04113         }
    04114
    04115         if(InterfaceDisposition == REG_CREATED_NEW_KEY) {
    04116             ZwDeleteKey(hTemp1);
    04117         } else {
    04118             ZwClose(hTemp1);
    04119         }
    04120     } else {
    04121         ZwClose(hInterfaceInstanceKey);
    04122         ZwClose(hTemp1);
    04123     }
    04124
    04125 clean2:
    04126     ExReleaseResource(&PpRegistryDeviceResource);
    04127     KeLeaveCriticalRegion();
    04128     IopFreeAllocatedUnicodeString(&otherString);
    04129     if (!NT_SUCCESS(status)) {
    04130         IopFreeAllocatedUnicodeString(SymbolicLinkName);
    04131     }
    04132
    04133 clean1:
    04134     RtlFreeUnicodeString(&guidString);
    04135 clean0:
    04136     return status;
    04137 }

NTSTATUS IopRegisterTargetDeviceNotification | ( | IN ULONG | Flags,
|  | IN PFILE_OBJECT | FileObject,
|  | IN PDRIVER_OBJECT | DriverObject,
|  | IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE | CallbackRoutine,
|  | IN PVOID | Context,
|  | IN BOOLEAN | AddLast,
|  | OUT PVOID * | NotificationEntry
| ) |

NTSTATUS IopRemoveDeviceInterfaces | ( | IN PUNICODE_STRING | DeviceInstancePath | ) |

Definition at line 4414 of file pnpioapi.c.

References _BUFFER_INFO::Buffer, DEVICE_INTERFACE_INCLUDE_NONACTIVE, ExFreePool(), FALSE, INITIAL_INFO_BUFFER_SIZE, IopAllocateBuffer(), IopAllocateUnicodeString(), IopDeleteKeyRecursive(), IopFreeAllocatedUnicodeString(), IopFreeBuffer(), IopGetDeviceInterfaces(), IopGetRegistryValue(), IopOpenRegistryKeyEx(), IopRegistryDataToUnicodeString, IopResizeBuffer(), IopUnregisterDeviceInterface(), KEY_VALUE_DATA, _BUFFER_INFO::MaxSize, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, RtlEqualUnicodeString(), RtlGUIDFromString(), RtlInitUnicodeString(), TRUE, and USHORT.

    04420                    :
    04421
    04422     This routine checks all device class keys under
    04423     HKLM\SYSTEM\CCS\Control\DeviceClasses for interfaces for which the
    04424     DeviceInstance value matches the supplied DeviceInstancePath.  Instances of
    04425     such device interfaces are unregistered, and the device interface subkey
    04426     itself is removed.
    04427
    04428     Note that a lock on the registry must have already been acquired,
    04429     by the caller of this routine.
    04430
    04431 Parameters:
    04432
    04433     DeviceInterfacePath - Supplies a pointer to a unicode string which
    04434         contains the DeviceInterface name of the device for which
    04435         interfaces to are to be removed.
    04436
    04437 Return Value:
    04438
    04439     Status code that indicates whether or not the function was
    04440     successful.
    04441
    04442 --*/
    04443
    04444 {
    04445     NTSTATUS       status, context;
    04446     HANDLE         hDeviceClasses=NULL, hClassGUID=NULL, hInterface=NULL;
    04447     UNICODE_STRING tempString, guidString, interfaceString, deviceInstanceString;
    04448     ULONG          resultSize, classIndex, interfaceIndex;
    04449     ULONG          symbolicLinkListSize;
    04450     PWCHAR         symbolicLinkList, symLink;
    04451     BUFFER_INFO    classInfoBuffer, interfaceInfoBuffer;
    04452     PKEY_VALUE_FULL_INFORMATION deviceInstanceInfo;
    04453     BOOLEAN        deletedInterface;
    04454     GUID           classGUID;
    04455
    04456     PAGED_CODE();
    04457
    04458     //
    04459     // Allocate initial buffers
    04460     //
    04461     status = IopAllocateBuffer(&classInfoBuffer,
    04462                                INITIAL_INFO_BUFFER_SIZE);
    04463     if (!NT_SUCCESS(status)) {
    04464         goto clean0;
    04465     }
    04466
    04467     status = IopAllocateBuffer(&interfaceInfoBuffer,
    04468                                INITIAL_INFO_BUFFER_SIZE);
    04469     if (!NT_SUCCESS(status)) {
    04470         IopFreeBuffer(&classInfoBuffer);
    04471         goto clean0;
    04472     }
    04473
    04474     //
    04475     // Open HKLM\System\CurrentControlSet\Control\DeviceClasses
    04476     //
    04477     PiWstrToUnicodeString(&tempString, REGSTR_FULL_PATH_DEVICE_CLASSES);
    04478     status = IopOpenRegistryKeyEx( &hDeviceClasses,
    04479                                    NULL,
    04480                                    &tempString,
    04481                                    KEY_READ
    04482                                    );
    04483     if(!NT_SUCCESS(status)){
    04484         goto clean1;
    04485     }
    04486
    04487     //
    04488     // Enumerate all device classes
    04489     //
    04490     classIndex = 0;
    04491
    04492     while((status = ZwEnumerateKey(hDeviceClasses,
    04493                                    classIndex,
    04494                                    KeyBasicInformation,
    04495                                    (PVOID) classInfoBuffer.Buffer,
    04496                                    classInfoBuffer.MaxSize,
    04497                                    &resultSize)) != STATUS_NO_MORE_ENTRIES) {
    04498
    04499         if (status == STATUS_BUFFER_TOO_SMALL) {
    04500             status = IopResizeBuffer(&classInfoBuffer, resultSize, FALSE);
    04501             continue;
    04502         } else if (!NT_SUCCESS(status)) {
    04503             goto clean1;
    04504         }
    04505
    04506         //
    04507         // Get the key name for this device class
    04508         //
    04509         guidString.Length = (USHORT)((PKEY_BASIC_INFORMATION)(classInfoBuffer.Buffer))->NameLength;
    04510         guidString.MaximumLength = guidString.Length;
    04511         guidString.Buffer = ((PKEY_BASIC_INFORMATION)(classInfoBuffer.Buffer))->Name;
    04512
    04513         //
    04514         // Open the key for this device class
    04515         //
    04516         status = IopOpenRegistryKeyEx( &hClassGUID,
    04517                                        hDeviceClasses,
    04518                                        &guidString,
    04519                                        KEY_ALL_ACCESS
    04520                                        );
    04521         if (!NT_SUCCESS(status)) {
    04522             //
    04523             // Couldn't open key for this device class -- skip it and move on.
    04524             //
    04525             goto CloseClassKeyAndContinue;
    04526         }
    04527
    04528         //
    04529         // Enumerate all device interfaces for this device class
    04530         //
    04531         interfaceIndex = 0;
    04532
    04533         while((status = ZwEnumerateKey(hClassGUID,
    04534                                        interfaceIndex,
    04535                                        KeyBasicInformation,
    04536                                        (PVOID) interfaceInfoBuffer.Buffer,
    04537                                        interfaceInfoBuffer.MaxSize,
    04538                                        &resultSize)) != STATUS_NO_MORE_ENTRIES) {
    04539
    04540             if (status == STATUS_BUFFER_TOO_SMALL) {
    04541                 status = IopResizeBuffer(&interfaceInfoBuffer, resultSize, FALSE);
    04542                 continue;
    04543             } else if (!NT_SUCCESS(status)) {
    04544                 goto clean1;
    04545             }
    04546
    04547             //
    04548             // This interface key has not yet been deleted
    04549             //
    04550             deletedInterface = FALSE;
    04551
    04552             //
    04553             // Create a NULL-terminated unicode string for the interface key name
    04554             //
    04555             status = IopAllocateUnicodeString(&interfaceString,
    04556                                               (USHORT)((PKEY_BASIC_INFORMATION)(interfaceInfoBuffer.Buffer))->NameLength);
    04557
    04558             if (!NT_SUCCESS(status)) {
    04559                 goto clean1;
    04560             }
    04561
    04562             interfaceString.Length = (USHORT)((PKEY_BASIC_INFORMATION)(interfaceInfoBuffer.Buffer))->NameLength;
    04563             interfaceString.MaximumLength = interfaceString.Length + sizeof(UNICODE_NULL);
    04564             RtlCopyMemory(interfaceString.Buffer,
    04565                           ((PKEY_BASIC_INFORMATION)(interfaceInfoBuffer.Buffer))->Name,
    04566                           interfaceString.Length);
    04567             interfaceString.Buffer[interfaceString.Length/sizeof(WCHAR)] = UNICODE_NULL;
    04568
    04569             //
    04570             // Open the device interface key
    04571             //
    04572             status = IopOpenRegistryKeyEx( &hInterface,
    04573                                            hClassGUID,
    04574                                            &interfaceString,
    04575                                            KEY_ALL_ACCESS
    04576                                            );
    04577             if (!NT_SUCCESS(status)) {
    04578                 //
    04579                 // Couldn't open the device interface key -- skip it and move on.
    04580                 //
    04581                 hInterface = NULL;
    04582                 goto CloseInterfaceKeyAndContinue;
    04583             }
    04584
    04585             //
    04586             // Get the DeviceInstance value for this interface key
    04587             //
    04588             status = IopGetRegistryValue(hInterface,
    04589                                          REGSTR_VAL_DEVICE_INSTANCE,
    04590                                          &deviceInstanceInfo);
    04591
    04592             if(!NT_SUCCESS(status)) {
    04593                 //
    04594                 //  Couldn't get the DeviceInstance for this interface --
    04595                 //  skip it and move on.
    04596                 //
    04597                 goto CloseInterfaceKeyAndContinue;
    04598             }
    04599
    04600             if((deviceInstanceInfo->Type == REG_SZ) &&
    04601                (deviceInstanceInfo->DataLength != 0)) {
    04602
    04603                 IopRegistryDataToUnicodeString(&deviceInstanceString,
    04604                                                (PWSTR)KEY_VALUE_DATA(deviceInstanceInfo),
    04605                                                deviceInstanceInfo->DataLength);
    04606
    04607             } else {
    04608                 //
    04609                 // DeviceInstance value is invalid -- skip it and move on.
    04610                 //
    04611                 ExFreePool(deviceInstanceInfo);
    04612                 goto CloseInterfaceKeyAndContinue;
    04613
    04614             }
    04615
    04616             //
    04617             // Compare the DeviceInstance of this interface to DeviceInstancePath
    04618             //
    04619             if (RtlEqualUnicodeString(&deviceInstanceString, DeviceInstancePath, TRUE)) {
    04620
    04621                 ZwClose(hInterface);
    04622                 hInterface = NULL;
    04623
    04624                 //
    04625                 // Retrieve all instances of this device interface
    04626                 // (active and non-active)
    04627                 //
    04628                 RtlGUIDFromString(&guidString, &classGUID);
    04629
    04630                 status = IopGetDeviceInterfaces(&classGUID,
    04631                                                 DeviceInstancePath,
    04632                                                 DEVICE_INTERFACE_INCLUDE_NONACTIVE,
    04633                                                 FALSE,       // kernel-mode format
    04634                                                 &symbolicLinkList,
    04635                                                 &symbolicLinkListSize);
    04636
    04637                 if (NT_SUCCESS(status)) {
    04638
    04639                     //
    04640                     // Iterate through all instances of the interface
    04641                     //
    04642                     symLink = symbolicLinkList;
    04643                     while(*symLink != UNICODE_NULL) {
    04644
    04645                         RtlInitUnicodeString(&tempString, symLink);
    04646
    04647                         //
    04648                         // Unregister this instance of the interface.  Since we are
    04649                         // removing the device, ignore any returned status, since
    04650                         // there isn't anything we can do about interfaces which
    04651                         // fail unregistration.
    04652                         //
    04653                         IopUnregisterDeviceInterface(&tempString);
    04654
    04655                         symLink += ((tempString.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR));
    04656                     }
    04657                     ExFreePool(symbolicLinkList);
    04658                 }
    04659
    04660                 //
    04661                 // Recursively delete the interface key, if it still exists.
    04662                 // While IopUnregisterDeviceInterface will itself delete the
    04663                 // interface key if no interface instance subkeys remain, if any
    04664                 // of the above calls to IopUnregisterDeviceInterface failed to
    04665                 // delete an interface instance key, subkeys will remain, and
    04666                 // the interface key will not have been deleted.  We'll catch
    04667                 // that here.
    04668                 //
    04669                 status = IopOpenRegistryKeyEx( &hInterface,
    04670                                                hClassGUID,
    04671                                                &interfaceString,
    04672                                                KEY_READ
    04673                                                );
    04674                 if(NT_SUCCESS(status)){
    04675                     if (NT_SUCCESS(IopDeleteKeyRecursive(hClassGUID,
    04676                                                          interfaceString.Buffer))) {
    04677                         deletedInterface = TRUE;
    04678                     }
    04679                     ZwDeleteKey(hInterface);
    04680                     ZwClose(hInterface);
    04681                     hInterface = NULL;
    04682                 } else if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
    04683                     //
    04684                     // Interface was already deleted by IopUnregisterDeviceInterface
    04685                     //
    04686                     deletedInterface = TRUE;
    04687                 }
    04688             }
    04689
    04690             //
    04691             // Free allocated key info structure
    04692             //
    04693             ExFreePool(deviceInstanceInfo);
    04694
    04695 CloseInterfaceKeyAndContinue:
    04696
    04697             if (hInterface != NULL) {
    04698                 ZwClose(hInterface);
    04699                 hInterface = NULL;
    04700             }
    04701
    04702             IopFreeAllocatedUnicodeString(&interfaceString);
    04703
    04704             //
    04705             // Only increment the enumeration index for non-deleted keys
    04706             //
    04707             if (!deletedInterface) {
    04708                 interfaceIndex++;
    04709             }
    04710
    04711         }
    04712
    04713 CloseClassKeyAndContinue:
    04714
    04715         if (hClassGUID != NULL) {
    04716             ZwClose(hClassGUID);
    04717             hClassGUID = NULL;
    04718         }
    04719         classIndex++;
    04720     }
    04721
    04722 clean1:
    04723     if (hInterface) {
    04724         ZwClose(hInterface);
    04725     }
    04726     if (hClassGUID) {
    04727         ZwClose(hClassGUID);
    04728     }
    04729     if (hDeviceClasses) {
    04730         ZwClose(hDeviceClasses);
    04731     }
    04732
    04733     IopFreeBuffer(&interfaceInfoBuffer);
    04734     IopFreeBuffer(&classInfoBuffer);
    04735
    04736 clean0:
    04737     return status;
    04738 }

NTSTATUS IopReplaceSeperatorWithPound | ( | OUT PUNICODE_STRING | OutString,
|  | IN PUNICODE_STRING | InString
| ) |

Definition at line 5280 of file pnpioapi.c.

References ALT_SEPERATOR_CHAR, ASSERT, PAGED_CODE, REPLACED_SEPERATOR_CHAR, SEPERATOR_CHAR, and USHORT.

    05287                    :
    05288
    05289     This routine will copy a string from InString to OutString replacing any occurence of
    05290     '\' or '/' with '#' as it goes.
    05291
    05292 Parameters:
    05293
    05294     OutString - Supplies a pointer to a string which has already been initialised to
    05295         have a buffer large enough to accomodate the string.  The contents of this
    05296         string will be over written
    05297
    05298     InString - Supplies a pointer to the string to be munged
    05299
    05300 Return Value:
    05301
    05302     Status code that indicates whether or not the function was successful.
    05303
    05304 Remarks:
    05305
    05306     In place munging can be performed - ie. the In and Out strings can be the same.
    05307
    05308 --*/
    05309
    05310 {
    05311     PWSTR pInPosition, pOutPosition;
    05312     USHORT count;
    05313
    05314     PAGED_CODE();
    05315
    05316     ASSERT(InString);
    05317     ASSERT(OutString);
    05318
    05319     //
    05320     // Ensure we have enough space in the output string
    05321     //
    05322
    05323     if(InString->Length > OutString->MaximumLength) {
    05324         return STATUS_BUFFER_TOO_SMALL;
    05325     }
    05326
    05327     pInPosition = InString->Buffer;
    05328     pOutPosition = OutString->Buffer;
    05329     count = InString->Length / sizeof(WCHAR);
    05330
    05331     //
    05332     // Traverse the in string copying and replacing all occurences of '\' or '/'
    05333     // with '#'
    05334     //
    05335
    05336     while (count--) {
    05337         if((*pInPosition == SEPERATOR_CHAR) || (*pInPosition == ALT_SEPERATOR_CHAR)) {
    05338             *pOutPosition = REPLACED_SEPERATOR_CHAR;
    05339         } else {
    05340             *pOutPosition = *pInPosition;
    05341         }
    05342         pInPosition++;
    05343         pOutPosition++;
    05344     }
    05345
    05346     OutString->Length = InString->Length;
    05347
    05348     return STATUS_SUCCESS;
    05349
    05350 }

VOID IopReportTargetDeviceChangeAsyncWorker | ( | PVOID | Context | ) |

Definition at line 6242 of file pnpioapi.c.

References _ASYNC_TDC_WORK_ITEM::Callback, _ASYNC_TDC_WORK_ITEM::Context, _ASYNC_TDC_WORK_ITEM::DeviceObject, ExFreePool(), _ASYNC_TDC_WORK_ITEM::NotificationStructure, NULL, ObDereferenceObject, PASYNC_TDC_WORK_ITEM, and PpSetCustomTargetEvent().

Referenced by IoReportTargetDeviceChangeAsynchronous().

    06248                    :
    06249
    06250     This routine is the worker routine of IoInvalidateDeviceState.
    06251     Its main purpose is to invoke IopSynchronousQueryDeviceState and release
    06252     work item space.
    06253
    06254 Parameters:
    06255
    06256     Context - Supplies a pointer to the ASYNC_TDC_WORK_ITEM.
    06257
    06258 ReturnValue:
    06259
    06260     None.
    06261
    06262 --*/
    06263
    06264 {
    06265     PASYNC_TDC_WORK_ITEM asyncWorkItem = (PASYNC_TDC_WORK_ITEM)Context;
    06266
    06267     PpSetCustomTargetEvent( asyncWorkItem->DeviceObject,
    06268                             NULL,
    06269                             NULL,
    06270                             asyncWorkItem->Callback,
    06271                             asyncWorkItem->Context,
    06272                             asyncWorkItem->NotificationStructure);
    06273
    06274     ObDereferenceObject(asyncWorkItem->DeviceObject);
    06275     ExFreePool(asyncWorkItem);
    06276 }

VOID IopRequestDeviceEjectWorker | ( | PVOID | Context | ) |

Definition at line 1520 of file pnpioapi.c.

References _DEVICE_WORK_ITEM::DeviceObject, ExFreePool(), NULL, ObDereferenceObject, PDEVICE_WORK_ITEM, PpSetTargetDeviceRemove(), and TRUE.

Referenced by IoRequestDeviceEject().

    01523 {
    01524     PDEVICE_WORK_ITEM deviceWorkItem = (PDEVICE_WORK_ITEM)Context;
    01525     PDEVICE_OBJECT deviceObject = deviceWorkItem->DeviceObject;
    01526
    01527     ExFreePool(deviceWorkItem);
    01528
    01529     //
    01530     // Queue the event, we'll return immediately after it's queued.
    01531     //
    01532
    01533     PpSetTargetDeviceRemove( deviceObject,
    01534                              TRUE,
    01535                              TRUE,
    01536                              TRUE,
    01537                              CM_PROB_DEVICE_NOT_THERE,
    01538                              NULL,
    01539                              NULL,
    01540                              NULL,
    01541                              NULL);
    01542
    01543     ObDereferenceObject(deviceObject);
    01544 }

NTSTATUS IopRequestHwProfileChangeNotification | ( | IN LPGUID | EventGuid,
|  | IN PROFILE_NOTIFICATION_TIME | NotificationTime,
|  | OUT PPNP_VETO_TYPE VetoType | OPTIONAL,
|  | OUT PUNICODE_STRING VetoName | OPTIONAL
| ) |

Definition at line 6672 of file pnpioapi.c.

References ASSERT, DbgPrint, ExAllocatePoolWithTag, Executive, FALSE, IopCompareGuid, IopNotifyHwProfileChange(), KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PagedPool, PiNotificationInProgress, PiNotifyUserMode(), PNP_DEVICE_EVENT_ENTRY_TAG, PpSetHwProfileChangeEvent(), PROFILE_NOT_IN_PNPEVENT, PROFILE_PERHAPS_IN_PNPEVENT, and TRUE.

Referenced by IopHardwareProfileQueryChange(), IopHardwareProfileSendCancel(), and IopHardwareProfileSendCommit().

    06681                    :
    06682
    06683     This routine is used to notify all registered drivers of a hardware profile
    06684     change.  If the operation is a HW provile change query then the operation
    06685     is synchronous and the veto information is propagated.  All other operations
    06686     are asynchronous and veto information is not returned.
    06687
    06688 Parameters:
    06689
    06690     EventTypeGuid       - The event that has occured
    06691
    06692     NotificationTime    - This is used to tell if we are already in an event
    06693                           when delivering a synchronous notification (ie,
    06694                           querying profile change to eject). It is one of
    06695                           three values:
    06696                               PROFILE_IN_PNPEVENT
    06697                               PROFILE_NOT_IN_PNPEVENT
    06698                               PROFILE_PERHAPS_IN_PNPEVENT
    06699
    06700     VetoType            - Type of vetoer.
    06701
    06702     VetoName            - Name of vetoer.
    06703
    06704 Return Value:
    06705
    06706     Status code that indicates whether or not the function was successful.
    06707
    06708 Note:
    06709
    06710     The contents of the notification structure *including* all pointers is only
    06711     valid during the callback routine to which it was passed.  If the data is
    06712     required after the duration of the callback then it must be physically copied
    06713     by the callback routine.
    06714
    06715 --*/
    06716
    06717 {
    06718     NTSTATUS status=STATUS_SUCCESS,completionStatus;
    06719     KEVENT completionEvent;
    06720     ULONG dataSize,totalSize;
    06721     PPNP_DEVICE_EVENT_ENTRY deviceEvent;
    06722
    06723     PAGED_CODE();
    06724
    06725     if (
    06726          (!IopCompareGuid(EventGuid,
    06727                        (LPGUID)&GUID_HWPROFILE_QUERY_CHANGE)) &&
    06728          (!IopCompareGuid(EventGuid,
    06729                        (LPGUID)&GUID_HWPROFILE_CHANGE_CANCELLED)) &&
    06730          (!IopCompareGuid(EventGuid,
    06731                        (LPGUID)&GUID_HWPROFILE_CHANGE_COMPLETE)) ) {
    06732
    06733          //
    06734          //  Passed in an illegal value
    06735          //
    06736
    06737  #if DBG
    06738          DbgPrint ("Illegal Event type passed as profile notification\n");
    06739  #endif
    06740          return STATUS_INVALID_DEVICE_REQUEST;
    06741      }
    06742
    06743
    06744      //
    06745      // Only the query changes are synchronous, and in that case we must
    06746      // know definitely whether we are nested within a Pnp event or not.
    06747      //
    06748      ASSERT((!IopCompareGuid(EventGuid, (LPGUID)&GUID_HWPROFILE_QUERY_CHANGE))||
    06749             (NotificationTime != PROFILE_PERHAPS_IN_PNPEVENT)) ;
    06750
    06751      if (!IopCompareGuid(EventGuid, (LPGUID)&GUID_HWPROFILE_QUERY_CHANGE) ) {
    06752
    06753          //
    06754          // Asynchronous case. Very easy.
    06755          //
    06756          ASSERT(!ARGUMENT_PRESENT(VetoName));
    06757          ASSERT(!ARGUMENT_PRESENT(VetoType));
    06758
    06759          return PpSetHwProfileChangeEvent( EventGuid,
    06760                                            NULL,
    06761                                            NULL,
    06762                                            NULL,
    06763                                            NULL
    06764                                            );
    06765      }
    06766
    06767      //
    06768      // Query notifications are synchronous. Determine if we are currently
    06769      // within an event, in which case we must do the notify here instead
    06770      // of queueing it up.
    06771      //
    06772      if (NotificationTime == PROFILE_NOT_IN_PNPEVENT) {
    06773
    06774          //
    06775          // Queue up and block on the notification.
    06776          //
    06777          KeInitializeEvent(&completionEvent, NotificationEvent, FALSE);
    06778
    06779          status = PpSetHwProfileChangeEvent( EventGuid,
    06780                                              &completionEvent,
    06781                                              &completionStatus,
    06782                                              VetoType,
    06783                                              VetoName
    06784                                              );
    06785
    06786          if (NT_SUCCESS(status))  {
    06787
    06788              KeWaitForSingleObject( &completionEvent, Executive, KernelMode, FALSE, NULL );
    06789
    06790              status = completionStatus;
    06791          }
    06792
    06793          return status ;
    06794      }
    06795
    06796      //
    06797      // Synchronous notify inside our Pnp event.
    06798      //
    06799      // ADRIAO BUGBUG 11/12/98 -
    06800      //     GROSS, UGLY, SINFUL HACK - We are MANUALLY sending the profile
    06801      // query change notification because we are blocking inside a PnPEvent and
    06802      // thus can't queue/wait on another!
    06803      //
    06804      ASSERT(PiNotificationInProgress == TRUE);
    06805
    06806      dataSize =  sizeof(PLUGPLAY_EVENT_BLOCK);
    06807
    06808      totalSize = dataSize + FIELD_OFFSET (PNP_DEVICE_EVENT_ENTRY,Data);
    06809
    06810      deviceEvent = ExAllocatePoolWithTag (PagedPool,
    06811                                           totalSize,
    06812                                           PNP_DEVICE_EVENT_ENTRY_TAG);
    06813
    06814      if (NULL == deviceEvent) {
    06815          return STATUS_INSUFFICIENT_RESOURCES;
    06816      }
    06817
    06818      //
    06819      //Setup the PLUGPLAY_EVENT_BLOCK
    06820      //
    06821      RtlZeroMemory ((PVOID)deviceEvent,totalSize);
    06822      deviceEvent->Data.EventCategory = HardwareProfileChangeEvent;
    06823      RtlCopyMemory(&deviceEvent->Data.EventGuid, EventGuid, sizeof(GUID));
    06824      deviceEvent->Data.TotalSize = dataSize;
    06825      deviceEvent->CallerEvent = &completionEvent;
    06826      deviceEvent->Data.Result = &completionStatus;
    06827      deviceEvent->VetoType = VetoType;
    06828      deviceEvent->VetoName = VetoName;
    06829
    06830      //
    06831      // Notify K-Mode
    06832      //
    06833      status = IopNotifyHwProfileChange(&deviceEvent->Data.EventGuid,
    06834                                        VetoType,
    06835                                        VetoName);
    06836
    06837      if (!NT_SUCCESS(status)) {
    06838          return status;
    06839      }
    06840
    06841      //
    06842      // Notify user-mode (synchronously).
    06843      //
    06844      status = PiNotifyUserMode(deviceEvent);
    06845
    06846      if (!NT_SUCCESS(status)) {
    06847          //
    06848          // Notify K-mode that the query has been cancelled.
    06849          //
    06850          IopNotifyHwProfileChange((LPGUID)&GUID_HWPROFILE_CHANGE_CANCELLED,
    06851                                   NULL,
    06852                                   NULL);
    06853      }
    06854      return status;
    06855 }

NTSTATUS IopResizeBuffer | ( | IN PBUFFER_INFO | Info,
|  | IN ULONG | NewSize,
|  | IN BOOLEAN | CopyContents
| ) |

Definition at line 2467 of file pnpioapi.c.

References ASSERT, ExAllocatePool, ExFreePool(), and PagedPool.

Referenced by IopAppendBuffer(), IopGetDeviceInterfaces(), IopOverwriteBuffer(), IopProcessCriticalDeviceRoutine(), and IopRemoveDeviceInterfaces().

    02475                    :
    02476
    02477     Allocates a new buffer of NewSize bytes and associates it with Info, freeing the
    02478     old buffer.  It will optionally copy the data stored in the old buffer into the
    02479     new buffer and update the current position.
    02480
    02481 Parameters:
    02482
    02483     Info - Pointer to a buffer info structure to be used to manage the buffer
    02484
    02485     NewSize - The new size of the buffer in bytes
    02486
    02487     CopyContents - If TRUE indicates that the contents of the old buffer should be
    02488                    copied to the new buffer
    02489
    02490 Return Value:
    02491
    02492     Status code that indicates whether or not the function was successful.
    02493
    02494 --*/
    02495
    02496 {
    02497     ULONG used;
    02498     PCHAR newBuffer;
    02499
    02500     ASSERT(Info);
    02501
    02502     used = (ULONG)(Info->Current - Info->Buffer);
    02503
    02504     if (!(newBuffer = ExAllocatePool(PagedPool, NewSize))) {
    02505         return STATUS_INSUFFICIENT_RESOURCES;
    02506     }
    02507
    02508     if (CopyContents) {
    02509
    02510         //
    02511         // Assert there is room in the buffer
    02512         //
    02513
    02514         ASSERT(used < NewSize);
    02515
    02516         RtlCopyMemory(newBuffer,
    02517                       Info->Buffer,
    02518                       used);
    02519
    02520         Info->Current = newBuffer + used;
    02521
    02522     } else {
    02523
    02524         Info->Current = newBuffer;
    02525     }
    02526
    02527     ExFreePool(Info->Buffer);
    02528
    02529     Info->Buffer = newBuffer;
    02530     Info->MaxSize = NewSize;
    02531
    02532     return STATUS_SUCCESS;
    02533 }

VOID IopResourceRequirementsChanged | ( | IN PDEVICE_OBJECT | PhysicalDeviceObject,
|  | IN BOOLEAN | StopRequired
| ) |

Definition at line 6439 of file pnpioapi.c.

References DNF_NO_RESOURCE_REQUIRED, DNF_NON_STOPPED_REBALANCE, DNF_RESOURCE_REQUIREMENTS_CHANGED, DNF_STARTED, FALSE, _DEVICE_NODE::Flags, IopClearDevNodeProblem, IopRequestDeviceAction(), NULL, PAGED_CODE, and ResourceRequirementsChanged.

Referenced by IopQueryDeviceState().

    06446                    :
    06447
    06448     This routine handles request of device resource requirements list change.
    06449
    06450 Parameters:
    06451
    06452     PhysicalDeviceObject - Provides a pointer to the PDO who's state is to be invalidated.
    06453
    06454     StopRequired - Supplies a BOOLEAN value to indicate if the resources reallocation needs
    06455                    to be done after device stopped.
    06456
    06457 Return Value:
    06458
    06459     none.
    06460
    06461 --*/
    06462
    06463 {
    06464     PDEVICE_NODE deviceNode;
    06465     PDEVICE_OBJECT device = NULL;
    06466
    06467     PAGED_CODE();
    06468
    06469     deviceNode = (PDEVICE_NODE)PhysicalDeviceObject->DeviceObjectExtension->DeviceNode;
    06470
    06471     //
    06472     // Clear the NO_RESOURCE_REQUIRED flags.
    06473     //
    06474
    06475     deviceNode->Flags &= ~DNF_NO_RESOURCE_REQUIRED;
    06476
    06477     //
    06478     // If for some reason this device did not start, we need to clear some flags
    06479     // such that it can be started later.  In this case, we call IopRequestDeviceEnumeration
    06480     // with NULL device object, so the devices will be handled in non-started case.  They will
    06481     // be assigned resources, started and enumerated.
    06482     //
    06483
    06484     deviceNode->Flags |= DNF_RESOURCE_REQUIREMENTS_CHANGED;
    06485
    06486     IopClearDevNodeProblem(deviceNode);
    06487
    06488     //
    06489     // If the device is already started, we call IopRequestDeviceEnumeration with
    06490     // the device object.
    06491     //
    06492
    06493     if (deviceNode->Flags & DNF_STARTED) {
    06494         device = PhysicalDeviceObject;
    06495         if (StopRequired == FALSE) {
    06496             deviceNode->Flags |= DNF_NON_STOPPED_REBALANCE;
    06497         } else {
    06498
    06499             //
    06500             // Explicitly clear it.
    06501             //
    06502
    06503             deviceNode->Flags &= ~DNF_NON_STOPPED_REBALANCE;
    06504         }
    06505     }
    06506
    06507     IopRequestDeviceAction( device, ResourceRequirementsChanged, NULL, NULL );
    06508 }

NTSTATUS IopSetRegistryStringValue | ( | IN HANDLE | KeyHandle,
|  | IN PUNICODE_STRING | ValueName,
|  | IN PUNICODE_STRING | ValueData
| ) |

| Referenced by IopBootLog(), and IopRegisterDeviceInterface().

NTSTATUS IopSetSecurityObjectFromRegistry | ( | IN PVOID | Object,
|  | IN HANDLE | Key
| ) |

Definition at line 8959 of file pnpioapi.c.

References ExFreePool(), FALSE, IopGetRegistryValue(), Key, NT_SUCCESS, NTSTATUS(), NULL, ObSetSecurityObjectByPointer(), PagedPool, RtlGetDaclSecurityDescriptor(), RtlGetGroupSecurityDescriptor(), RtlGetOwnerSecurityDescriptor(), RtlGetSaclSecurityDescriptor(), RtlInitUnicodeString(), SeCaptureSecurityDescriptor(), SeReleaseSecurityDescriptor(), and UserMode.

    08965                    :
    08966
    08967     This routine will read in the security information stored in the specified
    08968     registry key and assign that security to the specified object.  If the
    08969     registry key contains a SecurityDescriptor value it will be validated and
    08970     assigned to the object if valid.
    08971
    08972 Arguments:
    08973
    08974     Object - the object to be secured.
    08975
    08976     Key - the registry key these values are saved in.
    08977
    08978 Return Value:
    08979
    08980     status
    08981
    08982 --*/
    08983
    08984 {
    08985     UNICODE_STRING valueName;
    08986
    08987     PKEY_VALUE_FULL_INFORMATION info = NULL;
    08988
    08989     PSECURITY_DESCRIPTOR descriptor;
    08990     PSECURITY_DESCRIPTOR capturedDescriptor;
    08991
    08992     NTSTATUS status;
    08993
    08994     RtlInitUnicodeString(&valueName, REGSTR_VAL_DEVICE_SECURITY_DESCRIPTOR);
    08995
    08996     status = IopGetRegistryValue(Key,
    08997                                  valueName.Buffer,
    08998                                  &info);
    08999
    09000     if(!NT_SUCCESS(status)) {
    09001         return status;
    09002     }
    09003
    09004     descriptor = (((PUCHAR) info) + info->DataOffset);
    09005
    09006     status = SeCaptureSecurityDescriptor(descriptor,
    09007                                          UserMode,
    09008                                          PagedPool,
    09009                                          FALSE,
    09010                                          &capturedDescriptor);
    09011
    09012     ExFreePool(descriptor);
    09013
    09014     if(!NT_SUCCESS(status)) {
    09015         return status;
    09016     }
    09017
    09018     try {
    09019
    09020         SECURITY_INFORMATION securityInformation;
    09021
    09022         PSID sid;
    09023         PACL acl;
    09024         BOOLEAN present, tmp;
    09025
    09026         RtlZeroMemory(&securityInformation, sizeof(securityInformation));
    09027
    09028         //
    09029         // See what information is in the captured descriptor so we can build
    09030         // up a securityInformation block to go with it.
    09031         //
    09032
    09033         status = RtlGetOwnerSecurityDescriptor(capturedDescriptor, &sid, &tmp);
    09034
    09035         if(NT_SUCCESS(status) && (sid != NULL)) {
    09036             securityInformation |= OWNER_SECURITY_INFORMATION;
    09037         }
    09038
    09039         status = RtlGetGroupSecurityDescriptor(capturedDescriptor, &sid, &tmp);
    09040
    09041         if(NT_SUCCESS(status) && (sid != NULL)) {
    09042             securityInformation |= GROUP_SECURITY_INFORMATION;
    09043         }
    09044
    09045         status = RtlGetSaclSecurityDescriptor(capturedDescriptor,
    09046                                               &present,
    09047                                               &acl,
    09048                                               &tmp);
    09049
    09050         if(NT_SUCCESS(status) && (present)) {
    09051             securityInformation |= SACL_SECURITY_INFORMATION;
    09052         }
    09053
    09054         status = RtlGetDaclSecurityDescriptor(capturedDescriptor,
    09055                                               &present,
    09056                                               &acl,
    09057                                               &tmp);
    09058
    09059         if(NT_SUCCESS(status) && (present)) {
    09060             securityInformation |= DACL_SECURITY_INFORMATION;
    09061         }
    09062
    09063         status = ObSetSecurityObjectByPointer(Object,
    09064                                               securityInformation,
    09065                                               capturedDescriptor);
    09066     } finally {
    09067         SeReleaseSecurityDescriptor(capturedDescriptor,
    09068                                     UserMode,
    09069                                     FALSE);
    09070     }
    09071
    09072     return status;
    09073 }

NTSTATUS IopSetupDeviceObjectFromDeviceClass | ( | IN PDEVICE_OBJECT | Pdo,
|  | IN HANDLE | InterfaceClassKey
| ) |

| Referenced by IopProcessSetInterfaceState().

NTSTATUS IopUnregisterDeviceInterface | ( | IN PUNICODE_STRING | SymbolicLinkName | ) |

Definition at line 4140 of file pnpioapi.c.

References ExAcquireResourceExclusive, ExFreePool(), ExReleaseResource, FALSE, IopAllocateUnicodeString(), IopConstStringSize, IopDeleteKeyRecursive(), IopDeviceInterfaceKeysFromSymbolicLink(), IopFreeAllocatedUnicodeString(), IopGetRegistryKeyInformation(), IopGetRegistryValue(), IopOpenRegistryKeyEx(), IopParseSymbolicLinkName(), IoSetDeviceInterfaceState(), KeEnterCriticalRegion, KeLeaveCriticalRegion, KEY_STRING_PREFIX, KEY_VALUE_DATA, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PpRegistryDeviceResource, REFSTRING_PREFIX_CHAR, RtlAppendUnicodeStringToString(), TRUE, and USHORT.

Referenced by IopRemoveDeviceInterfaces().

    04146                    :
    04147
    04148     This routine removes the interface instance subkey of
    04149     ReferenceString from the interface for DeviceInstanceName to the
    04150     given InterfaceClassGuid.  If the interface instance specified by
    04151     the Reference String portion of SymbolicLinkName is the only
    04152     instance of the interface, the interface subkey is removed from
    04153     the device class key as well.
    04154
    04155 Parameters:
    04156
    04157     SymbolicLinkName - Supplies a pointer to a unicode string which
    04158         contains the symbolic link name of the device to unregister.
    04159
    04160 Return Value:
    04161
    04162     Status code that indicates whether or not the function was successful.
    04163
    04164 --*/
    04165
    04166 {
    04167     NTSTATUS        status = STATUS_SUCCESS, context;
    04168     HANDLE          hInterfaceClassKey=NULL, hInterfaceKey=NULL,
    04169                     hInterfaceInstanceKey=NULL, hControl=NULL;
    04170     UNICODE_STRING  tempString, mungedPathString, guidString, refString;
    04171     BOOLEAN         refStringPresent;
    04172     GUID            guid;
    04173     UNICODE_STRING  interfaceKeyName, instanceKeyName;
    04174     ULONG           linked, remainingSubKeys;
    04175     USHORT          length;
    04176     PKEY_VALUE_FULL_INFORMATION keyValueInformation;
    04177     PKEY_FULL_INFORMATION keyInformation;
    04178
    04179
    04180     PAGED_CODE();
    04181
    04182     //
    04183     // Check that the supplied symbolic link is present, and can be parsed
    04184     //
    04185     if ( (!ARGUMENT_PRESENT(SymbolicLinkName)) ||
    04186          (!NT_SUCCESS(IopParseSymbolicLinkName(SymbolicLinkName,
    04187                                               NULL,
    04188                                               &mungedPathString,
    04189                                               &guidString,
    04190                                               &refString,
    04191                                               &refStringPresent,
    04192                                               &guid))) ) {
    04193         status = STATUS_INVALID_PARAMETER;
    04194         goto clean0;
    04195     }
    04196
    04197     //
    04198     // Allocate a unicode string for the interface instance key name.
    04199     // (includes the REFSTRING_PREFIX_CHAR, and ReferenceString, if present)
    04200     //
    04201     length = sizeof(WCHAR) + refString.Length;
    04202     status = IopAllocateUnicodeString(&instanceKeyName,
    04203                                       length);
    04204     if(!NT_SUCCESS(status)) {
    04205         goto clean0;
    04206     }
    04207
    04208     //
    04209     // Set the MaximumLength of the Buffer, and append the
    04210     // REFSTRING_PREFIX_CHAR to it.
    04211     //
    04212     *instanceKeyName.Buffer = REFSTRING_PREFIX_CHAR;
    04213     instanceKeyName.Length = sizeof(WCHAR);
    04214     instanceKeyName.MaximumLength = length + sizeof(UNICODE_NULL);
    04215
    04216     //
    04217     // Append the ReferenceString to the prefix char, if necessary.
    04218     //
    04219     if (refStringPresent) {
    04220         RtlAppendUnicodeStringToString(&instanceKeyName, &refString);
    04221     }
    04222
    04223     instanceKeyName.Buffer[instanceKeyName.Length/sizeof(WCHAR)] = UNICODE_NULL;
    04224
    04225     //
    04226     // Allocate a unicode string for the interface key name.
    04227     // (includes KEY_STRING_PREFIX, mungedPathString, separating '#'
    04228     //  char, and the guidString)
    04229     //
    04230     length = IopConstStringSize(KEY_STRING_PREFIX) + mungedPathString.Length +
    04231              sizeof(WCHAR) + guidString.Length;
    04232
    04233     status = IopAllocateUnicodeString(&interfaceKeyName,
    04234                                       length);
    04235     if(!NT_SUCCESS(status)) {
    04236         goto clean1;
    04237     }
    04238
    04239     interfaceKeyName.MaximumLength = length + sizeof(UNICODE_NULL);
    04240
    04241     //
    04242     // Copy the symbolic link name (without refString) to the interfaceKeyNam
    04243     //
    04244     RtlCopyMemory(interfaceKeyName.Buffer, SymbolicLinkName->Buffer, length);
    04245     interfaceKeyName.Length = length;
    04246     interfaceKeyName.Buffer[interfaceKeyName.Length/sizeof(WCHAR)] = UNICODE_NULL;
    04247
    04248     //
    04249     // Replace the "\??\" or "\\?\" symbolic link name prefix with "##?#"
    04250     //
    04251     RtlCopyMemory(interfaceKeyName.Buffer,
    04252                   KEY_STRING_PREFIX,
    04253                   IopConstStringSize(KEY_STRING_PREFIX));
    04254
    04255     //
    04256     // Enter critical section and acquire a lock on the registry.  Both these
    04257     // mechanisms are required to prevent deadlock in the case where an APC
    04258     // routine calls this routine after the registry resource has been claimed
    04259     // in this case it would wait blocking this thread so the registry would
    04260     // never be released -> deadlock.  Critical sectioning the registry manipulation
    04261     // portion solves this problem
    04262     //
    04263
    04264     KeEnterCriticalRegion();
    04265     ExAcquireResourceExclusive(&PpRegistryDeviceResource, TRUE);
    04266
    04267     //
    04268     // Get class, interface, and instance handles
    04269     //
    04270     status = IopDeviceInterfaceKeysFromSymbolicLink(SymbolicLinkName,
    04271                                                     KEY_ALL_ACCESS,
    04272                                                     &hInterfaceClassKey,
    04273                                                     &hInterfaceKey,
    04274                                                     &hInterfaceInstanceKey
    04275                                                     );
    04276     if (!NT_SUCCESS(status)) {
    04277         goto clean2;
    04278     }
    04279
    04280     //
    04281     // Determine whether this interface is currently "enabled"
    04282     //
    04283     linked = 0;
    04284     PiWstrToUnicodeString(&tempString, REGSTR_KEY_CONTROL);
    04285     status = IopOpenRegistryKeyEx( &hControl,
    04286                                    hInterfaceInstanceKey,
    04287                                    &tempString,
    04288                                    KEY_ALL_ACCESS
    04289                                    );
    04290     if (NT_SUCCESS(status)) {
    04291         //
    04292         // Check the "linked" value under the "Control" subkey of this
    04293         // interface instance
    04294         //
    04295         keyValueInformation=NULL;
    04296         status = IopGetRegistryValue(hControl,
    04297                                      REGSTR_VAL_LINKED,
    04298                                      &keyValueInformation);
    04299
    04300         if(NT_SUCCESS(status)) {
    04301             if (keyValueInformation->Type == REG_DWORD &&
    04302                 keyValueInformation->DataLength == sizeof(ULONG)) {
    04303
    04304                 linked = *((PULONG) KEY_VALUE_DATA(keyValueInformation));
    04305                 ExFreePool(keyValueInformation);
    04306             }
    04307         }
    04308
    04309         ZwClose(hControl);
    04310         hControl = NULL;
    04311     }
    04312
    04313     //
    04314     // Ignore any status code returned while attempting to retieve the
    04315     // state of the device.  The value of linked will tell us if we
    04316     // need to disable the interface instance first.
    04317     //
    04318     // If no instance "Control" subkey or "linked" value was present
    04319     //     (status == STATUS_OBJECT_NAME_NOT_FOUND), this interface instance
    04320     //     is not currently enabled -- ok to delete.
    04321     //
    04322     // If the attempt to retrieve these values failed with some other error,
    04323     //     any attempt to disable the interface will also likely fail,
    04324     //     so we'll just have to delete this instance anyways.
    04325     //
    04326     status = STATUS_SUCCESS;
    04327
    04328     if (linked) {
    04329         //
    04330         // Disabled the active interface before unregistering it, ignore any
    04331         // status returned, we'll delete this interface instance key anyways.
    04332         //
    04333         IoSetDeviceInterfaceState(SymbolicLinkName, FALSE);
    04334     }
    04335
    04336     //
    04337     // Recursively delete the interface instance key, if it exists.
    04338     //
    04339     ZwClose(hInterfaceInstanceKey);
    04340     hInterfaceInstanceKey = NULL;
    04341     IopDeleteKeyRecursive (hInterfaceKey, instanceKeyName.Buffer);
    04342
    04343     //
    04344     // Find out how many subkeys to the interface key remain.
    04345     //
    04346     status = IopGetRegistryKeyInformation(hInterfaceKey,
    04347                                           &keyInformation);
    04348     if (!NT_SUCCESS(status)) {
    04349         goto clean3;
    04350     }
    04351
    04352     remainingSubKeys = keyInformation->SubKeys;
    04353
    04354     ExFreePool(keyInformation);
    04355
    04356     //
    04357     // See if a volatile "Control" subkey exists under this interface key
    04358     //
    04359     PiWstrToUnicodeString(&tempString, REGSTR_KEY_CONTROL);
    04360     status = IopOpenRegistryKeyEx( &hControl,
    04361                                    hInterfaceKey,
    04362                                    &tempString,
    04363                                    KEY_READ
    04364                                    );
    04365     if (NT_SUCCESS(status)) {
    04366         ZwClose(hControl);
    04367         hControl = NULL;
    04368     }
    04369     if ((remainingSubKeys==0) ||
    04370         ((remainingSubKeys==1) && (NT_SUCCESS(status)))) {
    04371         //
    04372         // If the interface key has no subkeys, or the only the remaining subkey
    04373         // is the volatile interface "Control" subkey, then there are no more
    04374         // instances to this interface.  We should delete the interface key
    04375         // itself also.
    04376         //
    04377         ZwClose(hInterfaceKey);
    04378         hInterfaceKey = NULL;
    04379
    04380         IopDeleteKeyRecursive (hInterfaceClassKey, interfaceKeyName.Buffer);
    04381     }
    04382
    04383     status = STATUS_SUCCESS;
    04384
    04385
    04386 clean3:
    04387     if (hControl) {
    04388         ZwClose(hControl);
    04389     }
    04390     if (hInterfaceInstanceKey) {
    04391         ZwClose(hInterfaceInstanceKey);
    04392     }
    04393     if (hInterfaceKey) {
    04394         ZwClose(hInterfaceKey);
    04395     }
    04396     if (hInterfaceClassKey) {
    04397         ZwClose(hInterfaceClassKey);
    04398     }
    04399
    04400 clean2:
    04401     ExReleaseResource(&PpRegistryDeviceResource);
    04402     KeLeaveCriticalRegion();
    04403
    04404     IopFreeAllocatedUnicodeString(&interfaceKeyName);
    04405
    04406 clean1:
    04407     IopFreeAllocatedUnicodeString(&instanceKeyName);
    04408
    04409 clean0:
    04410     return status;
    04411 }

NTSTATUS IoRegisterDeviceInterface | ( | IN PDEVICE_OBJECT | PhysicalDeviceObject,
|  | IN CONST GUID * | InterfaceClassGuid,
|  | IN PUNICODE_STRING ReferenceString | OPTIONAL,
|  | OUT PUNICODE_STRING | SymbolicLinkName
| ) |

Definition at line 3835 of file pnpioapi.c.

References ALT_SEPERATOR_CHAR, FALSE, _DEVICE_NODE::InstancePath, IopRegisterDeviceInterface(), NTSTATUS(), PAGED_CODE, SEPERATOR_CHAR, and USHORT.

    03844                    :
    03845
    03846     This device driver interface allows a WDM driver to register a particular
    03847     interface of its underlying hardware (ie PDO) as a member of a function class.
    03848
    03849 Parameters:
    03850
    03851     PhysicalDeviceObject - Supplies a pointer to the PDO for the P&P device
    03852         instance associated with the functionality being registered
    03853
    03854     InterfaceClassGuid - Supplies a pointer to the GUID representring the functionality
    03855         to be registered
    03856
    03857     ReferenceString - Optionally, supplies an additional context string which is
    03858         appended to the enumeration path of the device
    03859
    03860     SymbolicLinkName - Supplies a pointer to a string which on success will contain the
    03861         kernel mode path of the symbolic link used to open this device.
    03862
    03863 Return Value:
    03864
    03865     Status code that indicates whether or not the function was successful.
    03866
    03867 --*/
    03868
    03869 {
    03870     PDEVICE_NODE pDeviceNode;
    03871     PUNICODE_STRING pDeviceString;
    03872     NTSTATUS status;
    03873     PWSTR   pRefString;
    03874     USHORT  count;
    03875
    03876     PAGED_CODE();
    03877
    03878     //
    03879     // Until PartMgr/Disk stop registering non PDOs allow the system to boot.
    03880     //
    03881     // ASSERT_PDO(PhysicalDeviceObject);
    03882     //
    03883
    03884     //
    03885     // Ensure we have a PDO - only PDO's have a device node attached
    03886     //
    03887
    03888     pDeviceNode = (PDEVICE_NODE) PhysicalDeviceObject->DeviceObjectExtension->DeviceNode;
    03889     if (pDeviceNode) {
    03890
    03891         //
    03892         // Get the instance path string
    03893         //
    03894         pDeviceString = &pDeviceNode->InstancePath;
    03895
    03896         if (pDeviceNode->InstancePath.Length == 0) {
    03897             return STATUS_INVALID_DEVICE_REQUEST;
    03898         }
    03899
    03900         //
    03901         // Make sure the ReferenceString does not contain any path seperator characters
    03902         //
    03903         if (ReferenceString) {
    03904             pRefString = ReferenceString->Buffer;
    03905             count = ReferenceString->Length / sizeof(WCHAR);
    03906             while (count--) {
    03907                 if((*pRefString == SEPERATOR_CHAR) || (*pRefString == ALT_SEPERATOR_CHAR)) {
    03908                     status = STATUS_INVALID_DEVICE_REQUEST;
    03909                     KdPrint(("IoRegisterDeviceInterface: Invalid RefString!! failed with status = %8.8X\n", status));
    03910                     return status;
    03911                 }
    03912                 pRefString++;
    03913             }
    03914         }
    03915
    03916         return IopRegisterDeviceInterface(pDeviceString,
    03917                                           InterfaceClassGuid,
    03918                                           ReferenceString,
    03919                                           FALSE,           // kernel-mode format
    03920                                           SymbolicLinkName
    03921                                           );
    03922     } else {
    03923
    03924         return STATUS_INVALID_DEVICE_REQUEST;
    03925     }
    03926 }

NTSTATUS IoRegisterPlugPlayNotification | ( | IN IO_NOTIFICATION_EVENT_CATEGORY | EventCategory,
|  | IN ULONG | EventCategoryFlags,
|  | IN PVOID EventCategoryData | OPTIONAL,
|  | IN PDRIVER_OBJECT | DriverObject,
|  | IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE | CallbackRoutine,
|  | IN PVOID | Context,
|  | OUT PVOID * | NotificationEntry
| ) |

Definition at line 7495 of file pnpioapi.c.

References ASSERT, _DEVICE_CLASS_NOTIFY_ENTRY::Callback, _TARGET_DEVICE_NOTIFY_ENTRY::Callback, _HWPROFILE_NOTIFY_ENTRY::Callback, _SETUP_NOTIFY_DATA::Callback, _NOTIFICATION_CALLBACK_PARAM_BLOCK::Callout, _DEVICE_CLASS_NOTIFY_ENTRY::ClassGuid, _NOTIFICATION_CALLBACK_PARAM_BLOCK::Context, _DEVICE_CLASS_NOTIFY_ENTRY::Context, _TARGET_DEVICE_NOTIFY_ENTRY::Context, _HWPROFILE_NOTIFY_ENTRY::Context, _SETUP_NOTIFY_DATA::Context, DbgPrint, DEVICE_CLASS_NOTIFY_ENTRY, _DEVICE_CLASS_NOTIFY_ENTRY::DriverObject, _TARGET_DEVICE_NOTIFY_ENTRY::DriverObject, _HWPROFILE_NOTIFY_ENTRY::DriverObject, _SETUP_NOTIFY_DATA::DriverObject, _DEVICE_INTERFACE_CHANGE_NOTIFICATION::Event, _DEVICE_CLASS_NOTIFY_ENTRY::EventCategory, _TARGET_DEVICE_NOTIFY_ENTRY::EventCategory, _HWPROFILE_NOTIFY_ENTRY::EventCategory, _SETUP_NOTIFY_DATA::EventCategory, EventCategoryDeviceInterfaceChange, EventCategoryHardwareProfileChange, EventCategoryReserved, EventCategoryTargetDeviceChange, ExAllocatePool, ExFreePool(), FALSE, _TARGET_DEVICE_NOTIFY_ENTRY::FileObject, HWPROFILE_NOTIFY_ENTRY, _DEVICE_INTERFACE_CHANGE_NOTIFICATION::InterfaceClassGuid, IoDriverObjectType, IoGetDeviceInterfaces(), IopAcquireNotifyLock, IopDeferredRegistrationList, IopDeferredRegistrationLock, IopDeviceClassNotifyList, IopDeviceClassNotifyLock, IopGetRelatedTargetDevice(), IopHashGuid, IopHwProfileNotifyLock, IopPnPHydraCallback(), IopProfileNotifyList, IopReferenceNotify(), IopReleaseNotifyLock, IopSetupNotifyData, IopTargetDeviceNotifyLock, KeGetCurrentThread, KernelMode, _SETUP_NOTIFY_DATA::ListEntry, _DEVICE_CLASS_NOTIFY_ENTRY::Lock, _TARGET_DEVICE_NOTIFY_ENTRY::Lock, _HWPROFILE_NOTIFY_ENTRY::Lock, _SETUP_NOTIFY_DATA::Lock, MmDispatchWin32Callout(), _NOTIFICATION_CALLBACK_PARAM_BLOCK::NotificationStructure, _DEFERRED_REGISTRATION_ENTRY::NotifyEntry, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByPointer(), PAGED_CODE, PagedPool, PDEFERRED_REGISTRATION_ENTRY, _TARGET_DEVICE_NOTIFY_ENTRY::PhysicalDeviceObject, _DEVICE_NODE::PhysicalDeviceObject, PiNotificationInProgress, PiNotificationInProgressLock, PKWIN32_CALLOUT, PNP_NOTIFICATION_VERSION, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, _DEVICE_CLASS_NOTIFY_ENTRY::RefCount, _TARGET_DEVICE_NOTIFY_ENTRY::RefCount, _HWPROFILE_NOTIFY_ENTRY::RefCount, _SETUP_NOTIFY_DATA::RefCount, RtlInitUnicodeString(), SETUP_NOTIFY_DATA, _DEVICE_INTERFACE_CHANGE_NOTIFICATION::Size, _DEVICE_INTERFACE_CHANGE_NOTIFICATION::SymbolicLinkName, TARGET_DEVICE_NOTIFY_ENTRY, _DEVICE_NODE::TargetDeviceNotify, TRUE, _DEVICE_CLASS_NOTIFY_ENTRY::Unregistered, _TARGET_DEVICE_NOTIFY_ENTRY::Unregistered, _HWPROFILE_NOTIFY_ENTRY::Unregistered, _SETUP_NOTIFY_DATA::Unregistered, and _DEVICE_INTERFACE_CHANGE_NOTIFICATION::Version.

Referenced by DeviceClassCDROMNotify(), RegisterForDeviceChangeNotifications(), and xxxRegisterForDeviceClassNotifications().

    07506                    :
    07507
    07508     IoRegisterPlugPlayNotification provides a mechanism by which WDM drivers may
    07509     receive notification (via callback) for a variety of Plug&Play events.
    07510
    07511 Arguments:
    07512
    07513     EventCategory - Specifies the event category being registered for.  WDM drivers
    07514         may currently register for hard-ware profile changes, device class changes
    07515         (instance arrivals and removals), and target device changes (query-removal,
    07516         cancel-removal, removal-complete, as well as 3rd-party extensible events).
    07517
    07518     EventCategoryFlags - Supplies flags that modify the behavior of event registration.
    07519         There is a separate group of flags defined for each event category.  Presently,
    07520         only the interface device change event category has any flags defined:
    07521
    07522             DEVICE_CLASS_NOTIFY_FOR_EXISTING_DEVICES -- Drivers wishing to retrieve a
    07523                 complete list of all interface devices presently available, and keep
    07524                 the list up-to-date (i.e., receive notification of interface device
    07525                 arrivals and removals), may specify this flag.  This will cause the
    07526                 PnP manager to immediately notify the driver about every currently-existing
    07527                 device of the specified interface class.
    07528
    07529     EventCategoryData - Used to  'filter' events of the desired category based on the
    07530         supplied criteria.  Not all event categories will use this parameter.  The
    07531         event categories presently defined use this information as fol-lows:
    07532
    07533         EventCategoryHardwareProfileChange -- this parameter is unused, and should be NULL.
    07534         EventCategoryDeviceClassChange -- LPGUID representing the interface class of interest
    07535         EventCategoryTargetDeviceChange -- PFILE_OBJECT of interest
    07536
    07537     DriverObject - The caller must supply a reference to its driver object (obtained via
    07538         ObReferenceObject), to prevent the driver from being unloaded while registered for
    07539         notification.  The PnP Manager will dereference the driver object when the driver
    07540         unregisters for notification via IoUnregisterPlugPlayNotification).
    07541
    07542     CallbackRoutine - Entry point within the driver that the PnP manager should call
    07543         whenever an applicable PnP event occurs.  The entry point must have the
    07544         following prototype:
    07545
    07546             typedef
    07547             NTSTATUS
    07548             (*PDRIVER_NOTIFICATION_CALLBACK_ROUTINE) (
    07549                 IN PVOID NotificationStructure,
    07550                 IN PVOID Context
    07551                 );
    07552
    07553         where NotificationStructure contains information about the event.  Each event
    07554         GUID within an event category may potentially have its own notification structure
    07555         format, but the buffer must al-ways begin with a PLUGPLAY_NOTIFICATION_HEADER,
    07556         which indicates the size and ver-sion of the structure, as well as the GUID for
    07557         the event.
    07558
    07559         The Context parameter provides the callback with the same context data that the
    07560         caller passed in during registration.
    07561
    07562     Context - Points to the context data passed to the callback upon event notification.
    07563
    07564     NotificationEntry - Upon success, receives a handle representing the notification
    07565         registration.  This handle may be used to unregister for notification via
    07566         IoUnregisterPlugPlayNotification.
    07567
    07568 --*/
    07569 {
    07570
    07571     NTSTATUS status = STATUS_SUCCESS;
    07572 #if DBG
    07573     ULONG originalApcDisable;
    07574 #endif
    07575
    07576     PAGED_CODE();
    07577
    07578     ASSERT(NotificationEntry);
    07579
    07580     //
    07581     // Initialize out parameters
    07582     //
    07583
    07584     *NotificationEntry = NULL;
    07585
    07586     //
    07587     // Reference the driver object so it doesn't go away while we still have
    07588     // a pointer outstanding
    07589     //
    07590     status = ObReferenceObjectByPointer(DriverObject,
    07591                                         0,
    07592                                         IoDriverObjectType,
    07593                                         KernelMode
    07594                                         );
    07595
    07596     if (!NT_SUCCESS(status)) {
    07597         return status;
    07598     }
    07599
    07600     switch (EventCategory) {
    07601
    07602     case EventCategoryReserved:
    07603         {
    07604
    07605             PSETUP_NOTIFY_DATA setupData;
    07606
    07607             //
    07608             // Allocate space for the setup data
    07609             //
    07610
    07611             setupData = ExAllocatePool(PagedPool, sizeof(SETUP_NOTIFY_DATA));
    07612             if (!setupData) {
    07613                 status = STATUS_INSUFFICIENT_RESOURCES;
    07614                 goto clean0;
    07615             }
    07616
    07617             //
    07618             // Store the required information
    07619             //
    07620             InitializeListHead(&(setupData->ListEntry));
    07621             setupData->EventCategory = EventCategory;
    07622             setupData->Callback = CallbackRoutine;
    07623             setupData->Context = Context;
    07624             setupData->RefCount = 1;
    07625             setupData->Unregistered = FALSE;
    07626             setupData->Lock = NULL;
    07627             setupData->DriverObject = DriverObject;
    07628
    07629             //
    07630             // Activate the notifications
    07631             //
    07632
    07633             IopSetupNotifyData = setupData;
    07634
    07635             //
    07636             // Explicitly NULL out the returned entry as you can *NOT* unregister
    07637             // for setup notifications
    07638             //
    07639
    07640             *NotificationEntry = NULL;
    07641
    07642             break;
    07643
    07644         }
    07645
    07646     case EventCategoryHardwareProfileChange:
    07647         {
    07648             PHWPROFILE_NOTIFY_ENTRY entry;
    07649
    07650             //
    07651             // new entry
    07652             //
    07653             entry =ExAllocatePool (PagedPool,sizeof (HWPROFILE_NOTIFY_ENTRY));
    07654             if (!entry) {
    07655                 status = STATUS_INSUFFICIENT_RESOURCES;
    07656                 goto clean0;
    07657             }
    07658
    07659             //
    07660             // grab the fields
    07661             //
    07662
    07663             entry->EventCategory = EventCategory;
    07664             entry->Callback = CallbackRoutine;
    07665             entry->Context = Context;
    07666             entry->RefCount = 1;
    07667             entry->Unregistered = FALSE;
    07668             entry->Lock = &IopHwProfileNotifyLock;
    07669             entry->DriverObject = DriverObject;
    07670
    07671             ExAcquireFastMutex(&PiNotificationInProgressLock);
    07672             if (PiNotificationInProgress) {
    07673                 //
    07674                 // If a notification is in progress, mark the entry as
    07675                 // Unregistered until after the current notification is
    07676                 // complete.
    07677                 //
    07678
    07679                 PDEFERRED_REGISTRATION_ENTRY deferredNode;
    07680
    07681                 deferredNode = ExAllocatePool(PagedPool, sizeof(DEFERRED_REGISTRATION_ENTRY));
    07682                 if (!deferredNode) {
    07683                     ExReleaseFastMutex(&PiNotificationInProgressLock);
    07684                     status = STATUS_INSUFFICIENT_RESOURCES;
    07685                     goto clean0;
    07686                 }
    07687
    07688                 deferredNode->NotifyEntry = (PNOTIFY_ENTRY_HEADER)entry;
    07689
    07690                 //
    07691                 // Consider this entry unregistered during the current
    07692                 // notification
    07693                 //
    07694                 entry->Unregistered = TRUE;
    07695
    07696                 //
    07697                 // Reference the entry so that it doesn't go away until it has
    07698                 // been removed from the deferred registration list
    07699                 //
    07700                 IopReferenceNotify((PNOTIFY_ENTRY_HEADER)entry);
    07701
    07702                 //
    07703                 // Add this entry to the deferred registration list
    07704                 //
    07705                 IopAcquireNotifyLock(&IopDeferredRegistrationLock);
    07706                 InsertTailList(&IopDeferredRegistrationList, (PLIST_ENTRY)deferredNode);
    07707                 IopReleaseNotifyLock(&IopDeferredRegistrationLock);
    07708             } else {
    07709                 //
    07710                 // If there is currently no notification in progress, the deferred
    07711                 // registration list must be empty.
    07712                 //
    07713                 ASSERT(IsListEmpty(&IopDeferredRegistrationList));
    07714             }
    07715             ExReleaseFastMutex(&PiNotificationInProgressLock);
    07716
    07717             //
    07718             // Lock the list, insert the new entry, and unlock it.
    07719             //
    07720
    07721             IopAcquireNotifyLock(&IopHwProfileNotifyLock);
    07722             InsertTailList(&IopProfileNotifyList, (PLIST_ENTRY)entry);
    07723             IopReleaseNotifyLock(&IopHwProfileNotifyLock);
    07724
    07725             *NotificationEntry = entry;
    07726
    07727             break;
    07728         }
    07729     case EventCategoryTargetDeviceChange:
    07730         {
    07731             PTARGET_DEVICE_NOTIFY_ENTRY entry;
    07732             IO_STACK_LOCATION irpSp;
    07733             PDEVICE_NODE deviceNode;
    07734
    07735             ASSERT(EventCategoryData);
    07736
    07737             //
    07738             // Allocate a new list entry
    07739             //
    07740
    07741             entry = ExAllocatePool(PagedPool, sizeof(TARGET_DEVICE_NOTIFY_ENTRY));
    07742             if (!entry) {
    07743                 status = STATUS_INSUFFICIENT_RESOURCES;
    07744                 goto clean0;
    07745             }
    07746
    07747             //
    07748             // Retrieve the device object associated with this file handle.
    07749             //
    07750             status = IopGetRelatedTargetDevice((PFILE_OBJECT)EventCategoryData,
    07751                                                &deviceNode);
    07752             if (!NT_SUCCESS(status)) {
    07753                 ExFreePool(entry);
    07754                 goto clean0;
    07755             }
    07756
    07757             //
    07758             // Fill out the entry
    07759             //
    07760
    07761             entry->EventCategory = EventCategory;
    07762             entry->Callback = CallbackRoutine;
    07763             entry->Context = Context;
    07764             entry->DriverObject = DriverObject;
    07765             entry->RefCount = 1;
    07766             entry->Unregistered = FALSE;
    07767             entry->Lock = &IopTargetDeviceNotifyLock;
    07768             entry->FileObject = (PFILE_OBJECT)EventCategoryData;
    07769
    07770             //
    07771             // The PDO associated with the devnode we got back from
    07772             // IopGetRelatedTargetDevice has already been referenced by that
    07773             // routine.  Store this reference away in the notification entry,
    07774             // so we can deref it later when the notification entry is unregistered.
    07775             //
    07776
    07777             ASSERT(deviceNode->PhysicalDeviceObject);
    07778             entry->PhysicalDeviceObject = deviceNode->PhysicalDeviceObject;
    07779
    07780             ExAcquireFastMutex(&PiNotificationInProgressLock);
    07781             if (PiNotificationInProgress) {
    07782                 //
    07783                 // If a notification is in progress, mark the entry as
    07784                 // Unregistered until after the current notification is
    07785                 // complete.
    07786                 //
    07787
    07788                 PDEFERRED_REGISTRATION_ENTRY deferredNode;
    07789
    07790                 deferredNode = ExAllocatePool(PagedPool, sizeof(DEFERRED_REGISTRATION_ENTRY));
    07791                 if (!deferredNode) {
    07792                     ExReleaseFastMutex(&PiNotificationInProgressLock);
    07793                     status = STATUS_INSUFFICIENT_RESOURCES;
    07794                     goto clean0;
    07795                 }
    07796
    07797                 deferredNode->NotifyEntry = (PNOTIFY_ENTRY_HEADER)entry;
    07798
    07799                 //
    07800                 // Consider this entry unregistered during the current
    07801                 // notification
    07802                 //
    07803                 entry->Unregistered = TRUE;
    07804
    07805                 //
    07806                 // Reference the entry so that it doesn't go away until it has
    07807                 // been removed from the deferred registration list
    07808                 //
    07809                 IopReferenceNotify((PNOTIFY_ENTRY_HEADER)entry);
    07810
    07811                 //
    07812                 // Add this entry to the deferred registration list
    07813                 //
    07814                 IopAcquireNotifyLock(&IopDeferredRegistrationLock);
    07815                 InsertTailList(&IopDeferredRegistrationList, (PLIST_ENTRY)deferredNode);
    07816                 IopReleaseNotifyLock(&IopDeferredRegistrationLock);
    07817             } else {
    07818                 //
    07819                 // If there is currently no notification in progress, the deferred
    07820                 // registration list must be empty.
    07821                 //
    07822                 ASSERT(IsListEmpty(&IopDeferredRegistrationList));
    07823             }
    07824             ExReleaseFastMutex(&PiNotificationInProgressLock);
    07825
    07826             //
    07827             // Lock the list, insert the new entry, and unlock it.
    07828             //
    07829
    07830             IopAcquireNotifyLock(&IopTargetDeviceNotifyLock);
    07831             InsertTailList(&deviceNode->TargetDeviceNotify, (PLIST_ENTRY)entry);
    07832             IopReleaseNotifyLock(&IopTargetDeviceNotifyLock);
    07833
    07834             *NotificationEntry = entry;
    07835             break;
    07836         }
    07837
    07838     case EventCategoryDeviceInterfaceChange:
    07839         {
    07840             PDEVICE_CLASS_NOTIFY_ENTRY entry;
    07841
    07842             ASSERT(EventCategoryData);
    07843
    07844             //
    07845             // Allocate a new list entry
    07846             //
    07847
    07848             entry = ExAllocatePool(PagedPool, sizeof(DEVICE_CLASS_NOTIFY_ENTRY));
    07849             if (!entry) {
    07850                 status = STATUS_INSUFFICIENT_RESOURCES;
    07851                 goto clean0;
    07852             }
    07853
    07854             //
    07855             // Fill out the entry
    07856             //
    07857
    07858             entry->EventCategory = EventCategory;
    07859             entry->Callback = CallbackRoutine;
    07860             entry->Context = Context;
    07861             entry->ClassGuid = *((LPGUID) EventCategoryData);
    07862             entry->RefCount = 1;
    07863             entry->Unregistered = FALSE;
    07864             entry->Lock = &IopDeviceClassNotifyLock;
    07865             entry->DriverObject = DriverObject;
    07866
    07867             ExAcquireFastMutex(&PiNotificationInProgressLock);
    07868             if (PiNotificationInProgress) {
    07869                 //
    07870                 // If a notification is in progress, mark the entry as
    07871                 // Unregistered until after the current notification is
    07872                 // complete.
    07873                 //
    07874
    07875                 PDEFERRED_REGISTRATION_ENTRY deferredNode;
    07876
    07877                 deferredNode = ExAllocatePool(PagedPool, sizeof(DEFERRED_REGISTRATION_ENTRY));
    07878                 if (!deferredNode) {
    07879                     ExReleaseFastMutex(&PiNotificationInProgressLock);
    07880                     status = STATUS_INSUFFICIENT_RESOURCES;
    07881                     goto clean0;
    07882                 }
    07883
    07884                 deferredNode->NotifyEntry = (PNOTIFY_ENTRY_HEADER)entry;
    07885
    07886                 //
    07887                 // Consider this entry unregistered during the current
    07888                 // notification
    07889                 //
    07890                 entry->Unregistered = TRUE;
    07891
    07892                 //
    07893                 // Reference the entry so that it doesn't go away until it has
    07894                 // been removed from the deferred registration list
    07895                 //
    07896                 IopReferenceNotify((PNOTIFY_ENTRY_HEADER)entry);
    07897
    07898                 //
    07899                 // Add this entry to the deferred registration list
    07900                 //
    07901                 IopAcquireNotifyLock(&IopDeferredRegistrationLock);
    07902                 InsertTailList(&IopDeferredRegistrationList, (PLIST_ENTRY)deferredNode);
    07903                 IopReleaseNotifyLock(&IopDeferredRegistrationLock);
    07904             } else {
    07905                 //
    07906                 // If there is currently no notification in progress, the deferred
    07907                 // registration list must be empty.
    07908                 //
    07909                 ASSERT(IsListEmpty(&IopDeferredRegistrationList));
    07910             }
    07911             ExReleaseFastMutex(&PiNotificationInProgressLock);
    07912
    07913             //
    07914             // Lock the list
    07915             //
    07916
    07917             IopAcquireNotifyLock(&IopDeviceClassNotifyLock);
    07918
    07919             //
    07920             // Insert it at the tail
    07921             //
    07922
    07923             InsertTailList( (PLIST_ENTRY) &(IopDeviceClassNotifyList[ IopHashGuid(&(entry->ClassGuid)) ]),
    07924                             (PLIST_ENTRY) entry
    07925                           );
    07926
    07927             //
    07928             // Unlock the list
    07929             //
    07930
    07931             IopReleaseNotifyLock(&IopDeviceClassNotifyLock);
    07932
    07933             //
    07934             // See if we need to notify for all the device classes already present
    07935             //
    07936
    07937             if (EventCategoryFlags & PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES) {
    07938
    07939                 PWCHAR pSymbolicLinks, pCurrent;
    07940                 DEVICE_INTERFACE_CHANGE_NOTIFICATION notification;
    07941                 UNICODE_STRING unicodeString;
    07942
    07943                 //
    07944                 // Fill in the notification structure
    07945                 //
    07946
    07947                 notification.Version = PNP_NOTIFICATION_VERSION;
    07948                 notification.Size = sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION);
    07949                 notification.Event = GUID_DEVICE_INTERFACE_ARRIVAL;
    07950                 notification.InterfaceClassGuid = entry->ClassGuid;
    07951
    07952                 //
    07953                 // Get the list of all the devices of this function class that are
    07954                 // already in the system
    07955                 //
    07956
    07957                 status = IoGetDeviceInterfaces(&(entry->ClassGuid),
    07958                                                 NULL,
    07959                                                 0,
    07960                                                 &pSymbolicLinks
    07961                                                 );
    07962                 if (!NT_SUCCESS(status)) {
    07963                     //
    07964                     // No buffer will have been returned so just return status
    07965                     //
    07966                     goto clean0;
    07967                 }
    07968
    07969                 //
    07970                 // Callback for each device currently in the system
    07971                 //
    07972
    07973                 pCurrent = pSymbolicLinks;
    07974                 while(*pCurrent != UNICODE_NULL) {
    07975                     NOTIFICATION_CALLBACK_PARAM_BLOCK callparams;
    07976                     ULONG Console=0;
    07977
    07978                     RtlInitUnicodeString(&unicodeString, pCurrent);
    07979                     notification.SymbolicLinkName = &unicodeString;
    07980
    07981 #if DBG
    07982                     originalApcDisable = KeGetCurrentThread()->KernelApcDisable;
    07983 #endif
    07984                     //
    07985                     // Call back on the registered notification routine
    07986                     //
    07987                     callparams.Callout=(*CallbackRoutine);
    07988                     callparams.NotificationStructure=&notification;
    07989                     callparams.Context=Context;
    07990
    07991
    07992                     //
    07993                     // Dispatch this function via the memory manager.
    07994                     // Win32K is a driver that can have multiple copies. If Hydra
    07995                     // is running, the Mem. manager will check if the callback exists
    07996                     // in "per session" space. If that is the case, it will attach to the
    07997                     // console (hence the 3rd param of PULONG containing 0) session and deliver
    07998                     // it. If either Hydra is not running, or the callback is outside session space
    07999                     // then the callback is called directly.
    08000                     //
    08001                     MmDispatchWin32Callout ((PKWIN32_CALLOUT)callparams.Callout,&IopPnPHydraCallback,&callparams,&Console);
    08002
    08003 #if DBG
    08004                     if (originalApcDisable != KeGetCurrentThread()->KernelApcDisable) {
    08005                         DbgPrint("IoRegisterPlugPlayNotification: Driver %Z, notification handler @ 0x%p returned with different KernelApcDisable = %d, original = %d\n",
    08006                                  &entry->DriverObject->DriverName, entry->Callback, KeGetCurrentThread()->KernelApcDisable, originalApcDisable);
    08007                         DbgBreakPoint();
    08008                     }
    08009 #endif
    08010
    08011                     pCurrent += (unicodeString.Length / sizeof(WCHAR)) + 1;
    08012
    08013                 }
    08014
    08015                 ExFreePool(pSymbolicLinks);
    08016
    08017             }
    08018
    08019             *NotificationEntry = entry;
    08020         }
    08021
    08022         break;
    08023     }
    08024
    08025 clean0:
    08026
    08027     if (!NT_SUCCESS(status)) {
    08028         ObDereferenceObject(DriverObject);
    08029     }
    08030
    08031     return status;
    08032 }

NTSTATUS IoReportDetectedDevice | ( | IN PDRIVER_OBJECT | DriverObject,
|  | IN INTERFACE_TYPE | LegacyBusType,
|  | IN ULONG | BusNumber,
|  | IN ULONG | SlotNumber,
|  | IN PCM_RESOURCE_LIST | ResourceList,
|  | IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements | OPTIONAL,
|  | IN BOOLEAN | ResourceAssigned,
|  | IN OUT PDEVICE_OBJECT * | DeviceObject
| ) |

Definition at line 1548 of file pnpioapi.c.

References ArbiterRequestLegacyReported, ASSERT, BusNumber, CmRegistryMachineSystemCurrentControlSetEnumName, _DEVOBJ_EXTENSION::DeviceNode, _DEVICE_OBJECT::DeviceObjectExtension, DNF_ADDED, DNF_ENUMERATED, DNF_HAS_PROBLEM, DNF_MADEUP, DNF_NEED_ENUMERATION_ONLY, DNF_NEED_QUERY_IDS, DNF_NO_RESOURCE_REQUIRED, DNF_PROCESSED, DNF_STARTED, DO_BUS_ENUMERATED_DEVICE, DRVO_BUILTIN_DRIVER, ExAcquireResourceShared, ExAllocatePool, ExFreePool(), exit, ExReleaseResource, FALSE, _DEVICE_OBJECT::Flags, _DEVICE_NODE::Flags, _DEVICE_NODE::InstancePath, IoCreateDevice(), IoDeleteDevice(), IopAllocateDeviceNode(), IopConcatenateUnicodeStrings(), IopCreateRegistryKeyEx(), IopDeleteLegacyKey(), IopDetermineResourceListSize(), IopDeviceObjectFromDeviceInstance(), IopDeviceObjectToDeviceInstance(), IopDoDeferredSetInterfaceState(), IopDoesDevNodeHaveProblem, IopDuplicateDetection(), IopInsertTreeDeviceNode(), IopIsReportedAlready(), IopNotifySetupDeviceArrival(), IoPnpDriverObject, IopNumberDeviceNodes, IopOpenRegistryKeyEx(), IopReleaseDeviceResources(), IopRootDeviceNode, IopSetDevNodeProblem, IopWriteAllocatedResourcesToRegistry(), IoReportResourceUsageInternal(), KeEnterCriticalRegion, KeLeaveCriticalRegion, KeQueryTickCount(), L, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObject, PAGED_CODE, PagedPool, _DEVICE_NODE::PhysicalDeviceObject, PpCreateLegacyDeviceIds(), PpDeviceRegistration(), PpRegistryDeviceResource, _DEVICE_NODE::Problem, RtlInitUnicodeString(), _DEVICE_NODE::ServiceName, TITLE_INDEX_VALUE, TRUE, and USHORT.

    01561                    :
    01562
    01563     PnP device drivers call this API to report any device detected.  This routine
    01564     creates a Physical Device object, reference the Physical Device object and
    01565     returns back to the callers.  Once the detected device is reported, the Pnp manager
    01566     considers the device has been fully controlled by the reporting drivers.  Thus it
    01567     will not invoke AddDevice entry and send StartDevice irp to the driver.
    01568
    01569     The driver needs to report the resources it used to detect this device such that
    01570     pnp manager can perform duplicates detection on this device.
    01571
    01572     The caller must dereference the DeviceObject once it no longer needs it.
    01573
    01574 Parameters:
    01575
    01576     DriverObject - Supplies the driver object of the driver who detected
    01577                    this device.
    01578
    01579     ResourceList - Supplies a pointer to the resource list which the driver used
    01580                    to detect the device.
    01581
    01582     ResourceRequirements - supplies a pointer to the resource requirements list
    01583                    for the detected device.  This is optional.
    01584
    01585     ResourceAssigned - if TRUE, the driver already called IoReportResourceUsage or
    01586                    IoAssignResource to get the ownership of the resources.  Otherwise,
    01587                    the PnP manager will call IoReportResourceUsage to allocate the
    01588                    resources for the driver.
    01589
    01590     DeviceObject - if NULL, this routine will create a PDO and return it thru this variable.
    01591                    Otherwise, a PDO is already created and this routine will simply use the supplied
    01592                    PDO.
    01593
    01594 Return Value:
    01595
    01596     Status code that indicates whether or not the function was successful.
    01597
    01598
    01599 --*/
    01600
    01601 {
    01602     WCHAR buffer[60];
    01603     NTSTATUS status;
    01604     UNICODE_STRING deviceName, instanceName, unicodeName, *serviceName, driverName;
    01605     PDEVICE_NODE deviceNode;
    01606     ULONG length, i = 0, disposition, tmpValue, listSize = 0;
    01607     HANDLE handle, handle1, logConfHandle, controlHandle, hTreeHandle, enumHandle;
    01608     PCM_RESOURCE_LIST cmResource;
    01609     PWSTR p;
    01610     LARGE_INTEGER tickCount;
    01611     PDEVICE_OBJECT deviceObject;
    01612     BOOLEAN newlyCreated = FALSE;
    01613
    01614     PAGED_CODE();
    01615
    01616     if (*DeviceObject) {
    01617
    01618         deviceObject = *DeviceObject;
    01619
    01620         //
    01621         // The PDO is already known. simply handle the resourcelist and resreq list.
    01622         // This is a hack for NDIS drivers.
    01623         //
    01624         deviceNode = (PDEVICE_NODE)(*DeviceObject)->DeviceObjectExtension->DeviceNode;
    01625         if (!deviceNode) {
    01626             return STATUS_NO_SUCH_DEVICE;
    01627         }
    01628
    01629         KeEnterCriticalRegion();
    01630         ExAcquireResourceShared(&PpRegistryDeviceResource, TRUE);
    01631
    01632         //
    01633         // Write ResourceList and ResReq list to the device instance
    01634         //
    01635
    01636         status = IopDeviceObjectToDeviceInstance (*DeviceObject,
    01637                                                   &handle,
    01638                                                   KEY_ALL_ACCESS
    01639                                                   );
    01640         if (!NT_SUCCESS(status)) {
    01641             ExReleaseResource(&PpRegistryDeviceResource);
    01642             KeLeaveCriticalRegion();
    01643             return status;
    01644         }
    01645         if (ResourceAssigned) {
    01646             RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_NO_RESOURCE_AT_INIT);
    01647             tmpValue = 1;
    01648             ZwSetValueKey(handle,
    01649                           &unicodeName,
    01650                           TITLE_INDEX_VALUE,
    01651                           REG_DWORD,
    01652                           &tmpValue,
    01653                           sizeof(tmpValue)
    01654                           );
    01655         }
    01656         RtlInitUnicodeString(&unicodeName, REGSTR_KEY_LOG_CONF);
    01657         status = IopCreateRegistryKeyEx( &logConfHandle,
    01658                                          handle,
    01659                                          &unicodeName,
    01660                                          KEY_ALL_ACCESS,
    01661                                          REG_OPTION_NON_VOLATILE,
    01662                                          NULL
    01663                                          );
    01664         ZwClose(handle);
    01665         if (NT_SUCCESS(status)) {
    01666
    01667             //
    01668             // Write the ResourceList and and ResourceRequirements to the logconf key under
    01669             // device instance key.
    01670             //
    01671
    01672             if (ResourceList) {
    01673                 RtlInitUnicodeString(&unicodeName, REGSTR_VAL_BOOTCONFIG);
    01674                 ZwSetValueKey(
    01675                           logConfHandle,
    01676                           &unicodeName,
    01677                           TITLE_INDEX_VALUE,
    01678                           REG_RESOURCE_LIST,
    01679                           ResourceList,
    01680                           listSize = IopDetermineResourceListSize(ResourceList)
    01681                           );
    01682             }
    01683             if (ResourceRequirements) {
    01684                 RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_BASIC_CONFIG_VECTOR);
    01685                 ZwSetValueKey(
    01686                           logConfHandle,
    01687                           &unicodeName,
    01688                           TITLE_INDEX_VALUE,
    01689                           REG_RESOURCE_REQUIREMENTS_LIST,
    01690                           ResourceRequirements,
    01691                           ResourceRequirements->ListSize
    01692                           );
    01693             }
    01694             ZwClose(logConfHandle);
    01695         }
    01696         ExReleaseResource(&PpRegistryDeviceResource);
    01697         KeLeaveCriticalRegion();
    01698         if (NT_SUCCESS(status)) {
    01699             goto checkResource;
    01700         } else {
    01701             return status;
    01702         }
    01703     }
    01704
    01705     //
    01706     // Normal case: *DeviceObject is NULL
    01707     //
    01708
    01709     *DeviceObject = NULL;
    01710     serviceName = &DriverObject->DriverExtension->ServiceKeyName;
    01711
    01712     //
    01713     // Special handling for driver object created thru IoCreateDriver.
    01714     // When a builtin driver calls IoReportDetectedDevice, the ServiceKeyName of
    01715     // the driver object is set to \Driver\DriverName.  To create a detected device
    01716     // instance key, we will take only the DriverName.
    01717     //
    01718
    01719     if (DriverObject->Flags & DRVO_BUILTIN_DRIVER) {
    01720         p = serviceName->Buffer + (serviceName->Length / sizeof(WCHAR)) - 1;
    01721         driverName.Length = 0;
    01722         while (*p != '\\' && (p != serviceName->Buffer)) {
    01723             p--;
    01724             driverName.Length += sizeof(WCHAR);
    01725         }
    01726         if (p == serviceName->Buffer) {
    01727             return STATUS_UNSUCCESSFUL;
    01728         } else {
    01729             p++;
    01730             driverName.Buffer = p;
    01731             driverName.MaximumLength = driverName.Length + sizeof(WCHAR);
    01732         }
    01733     } else {
    01734
    01735         //
    01736         // Before doing anything first perform duplicate detection
    01737         //
    01738
    01739         status = IopDuplicateDetection(
    01740                      LegacyBusType,
    01741                      BusNumber,
    01742                      SlotNumber,
    01743                      &deviceNode
    01744                  );
    01745
    01746         if (NT_SUCCESS(status) && deviceNode) {
    01747             deviceObject = deviceNode->PhysicalDeviceObject;
    01748             if ((deviceNode->Flags & DNF_ADDED) ||
    01749                 (IopDoesDevNodeHaveProblem(deviceNode) &&
    01750                  deviceNode->Problem != CM_PROB_NOT_CONFIGURED &&
    01751                  deviceNode->Problem != CM_PROB_REINSTALL &&
    01752                  deviceNode->Problem != CM_PROB_FAILED_INSTALL)) {
    01753
    01754                 //
    01755                 // BUGBUG: This assumption may not be true.
    01756                 //
    01757
    01758                 ObDereferenceObject(deviceObject);
    01759
    01760                 return STATUS_NO_SUCH_DEVICE;
    01761             }
    01762
    01763             deviceNode->Flags &= ~DNF_HAS_PROBLEM;
    01764             deviceNode->Problem = 0;
    01765
    01766             IopDeleteLegacyKey(DriverObject);
    01767             goto checkResource;
    01768         }
    01769
    01770     }
    01771
    01772     //
    01773     // Create a PDO and its DeviceNode
    01774     //
    01775
    01776     //
    01777     // Madeup a name for the device object.
    01778     //
    01779
    01780     KeQueryTickCount(&tickCount);
    01781     length = _snwprintf(buffer, sizeof(buffer) / sizeof(WCHAR), L"\\Device\\%04u%x", IopNumberDeviceNodes, tickCount.LowPart);
    01782     deviceName.MaximumLength = sizeof(buffer);
    01783     deviceName.Length = (USHORT)(length * sizeof(WCHAR));
    01784     deviceName.Buffer = buffer;                                                           \
    01785
    01786     status = IoCreateDevice( IoPnpDriverObject,
    01787                              sizeof(IOPNP_DEVICE_EXTENSION),
    01788                              &deviceName,
    01789                              FILE_DEVICE_CONTROLLER,
    01790                              0,
    01791                              FALSE,
    01792                              &deviceObject );
    01793
    01794     if (NT_SUCCESS(status)) {
    01795         deviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;   // Mark this is a PDO
    01796         deviceNode = IopAllocateDeviceNode(deviceObject);
    01797         if (deviceNode) {
    01798
    01799             //
    01800             // First delete the Legacy_DriverName key and subkeys from Enum\Root, if exits.
    01801             //
    01802
    01803             if (!(DriverObject->Flags & DRVO_BUILTIN_DRIVER)) {
    01804                 IopDeleteLegacyKey(DriverObject);
    01805             }
    01806
    01807             //
    01808             // Create the compatible id list we'll use for this made-up device.
    01809             //
    01810
    01811             status = PpCreateLegacyDeviceIds(
    01812                         deviceObject,
    01813                         ((DriverObject->Flags & DRVO_BUILTIN_DRIVER) ?
    01814                             &driverName : serviceName),
    01815                         ResourceList);
    01816
    01817             if(!NT_SUCCESS(status)) {
    01818                 goto exit;
    01819             }
    01820
    01821             //
    01822             // Create/Open a registry key for the device instance and
    01823             // write the addr of the device object to registry
    01824             //
    01825
    01826             if (DriverObject->Flags & DRVO_BUILTIN_DRIVER) {
    01827                 length = _snwprintf(buffer, sizeof(buffer) / sizeof(WCHAR), L"ROOT\\%s", driverName.Buffer);
    01828             } else {
    01829                 length = _snwprintf(buffer, sizeof(buffer) / sizeof(WCHAR), L"ROOT\\%s", serviceName->Buffer);
    01830             }
    01831             deviceName.MaximumLength = sizeof(buffer);
    01832             ASSERT(length <= sizeof(buffer) - 10);
    01833             deviceName.Length = (USHORT)(length * sizeof(WCHAR));
    01834             deviceName.Buffer = buffer;
    01835
    01836             KeEnterCriticalRegion();
    01837             ExAcquireResourceShared(&PpRegistryDeviceResource, TRUE);
    01838
    01839             status = IopOpenRegistryKeyEx( &enumHandle,
    01840                                            NULL,
    01841                                            &CmRegistryMachineSystemCurrentControlSetEnumName,
    01842                                            KEY_ALL_ACCESS
    01843                                            );
    01844             if (!NT_SUCCESS(status)) {
    01845                 goto exit;
    01846             }
    01847
    01848             status = IopCreateRegistryKeyEx( &handle1,
    01849                                              enumHandle,
    01850                                              &deviceName,
    01851                                              KEY_ALL_ACCESS,
    01852                                              REG_OPTION_NON_VOLATILE,
    01853                                              &disposition
    01854                                              );
    01855
    01856             if (NT_SUCCESS(status)) {
    01857                 deviceName.Buffer[deviceName.Length / sizeof(WCHAR)] =
    01858                            OBJ_NAME_PATH_SEPARATOR;
    01859                 deviceName.Length += sizeof(WCHAR);
    01860                 if (disposition != REG_CREATED_NEW_KEY) {
    01861                     while (TRUE) {
    01862                         PiUlongToInstanceKeyUnicodeString(&instanceName,
    01863                                                           buffer + deviceName.Length / sizeof(WCHAR),
    01864                                                           sizeof(buffer) - deviceName.Length,
    01865                                                           i
    01866                                                           );
    01867                         status = IopCreateRegistryKeyEx( &handle,
    01868                                                          handle1,
    01869                                                          &instanceName,
    01870                                                          KEY_ALL_ACCESS,
    01871                                                          REG_OPTION_NON_VOLATILE,
    01872                                                          &disposition
    01873                                                          );
    01874                         if (NT_SUCCESS(status)) {
    01875                             if (disposition == REG_CREATED_NEW_KEY) {
    01876                                 ZwClose(handle1);
    01877                                 break;
    01878                             } else {
    01879                                 if (IopIsReportedAlready(handle, serviceName, ResourceList)) {
    01880
    01881                                     //
    01882                                     // Write the reported resources to registry in case the irq changed
    01883                                     //
    01884
    01885                                     RtlInitUnicodeString(&unicodeName, REGSTR_KEY_LOG_CONF);
    01886                                     status = IopCreateRegistryKeyEx( &logConfHandle,
    01887                                                                      handle,
    01888                                                                      &unicodeName,
    01889                                                                      KEY_ALL_ACCESS,
    01890                                                                      REG_OPTION_NON_VOLATILE,
    01891                                                                      NULL
    01892                                                                      );
    01893                                     if (NT_SUCCESS(status)) {
    01894
    01895                                         //
    01896                                         // Write the ResourceList and and ResourceRequirements to the device instance key
    01897                                         //
    01898
    01899                                         if (ResourceList) {
    01900                                             RtlInitUnicodeString(&unicodeName, REGSTR_VAL_BOOTCONFIG);
    01901                                             ZwSetValueKey(
    01902                                                       logConfHandle,
    01903                                                       &unicodeName,
    01904                                                       TITLE_INDEX_VALUE,
    01905                                                       REG_RESOURCE_LIST,
    01906                                                       ResourceList,
    01907                                                       listSize = IopDetermineResourceListSize(ResourceList)
    01908                                                       );
    01909                                         }
    01910                                         if (ResourceRequirements) {
    01911                                             RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_BASIC_CONFIG_VECTOR);
    01912                                             ZwSetValueKey(
    01913                                                       logConfHandle,
    01914                                                       &unicodeName,
    01915                                                       TITLE_INDEX_VALUE,
    01916                                                       REG_RESOURCE_REQUIREMENTS_LIST,
    01917                                                       ResourceRequirements,
    01918                                                       ResourceRequirements->ListSize
    01919                                                       );
    01920                                         }
    01921                                         ZwClose(logConfHandle);
    01922                                     }
    01923
    01924                                     ExReleaseResource(&PpRegistryDeviceResource);
    01925                                     KeLeaveCriticalRegion();
    01926                                     IoDeleteDevice(deviceObject);
    01927                                     ZwClose(handle1);
    01928                                     deviceObject = IopDeviceObjectFromDeviceInstance (
    01929                                                            handle, NULL);  // Add a reference
    01930                                     ZwClose(handle);
    01931                                     ZwClose(enumHandle);
    01932                                     ASSERT(deviceObject);
    01933                                     if (deviceObject == NULL) {
    01934                                         status = STATUS_UNSUCCESSFUL;
    01935                                         return status;
    01936                                     }
    01937                                     deviceNode = (PDEVICE_NODE)
    01938                                                   deviceObject->DeviceObjectExtension->DeviceNode;
    01939                                     goto checkResource;
    01940                                 } else {
    01941                                     i++;
    01942                                     ZwClose(handle);
    01943                                     continue;
    01944                                 }
    01945                             }
    01946                         } else {
    01947                             ZwClose(handle1);
    01948                             ZwClose(enumHandle);
    01949                             goto exit;
    01950                         }
    01951                     }
    01952                 } else {
    01953
    01954                     //
    01955                     // This is a new device key.  So, instance is 0.  Create it.
    01956                     //
    01957
    01958                     PiUlongToInstanceKeyUnicodeString(&instanceName,
    01959                                                       buffer + deviceName.Length / sizeof(WCHAR),
    01960                                                       sizeof(buffer) - deviceName.Length,
    01961                                                       i
    01962                                                       );
    01963                     status = IopCreateRegistryKeyEx( &handle,
    01964                                                      handle1,
    01965                                                      &instanceName,
    01966                                                      KEY_ALL_ACCESS,
    01967                                                      REG_OPTION_NON_VOLATILE,
    01968                                                      &disposition
    01969                                                      );
    01970                     ZwClose(handle1);
    01971                     if (!NT_SUCCESS(status)) {
    01972                         ZwClose(enumHandle);
    01973                         goto exit;
    01974                     }
    01975                     ASSERT(disposition == REG_CREATED_NEW_KEY);
    01976                 }
    01977             } else {
    01978                 ZwClose(enumHandle);
    01979                 goto exit;
    01980             }
    01981
    01982             deviceName.Length += instanceName.Length;
    01983             ASSERT(disposition == REG_CREATED_NEW_KEY);
    01984             newlyCreated = TRUE;
    01985
    01986             //
    01987             // Initialize new device instance registry key
    01988             //
    01989
    01990             if (ResourceAssigned) {
    01991                 RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_NO_RESOURCE_AT_INIT);
    01992                 tmpValue = 1;
    01993                 ZwSetValueKey(handle,
    01994                               &unicodeName,
    01995                               TITLE_INDEX_VALUE,
    01996                               REG_DWORD,
    01997                               &tmpValue,
    01998                               sizeof(tmpValue)
    01999                               );
    02000             }
    02001             RtlInitUnicodeString(&unicodeName, REGSTR_KEY_LOG_CONF);
    02002             logConfHandle = NULL;
    02003             status = IopCreateRegistryKeyEx( &logConfHandle,
    02004                                              handle,
    02005                                              &unicodeName,
    02006                                              KEY_ALL_ACCESS,
    02007                                              REG_OPTION_NON_VOLATILE,
    02008                                              NULL
    02009                                              );
    02010
    02011             ASSERT(status == STATUS_SUCCESS);
    02012
    02013             if (NT_SUCCESS(status)) {
    02014
    02015                 //
    02016                 // Write the ResourceList and and ResourceRequirements to the logconf key under
    02017                 // device instance key.
    02018                 //
    02019
    02020                 if (ResourceList) {
    02021                     RtlInitUnicodeString(&unicodeName, REGSTR_VAL_BOOTCONFIG);
    02022                     ZwSetValueKey(
    02023                               logConfHandle,
    02024                               &unicodeName,
    02025                               TITLE_INDEX_VALUE,
    02026                               REG_RESOURCE_LIST,
    02027                               ResourceList,
    02028                               listSize = IopDetermineResourceListSize(ResourceList)
    02029                               );
    02030                 }
    02031                 if (ResourceRequirements) {
    02032                     RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_BASIC_CONFIG_VECTOR);
    02033                     ZwSetValueKey(
    02034                               logConfHandle,
    02035                               &unicodeName,
    02036                               TITLE_INDEX_VALUE,
    02037                               REG_RESOURCE_REQUIREMENTS_LIST,
    02038                               ResourceRequirements,
    02039                               ResourceRequirements->ListSize
    02040                               );
    02041                 }
    02042                 //ZwClose(logConfHandle);
    02043             }
    02044
    02045             RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_CONFIG_FLAGS);
    02046             tmpValue = CONFIGFLAG_FINISH_INSTALL;
    02047             ZwSetValueKey(handle,
    02048                           &unicodeName,
    02049                           TITLE_INDEX_VALUE,
    02050                           REG_DWORD,
    02051                           &tmpValue,
    02052                           sizeof(tmpValue)
    02053                           );
    02054
    02055             PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_LEGACY);
    02056             tmpValue = 0;
    02057             ZwSetValueKey(
    02058                         handle,
    02059                         &unicodeName,
    02060                         TITLE_INDEX_VALUE,
    02061                         REG_DWORD,
    02062                         &tmpValue,
    02063                         sizeof(ULONG)
    02064                         );
    02065
    02066             RtlInitUnicodeString(&unicodeName, REGSTR_KEY_CONTROL);
    02067             controlHandle = NULL;
    02068             IopCreateRegistryKeyEx( &controlHandle,
    02069                                     handle,
    02070                                     &unicodeName,
    02071                                     KEY_ALL_ACCESS,
    02072                                     REG_OPTION_VOLATILE,
    02073                                     NULL
    02074                                     );
    02075
    02076             ASSERT(status == STATUS_SUCCESS);
    02077
    02078             if (NT_SUCCESS(status)) {
    02079
    02080                 //
    02081                 // Write DeviceObject reference ...
    02082                 //
    02083
    02084                 PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_DEVICE_REFERENCE);
    02085                 status = ZwSetValueKey(controlHandle,
    02086                                        &unicodeName,
    02087                                        TITLE_INDEX_VALUE,
    02088                                        REG_DWORD,
    02089                                        (PULONG_PTR)&deviceObject,
    02090                                        sizeof(ULONG_PTR)
    02091                                        );
    02092                 PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_DEVICE_REPORTED);
    02093                 tmpValue = 1;
    02094                 status = ZwSetValueKey(controlHandle,
    02095                                        &unicodeName,
    02096                                        TITLE_INDEX_VALUE,
    02097                                        REG_DWORD,
    02098                                        &tmpValue,
    02099                                        sizeof(ULONG)
    02100                                        );
    02101                 status = ZwSetValueKey(handle,
    02102                                        &unicodeName,
    02103                                        TITLE_INDEX_VALUE,
    02104                                        REG_DWORD,
    02105                                        &tmpValue,
    02106                                        sizeof(ULONG)
    02107                                        );
    02108
    02109                 //ZwClose(controlHandle);
    02110             }
    02111
    02112             ZwClose(enumHandle);
    02113
    02114             //
    02115             // Create Service value name and set it to the calling driver's service
    02116             // key name.
    02117             //
    02118
    02119             PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_SERVICE);
    02120             p = (PWSTR)ExAllocatePool(PagedPool, serviceName->Length + sizeof(UNICODE_NULL));
    02121             if (!p) {
    02122                 goto CleanupRegistry;
    02123             }
    02124             RtlMoveMemory(p, serviceName->Buffer, serviceName->Length);
    02125             p[serviceName->Length / sizeof (WCHAR)] = UNICODE_NULL;
    02126             ZwSetValueKey(
    02127                         handle,
    02128                         &unicodeName,
    02129                         TITLE_INDEX_VALUE,
    02130                         REG_SZ,
    02131                         p,
    02132                         serviceName->Length + sizeof(UNICODE_NULL)
    02133                         );
    02134             if (DriverObject->Flags & DRVO_BUILTIN_DRIVER) {
    02135                 deviceNode->ServiceName = *serviceName;
    02136             } else {
    02137                 ExFreePool(p);
    02138             }
    02139
    02140             ExReleaseResource(&PpRegistryDeviceResource);
    02141             KeLeaveCriticalRegion();
    02142             //ZwClose(logConfHandle);
    02143             //ZwClose(controlHandle);
    02144             //ZwClose(handle);
    02145
    02146             //
    02147             // Register the device for the driver and save the device
    02148             // instance path in device node.
    02149             //
    02150
    02151             if (!(DriverObject->Flags & DRVO_BUILTIN_DRIVER)) {
    02152                 PpDeviceRegistration( &deviceName,
    02153                                       TRUE,
    02154                                       &deviceNode->ServiceName
    02155                                       );
    02156             }
    02157
    02158             IopConcatenateUnicodeStrings(&deviceNode->InstancePath, &deviceName, NULL);
    02159
    02160             deviceNode->Flags = DNF_MADEUP + DNF_ENUMERATED + DNF_PROCESSED;
    02161
    02162             IopInsertTreeDeviceNode(IopRootDeviceNode, deviceNode);
    02163
    02164             //
    02165             // Add a reference to the DeviceObject for ourself
    02166             //
    02167
    02168             ObReferenceObject(deviceObject);
    02169
    02170             IopNotifySetupDeviceArrival(deviceObject, NULL, FALSE);
    02171
    02172             goto checkResource;
    02173         } else {
    02174             IoDeleteDevice(deviceObject);
    02175             status = STATUS_INSUFFICIENT_RESOURCES;
    02176         }
    02177     }
    02178     return status;
    02179 checkResource:
    02180
    02181
    02182     //
    02183     // At this point the *DeviceObject is established.  Check if we need to report resources for
    02184     // the detected device.  If we failed to
    02185     //
    02186
    02187     if (ResourceAssigned) {
    02188         //ASSERT(deviceNode->ResourceList == NULL);      // make sure we have not reported resources yet.
    02189
    02190         //
    02191         // If the driver specifies it already has acquired the resource.  We will put a flag
    02192         // in the device instance path to not to allocate resources at boot time.  The Driver
    02193         // may do detection and report it again.
    02194         //
    02195
    02196         deviceNode->Flags |= DNF_NO_RESOURCE_REQUIRED; // do not need resources for this boot.
    02197         if (ResourceList) {
    02198
    02199             //
    02200             // Write the resource list to the reported device instance key.
    02201             //
    02202
    02203             listSize = IopDetermineResourceListSize(ResourceList);
    02204             IopWriteAllocatedResourcesToRegistry (deviceNode, ResourceList, listSize);
    02205         }
    02206     } else {
    02207         BOOLEAN conflict;
    02208
    02209         if (ResourceList && ResourceList->Count && ResourceList->List[0].PartialResourceList.Count) {
    02210             if (listSize == 0) {
    02211                 listSize = IopDetermineResourceListSize(ResourceList);
    02212             }
    02213             cmResource = (PCM_RESOURCE_LIST) ExAllocatePool(PagedPool, listSize);
    02214             if (cmResource) {
    02215                 RtlCopyMemory(cmResource, ResourceList, listSize);
    02216                 RtlInitUnicodeString(&unicodeName, PNPMGR_STR_PNP_MANAGER);
    02217                 status = IoReportResourceUsageInternal(
    02218                              ArbiterRequestLegacyReported,
    02219                              &unicodeName,       // DriverClassName OPTIONAL,
    02220                              IoPnpDriverObject,  // DriverObject,
    02221                              NULL,               // DriverList OPTIONAL,
    02222                              0,                  // DriverListSize OPTIONAL,
    02223                              deviceNode->PhysicalDeviceObject,
    02224                                                  // DeviceObject OPTIONAL,
    02225                              cmResource,         // DeviceList OPTIONAL,
    02226                              listSize,           // DeviceListSize OPTIONAL,
    02227                              FALSE,              // OverrideConflict,
    02228                              &conflict           // ConflictDetected
    02229                              );
    02230                 ExFreePool(cmResource);
    02231                 if (!NT_SUCCESS(status) || conflict) {
    02232                     status = STATUS_CONFLICTING_ADDRESSES;
    02233                     IopSetDevNodeProblem(deviceNode, CM_PROB_NORMAL_CONFLICT);
    02234                 }
    02235             } else {
    02236                 status = STATUS_INSUFFICIENT_RESOURCES;
    02237                 IopSetDevNodeProblem(deviceNode, CM_PROB_OUT_OF_MEMORY);
    02238             }
    02239         } else {
    02240             ASSERT(ResourceRequirements == NULL);
    02241             deviceNode->Flags |= DNF_NO_RESOURCE_REQUIRED; // do not need resources for this boot.
    02242         }
    02243     }
    02244
    02245     if (NT_SUCCESS(status)) {
    02246
    02247         IopDoDeferredSetInterfaceState(deviceNode);
    02248
    02249         deviceNode->Flags |= DNF_STARTED | DNF_ADDED | DNF_NEED_ENUMERATION_ONLY | DNF_NEED_QUERY_IDS;
    02250         *DeviceObject = deviceObject;
    02251         if (newlyCreated) {
    02252             if (controlHandle) {
    02253                 ZwClose(controlHandle);
    02254             }
    02255             if (logConfHandle) {
    02256                 ZwClose(logConfHandle);
    02257             }
    02258             ZwClose(handle);
    02259         }
    02260         return status;
    02261
    02262     }
    02263 CleanupRegistry:
    02264     IopReleaseDeviceResources(deviceNode, FALSE);
    02265     if (newlyCreated) {
    02266         IoDeleteDevice(deviceObject);
    02267         if (controlHandle) {
    02268             ZwDeleteKey(controlHandle);
    02269         }
    02270         if (logConfHandle) {
    02271             ZwDeleteKey(logConfHandle);
    02272         }
    02273         if (handle) {
    02274             ZwDeleteKey(handle);
    02275         }
    02276     }
    02277     return status;
    02278 exit:
    02279     ExReleaseResource(&PpRegistryDeviceResource);
    02280     KeLeaveCriticalRegion();
    02281     IoDeleteDevice(*DeviceObject);
    02282     return status;
    02283 }

NTSTATUS IoReportTargetDeviceChange | ( | IN PDEVICE_OBJECT | PhysicalDeviceObject,
|  | IN PVOID | NotificationStructure
| ) |

Definition at line 6017 of file pnpioapi.c.

References ASSERT, ASSERT_PDO, DbgPrint, _TARGET_DEVICE_CUSTOM_NOTIFICATION::Event, Executive, FALSE, _TARGET_DEVICE_CUSTOM_NOTIFICATION::FileObject, IopCompareGuid, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), _TARGET_DEVICE_CUSTOM_NOTIFICATION::NameBufferOffset, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PpSetCustomTargetEvent(), and _TARGET_DEVICE_CUSTOM_NOTIFICATION::Size.

Referenced by FsRtlNotifyVolumeEvent(), and NtSetVolumeInformationFile().

    06024                    :
    06025
    06026     This routine may be used to give notification of 3rd-party target device
    06027     change events.  This API will notify every driver that has registered for
    06028     notification on a file object associated with PhysicalDeviceObject about
    06029     the event indicated in the NotificationStructure.
    06030
    06031 Parameters:
    06032
    06033     PhysicalDeviceObject - Provides a pointer to the PDO that the change begin
    06034         reported is associated with.
    06035
    06036     NotificationStructure - Provides a pointer to the notification structure to be
    06037         sent to all parties registered for notifications about changes to
    06038         PhysicalDeviceObject.
    06039
    06040 Return Value:
    06041
    06042     Status code that indicates whether or not the function was successful.
    06043
    06044 Note:
    06045
    06046     This API may only be used to report non-PnP target device changes.  In particular,
    06047     it will fail if it's called with the NotificationStructure->Event field set to
    06048     GUID_TARGET_DEVICE_QUERY_REMOVE, GUID_TARGET_DEVICE_REMOVE_CANCELLED, or
    06049     GUID_TARGET_DEVICE_REMOVE_COMPLETE.
    06050
    06051 --*/
    06052 {
    06053
    06054     NTSTATUS status = STATUS_SUCCESS;
    06055     KEVENT completionEvent;
    06056     NTSTATUS completionStatus;
    06057     PTARGET_DEVICE_CUSTOM_NOTIFICATION notifyStruct;
    06058     LONG                   dataSize;
    06059
    06060     PAGED_CODE();
    06061
    06062     notifyStruct = (PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure;
    06063
    06064     ASSERT(notifyStruct);
    06065
    06066     ASSERT_PDO(PhysicalDeviceObject);
    06067
    06068     ASSERT(NULL == notifyStruct->FileObject);
    06069
    06070
    06071     if (IopCompareGuid(&notifyStruct->Event, &GUID_TARGET_DEVICE_QUERY_REMOVE) ||
    06072         IopCompareGuid(&notifyStruct->Event, &GUID_TARGET_DEVICE_REMOVE_CANCELLED) ||
    06073         IopCompareGuid(&notifyStruct->Event, &GUID_TARGET_DEVICE_REMOVE_COMPLETE)) {
    06074
    06075         //
    06076         //  Passed in an illegal value
    06077         //
    06078
    06079 #if DBG
    06080         DbgPrint("Illegal Event type passed as custom notification\n");
    06081 #endif
    06082         return STATUS_INVALID_DEVICE_REQUEST;
    06083
    06084     }
    06085
    06086     if (notifyStruct->Size < FIELD_OFFSET(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer)) {
    06087
    06088         return STATUS_INVALID_DEVICE_REQUEST;
    06089     }
    06090
    06091     dataSize = notifyStruct->Size - FIELD_OFFSET(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer);
    06092
    06093     if (notifyStruct->NameBufferOffset != -1 && notifyStruct->NameBufferOffset > dataSize)  {
    06094
    06095         return STATUS_INVALID_DEVICE_REQUEST;
    06096     }
    06097
    06098     KeInitializeEvent(&completionEvent, NotificationEvent, FALSE);
    06099
    06100     status = PpSetCustomTargetEvent( PhysicalDeviceObject,
    06101                                      &completionEvent,
    06102                                      &completionStatus,
    06103                                      NULL,
    06104                                      NULL,
    06105                                      notifyStruct);
    06106
    06107     if (NT_SUCCESS(status))  {
    06108
    06109         KeWaitForSingleObject( &completionEvent, Executive, KernelMode, FALSE, NULL );
    06110
    06111         status = completionStatus;
    06112     }
    06113
    06114     return status;
    06115 }

NTSTATUS IoReportTargetDeviceChangeAsynchronous | ( | IN PDEVICE_OBJECT | PhysicalDeviceObject,
|  | IN PVOID | NotificationStructure,
|  | IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback | OPTIONAL,
|  | IN PVOID Context | OPTIONAL
| ) |

Definition at line 6118 of file pnpioapi.c.

References ASSERT, ASSERT_PDO, ASYNC_TDC_WORK_ITEM, _ASYNC_TDC_WORK_ITEM::Callback, _ASYNC_TDC_WORK_ITEM::Context, DbgPrint, DelayedWorkQueue, _ASYNC_TDC_WORK_ITEM::DeviceObject, _TARGET_DEVICE_CUSTOM_NOTIFICATION::Event, ExAllocatePool, ExInitializeWorkItem, ExQueueWorkItem(), _TARGET_DEVICE_CUSTOM_NOTIFICATION::FileObject, IopCompareGuid, IopReportTargetDeviceChangeAsyncWorker(), _TARGET_DEVICE_CUSTOM_NOTIFICATION::NameBufferOffset, NonPagedPool, _ASYNC_TDC_WORK_ITEM::NotificationStructure, NTSTATUS(), NULL, ObReferenceObject, PASYNC_TDC_WORK_ITEM, _TARGET_DEVICE_CUSTOM_NOTIFICATION::Size, and _ASYNC_TDC_WORK_ITEM::WorkItem.

Referenced by FsRtlNotifyVolumeEvent().

    06127                    :
    06128
    06129     This routine may be used to give notification of 3rd-party target device
    06130     change events.  This API will notify every driver that has registered for
    06131     notification on a file object associated with PhysicalDeviceObject about
    06132     the event indicated in the NotificationStructure.
    06133
    06134 Parameters:
    06135
    06136     PhysicalDeviceObject - Provides a pointer to the PDO that the change begin
    06137         reported is associated with.
    06138
    06139     NotificationStructure - Provides a pointer to the notification structure to be
    06140         sent to all parties registered for notifications about changes to
    06141         PhysicalDeviceObject.
    06142
    06143 Return Value:
    06144
    06145     Status code that indicates whether or not the function was successful.
    06146
    06147 Note:
    06148
    06149     This API may only be used to report non-PnP target device changes.  In particular,
    06150     it will fail if it's called with the NotificationStructure->Event field set to
    06151     GUID_TARGET_DEVICE_QUERY_REMOVE, GUID_TARGET_DEVICE_REMOVE_CANCELLED, or
    06152     GUID_TARGET_DEVICE_REMOVE_COMPLETE.
    06153
    06154 --*/
    06155 {
    06156     PASYNC_TDC_WORK_ITEM    asyncWorkItem;
    06157     PWORK_QUEUE_ITEM        workItem;
    06158     NTSTATUS                status;
    06159     LONG                    dataSize;
    06160
    06161     PTARGET_DEVICE_CUSTOM_NOTIFICATION   notifyStruct;
    06162
    06163     notifyStruct = (PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure;
    06164
    06165     ASSERT(notifyStruct);
    06166
    06167     ASSERT_PDO(PhysicalDeviceObject);
    06168
    06169     ASSERT(NULL == notifyStruct->FileObject);
    06170
    06171     if (IopCompareGuid(&notifyStruct->Event, &GUID_TARGET_DEVICE_QUERY_REMOVE) ||
    06172         IopCompareGuid(&notifyStruct->Event, &GUID_TARGET_DEVICE_REMOVE_CANCELLED) ||
    06173         IopCompareGuid(&notifyStruct->Event, &GUID_TARGET_DEVICE_REMOVE_COMPLETE)) {
    06174
    06175         //
    06176         //  Passed in an illegal value
    06177         //
    06178
    06179 #if DBG
    06180         DbgPrint("Illegal Event type passed as custom notification\n");
    06181 #endif
    06182         return STATUS_INVALID_DEVICE_REQUEST;
    06183
    06184     }
    06185
    06186     if (notifyStruct->Size < FIELD_OFFSET(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer)) {
    06187
    06188         return STATUS_INVALID_DEVICE_REQUEST;
    06189     }
    06190
    06191     dataSize = notifyStruct->Size - FIELD_OFFSET(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer);
    06192
    06193     if (notifyStruct->NameBufferOffset != -1 && notifyStruct->NameBufferOffset > dataSize)  {
    06194
    06195         return STATUS_INVALID_DEVICE_REQUEST;
    06196     }
    06197
    06198     //
    06199     // Since this routine can be called at DPC level we need to queue
    06200     // a work item and process it when the irql drops.
    06201     //
    06202
    06203     asyncWorkItem = ExAllocatePool( NonPagedPool,
    06204                                     sizeof(ASYNC_TDC_WORK_ITEM) + notifyStruct->Size);
    06205
    06206     if (asyncWorkItem != NULL) {
    06207
    06208         ObReferenceObject(PhysicalDeviceObject);
    06209
    06210         asyncWorkItem->DeviceObject = PhysicalDeviceObject;
    06211         asyncWorkItem->NotificationStructure =
    06212             (PTARGET_DEVICE_CUSTOM_NOTIFICATION)((PUCHAR)asyncWorkItem + sizeof(ASYNC_TDC_WORK_ITEM));
    06213
    06214         RtlCopyMemory( asyncWorkItem->NotificationStructure,
    06215                        notifyStruct,
    06216                        notifyStruct->Size);
    06217
    06218         asyncWorkItem->Callback = Callback;
    06219         asyncWorkItem->Context = Context;
    06220         workItem = &asyncWorkItem->WorkItem;
    06221
    06222         ExInitializeWorkItem(workItem, IopReportTargetDeviceChangeAsyncWorker, asyncWorkItem);
    06223
    06224         //
    06225         // Queue a work item to do the enumeration
    06226         //
    06227
    06228         ExQueueWorkItem(workItem, DelayedWorkQueue);
    06229         status = STATUS_PENDING;
    06230     } else {
    06231         //
    06232         // Failed to allocate memory for work item.  Nothing we can do ...
    06233         //
    06234
    06235         status = STATUS_INSUFFICIENT_RESOURCES;
    06236     }
    06237
    06238     return status;
    06239 }

VOID IoRequestDeviceEject | ( | PDEVICE_OBJECT | DeviceObject | ) |

Definition at line 1481 of file pnpioapi.c.

References ASSERT_PDO, IopQueueDeviceWorkItem(), IopRequestDeviceEjectWorker(), and NULL.

Referenced by IopDeviceStartComplete().

    01487                    :
    01488
    01489     This API notifies that the device eject button has been pressed. This API must
    01490     be called at IRQL <= DISPATCH_LEVEL.
    01491
    01492     This API informs PnP that a device eject has been requested, the device will
    01493     not necessarily be ejected as a result of this API.  The device will only be
    01494     ejected if the drivers associated with it agree to stop and the device is
    01495     successfully powered down.  Note that eject in this context refers to device
    01496     eject, not to media (floppies, cds, tapes) eject.  For example, eject of a
    01497     cd-rom disk drive, not ejection of a cd-rom disk.
    01498
    01499 Arguments:
    01500
    01501     DeviceObject - the PDEVICE_OBJECT for the device whose eject button has
    01502                    been pressed.  This pointer is valid for the duration of
    01503                    the call, if the API wants to keep a copy of it, it
    01504                    should obtain its own reference to the object
    01505                    (ObReferenceObject).
    01506
    01507 ReturnValue:
    01508
    01509     None.
    01510
    01511 --*/
    01512
    01513 {
    01514     ASSERT_PDO(DeviceObject);
    01515
    01516     IopQueueDeviceWorkItem(DeviceObject, IopRequestDeviceEjectWorker, NULL);
    01517 }

NTSTATUS IoSetDeviceInterfaceState | ( | IN PUNICODE_STRING | SymbolicLinkName,
|  | IN BOOLEAN | Enable
| ) |

Definition at line 3563 of file pnpioapi.c.

References ExAcquireResourceExclusive, ExReleaseResource, IopProcessSetInterfaceState(), KeEnterCriticalRegion, KeLeaveCriticalRegion, NT_SUCCESS, NTSTATUS(), PAGED_CODE, PpRegistryDeviceResource, and TRUE.

Referenced by IopUnregisterDeviceInterface().

    03570                    :
    03571
    03572     This DDI allows a device class to activate and deactivate an association
    03573     previously registered using IoRegisterDeviceInterface
    03574
    03575 Parameters:
    03576
    03577     SymbolicLinkName - Supplies a pointer to the symbolic link name which was
    03578         returned by IoRegisterDeviceInterface when the interface was registered,
    03579         or as returned by IoGetDeviceInterfaces.
    03580
    03581     Enable - If TRUE (non-zero), the interface will be enabled.  If FALSE, it
    03582         will be disabled.
    03583
    03584 Return Value:
    03585
    03586     Status code that indicates whether or not the function was successful.
    03587
    03588 --*/
    03589
    03590 {
    03591     NTSTATUS status;
    03592
    03593     PAGED_CODE();
    03594
    03595     //
    03596     // Enter critical section and acquire a lock on the registry.  Both these
    03597     // mechanisms are required to prevent deadlock in the case where an APC
    03598     // routine calls this routine after the registry resource has been claimed
    03599     // in this case it would wait blocking this thread so the registry would
    03600     // never be released -> deadlock.  Critical sectioning the registry manipulation
    03601     // portion solves this problem
    03602     //
    03603
    03604     KeEnterCriticalRegion();
    03605     ExAcquireResourceExclusive(&PpRegistryDeviceResource, TRUE);
    03606
    03607     status = IopProcessSetInterfaceState(SymbolicLinkName, Enable, TRUE);
    03608
    03609     ExReleaseResource(&PpRegistryDeviceResource);
    03610     KeLeaveCriticalRegion();
    03611
    03612     if (!NT_SUCCESS(status) && !Enable) {
    03613         //
    03614         // If we failed to disable an interface (most likely because the
    03615         // interface keys have already been deleted) report success.
    03616         //
    03617         status = STATUS_SUCCESS;
    03618     }
    03619
    03620     return status;
    03621 }

NTSTATUS IoSynchronousInvalidateDeviceRelations | ( | PDEVICE_OBJECT | DeviceObject,
|  | DEVICE_RELATION_TYPE | Type
| ) |

Definition at line 1291 of file pnpioapi.c.

References ASSERT_PDO, BusRelations, _DEVOBJ_EXTENSION::DeviceNode, _DEVICE_OBJECT::DeviceObjectExtension, DNF_STARTED, EjectionRelations, Executive, FALSE, _DEVICE_NODE::Flags, IopRequestDeviceAction(), KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PnPInitialized, PoInvalidateDevicePowerRelations(), PowerRelations, and ReenumerateDeviceTree.

    01298                    :
    01299
    01300     This API notifies the system that changes have occurred in the device
    01301     relations of the specified type for the supplied DeviceObject.   All
    01302     cached information concerning the relationships must be invalidated,
    01303     and if needed re-obtained via IRP_MN_QUERY_DEVICE_RELATIONS.
    01304
    01305     This routine performs device enumeration synchronously.
    01306     Note, A driver can NOT call this IO api while processing pnp irps AND
    01307     A driver can NOT call this api from any system thread except the system
    01308     threads created by the driver itself.
    01309
    01310 Parameters:
    01311
    01312     DeviceObject - the PDEVICE_OBJECT for which the specified relation type
    01313                    information has been invalidated.  This pointer is valid
    01314                    for the duration of the call.
    01315
    01316     Type - specifies the type of the relation being invalidated.
    01317
    01318 ReturnValue:
    01319
    01320     Status code that indicates whether or not the function was successful.
    01321
    01322 --*/
    01323
    01324 {
    01325     PDEVICE_NODE deviceNode;
    01326     NTSTATUS status = STATUS_SUCCESS;
    01327     KEVENT completionEvent;
    01328
    01329     PAGED_CODE();
    01330
    01331     ASSERT_PDO(DeviceObject);
    01332
    01333     switch (Type) {
    01334     case BusRelations:
    01335
    01336         if (PnPInitialized) {
    01337
    01338             deviceNode = (PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
    01339
    01340             if (deviceNode->Flags & DNF_STARTED) {
    01341
    01342                 KeInitializeEvent( &completionEvent, NotificationEvent, FALSE );
    01343
    01344                 status = IopRequestDeviceAction( DeviceObject,
    01345                                                  ReenumerateDeviceTree,
    01346                                                  &completionEvent,
    01347                                                  NULL );
    01348
    01349                 if (NT_SUCCESS(status)) {
    01350
    01351                     status = KeWaitForSingleObject( &completionEvent,
    01352                                                     Executive,
    01353                                                     KernelMode,
    01354                                                     FALSE,
    01355                                                     NULL);
    01356                 }
    01357             } else {
    01358                 status = STATUS_UNSUCCESSFUL;
    01359             }
    01360         } else {
    01361             //
    01362             // BUGBUG - This check may be too much.  For now ...
    01363             //
    01364
    01365             status = STATUS_UNSUCCESSFUL;  // BUGBUG- better status code
    01366         }
    01367
    01368
    01369         break;
    01370
    01371     case EjectionRelations:
    01372
    01373         //
    01374         // For Ejection relation change, we will ignore it.  We don't keep track
    01375         // the Ejection relation.  We will query the Ejection relation only when
    01376         // we are requested to eject a device.
    01377         //
    01378
    01379         status = STATUS_NOT_SUPPORTED;
    01380         break;
    01381
    01382     case PowerRelations:
    01383
    01384
    01385         //
    01386         // Call off to Po code, which will do the right thing
    01387         //
    01388         PoInvalidateDevicePowerRelations(DeviceObject);
    01389         break;
    01390     }
    01391     return status;
    01392 }

NTSTATUS IoUnregisterPlugPlayNotification | ( | IN PVOID | NotificationEntry | ) |

Definition at line 5829 of file pnpioapi.c.

References ASSERT, ExFreePool(), FALSE, IopAcquireNotifyLock, IopDeferredRegistrationList, IopDeferredRegistrationLock, IopDereferenceNotify(), IopReleaseNotifyLock, _NOTIFY_ENTRY_HEADER::Lock, _DEFERRED_REGISTRATION_ENTRY::NotifyEntry, PAGED_CODE, PDEFERRED_REGISTRATION_ENTRY, PiNotificationInProgress, PiNotificationInProgressLock, TRUE, and _NOTIFY_ENTRY_HEADER::Unregistered.

Referenced by DeviceCDROMNotify(), and UnregisterForDeviceChangeNotifications().

    05835                    :
    05836
    05837     This routine unregisters a notification previously registered via
    05838     IoRegisterPlugPlayNotification.  A driver cannot be unloaded until it has
    05839     unregistered all of its notification handles.
    05840
    05841 Parameters:
    05842
    05843     NotificationEntry - This provices the cookie returned by IoRegisterPlugPlayNotification
    05844         which identifies the registration in question.
    05845
    05846 Return Value:
    05847
    05848     Status code that indicates whether or not the function was successful.
    05849
    05850 --*/
    05851
    05852 {
    05853     PNOTIFY_ENTRY_HEADER entry;
    05854     PFAST_MUTEX lock;
    05855     BOOLEAN wasDeferred = FALSE;
    05856
    05857     PAGED_CODE();
    05858
    05859     ASSERT(NotificationEntry);
    05860
    05861     entry = (PNOTIFY_ENTRY_HEADER)NotificationEntry;
    05862
    05863     lock = entry->Lock;
    05864
    05865     ExAcquireFastMutex(&PiNotificationInProgressLock);
    05866     if (PiNotificationInProgress) {
    05867         //
    05868         // Before unregistering the entry, we need to make sure that it's not sitting
    05869         // around in the deferred registration list.
    05870         //
    05871         IopAcquireNotifyLock(&IopDeferredRegistrationLock);
    05872
    05873         if (!IsListEmpty(&IopDeferredRegistrationList)) {
    05874
    05875             PLIST_ENTRY link;
    05876             PDEFERRED_REGISTRATION_ENTRY deferredNode;
    05877
    05878             link = IopDeferredRegistrationList.Flink;
    05879             deferredNode = (PDEFERRED_REGISTRATION_ENTRY)link;
    05880
    05881             while (link != (PLIST_ENTRY)&IopDeferredRegistrationList) {
    05882                 ASSERT(deferredNode->NotifyEntry->Unregistered);
    05883                 if (deferredNode->NotifyEntry == entry) {
    05884                     wasDeferred = TRUE;
    05885                     if (lock) {
    05886                         IopAcquireNotifyLock(lock);
    05887                     }
    05888                     link = link->Flink;
    05889                     RemoveEntryList((PLIST_ENTRY)deferredNode);
    05890                     IopDereferenceNotify((PNOTIFY_ENTRY_HEADER)deferredNode->NotifyEntry);
    05891                     if (lock) {
    05892                         IopReleaseNotifyLock(lock);
    05893                     }
    05894                     ExFreePool(deferredNode);
    05895                     deferredNode = (PDEFERRED_REGISTRATION_ENTRY)link;
    05896                 } else {
    05897                     link = link->Flink;
    05898                     deferredNode = (PDEFERRED_REGISTRATION_ENTRY)link;
    05899                 }
    05900             }
    05901         }
    05902
    05903         IopReleaseNotifyLock(&IopDeferredRegistrationLock);
    05904     } else {
    05905         //
    05906         // If there is currently no notification in progress, the deferred
    05907         // registration list must be empty.
    05908         //
    05909         ASSERT(IsListEmpty(&IopDeferredRegistrationList));
    05910     }
    05911     ExReleaseFastMutex(&PiNotificationInProgressLock);
    05912
    05913     //
    05914     // Acquire lock
    05915     //
    05916     if (lock) {
    05917         IopAcquireNotifyLock(lock);
    05918     }
    05919
    05920     ASSERT(wasDeferred == entry->Unregistered);
    05921
    05922     if (!entry->Unregistered || wasDeferred) {
    05923         //
    05924         // Dereference the entry if it is currently registered, or had its
    05925         // registration pending completion of the notification in progress.
    05926         //
    05927
    05928         //
    05929         // Mark the entry as unregistered so we don't notify on it
    05930         //
    05931
    05932         entry->Unregistered = TRUE;
    05933
    05934         //
    05935         // Dereference it thus deleting if no longer required
    05936         //
    05937
    05938         IopDereferenceNotify(entry);
    05939     }
    05940
    05941     //
    05942     // Release the lock
    05943     //
    05944
    05945     if (lock) {
    05946         IopReleaseNotifyLock(lock);
    05947     }
    05948
    05949     return STATUS_SUCCESS;
    05950
    05951 }

NTSTATUS PiNotifyUserMode | ( | PPNP_DEVICE_EVENT_ENTRY | DeviceEvent | ) |

| Referenced by IopRequestHwProfileChangeNotification().

NTSTATUS PpCreateLegacyDeviceIds | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN PUNICODE_STRING | DriverName,
|  | IN PCM_RESOURCE_LIST | Resources
| ) |

Definition at line 9077 of file pnpioapi.c.

References _IOPNP_DEVICE_EXTENSION::CompatibleIdList, _IOPNP_DEVICE_EXTENSION::CompatibleIdListSize, ExAllocatePool, L, LEGACY_COMPATIBLE_ID_BASE, NULL, PAGED_CODE, and PagedPool.

Referenced by IoReportDetectedDevice().

    09082 {
    09083     PIOPNP_DEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
    09084     PWCHAR buffer;
    09085
    09086     ULONG length = 0;
    09087
    09088     INTERFACE_TYPE interface;
    09089     PWCHAR interfaceNames[] ={L"",
    09090                               L"Internal",
    09091                               L"Isa",
    09092                               L"Eisa",
    09093                               L"MicroChannel",
    09094                               L"TurboChannel",
    09095                               L"PCIBus",
    09096                               L"VMEBus",
    09097                               L"NuBus",
    09098                               L"PCMCIABus",
    09099                               L"CBus",
    09100                               L"MPIBus",
    09101                               L"MPSABus",
    09102                               L"ProcessorInternal",
    09103                               L"InternalPowerBus",
    09104                               L"PNPISABus",
    09105                               L"PNPBus",
    09106                               L"Other",
    09107                               L"Root"};
    09108
    09109
    09110      PAGED_CODE();
    09111
    09112     if(Resources != NULL) {
    09113
    09114         interface = Resources->List[0].InterfaceType;
    09115
    09116         if((interface > MaximumInterfaceType) ||
    09117            (interface < InterfaceTypeUndefined)) {
    09118             interface = MaximumInterfaceType;
    09119         }
    09120     } else {
    09121         interface = Internal;
    09122     }
    09123
    09124     interface++;
    09125
    09126     //
    09127     // The compatible ID generated will be
    09128     // DETECTED<InterfaceName><Driver Name>
    09129     //
    09130
    09131     length = wcslen(LEGACY_COMPATIBLE_ID_BASE) * sizeof(WCHAR);
    09132     length += wcslen(interfaceNames[interface]) * sizeof(WCHAR);
    09133     length += sizeof(L'\\');
    09134     length += DriverName->Length;
    09135     length += sizeof(UNICODE_NULL);
    09136
    09137     length += wcslen(LEGACY_COMPATIBLE_ID_BASE) * sizeof(WCHAR);
    09138     length += sizeof(L'\\');
    09139     length += DriverName->Length;
    09140     length += sizeof(UNICODE_NULL) * 2;
    09141
    09142     buffer = ExAllocatePool(PagedPool, length);
    09143     deviceExtension->CompatibleIdList = buffer;
    09144
    09145     if(buffer == NULL) {
    09146         return STATUS_INSUFFICIENT_RESOURCES;
    09147     }
    09148
    09149     RtlZeroMemory(buffer, length);
    09150
    09151     swprintf(buffer, L"%ws%ws\\%wZ", LEGACY_COMPATIBLE_ID_BASE,
    09152                                      interfaceNames[interface],
    09153                                      DriverName);
    09154
    09155     //
    09156     // Adjust the buffer to point to the end and generate the second
    09157     // compatible id string.
    09158     //
    09159
    09160     buffer += wcslen(buffer) + 1;
    09161
    09162     swprintf(buffer, L"%ws\\%wZ", LEGACY_COMPATIBLE_ID_BASE, DriverName);
    09163
    09164     deviceExtension->CompatibleIdListSize = length;
    09165
    09166     return STATUS_SUCCESS;
    09167 }

## Variable Documentation

LIST_ENTRY IopDeferredRegistrationList

| Definition at line 199 of file pnpioapi.c. Referenced by IopInitializePlugPlayNotification(), IopProcessDeferredRegistrations(), IoRegisterPlugPlayNotification(), and IoUnregisterPlugPlayNotification().

FAST_MUTEX IopDeferredRegistrationLock

| Definition at line 200 of file pnpioapi.c. Referenced by IopInitializePlugPlayNotification(), IopProcessDeferredRegistrations(), IoRegisterPlugPlayNotification(), and IoUnregisterPlugPlayNotification().

LIST_ENTRY IopDeviceClassNotifyList[NOTIFY_DEVICE_CLASS_HASH_BUCKETS]

| Definition at line 183 of file pnpioapi.c. Referenced by IopInitializePlugPlayNotification(), IopNotifyDeviceClassChange(), and IoRegisterPlugPlayNotification().

FAST_MUTEX IopDeviceClassNotifyLock

| Definition at line 184 of file pnpioapi.c. Referenced by IopInitializePlugPlayNotification(), IopNotifyDeviceClassChange(), and IoRegisterPlugPlayNotification().

FAST_MUTEX IopHwProfileNotifyLock

| Definition at line 188 of file pnpioapi.c. Referenced by IopInitializePlugPlayNotification(), IopNotifyHwProfileChange(), and IoRegisterPlugPlayNotification().

LIST_ENTRY IopProfileNotifyList

| Definition at line 187 of file pnpioapi.c. Referenced by IopInitializePlugPlayNotification(), IopNotifyHwProfileChange(), and IoRegisterPlugPlayNotification().

PSETUP_NOTIFY_DATA IopSetupNotifyData = NULL

| Definition at line 185 of file pnpioapi.c. Referenced by IopNotifySetupDeviceArrival(), and IoRegisterPlugPlayNotification().

FAST_MUTEX IopTargetDeviceNotifyLock

| Definition at line 186 of file pnpioapi.c. Referenced by IopInitializePlugPlayNotification(), IopNotifyTargetDeviceChange(), IopOrphanNotification(), and IoRegisterPlugPlayNotification().

BOOLEAN PiNotificationInProgress

| Definition at line 189 of file pnpioapi.c. Referenced by IopRequestHwProfileChangeNotification(), IoRegisterPlugPlayNotification(), and IoUnregisterPlugPlayNotification().

FAST_MUTEX PiNotificationInProgressLock

| Definition at line 190 of file pnpioapi.c. Referenced by IoRegisterPlugPlayNotification(), and IoUnregisterPlugPlayNotification().