ReactOS  0.4.14-dev-115-g4576127
pnpnotify.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * COPYRIGHT: GPL - See COPYING in the top level directory
4  * FILE: ntoskrnl/io/pnpmgr/pnpnotify.c
5  * PURPOSE: Plug & Play notification functions
6  * PROGRAMMERS: Filip Navara (xnavara@volny.cz)
7  * Hervé Poussineau (hpoussin@reactos.org)
8  * Pierre Schweitzer
9  */
10 
11 /* INCLUDES ******************************************************************/
12 
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* TYPES *******************************************************************/
18 
19 typedef struct _PNP_NOTIFY_ENTRY
20 {
29 
32 
33 /* FUNCTIONS *****************************************************************/
34 
35 VOID
38  IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory,
40  IN PVOID EventCategoryData1,
41  IN PVOID EventCategoryData2)
42 {
43  PPNP_NOTIFY_ENTRY ChangeEntry;
44  PLIST_ENTRY ListEntry;
46  BOOLEAN CallCurrentEntry;
49  PDEVICE_OBJECT EntryDeviceObject = NULL;
50 
52 
55  {
57  return;
58  }
59 
60  switch (EventCategory)
61  {
63  {
64  PDEVICE_INTERFACE_CHANGE_NOTIFICATION NotificationInfos;
65  NotificationStructure = NotificationInfos = ExAllocatePoolWithTag(
66  PagedPool,
69  if (!NotificationInfos)
70  {
72  return;
73  }
74  NotificationInfos->Version = 1;
75  NotificationInfos->Size = sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION);
76  RtlCopyMemory(&NotificationInfos->Event, Event, sizeof(GUID));
77  RtlCopyMemory(&NotificationInfos->InterfaceClassGuid, EventCategoryData1, sizeof(GUID));
78  NotificationInfos->SymbolicLinkName = (PUNICODE_STRING)EventCategoryData2;
79  Status = RtlStringFromGUID(&NotificationInfos->InterfaceClassGuid, &GuidString);
80  if (!NT_SUCCESS(Status))
81  {
84  return;
85  }
86  break;
87  }
89  {
90  PHWPROFILE_CHANGE_NOTIFICATION NotificationInfos;
91  NotificationStructure = NotificationInfos = ExAllocatePoolWithTag(
92  PagedPool,
95  if (!NotificationInfos)
96  {
98  return;
99  }
100  NotificationInfos->Version = 1;
101  NotificationInfos->Size = sizeof(HWPROFILE_CHANGE_NOTIFICATION);
102  RtlCopyMemory(&NotificationInfos->Event, Event, sizeof(GUID));
103  break;
104  }
106  {
107  if (Event != &GUID_PNP_CUSTOM_NOTIFICATION)
108  {
109  PTARGET_DEVICE_REMOVAL_NOTIFICATION NotificationInfos;
110  NotificationStructure = NotificationInfos = ExAllocatePoolWithTag(
111  PagedPool,
114  if (!NotificationInfos)
115  {
117  return;
118  }
119  NotificationInfos->Version = 1;
120  NotificationInfos->Size = sizeof(TARGET_DEVICE_REMOVAL_NOTIFICATION);
121  RtlCopyMemory(&NotificationInfos->Event, Event, sizeof(GUID));
122  }
123  else
124  {
125  PTARGET_DEVICE_CUSTOM_NOTIFICATION NotificationInfos;
126  NotificationStructure = NotificationInfos = ExAllocatePoolWithTag(
127  PagedPool,
130  if (!NotificationInfos)
131  {
133  return;
134  }
135  RtlCopyMemory(NotificationInfos, EventCategoryData1, sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION));
136  }
137  break;
138  }
139  default:
140  {
141  DPRINT1("IopNotifyPlugPlayNotification(): unknown EventCategory 0x%x UNIMPLEMENTED\n", EventCategory);
143  return;
144  }
145  }
146 
147  /* Loop through procedures registred in PnpNotifyListHead
148  * list to find those that meet some criteria.
149  */
150  ListEntry = PnpNotifyListHead.Flink;
151  while (ListEntry != &PnpNotifyListHead)
152  {
153  ChangeEntry = CONTAINING_RECORD(ListEntry, PNP_NOTIFY_ENTRY, PnpNotifyList);
154  CallCurrentEntry = FALSE;
155 
156  if (ChangeEntry->EventCategory != EventCategory)
157  {
158  ListEntry = ListEntry->Flink;
159  continue;
160  }
161 
162  switch (EventCategory)
163  {
165  {
166  if (RtlCompareUnicodeString(&ChangeEntry->Guid, &GuidString, FALSE) == 0)
167  {
168  CallCurrentEntry = TRUE;
169  }
170  break;
171  }
173  {
174  CallCurrentEntry = TRUE;
175  break;
176  }
178  {
179  Status = IoGetRelatedTargetDevice(ChangeEntry->FileObject, &EntryDeviceObject);
180  if (NT_SUCCESS(Status))
181  {
182  if (DeviceObject == EntryDeviceObject)
183  {
184  if (Event == &GUID_PNP_CUSTOM_NOTIFICATION)
185  {
187  }
188  else
189  {
191  }
192  CallCurrentEntry = TRUE;
193  }
194  }
195  break;
196  }
197  default:
198  {
199  DPRINT1("IopNotifyPlugPlayNotification(): unknown EventCategory 0x%x UNIMPLEMENTED\n", EventCategory);
200  break;
201  }
202  }
203 
204  /* Move to the next element now, as callback may unregister itself */
205  ListEntry = ListEntry->Flink;
206  /* FIXME: If ListEntry was the last element and that callback registers
207  * new notifications, those won't be checked... */
208 
209  if (CallCurrentEntry)
210  {
211  /* Call entry into new allocated memory */
212  DPRINT("IopNotifyPlugPlayNotification(): found suitable callback %p\n",
213  ChangeEntry);
214 
217  ChangeEntry->Context);
219  }
220 
221  }
224  if (EventCategory == EventCategoryDeviceInterfaceChange)
226 }
227 
228 /* PUBLIC FUNCTIONS **********************************************************/
229 
230 /*
231  * @unimplemented
232  */
233 ULONG
234 NTAPI
236  ULONG PowerNotification,
238  BOOLEAN Synchronous)
239 {
241  return 0;
242 }
243 
244 /*
245  * @implemented
246  */
247 NTSTATUS
248 NTAPI
254  IN PVOID Context,
256 {
260  PAGED_CODE();
261 
262  DPRINT("%s(EventCategory 0x%x, EventCategoryFlags 0x%lx, DriverObject %p) called.\n",
263  __FUNCTION__,
264  EventCategory,
266  DriverObject);
267 
269 
270  /* Try to allocate entry for notification before sending any notification */
272  sizeof(PNP_NOTIFY_ENTRY),
274 
275  if (!Entry)
276  {
277  DPRINT("ExAllocatePool() failed\n");
280  }
281 
282  if (EventCategory == EventCategoryDeviceInterfaceChange &&
284  {
285  DEVICE_INTERFACE_CHANGE_NOTIFICATION NotificationInfos;
286  UNICODE_STRING SymbolicLinkU;
288 
290  NULL, /* PhysicalDeviceObject OPTIONAL */
291  0, /* Flags */
293  if (NT_SUCCESS(Status))
294  {
295  /* Enumerate SymbolicLinkList */
296  NotificationInfos.Version = 1;
297  NotificationInfos.Size = sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION);
298  RtlCopyMemory(&NotificationInfos.Event,
300  sizeof(GUID));
301  RtlCopyMemory(&NotificationInfos.InterfaceClassGuid,
303  sizeof(GUID));
304  NotificationInfos.SymbolicLinkName = &SymbolicLinkU;
305 
307  *SymbolicLink;
309  {
310  RtlInitUnicodeString(&SymbolicLinkU, SymbolicLink);
311  DPRINT("Calling callback routine for %S\n", SymbolicLink);
312  (*CallbackRoutine)(&NotificationInfos, Context);
313  }
314 
316  }
317  }
318 
319  Entry->PnpNotificationProc = CallbackRoutine;
320  Entry->EventCategory = EventCategory;
321  Entry->Context = Context;
322  Entry->DriverObject = DriverObject;
323  switch (EventCategory)
324  {
326  {
328  if (!NT_SUCCESS(Status))
329  {
332  return Status;
333  }
334  break;
335  }
337  {
338  /* nothing to do */
339  break;
340  }
342  {
343  Entry->FileObject = (PFILE_OBJECT)EventCategoryData;
344  break;
345  }
346  default:
347  {
348  DPRINT1("%s: unknown EventCategory 0x%x UNIMPLEMENTED\n",
349  __FUNCTION__, EventCategory);
350  break;
351  }
352  }
353 
356  &Entry->PnpNotifyList);
358 
359  DPRINT("%s returns NotificationEntry %p\n", __FUNCTION__, Entry);
360 
362 
363  return STATUS_SUCCESS;
364 }
365 
366 /*
367  * @implemented
368  */
369 NTSTATUS
370 NTAPI
372 {
374  PAGED_CODE();
375 
377  DPRINT("%s(NotificationEntry %p) called\n", __FUNCTION__, Entry);
378 
380  RemoveEntryList(&Entry->PnpNotifyList);
382 
383  RtlFreeUnicodeString(&Entry->Guid);
384 
385  ObDereferenceObject(Entry->DriverObject);
386 
388 
389  return STATUS_SUCCESS;
390 }
_In_ PVOID NotificationStructure
Definition: iofuncs.h:1203
NTSTATUS NTAPI IoUnregisterPlugPlayNotification(IN PVOID NotificationEntry)
Definition: pnpnotify.c:371
static PWSTR GuidString
Definition: apphelp.c:91
#define IN
Definition: typedefs.h:38
struct _TARGET_DEVICE_REMOVAL_NOTIFICATION TARGET_DEVICE_REMOVAL_NOTIFICATION
DRIVER_NOTIFICATION_CALLBACK_ROUTINE * PDRIVER_NOTIFICATION_CALLBACK_ROUTINE
Definition: iotypes.h:1204
NTSTATUS NTAPI IoGetRelatedTargetDevice(IN PFILE_OBJECT FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1607
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
const GUID GUID_DEVICE_INTERFACE_ARRIVAL
Definition: deviface.c:14
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_opt_ PDEVICE_OBJECT _In_ ULONG _Outptr_result_nullonfailure_ _At_ * SymbolicLinkList(return==0, __drv_allocatesMem(Mem))) PZZWSTR *SymbolicLinkList
struct _TARGET_DEVICE_REMOVAL_NOTIFICATION * PTARGET_DEVICE_REMOVAL_NOTIFICATION
struct _Entry Entry
Definition: kefuncs.h:640
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
_In_ ULONG _In_opt_ PVOID EventCategoryData
Definition: iofuncs.h:1146
uint16_t * PWSTR
Definition: typedefs.h:54
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
LONG NTSTATUS
Definition: precomp.h:26
LIST_ENTRY PnpNotifyListHead
Definition: pnpnotify.c:31
ULONG NTAPI IoPnPDeliverServicePowerNotification(ULONG VetoedPowerOperation OPTIONAL, ULONG PowerNotification, ULONG Unknown OPTIONAL, BOOLEAN Synchronous)
Definition: pnpnotify.c:235
NTSTATUS NTAPI IoGetDeviceInterfaces(IN CONST GUID *InterfaceClassGuid, IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, IN ULONG Flags, OUT PWSTR *SymbolicLinkList)
Definition: deviface.c:454
#define PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES
Definition: iotypes.h:1196
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
_In_ ULONG EventCategoryFlags
Definition: iofuncs.h:1146
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
enum _IO_NOTIFICATION_EVENT_CATEGORY IO_NOTIFICATION_EVENT_CATEGORY
#define PAGED_CODE()
Definition: video.h:57
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
_Must_inspect_result_ _In_ PFLT_GET_OPERATION_STATUS_CALLBACK CallbackRoutine
Definition: fltkernel.h:1035
struct _HWPROFILE_CHANGE_NOTIFICATION HWPROFILE_CHANGE_NOTIFICATION
_In_ ULONG _In_opt_ PVOID _In_ PDRIVER_OBJECT _In_ PDRIVER_NOTIFICATION_CALLBACK_ROUTINE _Inout_opt_ __drv_aliasesMem PVOID _Outptr_result_nullonfailure_ _At_ * NotificationEntry(return==0, __drv_allocatesMem(Mem))) PVOID *NotificationEntry
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
static PDRIVER_OBJECT DriverObject
Definition: template.c:42
struct _PNP_NOTIFY_ENTRY PNP_NOTIFY_ENTRY
void DPRINT(...)
Definition: polytest.cpp:61
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
PDRIVER_NOTIFICATION_CALLBACK_ROUTINE PnpNotificationProc
Definition: pnpnotify.c:27
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
struct _TARGET_DEVICE_CUSTOM_NOTIFICATION * PTARGET_DEVICE_CUSTOM_NOTIFICATION
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
LIST_ENTRY PnpNotifyList
Definition: pnpnotify.c:21
Definition: pnpnotify.c:19
struct _PNP_NOTIFY_ENTRY * PPNP_NOTIFY_ENTRY
IO_NOTIFICATION_EVENT_CATEGORY EventCategory
Definition: pnpnotify.c:22
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
* PFILE_OBJECT
Definition: iotypes.h:1955
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
UNICODE_STRING Guid
Definition: pnpnotify.c:24
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)
Definition: pnpnotify.c:249
Definition: typedefs.h:117
NTSYSAPI NTSTATUS WINAPI RtlStringFromGUID(REFGUID, PUNICODE_STRING)
Status
Definition: gdiplustypes.h:24
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
VOID IopNotifyPlugPlayNotification(IN PDEVICE_OBJECT DeviceObject, IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory, IN LPCGUID Event, IN PVOID EventCategoryData1, IN PVOID EventCategoryData2)
Definition: pnpnotify.c:36
#define TAG_PNP_NOTIFY
Definition: tag.h:92
struct _DEVICE_INTERFACE_CHANGE_NOTIFICATION DEVICE_INTERFACE_CHANGE_NOTIFICATION
PFILE_OBJECT FileObject
Definition: pnpnotify.c:25
KGUARDED_MUTEX PnpNotifyListLock
Definition: pnpnotify.c:30
UNICODE_STRING * PUNICODE_STRING
Definition: env_spec_w32.h:373
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
#define DPRINT1
Definition: precomp.h:8
#define OUT
Definition: typedefs.h:39
#define ObReferenceObject
Definition: obfuncs.h:204
struct tagContext Context
Definition: acpixf.h:1024
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define UNIMPLEMENTED
Definition: debug.h:114
PDRIVER_OBJECT DriverObject
Definition: pnpnotify.c:26
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
PVOID Context
Definition: pnpnotify.c:23
return STATUS_SUCCESS
Definition: btrfs.c:2966
#define __FUNCTION__
Definition: types.h:112
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
base of all file and directory entries
Definition: entries.h:82
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
static const WCHAR SymbolicLink[]
Definition: interface.c:31
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68