mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[NTOS:PNP] Improve and refactor PnP notifications
- BUGFIX: do not call IoGetRelatedTargetDevice while guarded mutex is acquired (the function issues an APC, but they are disabled inside a critical section) - BUGFIX: only the beginning of a structure for GUID_PNP_CUSTOM_NOTIFICATION was copied and queued. Just pass it as-is to a subscriber, without copying - Don't convert event GUID to string, store and compare GUID struct itself - Split IopNotifyPlugPlayNotification into 3 functions for each type of notification (less stack usage and for future changes) - Move initialization code for notifications into a separate routine - Use separate lists and locks for every type of notification - Put "TargetDeviceChange" notifications into their place inside DEVICE_NODE
This commit is contained in:
parent
e3198fb644
commit
582ca68696
7 changed files with 442 additions and 317 deletions
|
@ -609,20 +609,6 @@ IopInitDriverImplementation(
|
|||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
IopInitPnpNotificationImplementation(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
IopNotifyPlugPlayNotification(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory,
|
||||
IN LPCGUID Event,
|
||||
IN PVOID EventCategoryData1,
|
||||
IN PVOID EventCategoryData2
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
IopGetSystemPowerDeviceObject(
|
||||
IN PDEVICE_OBJECT *DeviceObject
|
||||
|
@ -828,6 +814,10 @@ IoInitializeCrashDump(
|
|||
IN HANDLE PageFileHandle
|
||||
);
|
||||
|
||||
VOID
|
||||
PiInitializeNotifications(
|
||||
VOID);
|
||||
|
||||
//
|
||||
// Device/Volume Routines
|
||||
//
|
||||
|
@ -926,6 +916,12 @@ IopDereferenceDeviceObject(
|
|||
IN BOOLEAN ForceUnload
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IopGetRelatedTargetDevice(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
OUT PDEVICE_NODE *DeviceNode);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IoGetRelatedTargetDevice(
|
||||
|
@ -1412,6 +1408,25 @@ PiPerformSyncDeviceAction(
|
|||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ DEVICE_ACTION Action);
|
||||
|
||||
//
|
||||
// PnP notifications
|
||||
//
|
||||
VOID
|
||||
PiNotifyDeviceInterfaceChange(
|
||||
_In_ LPCGUID Event,
|
||||
_In_ LPCGUID InterfaceClassGuid,
|
||||
_In_ PUNICODE_STRING SymbolicLinkName);
|
||||
|
||||
VOID
|
||||
PiNotifyHardwareProfileChange(
|
||||
_In_ LPCGUID Event);
|
||||
|
||||
VOID
|
||||
PiNotifyTargetDeviceChange(
|
||||
_In_ LPCGUID Event,
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_opt_ PTARGET_DEVICE_CUSTOM_NOTIFICATION CustomNotification);
|
||||
|
||||
//
|
||||
// Global I/O Data
|
||||
//
|
||||
|
|
|
@ -1463,12 +1463,8 @@ IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName,
|
|||
ExFreePoolWithTag(DeviceInstance.Buffer, TAG_IO);
|
||||
|
||||
EventGuid = Enable ? &GUID_DEVICE_INTERFACE_ARRIVAL : &GUID_DEVICE_INTERFACE_REMOVAL;
|
||||
IopNotifyPlugPlayNotification(
|
||||
PhysicalDeviceObject,
|
||||
EventCategoryDeviceInterfaceChange,
|
||||
EventGuid,
|
||||
&DeviceGuid,
|
||||
(PVOID)SymbolicLinkName);
|
||||
|
||||
PiNotifyDeviceInterfaceChange(EventGuid, &DeviceGuid, SymbolicLinkName);
|
||||
|
||||
ObDereferenceObject(PhysicalDeviceObject);
|
||||
DPRINT("Status %x\n", Status);
|
||||
|
|
|
@ -59,14 +59,12 @@ extern POBJECT_TYPE IoAdapterObjectType;
|
|||
extern ERESOURCE IopDatabaseResource;
|
||||
ERESOURCE IopSecurityResource;
|
||||
extern ERESOURCE IopDriverLoadResource;
|
||||
extern KGUARDED_MUTEX PnpNotifyListLock;
|
||||
extern LIST_ENTRY IopDiskFileSystemQueueHead;
|
||||
extern LIST_ENTRY IopCdRomFileSystemQueueHead;
|
||||
extern LIST_ENTRY IopTapeFileSystemQueueHead;
|
||||
extern LIST_ENTRY IopNetworkFileSystemQueueHead;
|
||||
extern LIST_ENTRY DriverBootReinitListHead;
|
||||
extern LIST_ENTRY DriverReinitListHead;
|
||||
extern LIST_ENTRY PnpNotifyListHead;
|
||||
extern LIST_ENTRY IopFsNotifyChangeQueueHead;
|
||||
extern LIST_ENTRY IopErrorLogListHead;
|
||||
extern LIST_ENTRY IopTimerQueueHead;
|
||||
|
@ -480,14 +478,12 @@ IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|||
ExInitializeResourceLite(&IopDatabaseResource);
|
||||
ExInitializeResourceLite(&IopSecurityResource);
|
||||
ExInitializeResourceLite(&IopDriverLoadResource);
|
||||
KeInitializeGuardedMutex(&PnpNotifyListLock);
|
||||
InitializeListHead(&IopDiskFileSystemQueueHead);
|
||||
InitializeListHead(&IopCdRomFileSystemQueueHead);
|
||||
InitializeListHead(&IopTapeFileSystemQueueHead);
|
||||
InitializeListHead(&IopNetworkFileSystemQueueHead);
|
||||
InitializeListHead(&DriverBootReinitListHead);
|
||||
InitializeListHead(&DriverReinitListHead);
|
||||
InitializeListHead(&PnpNotifyListHead);
|
||||
InitializeListHead(&ShutdownListHead);
|
||||
InitializeListHead(&LastChanceShutdownListHead);
|
||||
InitializeListHead(&IopFsNotifyChangeQueueHead);
|
||||
|
@ -498,6 +494,9 @@ IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|||
KeInitializeSpinLock(&ShutdownListLock);
|
||||
KeInitializeSpinLock(&IopLogListLock);
|
||||
|
||||
/* Initialize PnP notifications */
|
||||
PiInitializeNotifications();
|
||||
|
||||
/* Initialize the reserve IRP */
|
||||
if (!IopInitializeReserveIrp(&IopReserveIrpAllocator))
|
||||
{
|
||||
|
|
|
@ -1513,11 +1513,7 @@ IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
|
|||
/* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
|
||||
IopSynchronousCall(DeviceObject, &Stack, &Dummy);
|
||||
|
||||
IopNotifyPlugPlayNotification(DeviceObject,
|
||||
EventCategoryTargetDeviceChange,
|
||||
&GUID_TARGET_DEVICE_REMOVE_COMPLETE,
|
||||
NULL,
|
||||
NULL);
|
||||
PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_REMOVE_COMPLETE, DeviceObject, NULL);
|
||||
ObDereferenceObject(DeviceObject);
|
||||
}
|
||||
|
||||
|
@ -1592,11 +1588,7 @@ IopCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
|
|||
/* Drivers should never fail a IRP_MN_CANCEL_REMOVE_DEVICE request */
|
||||
IopSynchronousCall(DeviceObject, &Stack, &Dummy);
|
||||
|
||||
IopNotifyPlugPlayNotification(DeviceObject,
|
||||
EventCategoryTargetDeviceChange,
|
||||
&GUID_TARGET_DEVICE_REMOVE_CANCELLED,
|
||||
NULL,
|
||||
NULL);
|
||||
PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_REMOVE_CANCELLED, DeviceObject, NULL);
|
||||
}
|
||||
|
||||
static
|
||||
|
@ -1692,11 +1684,7 @@ IopQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
|
|||
|
||||
Status = IopSynchronousCall(DeviceObject, &Stack, &Dummy);
|
||||
|
||||
IopNotifyPlugPlayNotification(DeviceObject,
|
||||
EventCategoryTargetDeviceChange,
|
||||
&GUID_TARGET_DEVICE_QUERY_REMOVE,
|
||||
NULL,
|
||||
NULL);
|
||||
PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_QUERY_REMOVE, DeviceObject, NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
|
|
|
@ -114,6 +114,7 @@ IopCreateDeviceNode(
|
|||
}
|
||||
|
||||
RtlZeroMemory(Node, sizeof(DEVICE_NODE));
|
||||
InitializeListHead(&Node->TargetDeviceNotify);
|
||||
|
||||
if (!ServiceName)
|
||||
ServiceName1 = &UnknownDeviceName;
|
||||
|
@ -259,6 +260,8 @@ IopFreeDeviceNode(
|
|||
/* All children must be deleted before a parent is deleted */
|
||||
ASSERT(!DeviceNode->Child);
|
||||
ASSERT(DeviceNode->PhysicalDeviceObject);
|
||||
/* No notifications should be registered for this device */
|
||||
ASSERT(IsListEmpty(&DeviceNode->TargetDeviceNotify));
|
||||
|
||||
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* COPYRIGHT: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/io/pnpmgr/pnpnotify.c
|
||||
* PURPOSE: Plug & Play notification functions
|
||||
* PROGRAMMERS: Filip Navara (xnavara@volny.cz)
|
||||
* Hervé Poussineau (hpoussin@reactos.org)
|
||||
* Pierre Schweitzer
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Plug & Play notification functions
|
||||
* COPYRIGHT: Copyright 2003 Filip Navara <xnavara@volny.cz>
|
||||
* Copyright 2005-2006 Hervé Poussineau <hpoussin@reactos.org>
|
||||
* Copyright 2010 Pierre Schweitzer <pierre@reactos.org>
|
||||
* Copyright 2020 Victor Perevertkin <victor.perevertkin@reactos.org>
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
@ -14,215 +14,309 @@
|
|||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* TYPES *******************************************************************/
|
||||
/* DATA **********************************************************************/
|
||||
|
||||
KGUARDED_MUTEX PiNotifyTargetDeviceLock;
|
||||
KGUARDED_MUTEX PiNotifyHwProfileLock;
|
||||
KGUARDED_MUTEX PiNotifyDeviceInterfaceLock;
|
||||
|
||||
_Guarded_by_(PiNotifyHwProfileLock)
|
||||
LIST_ENTRY PiNotifyHwProfileListHead;
|
||||
|
||||
_Guarded_by_(PiNotifyDeviceInterfaceLock)
|
||||
LIST_ENTRY PiNotifyDeviceInterfaceListHead;
|
||||
|
||||
/* TYPES *********************************************************************/
|
||||
|
||||
typedef struct _PNP_NOTIFY_ENTRY
|
||||
{
|
||||
LIST_ENTRY PnpNotifyList;
|
||||
IO_NOTIFICATION_EVENT_CATEGORY EventCategory;
|
||||
PVOID Context;
|
||||
UNICODE_STRING Guid;
|
||||
PFILE_OBJECT FileObject;
|
||||
PDRIVER_OBJECT DriverObject;
|
||||
PDRIVER_NOTIFICATION_CALLBACK_ROUTINE PnpNotificationProc;
|
||||
union
|
||||
{
|
||||
GUID Guid; // for EventCategoryDeviceInterfaceChange
|
||||
struct
|
||||
{
|
||||
PFILE_OBJECT FileObject; // for EventCategoryTargetDeviceChange
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
};
|
||||
};
|
||||
IO_NOTIFICATION_EVENT_CATEGORY EventCategory;
|
||||
UINT8 RefCount;
|
||||
BOOLEAN Deleted;
|
||||
} PNP_NOTIFY_ENTRY, *PPNP_NOTIFY_ENTRY;
|
||||
|
||||
KGUARDED_MUTEX PnpNotifyListLock;
|
||||
LIST_ENTRY PnpNotifyListHead;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
CODE_SEG("INIT")
|
||||
VOID
|
||||
IopNotifyPlugPlayNotification(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory,
|
||||
IN LPCGUID Event,
|
||||
IN PVOID EventCategoryData1,
|
||||
IN PVOID EventCategoryData2)
|
||||
PiInitializeNotifications(VOID)
|
||||
{
|
||||
PPNP_NOTIFY_ENTRY ChangeEntry;
|
||||
PLIST_ENTRY ListEntry;
|
||||
PVOID NotificationStructure;
|
||||
BOOLEAN CallCurrentEntry;
|
||||
UNICODE_STRING GuidString;
|
||||
NTSTATUS Status;
|
||||
PDEVICE_OBJECT EntryDeviceObject = NULL;
|
||||
KeInitializeGuardedMutex(&PiNotifyTargetDeviceLock);
|
||||
KeInitializeGuardedMutex(&PiNotifyHwProfileLock);
|
||||
KeInitializeGuardedMutex(&PiNotifyDeviceInterfaceLock);
|
||||
InitializeListHead(&PiNotifyHwProfileListHead);
|
||||
InitializeListHead(&PiNotifyDeviceInterfaceListHead);
|
||||
}
|
||||
|
||||
ASSERT(DeviceObject);
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
PiDereferencePnpNotifyEntry(
|
||||
_In_ PPNP_NOTIFY_ENTRY Entry)
|
||||
{
|
||||
PAGED_CODE();
|
||||
ASSERT(Entry->RefCount > 0);
|
||||
|
||||
KeAcquireGuardedMutex(&PnpNotifyListLock);
|
||||
if (IsListEmpty(&PnpNotifyListHead))
|
||||
ObDereferenceObject(Entry->DriverObject);
|
||||
Entry->RefCount--;
|
||||
if (Entry->RefCount == 0)
|
||||
{
|
||||
ASSERT(Entry->Deleted);
|
||||
|
||||
RemoveEntryList(&Entry->PnpNotifyList);
|
||||
if (Entry->EventCategory == EventCategoryTargetDeviceChange)
|
||||
{
|
||||
// IopGetRelatedTargetDevice referenced the device upon the notification registration
|
||||
ObDereferenceObject(Entry->DeviceObject);
|
||||
}
|
||||
ExFreePoolWithTag(Entry, TAG_PNP_NOTIFY);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
PiReferencePnpNotifyEntry(
|
||||
_In_ PPNP_NOTIFY_ENTRY Entry)
|
||||
{
|
||||
PAGED_CODE();
|
||||
ObReferenceObject(Entry->DriverObject);
|
||||
Entry->RefCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calls PnP notification routine and makes some checks to detect faulty drivers
|
||||
*/
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
PiCallNotifyProc(
|
||||
_In_ PDRIVER_NOTIFICATION_CALLBACK_ROUTINE Proc,
|
||||
_In_ PVOID NotificationStructure,
|
||||
_In_ PVOID Context)
|
||||
{
|
||||
PAGED_CODE();
|
||||
#if DBG
|
||||
KIRQL oldIrql = KeGetCurrentIrql();
|
||||
ULONG oldApcDisable = KeGetCurrentThread()->CombinedApcDisable;
|
||||
#endif
|
||||
|
||||
Proc(NotificationStructure, Context);
|
||||
|
||||
ASSERT(oldIrql == KeGetCurrentIrql() &&
|
||||
oldApcDisable == KeGetCurrentThread()->CombinedApcDisable);
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
_Requires_lock_held_(Lock)
|
||||
VOID
|
||||
PiProcessSingleNotification(
|
||||
_In_ PPNP_NOTIFY_ENTRY Entry,
|
||||
_In_ PVOID NotificationStructure,
|
||||
_In_ PKGUARDED_MUTEX Lock,
|
||||
_Out_ PLIST_ENTRY *NextEntry)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
// the notification may be unregistered inside the procedure
|
||||
// thus reference the entry so we may proceed
|
||||
PiReferencePnpNotifyEntry(Entry);
|
||||
|
||||
// release the lock because the notification routine has to be called without any
|
||||
// limitations regarding APCs
|
||||
KeReleaseGuardedMutex(Lock);
|
||||
PiCallNotifyProc(Entry->PnpNotificationProc, NotificationStructure, Entry->Context);
|
||||
KeAcquireGuardedMutex(Lock);
|
||||
|
||||
// take the next entry link only after the callback finishes
|
||||
// the lock is not held there, so Entry may have changed at this point
|
||||
*NextEntry = Entry->PnpNotifyList.Flink;
|
||||
PiDereferencePnpNotifyEntry(Entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delivers the event to all drivers subscribed to
|
||||
* EventCategoryDeviceInterfaceChange
|
||||
*
|
||||
* @param[in] Event The PnP event GUID
|
||||
* @param[in] InterfaceClassGuid The GUID of an interface class
|
||||
* @param[in] SymbolicLinkName Pointer to a string identifying the device interface name
|
||||
*/
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
PiNotifyDeviceInterfaceChange(
|
||||
_In_ LPCGUID Event,
|
||||
_In_ LPCGUID InterfaceClassGuid,
|
||||
_In_ PUNICODE_STRING SymbolicLinkName)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
PDEVICE_INTERFACE_CHANGE_NOTIFICATION notifyStruct;
|
||||
notifyStruct = ExAllocatePoolWithTag(PagedPool, sizeof(*notifyStruct), TAG_PNP_NOTIFY);
|
||||
if (!notifyStruct)
|
||||
{
|
||||
KeReleaseGuardedMutex(&PnpNotifyListLock);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (EventCategory)
|
||||
{
|
||||
case EventCategoryDeviceInterfaceChange:
|
||||
{
|
||||
PDEVICE_INTERFACE_CHANGE_NOTIFICATION NotificationInfos;
|
||||
NotificationStructure = NotificationInfos = ExAllocatePoolWithTag(
|
||||
PagedPool,
|
||||
sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION),
|
||||
TAG_PNP_NOTIFY);
|
||||
if (!NotificationInfos)
|
||||
{
|
||||
KeReleaseGuardedMutex(&PnpNotifyListLock);
|
||||
return;
|
||||
}
|
||||
NotificationInfos->Version = 1;
|
||||
NotificationInfos->Size = sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION);
|
||||
RtlCopyMemory(&NotificationInfos->Event, Event, sizeof(GUID));
|
||||
RtlCopyMemory(&NotificationInfos->InterfaceClassGuid, EventCategoryData1, sizeof(GUID));
|
||||
NotificationInfos->SymbolicLinkName = (PUNICODE_STRING)EventCategoryData2;
|
||||
Status = RtlStringFromGUID(&NotificationInfos->InterfaceClassGuid, &GuidString);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KeReleaseGuardedMutex(&PnpNotifyListLock);
|
||||
ExFreePoolWithTag(NotificationStructure, TAG_PNP_NOTIFY);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EventCategoryHardwareProfileChange:
|
||||
{
|
||||
PHWPROFILE_CHANGE_NOTIFICATION NotificationInfos;
|
||||
NotificationStructure = NotificationInfos = ExAllocatePoolWithTag(
|
||||
PagedPool,
|
||||
sizeof(HWPROFILE_CHANGE_NOTIFICATION),
|
||||
TAG_PNP_NOTIFY);
|
||||
if (!NotificationInfos)
|
||||
{
|
||||
KeReleaseGuardedMutex(&PnpNotifyListLock);
|
||||
return;
|
||||
}
|
||||
NotificationInfos->Version = 1;
|
||||
NotificationInfos->Size = sizeof(HWPROFILE_CHANGE_NOTIFICATION);
|
||||
RtlCopyMemory(&NotificationInfos->Event, Event, sizeof(GUID));
|
||||
break;
|
||||
}
|
||||
case EventCategoryTargetDeviceChange:
|
||||
{
|
||||
if (Event != &GUID_PNP_CUSTOM_NOTIFICATION)
|
||||
{
|
||||
PTARGET_DEVICE_REMOVAL_NOTIFICATION NotificationInfos;
|
||||
NotificationStructure = NotificationInfos = ExAllocatePoolWithTag(
|
||||
PagedPool,
|
||||
sizeof(TARGET_DEVICE_REMOVAL_NOTIFICATION),
|
||||
TAG_PNP_NOTIFY);
|
||||
if (!NotificationInfos)
|
||||
{
|
||||
KeReleaseGuardedMutex(&PnpNotifyListLock);
|
||||
return;
|
||||
}
|
||||
NotificationInfos->Version = 1;
|
||||
NotificationInfos->Size = sizeof(TARGET_DEVICE_REMOVAL_NOTIFICATION);
|
||||
RtlCopyMemory(&NotificationInfos->Event, Event, sizeof(GUID));
|
||||
}
|
||||
else
|
||||
{
|
||||
PTARGET_DEVICE_CUSTOM_NOTIFICATION NotificationInfos;
|
||||
NotificationStructure = NotificationInfos = ExAllocatePoolWithTag(
|
||||
PagedPool,
|
||||
sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION),
|
||||
TAG_PNP_NOTIFY);
|
||||
if (!NotificationInfos)
|
||||
{
|
||||
KeReleaseGuardedMutex(&PnpNotifyListLock);
|
||||
return;
|
||||
}
|
||||
RtlCopyMemory(NotificationInfos, EventCategoryData1, sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
DPRINT1("IopNotifyPlugPlayNotification(): unknown EventCategory 0x%x UNIMPLEMENTED\n", EventCategory);
|
||||
KeReleaseGuardedMutex(&PnpNotifyListLock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
*notifyStruct = (DEVICE_INTERFACE_CHANGE_NOTIFICATION) {
|
||||
.Version = 1,
|
||||
.Size = sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION),
|
||||
.Event = *Event,
|
||||
.InterfaceClassGuid = *InterfaceClassGuid,
|
||||
.SymbolicLinkName = SymbolicLinkName
|
||||
};
|
||||
|
||||
/* Loop through procedures registred in PnpNotifyListHead
|
||||
* list to find those that meet some criteria.
|
||||
*/
|
||||
ListEntry = PnpNotifyListHead.Flink;
|
||||
while (ListEntry != &PnpNotifyListHead)
|
||||
{
|
||||
ChangeEntry = CONTAINING_RECORD(ListEntry, PNP_NOTIFY_ENTRY, PnpNotifyList);
|
||||
CallCurrentEntry = FALSE;
|
||||
DPRINT("Delivering a DeviceInterfaceChange PnP event\n");
|
||||
|
||||
if (ChangeEntry->EventCategory != EventCategory)
|
||||
KeAcquireGuardedMutex(&PiNotifyDeviceInterfaceLock);
|
||||
|
||||
PLIST_ENTRY entry = PiNotifyDeviceInterfaceListHead.Flink;
|
||||
while (entry != &PiNotifyDeviceInterfaceListHead)
|
||||
{
|
||||
PPNP_NOTIFY_ENTRY nEntry = CONTAINING_RECORD(entry, PNP_NOTIFY_ENTRY, PnpNotifyList);
|
||||
|
||||
if (!IsEqualGUID(¬ifyStruct->InterfaceClassGuid, &nEntry->Guid))
|
||||
{
|
||||
ListEntry = ListEntry->Flink;
|
||||
entry = entry->Flink;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (EventCategory)
|
||||
{
|
||||
case EventCategoryDeviceInterfaceChange:
|
||||
{
|
||||
if (RtlCompareUnicodeString(&ChangeEntry->Guid, &GuidString, FALSE) == 0)
|
||||
{
|
||||
CallCurrentEntry = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EventCategoryHardwareProfileChange:
|
||||
{
|
||||
CallCurrentEntry = TRUE;
|
||||
break;
|
||||
}
|
||||
case EventCategoryTargetDeviceChange:
|
||||
{
|
||||
Status = IoGetRelatedTargetDevice(ChangeEntry->FileObject, &EntryDeviceObject);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
if (DeviceObject == EntryDeviceObject)
|
||||
{
|
||||
if (Event == &GUID_PNP_CUSTOM_NOTIFICATION)
|
||||
{
|
||||
((PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure)->FileObject = ChangeEntry->FileObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
((PTARGET_DEVICE_REMOVAL_NOTIFICATION)NotificationStructure)->FileObject = ChangeEntry->FileObject;
|
||||
}
|
||||
CallCurrentEntry = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
DPRINT1("IopNotifyPlugPlayNotification(): unknown EventCategory 0x%x UNIMPLEMENTED\n", EventCategory);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move to the next element now, as callback may unregister itself */
|
||||
ListEntry = ListEntry->Flink;
|
||||
/* FIXME: If ListEntry was the last element and that callback registers
|
||||
* new notifications, those won't be checked... */
|
||||
|
||||
if (CallCurrentEntry)
|
||||
{
|
||||
/* Call entry into new allocated memory */
|
||||
DPRINT("IopNotifyPlugPlayNotification(): found suitable callback %p\n",
|
||||
ChangeEntry);
|
||||
|
||||
KeReleaseGuardedMutex(&PnpNotifyListLock);
|
||||
(ChangeEntry->PnpNotificationProc)(NotificationStructure,
|
||||
ChangeEntry->Context);
|
||||
KeAcquireGuardedMutex(&PnpNotifyListLock);
|
||||
}
|
||||
|
||||
PiProcessSingleNotification(nEntry, notifyStruct, &PiNotifyDeviceInterfaceLock, &entry);
|
||||
}
|
||||
KeReleaseGuardedMutex(&PnpNotifyListLock);
|
||||
ExFreePoolWithTag(NotificationStructure, TAG_PNP_NOTIFY);
|
||||
if (EventCategory == EventCategoryDeviceInterfaceChange)
|
||||
RtlFreeUnicodeString(&GuidString);
|
||||
|
||||
KeReleaseGuardedMutex(&PiNotifyDeviceInterfaceLock);
|
||||
ExFreePoolWithTag(notifyStruct, TAG_PNP_NOTIFY);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Delivers the event to all drivers subscribed to
|
||||
* EventCategoryHardwareProfileChange PnP event
|
||||
*
|
||||
* @param[in] Event The PnP event GUID
|
||||
*/
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
PiNotifyHardwareProfileChange(
|
||||
_In_ LPCGUID Event)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
PHWPROFILE_CHANGE_NOTIFICATION notifyStruct;
|
||||
notifyStruct = ExAllocatePoolWithTag(PagedPool, sizeof(*notifyStruct), TAG_PNP_NOTIFY);
|
||||
if (!notifyStruct)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
*notifyStruct = (HWPROFILE_CHANGE_NOTIFICATION) {
|
||||
.Version = 1,
|
||||
.Size = sizeof(HWPROFILE_CHANGE_NOTIFICATION),
|
||||
.Event = *Event
|
||||
};
|
||||
|
||||
DPRINT("Delivering a HardwareProfileChange PnP event\n");
|
||||
|
||||
KeAcquireGuardedMutex(&PiNotifyHwProfileLock);
|
||||
|
||||
PLIST_ENTRY entry = PiNotifyHwProfileListHead.Flink;
|
||||
while (entry != &PiNotifyHwProfileListHead)
|
||||
{
|
||||
PPNP_NOTIFY_ENTRY nEntry = CONTAINING_RECORD(entry, PNP_NOTIFY_ENTRY, PnpNotifyList);
|
||||
|
||||
PiProcessSingleNotification(nEntry, notifyStruct, &PiNotifyHwProfileLock, &entry);
|
||||
}
|
||||
|
||||
KeReleaseGuardedMutex(&PiNotifyHwProfileLock);
|
||||
ExFreePoolWithTag(notifyStruct, TAG_PNP_NOTIFY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delivers the event to all drivers subscribed to
|
||||
* EventCategoryTargetDeviceChange PnP event
|
||||
*
|
||||
* @param[in] Event The PnP event GUID
|
||||
* @param[in] DeviceObject The (target) device object
|
||||
* @param[in] CustomNotification Pointer to a custom notification for GUID_PNP_CUSTOM_NOTIFICATION
|
||||
*/
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
PiNotifyTargetDeviceChange(
|
||||
_In_ LPCGUID Event,
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_opt_ PTARGET_DEVICE_CUSTOM_NOTIFICATION CustomNotification)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
PVOID notificationStruct;
|
||||
// just in case our device is removed during the operation
|
||||
ObReferenceObject(DeviceObject);
|
||||
|
||||
PDEVICE_NODE deviceNode = IopGetDeviceNode(DeviceObject);
|
||||
ASSERT(deviceNode);
|
||||
|
||||
if (!IsEqualGUID(Event, &GUID_PNP_CUSTOM_NOTIFICATION))
|
||||
{
|
||||
PTARGET_DEVICE_REMOVAL_NOTIFICATION notifStruct;
|
||||
notifStruct = ExAllocatePoolWithTag(PagedPool, sizeof(*notifStruct), TAG_PNP_NOTIFY);
|
||||
if (!notifStruct)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
*notifStruct = (TARGET_DEVICE_REMOVAL_NOTIFICATION) {
|
||||
.Version = 1,
|
||||
.Size = sizeof(TARGET_DEVICE_REMOVAL_NOTIFICATION),
|
||||
.Event = *Event
|
||||
};
|
||||
|
||||
notificationStruct = notifStruct;
|
||||
|
||||
DPRINT("Delivering a (non-custom) TargetDeviceChange PnP event\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(CustomNotification);
|
||||
// assuming everythng else is correct
|
||||
|
||||
notificationStruct = CustomNotification;
|
||||
|
||||
DPRINT("Delivering a (custom) TargetDeviceChange PnP event\n");
|
||||
}
|
||||
|
||||
KeAcquireGuardedMutex(&PiNotifyTargetDeviceLock);
|
||||
|
||||
PLIST_ENTRY entry = deviceNode->TargetDeviceNotify.Flink;
|
||||
while (entry != &deviceNode->TargetDeviceNotify)
|
||||
{
|
||||
PPNP_NOTIFY_ENTRY nEntry = CONTAINING_RECORD(entry, PNP_NOTIFY_ENTRY, PnpNotifyList);
|
||||
|
||||
// put the file object from our saved entry to this particular notification's struct
|
||||
((PTARGET_DEVICE_REMOVAL_NOTIFICATION)notificationStruct)->FileObject = nEntry->FileObject;
|
||||
// so you don't need to look at the definition ;)
|
||||
C_ASSERT(FIELD_OFFSET(TARGET_DEVICE_REMOVAL_NOTIFICATION, FileObject)
|
||||
== FIELD_OFFSET(TARGET_DEVICE_CUSTOM_NOTIFICATION, FileObject));
|
||||
|
||||
PiProcessSingleNotification(nEntry, notificationStruct, &PiNotifyTargetDeviceLock, &entry);
|
||||
}
|
||||
|
||||
KeReleaseGuardedMutex(&PiNotifyTargetDeviceLock);
|
||||
ExFreePoolWithTag(notificationStruct, TAG_PNP_NOTIFY);
|
||||
ObDereferenceObject(DeviceObject);
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS **********************************************************/
|
||||
|
@ -232,10 +326,11 @@ IopNotifyPlugPlayNotification(
|
|||
*/
|
||||
ULONG
|
||||
NTAPI
|
||||
IoPnPDeliverServicePowerNotification(ULONG VetoedPowerOperation OPTIONAL,
|
||||
ULONG PowerNotification,
|
||||
ULONG Unknown OPTIONAL,
|
||||
BOOLEAN Synchronous)
|
||||
IoPnPDeliverServicePowerNotification(
|
||||
_In_ ULONG VetoedPowerOperation,
|
||||
_In_ ULONG PowerNotificationCode,
|
||||
_In_ ULONG PowerNotificationData,
|
||||
_In_ BOOLEAN Synchronous)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return 0;
|
||||
|
@ -244,15 +339,17 @@ IoPnPDeliverServicePowerNotification(ULONG VetoedPowerOperation OPTIONAL,
|
|||
/*
|
||||
* @implemented
|
||||
*/
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
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)
|
||||
IoRegisterPlugPlayNotification(
|
||||
_In_ IO_NOTIFICATION_EVENT_CATEGORY EventCategory,
|
||||
_In_ ULONG EventCategoryFlags,
|
||||
_In_opt_ PVOID EventCategoryData,
|
||||
_In_ PDRIVER_OBJECT DriverObject,
|
||||
_In_ PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine,
|
||||
_Inout_opt_ PVOID Context,
|
||||
_Out_ PVOID *NotificationEntry)
|
||||
{
|
||||
PPNP_NOTIFY_ENTRY Entry;
|
||||
PWSTR SymbolicLinkList;
|
||||
|
@ -260,18 +357,12 @@ IoRegisterPlugPlayNotification(IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory,
|
|||
PAGED_CODE();
|
||||
|
||||
DPRINT("%s(EventCategory 0x%x, EventCategoryFlags 0x%lx, DriverObject %p) called.\n",
|
||||
__FUNCTION__,
|
||||
EventCategory,
|
||||
EventCategoryFlags,
|
||||
DriverObject);
|
||||
__FUNCTION__, EventCategory, EventCategoryFlags, DriverObject);
|
||||
|
||||
ObReferenceObject(DriverObject);
|
||||
|
||||
/* Try to allocate entry for notification before sending any notification */
|
||||
Entry = ExAllocatePoolWithTag(NonPagedPool,
|
||||
sizeof(PNP_NOTIFY_ENTRY),
|
||||
TAG_PNP_NOTIFY);
|
||||
|
||||
Entry = ExAllocatePoolWithTag(PagedPool, sizeof(PNP_NOTIFY_ENTRY), TAG_PNP_NOTIFY);
|
||||
if (!Entry)
|
||||
{
|
||||
DPRINT("ExAllocatePool() failed\n");
|
||||
|
@ -279,83 +370,99 @@ IoRegisterPlugPlayNotification(IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory,
|
|||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
if (EventCategory == EventCategoryDeviceInterfaceChange &&
|
||||
EventCategoryFlags & PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES)
|
||||
{
|
||||
DEVICE_INTERFACE_CHANGE_NOTIFICATION NotificationInfos;
|
||||
UNICODE_STRING SymbolicLinkU;
|
||||
PWSTR SymbolicLink;
|
||||
*Entry = (PNP_NOTIFY_ENTRY) {
|
||||
.PnpNotificationProc = CallbackRoutine,
|
||||
.Context = Context,
|
||||
.DriverObject = DriverObject,
|
||||
.EventCategory = EventCategory,
|
||||
.RefCount = 1
|
||||
};
|
||||
|
||||
Status = IoGetDeviceInterfaces((LPGUID)EventCategoryData,
|
||||
NULL, /* PhysicalDeviceObject OPTIONAL */
|
||||
0, /* Flags */
|
||||
&SymbolicLinkList);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Enumerate SymbolicLinkList */
|
||||
NotificationInfos.Version = 1;
|
||||
NotificationInfos.Size = sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION);
|
||||
RtlCopyMemory(&NotificationInfos.Event,
|
||||
&GUID_DEVICE_INTERFACE_ARRIVAL,
|
||||
sizeof(GUID));
|
||||
RtlCopyMemory(&NotificationInfos.InterfaceClassGuid,
|
||||
EventCategoryData,
|
||||
sizeof(GUID));
|
||||
NotificationInfos.SymbolicLinkName = &SymbolicLinkU;
|
||||
|
||||
for (SymbolicLink = SymbolicLinkList;
|
||||
*SymbolicLink;
|
||||
SymbolicLink += wcslen(SymbolicLink) + 1)
|
||||
{
|
||||
RtlInitUnicodeString(&SymbolicLinkU, SymbolicLink);
|
||||
DPRINT("Calling callback routine for %S\n", SymbolicLink);
|
||||
(*CallbackRoutine)(&NotificationInfos, Context);
|
||||
}
|
||||
|
||||
ExFreePool(SymbolicLinkList);
|
||||
}
|
||||
}
|
||||
|
||||
Entry->PnpNotificationProc = CallbackRoutine;
|
||||
Entry->EventCategory = EventCategory;
|
||||
Entry->Context = Context;
|
||||
Entry->DriverObject = DriverObject;
|
||||
switch (EventCategory)
|
||||
{
|
||||
case EventCategoryDeviceInterfaceChange:
|
||||
{
|
||||
Status = RtlStringFromGUID(EventCategoryData, &Entry->Guid);
|
||||
if (!NT_SUCCESS(Status))
|
||||
Entry->Guid = *(LPGUID)EventCategoryData;
|
||||
|
||||
// first register the notification
|
||||
KeAcquireGuardedMutex(&PiNotifyDeviceInterfaceLock);
|
||||
InsertTailList(&PiNotifyDeviceInterfaceListHead, &Entry->PnpNotifyList);
|
||||
KeReleaseGuardedMutex(&PiNotifyDeviceInterfaceLock);
|
||||
|
||||
// then process existing interfaces if asked
|
||||
if (EventCategoryFlags & PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES)
|
||||
{
|
||||
ExFreePoolWithTag(Entry, TAG_PNP_NOTIFY);
|
||||
ObDereferenceObject(DriverObject);
|
||||
return Status;
|
||||
DEVICE_INTERFACE_CHANGE_NOTIFICATION NotificationInfos;
|
||||
UNICODE_STRING SymbolicLinkU;
|
||||
PWSTR SymbolicLink;
|
||||
|
||||
Status = IoGetDeviceInterfaces((LPGUID)EventCategoryData,
|
||||
NULL, /* PhysicalDeviceObject OPTIONAL */
|
||||
0, /* Flags */
|
||||
&SymbolicLinkList);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Enumerate SymbolicLinkList */
|
||||
NotificationInfos.Version = 1;
|
||||
NotificationInfos.Size = sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION);
|
||||
NotificationInfos.Event = GUID_DEVICE_INTERFACE_ARRIVAL;
|
||||
NotificationInfos.InterfaceClassGuid = *(LPGUID)EventCategoryData;
|
||||
NotificationInfos.SymbolicLinkName = &SymbolicLinkU;
|
||||
|
||||
for (SymbolicLink = SymbolicLinkList;
|
||||
*SymbolicLink;
|
||||
SymbolicLink += (SymbolicLinkU.Length / sizeof(WCHAR)) + 1)
|
||||
{
|
||||
RtlInitUnicodeString(&SymbolicLinkU, SymbolicLink);
|
||||
DPRINT("Calling callback routine for %S\n", SymbolicLink);
|
||||
PiCallNotifyProc(CallbackRoutine, &NotificationInfos, Context);
|
||||
}
|
||||
|
||||
ExFreePool(SymbolicLinkList);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EventCategoryHardwareProfileChange:
|
||||
{
|
||||
/* nothing to do */
|
||||
break;
|
||||
KeAcquireGuardedMutex(&PiNotifyHwProfileLock);
|
||||
InsertTailList(&PiNotifyHwProfileListHead, &Entry->PnpNotifyList);
|
||||
KeReleaseGuardedMutex(&PiNotifyHwProfileLock);
|
||||
break;
|
||||
}
|
||||
case EventCategoryTargetDeviceChange:
|
||||
{
|
||||
PDEVICE_NODE deviceNode;
|
||||
Entry->FileObject = (PFILE_OBJECT)EventCategoryData;
|
||||
|
||||
// NOTE: the device node's PDO is referenced here
|
||||
Status = IopGetRelatedTargetDevice(Entry->FileObject, &deviceNode);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ObDereferenceObject(DriverObject);
|
||||
ExFreePoolWithTag(Entry, TAG_PNP_NOTIFY);
|
||||
return Status;
|
||||
}
|
||||
// save it so we can dereference it later
|
||||
Entry->DeviceObject = deviceNode->PhysicalDeviceObject;
|
||||
|
||||
// each DEVICE_NODE has its own registered notifications list
|
||||
KeAcquireGuardedMutex(&PiNotifyTargetDeviceLock);
|
||||
InsertTailList(&deviceNode->TargetDeviceNotify, &Entry->PnpNotifyList);
|
||||
KeReleaseGuardedMutex(&PiNotifyTargetDeviceLock);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
DPRINT1("%s: unknown EventCategory 0x%x UNIMPLEMENTED\n",
|
||||
__FUNCTION__, EventCategory);
|
||||
break;
|
||||
|
||||
ObDereferenceObject(DriverObject);
|
||||
ExFreePoolWithTag(Entry, TAG_PNP_NOTIFY);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
KeAcquireGuardedMutex(&PnpNotifyListLock);
|
||||
InsertHeadList(&PnpNotifyListHead,
|
||||
&Entry->PnpNotifyList);
|
||||
KeReleaseGuardedMutex(&PnpNotifyListLock);
|
||||
|
||||
DPRINT("%s returns NotificationEntry %p\n", __FUNCTION__, Entry);
|
||||
|
||||
*NotificationEntry = Entry;
|
||||
|
@ -366,25 +473,46 @@ IoRegisterPlugPlayNotification(IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory,
|
|||
/*
|
||||
* @implemented
|
||||
*/
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IoUnregisterPlugPlayNotification(IN PVOID NotificationEntry)
|
||||
IoUnregisterPlugPlayNotification(
|
||||
_In_ PVOID NotificationEntry)
|
||||
{
|
||||
PPNP_NOTIFY_ENTRY Entry;
|
||||
PPNP_NOTIFY_ENTRY Entry = NotificationEntry;
|
||||
PKGUARDED_MUTEX Lock;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
Entry = (PPNP_NOTIFY_ENTRY)NotificationEntry;
|
||||
DPRINT("%s(NotificationEntry %p) called\n", __FUNCTION__, Entry);
|
||||
|
||||
KeAcquireGuardedMutex(&PnpNotifyListLock);
|
||||
RemoveEntryList(&Entry->PnpNotifyList);
|
||||
KeReleaseGuardedMutex(&PnpNotifyListLock);
|
||||
switch (Entry->EventCategory)
|
||||
{
|
||||
case EventCategoryDeviceInterfaceChange:
|
||||
Lock = &PiNotifyDeviceInterfaceLock;
|
||||
break;
|
||||
case EventCategoryHardwareProfileChange:
|
||||
Lock = &PiNotifyHwProfileLock;
|
||||
break;
|
||||
case EventCategoryTargetDeviceChange:
|
||||
Lock = &PiNotifyTargetDeviceLock;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE;
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
RtlFreeUnicodeString(&Entry->Guid);
|
||||
|
||||
ObDereferenceObject(Entry->DriverObject);
|
||||
|
||||
ExFreePoolWithTag(Entry, TAG_PNP_NOTIFY);
|
||||
KeAcquireGuardedMutex(Lock);
|
||||
if (!Entry->Deleted)
|
||||
{
|
||||
Entry->Deleted = TRUE; // so it can't be unregistered two times
|
||||
PiDereferencePnpNotifyEntry(Entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("IoUnregisterPlugPlayNotification called two times for 0x%p\n", NotificationEntry);
|
||||
}
|
||||
KeReleaseGuardedMutex(Lock);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -131,11 +131,7 @@ PpSetCustomTargetEvent(IN PDEVICE_OBJECT DeviceObject,
|
|||
}
|
||||
|
||||
/* That call is totally wrong but notifications handler must be fixed first */
|
||||
IopNotifyPlugPlayNotification(DeviceObject,
|
||||
EventCategoryTargetDeviceChange,
|
||||
&GUID_PNP_CUSTOM_NOTIFICATION,
|
||||
NotificationStructure,
|
||||
NULL);
|
||||
PiNotifyTargetDeviceChange(&GUID_PNP_CUSTOM_NOTIFICATION, DeviceObject, NotificationStructure);
|
||||
|
||||
if (SyncEvent)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue