- Link ntoskrnl against libwdmguid.a.
- Report device arrival events to the user-mode pnp manager.
Modified: trunk/reactos/include/ntos/ntpnp.h
Modified: trunk/reactos/ntoskrnl/Makefile
Modified: trunk/reactos/ntoskrnl/include/internal/io.h
Modified: trunk/reactos/ntoskrnl/io/plugplay.c
Modified: trunk/reactos/ntoskrnl/io/pnpmgr.c

Modified: trunk/reactos/include/ntos/ntpnp.h
--- trunk/reactos/include/ntos/ntpnp.h	2005-02-04 23:24:32 UTC (rev 13408)
+++ trunk/reactos/include/ntos/ntpnp.h	2005-02-05 00:04:52 UTC (rev 13409)
@@ -244,6 +244,8 @@
  *    ...
  */
 
+#define PLUGPLAY_USER_RESPONSE 0x07
+
 NTSTATUS STDCALL
 NtPlugPlayControl(
    ULONG ControlCode,

Modified: trunk/reactos/ntoskrnl/Makefile
--- trunk/reactos/ntoskrnl/Makefile	2005-02-04 23:24:32 UTC (rev 13408)
+++ trunk/reactos/ntoskrnl/Makefile	2005-02-05 00:04:52 UTC (rev 13409)
@@ -185,9 +185,9 @@
 	io/parttab.o \
 	io/plugplay.o \
 	io/process.o \
-	io/pnpnotify.o \
 	io/pnpdma.o \
 	io/pnpmgr.o \
+	io/pnpnotify.o \
 	io/pnpreport.o \
 	io/pnproot.o \
 	io/queue.o \
@@ -516,6 +516,7 @@
 	$(SDK_PATH_LIB)/libstring.a \
 	$(SDK_PATH_LIB)/librosrtl.a \
 	$(SDK_PATH_LIB)/libpseh.a \
+	$(SDK_PATH_LIB)/libwdmguid.a \
 	$(PATH_TO_TOP)/drivers/lib/csq/csq.o
 
 TARGET_LFLAGS = \
@@ -542,7 +543,7 @@
 
 TARGET_CLEAN = \
   $(PATH_TO_TOP)/include/reactos/bugcodes.h \
-  $(DEP_OBJECTS) $(DEP_FILES) MSG00409.bin bugcodes.rc 
+  $(DEP_OBJECTS) $(DEP_FILES) MSG00409.bin bugcodes.rc
 
 ex/napi.o: ex/zw.S $(PATH_TO_TOP)/include/ntdll/napi.h
 

Modified: trunk/reactos/ntoskrnl/include/internal/io.h
--- trunk/reactos/ntoskrnl/include/internal/io.h	2005-02-04 23:24:32 UTC (rev 13408)
+++ trunk/reactos/ntoskrnl/include/internal/io.h	2005-02-05 00:04:52 UTC (rev 13409)
@@ -501,12 +501,16 @@
 IopReinitializeDrivers(VOID);
 
 
-/* pnpevent.c */
+/* plugplay.c */
 
 NTSTATUS INIT_FUNCTION
 IopInitPlugPlayEvents(VOID);
 
+NTSTATUS
+IopQueueTargetDeviceEvent(const GUID *Guid,
+                          PUNICODE_STRING DeviceIds);
 
+
 /* pnpmgr.c */
 
 NTSTATUS

Modified: trunk/reactos/ntoskrnl/io/plugplay.c
--- trunk/reactos/ntoskrnl/io/plugplay.c	2005-02-04 23:24:32 UTC (rev 13408)
+++ trunk/reactos/ntoskrnl/io/plugplay.c	2005-02-05 00:04:52 UTC (rev 13409)
@@ -15,9 +15,17 @@
 #define NDEBUG
 #include <internal/debug.h>
 
+
+typedef struct _PNP_EVENT_ENTRY
+{
+  LIST_ENTRY ListEntry;
+  PLUGPLAY_EVENT_BLOCK Event;
+} PNP_EVENT_ENTRY, *PPNP_EVENT_ENTRY;
+
+
 /* GLOBALS *******************************************************************/
 
-static LIST_ENTRY IopPnpEventListHead;
+static LIST_ENTRY IopPnpEventQueueHead;
 static KEVENT IopPnpNotifyEvent;
 
 /* FUNCTIONS *****************************************************************/
@@ -26,41 +34,77 @@
 IopInitPlugPlayEvents(VOID)
 {
 
-  InitializeListHead(&IopPnpEventListHead);
+  InitializeListHead(&IopPnpEventQueueHead);
 
   KeInitializeEvent(&IopPnpNotifyEvent,
-		    NotificationEvent,
+		    SynchronizationEvent,
 		    FALSE);
 
   return STATUS_SUCCESS;
 }
 
 
-#if 0
-/* Insert a new pnp event at the head of the event queue */
-VOID
-IopEnqueuePlugPlayEvent(VOID)
+NTSTATUS
+IopQueueTargetDeviceEvent(const GUID *Guid,
+                          PUNICODE_STRING DeviceIds)
 {
+  PPNP_EVENT_ENTRY EventEntry;
+  DWORD TotalSize;
 
+  TotalSize =
+    FIELD_OFFSET(PLUGPLAY_EVENT_BLOCK, TargetDevice.DeviceIds) +
+    DeviceIds->MaximumLength;
+
+  EventEntry = ExAllocatePool(NonPagedPool,
+                              TotalSize + FIELD_OFFSET(PNP_EVENT_ENTRY, Event));
+  if (EventEntry == NULL)
+    return STATUS_INSUFFICIENT_RESOURCES;
+
+  memcpy(&EventEntry->Event.EventGuid,
+         Guid,
+         sizeof(GUID));
+  EventEntry->Event.EventCategory = TargetDeviceChangeEvent;
+  EventEntry->Event.TotalSize = TotalSize;
+
+  memcpy(&EventEntry->Event.TargetDevice.DeviceIds,
+         DeviceIds->Buffer,
+         DeviceIds->MaximumLength);
+
+  InsertHeadList(&IopPnpEventQueueHead,
+                 &EventEntry->ListEntry);
+  KeSetEvent(&IopPnpNotifyEvent,
+             0,
+             FALSE);
+
+  return STATUS_SUCCESS;
 }
-#endif
 
 
-#if 0
 /*
  * Remove the current PnP event from the tail of the event queue
  * and signal IopPnpNotifyEvent if there is yet another event in the queue.
  */
-VOID
-IopDequeuePlugPlayEvent(VOID)
+static VOID
+IopRemovePlugPlayEvent(VOID)
 {
+  /* Remove a pnp event entry from the tail of the queue */
+  if (!IsListEmpty(&IopPnpEventQueueHead))
+  {
+    ExFreePool(RemoveTailList(&IopPnpEventQueueHead));
+  }
 
+  /* Signal the next pnp event in the queue */
+  if (!IsListEmpty(&IopPnpEventQueueHead))
+  {
+    KeSetEvent(&IopPnpNotifyEvent,
+               0,
+               FALSE);
+  }
 }
-#endif
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 NTSTATUS STDCALL
 NtGetPlugPlayEvent(IN ULONG Reserved1,
@@ -68,6 +112,7 @@
                    OUT PPLUGPLAY_EVENT_BLOCK Buffer,
                    IN ULONG BufferLength)
 {
+  PPNP_EVENT_ENTRY Entry;
   NTSTATUS Status;
 
   DPRINT("NtGetPlugPlayEvent() called\n");
@@ -83,7 +128,7 @@
   if (!SeSinglePrivilegeCheck(SeTcbPrivilege,
                               UserMode))
   {
-    DPRINT1("NtGetPlugPlayEvent: Caller requires the SeTcbPrivilege privilege!\n");
+    DPRINT1("NtGetPlugPlayEvent: Caller does not hold the SeTcbPrivilege privilege!\n");
     return STATUS_PRIVILEGE_NOT_HELD;
   }
 
@@ -94,31 +139,30 @@
                                  KernelMode,
                                  FALSE,
                                  NULL);
-  if (NT_SUCCESS(Status))
+  if (!NT_SUCCESS(Status))
   {
-    DPRINT("Waiting done\n");
+    DPRINT1("KeWaitForSingleObject() failed (Status %lx)\n", Status);
+    return Status;
+  }
 
-#if 0
-    /* Get entry from the tail of the list */
-    Entry = IopPnpEventListHead.Blink;
+  /* Get entry from the tail of the queue */
+  Entry = (PPNP_EVENT_ENTRY)IopPnpEventQueueHead.Blink;
 
-    /* Check the buffer size */
-    if (BufferLength < Entry->Event.Size)
-    {
-      DPRINT1("Buffer is too small for the pnp-event\n");
-      return STATUS_BUFFER_TOO_SMALL;
-    }
-
-    /* Copy event data to user buffer */
-    memcpy(Buffer,
-           &Entry->Event,
-           &Entry->Event.Size);
-#endif
+  /* Check the buffer size */
+  if (BufferLength < Entry->Event.TotalSize)
+  {
+    DPRINT1("Buffer is too small for the pnp-event\n");
+    return STATUS_BUFFER_TOO_SMALL;
   }
 
+  /* Copy event data to the user buffer */
+  memcpy(Buffer,
+         &Entry->Event,
+         Entry->Event.TotalSize);
+
   DPRINT("NtGetPlugPlayEvent() done\n");
 
-  return Status;
+  return STATUS_SUCCESS;
 }
 
 
@@ -130,7 +174,16 @@
                   IN OUT PVOID Buffer,
                   IN ULONG BufferLength)
 {
-  UNIMPLEMENTED;
+  DPRINT("NtPlugPlayControl(%lu %p %lu) called\n",
+         ControlCode, Buffer, BufferLength);
+
+  switch (ControlCode)
+  {
+    case PLUGPLAY_USER_RESPONSE:
+      IopRemovePlugPlayEvent();
+      return STATUS_SUCCESS;
+  }
+
   return STATUS_NOT_IMPLEMENTED;
 }
 

Modified: trunk/reactos/ntoskrnl/io/pnpmgr.c
--- trunk/reactos/ntoskrnl/io/pnpmgr.c	2005-02-04 23:24:32 UTC (rev 13408)
+++ trunk/reactos/ntoskrnl/io/pnpmgr.c	2005-02-05 00:04:52 UTC (rev 13409)
@@ -11,6 +11,7 @@
 /* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
+#include <ddk/wdmguid.h>
 
 #define NDEBUG
 #include <internal/debug.h>
@@ -434,7 +435,7 @@
 
 BOOLEAN
 IopCreateUnicodeString(
-  PUNICODE_STRING	Destination,
+  PUNICODE_STRING Destination,
   PWSTR Source,
   POOL_TYPE PoolType)
 {
@@ -1318,6 +1319,10 @@
 
    DeviceNode->Flags |= DNF_PROCESSED;
 
+   /* Report the device to the user-mode pnp manager */
+   IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL,
+                             &DeviceNode->InstancePath);
+
    return STATUS_SUCCESS;
 }