diff --git a/reactos/include/ntos/ntpnp.h b/reactos/include/ntos/ntpnp.h index 11bfc8e08b7..bf551f71e08 100644 --- a/reactos/include/ntos/ntpnp.h +++ b/reactos/include/ntos/ntpnp.h @@ -244,6 +244,8 @@ NtGetPlugPlayEvent( * ... */ +#define PLUGPLAY_USER_RESPONSE 0x07 + NTSTATUS STDCALL NtPlugPlayControl( ULONG ControlCode, diff --git a/reactos/ntoskrnl/Makefile b/reactos/ntoskrnl/Makefile index e1123a5ed1b..63d323aacf8 100644 --- a/reactos/ntoskrnl/Makefile +++ b/reactos/ntoskrnl/Makefile @@ -185,9 +185,9 @@ OBJECTS_IO = \ 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 @@ TARGET_LIBS = \ $(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 @@ $(PATH_TO_TOP)/include/reactos/bugcodes.h bugcodes.rc: ntoskrnl.mc 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 diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index b102b1ac4b1..823c153c197 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -501,11 +501,15 @@ VOID FASTCALL IopReinitializeDrivers(VOID); -/* pnpevent.c */ +/* plugplay.c */ NTSTATUS INIT_FUNCTION IopInitPlugPlayEvents(VOID); +NTSTATUS +IopQueueTargetDeviceEvent(const GUID *Guid, + PUNICODE_STRING DeviceIds); + /* pnpmgr.c */ diff --git a/reactos/ntoskrnl/io/plugplay.c b/reactos/ntoskrnl/io/plugplay.c index e309df1cd8f..810a6d597fa 100644 --- a/reactos/ntoskrnl/io/plugplay.c +++ b/reactos/ntoskrnl/io/plugplay.c @@ -15,9 +15,17 @@ #define NDEBUG #include + +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 @@ NTSTATUS INIT_FUNCTION 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 @@ NtGetPlugPlayEvent(IN ULONG Reserved1, OUT PPLUGPLAY_EVENT_BLOCK Buffer, IN ULONG BufferLength) { + PPNP_EVENT_ENTRY Entry; NTSTATUS Status; DPRINT("NtGetPlugPlayEvent() called\n"); @@ -83,7 +128,7 @@ NtGetPlugPlayEvent(IN ULONG Reserved1, 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 @@ NtGetPlugPlayEvent(IN ULONG Reserved1, KernelMode, FALSE, NULL); - if (NT_SUCCESS(Status)) + if (!NT_SUCCESS(Status)) { - DPRINT("Waiting done\n"); - -#if 0 - /* Get entry from the tail of the list */ - Entry = IopPnpEventListHead.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 + DPRINT1("KeWaitForSingleObject() failed (Status %lx)\n", Status); + return Status; } + /* Get entry from the tail of the queue */ + Entry = (PPNP_EVENT_ENTRY)IopPnpEventQueueHead.Blink; + + /* 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 @@ NtPlugPlayControl(IN ULONG ControlCode, 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; } diff --git a/reactos/ntoskrnl/io/pnpmgr.c b/reactos/ntoskrnl/io/pnpmgr.c index 13bb59a6c03..352e4c4ce3e 100644 --- a/reactos/ntoskrnl/io/pnpmgr.c +++ b/reactos/ntoskrnl/io/pnpmgr.c @@ -11,6 +11,7 @@ /* INCLUDES ******************************************************************/ #include +#include #define NDEBUG #include @@ -434,7 +435,7 @@ IoRequestDeviceEject( BOOLEAN IopCreateUnicodeString( - PUNICODE_STRING Destination, + PUNICODE_STRING Destination, PWSTR Source, POOL_TYPE PoolType) { @@ -1318,6 +1319,10 @@ IopActionInterrogateDeviceStack( DeviceNode->Flags |= DNF_PROCESSED; + /* Report the device to the user-mode pnp manager */ + IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, + &DeviceNode->InstancePath); + return STATUS_SUCCESS; }