3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/pnpnotify.c
6 * PURPOSE: Plug & Play notification functions
8 * PROGRAMMERS: Filip Navara (xnavara@volny.cz)
9 * Hervé Poussineau (hpoussin@reactos.com)
12 /* INCLUDES ******************************************************************/
16 #include <internal/debug.h>
18 #if defined (ALLOC_PRAGMA)
19 #pragma alloc_text(INIT, IopInitPnpNotificationImplementation)
23 /* TYPES *******************************************************************/
25 typedef struct _PNP_NOTIFY_ENTRY
27 LIST_ENTRY PnpNotifyList
;
28 IO_NOTIFICATION_EVENT_CATEGORY EventCategory
;
31 PFILE_OBJECT FileObject
;
32 PDRIVER_NOTIFICATION_CALLBACK_ROUTINE PnpNotificationProc
;
33 } PNP_NOTIFY_ENTRY
, *PPNP_NOTIFY_ENTRY
;
35 static KGUARDED_MUTEX PnpNotifyListLock
;
36 static LIST_ENTRY PnpNotifyListHead
;
38 /* FUNCTIONS *****************************************************************/
45 IoPnPDeliverServicePowerNotification(
46 ULONG VetoedPowerOperation OPTIONAL
,
47 ULONG PowerNotification
,
48 ULONG Unknown OPTIONAL
,
61 IoRegisterPlugPlayNotification(
62 IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory
,
63 IN ULONG EventCategoryFlags
,
64 IN PVOID EventCategoryData OPTIONAL
,
65 IN PDRIVER_OBJECT DriverObject
,
66 IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine
,
68 OUT PVOID
*NotificationEntry
)
70 PPNP_NOTIFY_ENTRY Entry
;
71 PWSTR SymbolicLinkList
;
76 DPRINT("IoRegisterPlugPlayNotification(EventCategory 0x%x, EventCategoryFlags 0x%lx, DriverObject %p) called.\n",
81 ObReferenceObject(DriverObject
);
83 /* Try to allocate entry for notification before sending any notification */
84 Entry
= ExAllocatePoolWithTag(
86 sizeof(PNP_NOTIFY_ENTRY
),
90 DPRINT("ExAllocatePool() failed\n");
91 ObDereferenceObject(DriverObject
);
92 return STATUS_INSUFFICIENT_RESOURCES
;
95 if (EventCategory
== EventCategoryTargetDeviceChange
96 && EventCategoryFlags
& PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES
)
98 Status
= IoGetDeviceInterfaces(
99 (LPGUID
)EventCategoryData
,
100 NULL
, /* PhysicalDeviceObject OPTIONAL */
103 if (!NT_SUCCESS(Status
))
105 DPRINT("IoGetDeviceInterfaces() failed with status 0x%08lx\n", Status
);
106 ExFreePoolWithTag(Entry
, TAG_PNP_NOTIFY
);
107 ObDereferenceObject(DriverObject
);
110 /* FIXME: enumerate SymbolicLinkList */
111 DPRINT1("IoRegisterPlugPlayNotification(): need to send notifications for existing interfaces!\n");
112 ExFreePool(SymbolicLinkList
);
115 Entry
->PnpNotificationProc
= CallbackRoutine
;
116 Entry
->EventCategory
= EventCategory
;
117 Entry
->Context
= Context
;
118 switch (EventCategory
)
120 case EventCategoryDeviceInterfaceChange
:
122 Status
= RtlStringFromGUID(EventCategoryData
, &Entry
->Guid
);
123 if (!NT_SUCCESS(Status
))
125 ExFreePoolWithTag(Entry
, TAG_PNP_NOTIFY
);
126 ObDereferenceObject(DriverObject
);
131 case EventCategoryHardwareProfileChange
:
136 case EventCategoryTargetDeviceChange
:
138 Entry
->FileObject
= (PFILE_OBJECT
)EventCategoryData
;
143 DPRINT1("IoRegisterPlugPlayNotification(): unknown EventCategory 0x%x UNIMPLEMENTED\n", EventCategory
);
148 KeAcquireGuardedMutex(&PnpNotifyListLock
);
149 InsertHeadList(&PnpNotifyListHead
,
150 &Entry
->PnpNotifyList
);
151 KeReleaseGuardedMutex(&PnpNotifyListLock
);
153 DPRINT("IoRegisterPlugPlayNotification() returns NotificationEntry %p\n",
155 *NotificationEntry
= Entry
;
156 return STATUS_SUCCESS
;
164 IoUnregisterPlugPlayNotification(
165 IN PVOID NotificationEntry
)
167 PPNP_NOTIFY_ENTRY Entry
;
171 Entry
= (PPNP_NOTIFY_ENTRY
)NotificationEntry
;
172 DPRINT("IoUnregisterPlugPlayNotification(NotificationEntry %p) called\n",
175 KeAcquireGuardedMutex(&PnpNotifyListLock
);
176 RtlFreeUnicodeString(&Entry
->Guid
);
177 RemoveEntryList(&Entry
->PnpNotifyList
);
178 KeReleaseGuardedMutex(&PnpNotifyListLock
);
180 return STATUS_SUCCESS
;
184 IopNotifyPlugPlayNotification(
185 IN PDEVICE_OBJECT DeviceObject
,
186 IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory
,
188 IN PVOID EventCategoryData1
,
189 IN PVOID EventCategoryData2
)
191 PPNP_NOTIFY_ENTRY ChangeEntry
;
192 PVOID NotificationStructure
;
193 BOOLEAN CallCurrentEntry
;
195 ASSERT(DeviceObject
);
197 KeAcquireGuardedMutex(&PnpNotifyListLock
);
198 if (IsListEmpty(&PnpNotifyListHead
))
200 KeReleaseGuardedMutex(&PnpNotifyListLock
);
204 switch (EventCategory
)
206 case EventCategoryDeviceInterfaceChange
:
208 PDEVICE_INTERFACE_CHANGE_NOTIFICATION NotificationInfos
;
209 NotificationStructure
= NotificationInfos
= ExAllocatePoolWithTag(
211 sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION
),
213 NotificationInfos
->Version
= 1;
214 NotificationInfos
->Size
= sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION
);
215 RtlCopyMemory(&NotificationInfos
->Event
, Event
, sizeof(GUID
));
216 RtlCopyMemory(&NotificationInfos
->InterfaceClassGuid
, EventCategoryData1
, sizeof(GUID
));
217 NotificationInfos
->SymbolicLinkName
= (PUNICODE_STRING
)EventCategoryData2
;
220 case EventCategoryHardwareProfileChange
:
222 PHWPROFILE_CHANGE_NOTIFICATION NotificationInfos
;
223 NotificationStructure
= NotificationInfos
= ExAllocatePoolWithTag(
225 sizeof(HWPROFILE_CHANGE_NOTIFICATION
),
227 NotificationInfos
->Version
= 1;
228 NotificationInfos
->Size
= sizeof(HWPROFILE_CHANGE_NOTIFICATION
);
229 RtlCopyMemory(&NotificationInfos
->Event
, Event
, sizeof(GUID
));
232 case EventCategoryTargetDeviceChange
:
234 PTARGET_DEVICE_REMOVAL_NOTIFICATION NotificationInfos
;
235 NotificationStructure
= NotificationInfos
= ExAllocatePoolWithTag(
237 sizeof(TARGET_DEVICE_REMOVAL_NOTIFICATION
),
239 NotificationInfos
->Version
= 1;
240 NotificationInfos
->Size
= sizeof(TARGET_DEVICE_REMOVAL_NOTIFICATION
);
241 RtlCopyMemory(&NotificationInfos
->Event
, Event
, sizeof(GUID
));
242 NotificationInfos
->FileObject
= (PFILE_OBJECT
)EventCategoryData1
;
247 DPRINT1("IopNotifyPlugPlayNotification(): unknown EventCategory 0x%x UNIMPLEMENTED\n", EventCategory
);
252 /* Loop through procedures registred in PnpNotifyListHead
253 * list to find those that meet some criteria.
256 LIST_FOR_EACH(ChangeEntry
,&PnpNotifyListHead
, PNP_NOTIFY_ENTRY
, PnpNotifyList
)
258 CallCurrentEntry
= FALSE
;
260 switch (EventCategory
)
262 case EventCategoryDeviceInterfaceChange
:
264 if (ChangeEntry
->EventCategory
== EventCategory
265 && RtlCompareUnicodeString(&ChangeEntry
->Guid
, (PUNICODE_STRING
)EventCategoryData1
, FALSE
) == 0)
267 CallCurrentEntry
= TRUE
;
271 case EventCategoryHardwareProfileChange
:
273 CallCurrentEntry
= TRUE
;
276 case EventCategoryTargetDeviceChange
:
278 if (ChangeEntry
->FileObject
== (PFILE_OBJECT
)EventCategoryData1
)
279 CallCurrentEntry
= TRUE
;
283 DPRINT1("IopNotifyPlugPlayNotification(): unknown EventCategory 0x%x UNIMPLEMENTED\n", EventCategory
);
288 if (CallCurrentEntry
)
290 /* Call entry into new allocated memory */
291 DPRINT("IopNotifyPlugPlayNotification(): found suitable callback %p\n",
294 (ChangeEntry
->PnpNotificationProc
)(
295 NotificationStructure
,
296 ChangeEntry
->Context
);
300 KeReleaseGuardedMutex(&PnpNotifyListLock
);
301 ExFreePoolWithTag(NotificationStructure
, TAG_PNP_NOTIFY
);
305 IopInitPnpNotificationImplementation(VOID
)
307 KeInitializeGuardedMutex(&PnpNotifyListLock
);
308 InitializeListHead(&PnpNotifyListHead
);