3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/plugplay.c
6 * PURPOSE: Plug-and-play interface routines
8 * PROGRAMMERS: Eric Kohl <eric.kohl@t-online.de>
11 /* INCLUDES *****************************************************************/
16 #include <internal/debug.h>
19 typedef struct _PNP_EVENT_ENTRY
22 PLUGPLAY_EVENT_BLOCK Event
;
23 } PNP_EVENT_ENTRY
, *PPNP_EVENT_ENTRY
;
26 /* GLOBALS *******************************************************************/
28 static LIST_ENTRY IopPnpEventQueueHead
;
29 static KEVENT IopPnpNotifyEvent
;
31 /* FUNCTIONS *****************************************************************/
33 NTSTATUS INIT_FUNCTION
34 IopInitPlugPlayEvents(VOID
)
37 InitializeListHead(&IopPnpEventQueueHead
);
39 KeInitializeEvent(&IopPnpNotifyEvent
,
43 return STATUS_SUCCESS
;
48 IopQueueTargetDeviceEvent(const GUID
*Guid
,
49 PUNICODE_STRING DeviceIds
)
51 PPNP_EVENT_ENTRY EventEntry
;
55 FIELD_OFFSET(PLUGPLAY_EVENT_BLOCK
, TargetDevice
.DeviceIds
) +
56 DeviceIds
->MaximumLength
;
58 EventEntry
= ExAllocatePool(NonPagedPool
,
59 TotalSize
+ FIELD_OFFSET(PNP_EVENT_ENTRY
, Event
));
60 if (EventEntry
== NULL
)
61 return STATUS_INSUFFICIENT_RESOURCES
;
63 memcpy(&EventEntry
->Event
.EventGuid
,
66 EventEntry
->Event
.EventCategory
= TargetDeviceChangeEvent
;
67 EventEntry
->Event
.TotalSize
= TotalSize
;
69 memcpy(&EventEntry
->Event
.TargetDevice
.DeviceIds
,
71 DeviceIds
->MaximumLength
);
73 InsertHeadList(&IopPnpEventQueueHead
,
74 &EventEntry
->ListEntry
);
75 KeSetEvent(&IopPnpNotifyEvent
,
79 return STATUS_SUCCESS
;
84 * Remove the current PnP event from the tail of the event queue
85 * and signal IopPnpNotifyEvent if there is yet another event in the queue.
88 IopRemovePlugPlayEvent(VOID
)
90 /* Remove a pnp event entry from the tail of the queue */
91 if (!IsListEmpty(&IopPnpEventQueueHead
))
93 ExFreePool(RemoveTailList(&IopPnpEventQueueHead
));
96 /* Signal the next pnp event in the queue */
97 if (!IsListEmpty(&IopPnpEventQueueHead
))
99 KeSetEvent(&IopPnpNotifyEvent
,
110 NtGetPlugPlayEvent(IN ULONG Reserved1
,
112 OUT PPLUGPLAY_EVENT_BLOCK Buffer
,
113 IN ULONG BufferLength
)
115 PPNP_EVENT_ENTRY Entry
;
118 DPRINT("NtGetPlugPlayEvent() called\n");
120 /* Function can only be called from user-mode */
121 if (KeGetPreviousMode() != UserMode
)
123 DPRINT1("NtGetPlugPlayEvent cannot be called from kernel mode!\n");
124 return STATUS_ACCESS_DENIED
;
127 /* Check for Tcb privilege */
128 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
,
131 DPRINT1("NtGetPlugPlayEvent: Caller does not hold the SeTcbPrivilege privilege!\n");
132 return STATUS_PRIVILEGE_NOT_HELD
;
135 /* Wait for a PnP event */
136 DPRINT("Waiting for pnp notification event\n");
137 Status
= KeWaitForSingleObject(&IopPnpNotifyEvent
,
142 if (!NT_SUCCESS(Status
))
144 DPRINT1("KeWaitForSingleObject() failed (Status %lx)\n", Status
);
148 /* Get entry from the tail of the queue */
149 Entry
= CONTAINING_RECORD(IopPnpEventQueueHead
.Blink
,
153 /* Check the buffer size */
154 if (BufferLength
< Entry
->Event
.TotalSize
)
156 DPRINT1("Buffer is too small for the pnp-event\n");
157 return STATUS_BUFFER_TOO_SMALL
;
160 /* Copy event data to the user buffer */
163 Entry
->Event
.TotalSize
);
165 DPRINT("NtGetPlugPlayEvent() done\n");
167 return STATUS_SUCCESS
;
175 NtPlugPlayControl(IN ULONG ControlCode
,
177 IN ULONG BufferLength
)
179 DPRINT("NtPlugPlayControl(%lu %p %lu) called\n",
180 ControlCode
, Buffer
, BufferLength
);
184 case PLUGPLAY_USER_RESPONSE
:
185 IopRemovePlugPlayEvent();
186 return STATUS_SUCCESS
;
189 return STATUS_NOT_IMPLEMENTED
;