ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pnpnotify.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.