Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpnpnotify.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * COPYRIGHT: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/io/pnpmgr/pnpnotify.c 00005 * PURPOSE: Plug & Play notification functions 00006 * PROGRAMMERS: Filip Navara (xnavara@volny.cz) 00007 * Hervé Poussineau (hpoussin@reactos.org) 00008 * Pierre Schweitzer 00009 */ 00010 00011 /* INCLUDES ******************************************************************/ 00012 00013 #include <ntoskrnl.h> 00014 #define NDEBUG 00015 #include <debug.h> 00016 00017 /* TYPES *******************************************************************/ 00018 00019 typedef struct _PNP_NOTIFY_ENTRY 00020 { 00021 LIST_ENTRY PnpNotifyList; 00022 IO_NOTIFICATION_EVENT_CATEGORY EventCategory; 00023 PVOID Context; 00024 UNICODE_STRING Guid; 00025 PFILE_OBJECT FileObject; 00026 PDRIVER_OBJECT DriverObject; 00027 PDRIVER_NOTIFICATION_CALLBACK_ROUTINE PnpNotificationProc; 00028 } PNP_NOTIFY_ENTRY, *PPNP_NOTIFY_ENTRY; 00029 00030 KGUARDED_MUTEX PnpNotifyListLock; 00031 LIST_ENTRY PnpNotifyListHead; 00032 00033 /* FUNCTIONS *****************************************************************/ 00034 00035 VOID 00036 IopNotifyPlugPlayNotification( 00037 IN PDEVICE_OBJECT DeviceObject, 00038 IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory, 00039 IN LPCGUID Event, 00040 IN PVOID EventCategoryData1, 00041 IN PVOID EventCategoryData2) 00042 { 00043 PPNP_NOTIFY_ENTRY ChangeEntry; 00044 PLIST_ENTRY ListEntry; 00045 PVOID NotificationStructure; 00046 BOOLEAN CallCurrentEntry; 00047 UNICODE_STRING GuidString; 00048 NTSTATUS Status; 00049 PDEVICE_OBJECT EntryDeviceObject = NULL; 00050 00051 ASSERT(DeviceObject); 00052 00053 KeAcquireGuardedMutex(&PnpNotifyListLock); 00054 if (IsListEmpty(&PnpNotifyListHead)) 00055 { 00056 KeReleaseGuardedMutex(&PnpNotifyListLock); 00057 return; 00058 } 00059 00060 switch (EventCategory) 00061 { 00062 case EventCategoryDeviceInterfaceChange: 00063 { 00064 PDEVICE_INTERFACE_CHANGE_NOTIFICATION NotificationInfos; 00065 NotificationStructure = NotificationInfos = ExAllocatePoolWithTag( 00066 PagedPool, 00067 sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION), 00068 TAG_PNP_NOTIFY); 00069 if (!NotificationInfos) 00070 { 00071 KeReleaseGuardedMutex(&PnpNotifyListLock); 00072 return; 00073 } 00074 NotificationInfos->Version = 1; 00075 NotificationInfos->Size = sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION); 00076 RtlCopyMemory(&NotificationInfos->Event, Event, sizeof(GUID)); 00077 RtlCopyMemory(&NotificationInfos->InterfaceClassGuid, EventCategoryData1, sizeof(GUID)); 00078 NotificationInfos->SymbolicLinkName = (PUNICODE_STRING)EventCategoryData2; 00079 Status = RtlStringFromGUID(&NotificationInfos->InterfaceClassGuid, &GuidString); 00080 if (!NT_SUCCESS(Status)) 00081 { 00082 KeReleaseGuardedMutex(&PnpNotifyListLock); 00083 ExFreePool(NotificationStructure); 00084 return; 00085 } 00086 break; 00087 } 00088 case EventCategoryHardwareProfileChange: 00089 { 00090 PHWPROFILE_CHANGE_NOTIFICATION NotificationInfos; 00091 NotificationStructure = NotificationInfos = ExAllocatePoolWithTag( 00092 PagedPool, 00093 sizeof(HWPROFILE_CHANGE_NOTIFICATION), 00094 TAG_PNP_NOTIFY); 00095 if (!NotificationInfos) 00096 { 00097 KeReleaseGuardedMutex(&PnpNotifyListLock); 00098 return; 00099 } 00100 NotificationInfos->Version = 1; 00101 NotificationInfos->Size = sizeof(HWPROFILE_CHANGE_NOTIFICATION); 00102 RtlCopyMemory(&NotificationInfos->Event, Event, sizeof(GUID)); 00103 break; 00104 } 00105 case EventCategoryTargetDeviceChange: 00106 { 00107 if (Event != &GUID_PNP_CUSTOM_NOTIFICATION) 00108 { 00109 PTARGET_DEVICE_REMOVAL_NOTIFICATION NotificationInfos; 00110 NotificationStructure = NotificationInfos = ExAllocatePoolWithTag( 00111 PagedPool, 00112 sizeof(TARGET_DEVICE_REMOVAL_NOTIFICATION), 00113 TAG_PNP_NOTIFY); 00114 if (!NotificationInfos) 00115 { 00116 KeReleaseGuardedMutex(&PnpNotifyListLock); 00117 return; 00118 } 00119 NotificationInfos->Version = 1; 00120 NotificationInfos->Size = sizeof(TARGET_DEVICE_REMOVAL_NOTIFICATION); 00121 RtlCopyMemory(&NotificationInfos->Event, Event, sizeof(GUID)); 00122 } 00123 else 00124 { 00125 PTARGET_DEVICE_CUSTOM_NOTIFICATION NotificationInfos; 00126 NotificationStructure = NotificationInfos = ExAllocatePoolWithTag( 00127 PagedPool, 00128 sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION), 00129 TAG_PNP_NOTIFY); 00130 if (!NotificationInfos) 00131 { 00132 KeReleaseGuardedMutex(&PnpNotifyListLock); 00133 return; 00134 } 00135 RtlCopyMemory(NotificationInfos, EventCategoryData1, sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION)); 00136 } 00137 break; 00138 } 00139 default: 00140 { 00141 DPRINT1("IopNotifyPlugPlayNotification(): unknown EventCategory 0x%x UNIMPLEMENTED\n", EventCategory); 00142 KeReleaseGuardedMutex(&PnpNotifyListLock); 00143 return; 00144 } 00145 } 00146 00147 /* Loop through procedures registred in PnpNotifyListHead 00148 * list to find those that meet some criteria. 00149 */ 00150 ListEntry = PnpNotifyListHead.Flink; 00151 while (ListEntry != &PnpNotifyListHead) 00152 { 00153 ChangeEntry = CONTAINING_RECORD(ListEntry, PNP_NOTIFY_ENTRY, PnpNotifyList); 00154 CallCurrentEntry = FALSE; 00155 00156 if (ChangeEntry->EventCategory != EventCategory) 00157 { 00158 ListEntry = ListEntry->Flink; 00159 continue; 00160 } 00161 00162 switch (EventCategory) 00163 { 00164 case EventCategoryDeviceInterfaceChange: 00165 { 00166 if (RtlCompareUnicodeString(&ChangeEntry->Guid, &GuidString, FALSE) == 0) 00167 { 00168 CallCurrentEntry = TRUE; 00169 } 00170 break; 00171 } 00172 case EventCategoryHardwareProfileChange: 00173 { 00174 CallCurrentEntry = TRUE; 00175 break; 00176 } 00177 case EventCategoryTargetDeviceChange: 00178 { 00179 Status = IoGetRelatedTargetDevice(ChangeEntry->FileObject, &EntryDeviceObject); 00180 if (NT_SUCCESS(Status)) 00181 { 00182 if (DeviceObject == EntryDeviceObject) 00183 { 00184 if (Event == &GUID_PNP_CUSTOM_NOTIFICATION) 00185 { 00186 ((PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure)->FileObject = ChangeEntry->FileObject; 00187 } 00188 else 00189 { 00190 ((PTARGET_DEVICE_REMOVAL_NOTIFICATION)NotificationStructure)->FileObject = ChangeEntry->FileObject; 00191 } 00192 CallCurrentEntry = TRUE; 00193 } 00194 } 00195 } 00196 default: 00197 { 00198 DPRINT1("IopNotifyPlugPlayNotification(): unknown EventCategory 0x%x UNIMPLEMENTED\n", EventCategory); 00199 break; 00200 } 00201 } 00202 00203 /* Move to the next element now, as callback may unregister itself */ 00204 ListEntry = ListEntry->Flink; 00205 /* FIXME: If ListEntry was the last element and that callback registers 00206 * new notifications, those won't be checked... */ 00207 00208 if (CallCurrentEntry) 00209 { 00210 /* Call entry into new allocated memory */ 00211 DPRINT("IopNotifyPlugPlayNotification(): found suitable callback %p\n", 00212 ChangeEntry); 00213 00214 KeReleaseGuardedMutex(&PnpNotifyListLock); 00215 (ChangeEntry->PnpNotificationProc)( 00216 NotificationStructure, 00217 ChangeEntry->Context); 00218 KeAcquireGuardedMutex(&PnpNotifyListLock); 00219 } 00220 00221 } 00222 KeReleaseGuardedMutex(&PnpNotifyListLock); 00223 ExFreePoolWithTag(NotificationStructure, TAG_PNP_NOTIFY); 00224 if (EventCategory == EventCategoryDeviceInterfaceChange) 00225 RtlFreeUnicodeString(&GuidString); 00226 } 00227 00228 /* PUBLIC FUNCTIONS **********************************************************/ 00229 00230 /* 00231 * @unimplemented 00232 */ 00233 ULONG 00234 NTAPI 00235 IoPnPDeliverServicePowerNotification(ULONG VetoedPowerOperation OPTIONAL, 00236 ULONG PowerNotification, 00237 ULONG Unknown OPTIONAL, 00238 BOOLEAN Synchronous) 00239 { 00240 UNIMPLEMENTED; 00241 return 0; 00242 } 00243 00244 /* 00245 * @implemented 00246 */ 00247 NTSTATUS 00248 NTAPI 00249 IoRegisterPlugPlayNotification(IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory, 00250 IN ULONG EventCategoryFlags, 00251 IN PVOID EventCategoryData OPTIONAL, 00252 IN PDRIVER_OBJECT DriverObject, 00253 IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine, 00254 IN PVOID Context, 00255 OUT PVOID *NotificationEntry) 00256 { 00257 PPNP_NOTIFY_ENTRY Entry; 00258 PWSTR SymbolicLinkList; 00259 NTSTATUS Status; 00260 PAGED_CODE(); 00261 00262 DPRINT("%s(EventCategory 0x%x, EventCategoryFlags 0x%lx, DriverObject %p) called.\n", 00263 __FUNCTION__, 00264 EventCategory, 00265 EventCategoryFlags, 00266 DriverObject); 00267 00268 ObReferenceObject(DriverObject); 00269 00270 /* Try to allocate entry for notification before sending any notification */ 00271 Entry = ExAllocatePoolWithTag(NonPagedPool, 00272 sizeof(PNP_NOTIFY_ENTRY), 00273 TAG_PNP_NOTIFY); 00274 00275 if (!Entry) 00276 { 00277 DPRINT("ExAllocatePool() failed\n"); 00278 ObDereferenceObject(DriverObject); 00279 return STATUS_INSUFFICIENT_RESOURCES; 00280 } 00281 00282 if (EventCategory == EventCategoryDeviceInterfaceChange && 00283 EventCategoryFlags & PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES) 00284 { 00285 DEVICE_INTERFACE_CHANGE_NOTIFICATION NotificationInfos; 00286 UNICODE_STRING SymbolicLinkU; 00287 PWSTR SymbolicLink; 00288 00289 Status = IoGetDeviceInterfaces((LPGUID)EventCategoryData, 00290 NULL, /* PhysicalDeviceObject OPTIONAL */ 00291 0, /* Flags */ 00292 &SymbolicLinkList); 00293 if (NT_SUCCESS(Status)) 00294 { 00295 /* Enumerate SymbolicLinkList */ 00296 NotificationInfos.Version = 1; 00297 NotificationInfos.Size = sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION); 00298 RtlCopyMemory(&NotificationInfos.Event, 00299 &GUID_DEVICE_INTERFACE_ARRIVAL, 00300 sizeof(GUID)); 00301 RtlCopyMemory(&NotificationInfos.InterfaceClassGuid, 00302 EventCategoryData, 00303 sizeof(GUID)); 00304 NotificationInfos.SymbolicLinkName = &SymbolicLinkU; 00305 00306 for (SymbolicLink = SymbolicLinkList; 00307 *SymbolicLink; 00308 SymbolicLink += wcslen(SymbolicLink) + 1) 00309 { 00310 RtlInitUnicodeString(&SymbolicLinkU, SymbolicLink); 00311 DPRINT("Calling callback routine for %S\n", SymbolicLink); 00312 (*CallbackRoutine)(&NotificationInfos, Context); 00313 } 00314 00315 ExFreePool(SymbolicLinkList); 00316 } 00317 } 00318 00319 Entry->PnpNotificationProc = CallbackRoutine; 00320 Entry->EventCategory = EventCategory; 00321 Entry->Context = Context; 00322 Entry->DriverObject = DriverObject; 00323 switch (EventCategory) 00324 { 00325 case EventCategoryDeviceInterfaceChange: 00326 { 00327 Status = RtlStringFromGUID(EventCategoryData, &Entry->Guid); 00328 if (!NT_SUCCESS(Status)) 00329 { 00330 ExFreePoolWithTag(Entry, TAG_PNP_NOTIFY); 00331 ObDereferenceObject(DriverObject); 00332 return Status; 00333 } 00334 break; 00335 } 00336 case EventCategoryHardwareProfileChange: 00337 { 00338 /* nothing to do */ 00339 break; 00340 } 00341 case EventCategoryTargetDeviceChange: 00342 { 00343 Entry->FileObject = (PFILE_OBJECT)EventCategoryData; 00344 break; 00345 } 00346 default: 00347 { 00348 DPRINT1("%s: unknown EventCategory 0x%x UNIMPLEMENTED\n", 00349 __FUNCTION__, EventCategory); 00350 break; 00351 } 00352 } 00353 00354 KeAcquireGuardedMutex(&PnpNotifyListLock); 00355 InsertHeadList(&PnpNotifyListHead, 00356 &Entry->PnpNotifyList); 00357 KeReleaseGuardedMutex(&PnpNotifyListLock); 00358 00359 DPRINT("%s returns NotificationEntry %p\n", __FUNCTION__, Entry); 00360 00361 *NotificationEntry = Entry; 00362 00363 return STATUS_SUCCESS; 00364 } 00365 00366 /* 00367 * @implemented 00368 */ 00369 NTSTATUS 00370 NTAPI 00371 IoUnregisterPlugPlayNotification(IN PVOID NotificationEntry) 00372 { 00373 PPNP_NOTIFY_ENTRY Entry; 00374 PAGED_CODE(); 00375 00376 Entry = (PPNP_NOTIFY_ENTRY)NotificationEntry; 00377 DPRINT("%s(NotificationEntry %p) called\n", __FUNCTION__, Entry); 00378 00379 KeAcquireGuardedMutex(&PnpNotifyListLock); 00380 RemoveEntryList(&Entry->PnpNotifyList); 00381 KeReleaseGuardedMutex(&PnpNotifyListLock); 00382 00383 RtlFreeUnicodeString(&Entry->Guid); 00384 00385 ObDereferenceObject(Entry->DriverObject); 00386 00387 ExFreePoolWithTag(Entry, TAG_PNP_NOTIFY); 00388 00389 return STATUS_SUCCESS; 00390 } Generated on Sun May 27 2012 04:37:18 for ReactOS by
1.7.6.1
|