/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/io/plugplay.c
+ * PROJECT: ReactOS Kernel
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * FILE: ntoskrnl/io/pnpmgr/plugplay.c
* PURPOSE: Plug-and-play interface routines
- *
* PROGRAMMERS: Eric Kohl <eric.kohl@t-online.de>
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
-
#define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
#if defined (ALLOC_PRAGMA)
#pragma alloc_text(INIT, IopInitPlugPlayEvents)
return STATUS_SUCCESS;
}
-
NTSTATUS
IopQueueTargetDeviceEvent(const GUID *Guid,
PUNICODE_STRING DeviceIds)
{
PPNP_EVENT_ENTRY EventEntry;
- DWORD TotalSize;
+ UNICODE_STRING Copy;
+ ULONG TotalSize;
+ NTSTATUS Status;
+
+ ASSERT(DeviceIds);
+ /* Allocate a big enough buffer */
+ Copy.Length = 0;
+ Copy.MaximumLength = DeviceIds->Length + sizeof(UNICODE_NULL);
TotalSize =
FIELD_OFFSET(PLUGPLAY_EVENT_BLOCK, TargetDevice.DeviceIds) +
- DeviceIds->MaximumLength;
+ Copy.MaximumLength;
EventEntry = ExAllocatePool(NonPagedPool,
TotalSize + FIELD_OFFSET(PNP_EVENT_ENTRY, Event));
- if (EventEntry == NULL)
+ if (!EventEntry)
return STATUS_INSUFFICIENT_RESOURCES;
- memcpy(&EventEntry->Event.EventGuid,
- Guid,
- sizeof(GUID));
+ /* Fill the buffer with the event GUID */
+ RtlCopyMemory(&EventEntry->Event.EventGuid,
+ Guid,
+ sizeof(GUID));
EventEntry->Event.EventCategory = TargetDeviceChangeEvent;
EventEntry->Event.TotalSize = TotalSize;
- memcpy(&EventEntry->Event.TargetDevice.DeviceIds,
- DeviceIds->Buffer,
- DeviceIds->MaximumLength);
+ /* Fill the device id */
+ Copy.Buffer = EventEntry->Event.TargetDevice.DeviceIds;
+ Status = RtlAppendUnicodeStringToString(&Copy, DeviceIds);
+ if (!NT_SUCCESS(Status))
+ return Status;
InsertHeadList(&IopPnpEventQueueHead,
&EventEntry->ListEntry);
return STATUS_SUCCESS;
}
-
-/*
- * Plug and Play event structure used by NtGetPlugPlayEvent.
- *
- * EventGuid
- * Can be one of the following values:
- * GUID_HWPROFILE_QUERY_CHANGE
- * GUID_HWPROFILE_CHANGE_CANCELLED
- * GUID_HWPROFILE_CHANGE_COMPLETE
- * GUID_TARGET_DEVICE_QUERY_REMOVE
- * GUID_TARGET_DEVICE_REMOVE_CANCELLED
- * GUID_TARGET_DEVICE_REMOVE_COMPLETE
- * GUID_PNP_CUSTOM_NOTIFICATION
- * GUID_PNP_POWER_NOTIFICATION
- * GUID_DEVICE_* (see above)
- *
- * EventCategory
- * Type of the event that happened.
- *
- * Result
- * ?
- *
- * Flags
- * ?
- *
- * TotalSize
- * Size of the event block including the device IDs and other
- * per category specific fields.
- */
-/*
- * NtGetPlugPlayEvent
- *
- * Returns one Plug & Play event from a global queue.
- *
- * Parameters
- * Reserved1
- * Reserved2
- * Always set to zero.
- *
- * Buffer
- * The buffer that will be filled with the event information on
- * successful return from the function.
- *
- * BufferSize
- * Size of the buffer pointed by the Buffer parameter. If the
- * buffer size is not large enough to hold the whole event
- * information, error STATUS_BUFFER_TOO_SMALL is returned and
- * the buffer remains untouched.
- *
- * Return Values
- * STATUS_PRIVILEGE_NOT_HELD
- * STATUS_BUFFER_TOO_SMALL
- * STATUS_SUCCESS
- *
- * Remarks
- * This function isn't multi-thread safe!
- *
- * @implemented
- */
-NTSTATUS STDCALL
-NtGetPlugPlayEvent(IN ULONG Reserved1,
- IN ULONG Reserved2,
- OUT PPLUGPLAY_EVENT_BLOCK Buffer,
- IN ULONG BufferSize)
-{
- PPNP_EVENT_ENTRY Entry;
- NTSTATUS Status;
-
- DPRINT("NtGetPlugPlayEvent() called\n");
-
- /* Function can only be called from user-mode */
- if (KeGetPreviousMode() == KernelMode)
- {
- DPRINT1("NtGetPlugPlayEvent cannot be called from kernel mode!\n");
- return STATUS_ACCESS_DENIED;
- }
-
- /* Check for Tcb privilege */
- if (!SeSinglePrivilegeCheck(SeTcbPrivilege,
- UserMode))
- {
- DPRINT1("NtGetPlugPlayEvent: Caller does not hold the SeTcbPrivilege privilege!\n");
- return STATUS_PRIVILEGE_NOT_HELD;
- }
-
- /* Wait for a PnP event */
- DPRINT("Waiting for pnp notification event\n");
- Status = KeWaitForSingleObject(&IopPnpNotifyEvent,
- UserRequest,
- KernelMode,
- FALSE,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("KeWaitForSingleObject() failed (Status %lx)\n", Status);
- return Status;
- }
-
- /* Get entry from the tail of the queue */
- Entry = CONTAINING_RECORD(IopPnpEventQueueHead.Blink,
- PNP_EVENT_ENTRY,
- ListEntry);
-
- /* Check the buffer size */
- if (BufferSize < 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_SUCCESS;
-}
-
-
static PDEVICE_OBJECT
IopTraverseDeviceNode(PDEVICE_NODE Node, PUNICODE_STRING DeviceInstance)
{
/* Traversal of all children nodes */
for (ChildNode = Node->Child;
ChildNode != NULL;
- ChildNode = ChildNode->NextSibling)
+ ChildNode = ChildNode->Sibling)
{
DeviceObject = IopTraverseDeviceNode(ChildNode, DeviceInstance);
if (DeviceObject != NULL)
static PDEVICE_OBJECT
IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance)
{
-#if 0
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING KeyName, ValueName;
- LPWSTR KeyNameBuffer;
- HANDLE InstanceKeyHandle;
- HANDLE ControlKeyHandle;
- NTSTATUS Status;
- PKEY_VALUE_PARTIAL_INFORMATION ValueInformation;
- ULONG ValueInformationLength;
- PDEVICE_OBJECT DeviceObject = NULL;
-
- DPRINT("IopGetDeviceObjectFromDeviceInstance(%wZ) called\n", DeviceInstance);
-
- KeyNameBuffer = ExAllocatePool(PagedPool,
- (49 * sizeof(WCHAR)) + DeviceInstance->Length);
- if (KeyNameBuffer == NULL)
- {
- DPRINT1("Failed to allocate key name buffer!\n");
- return NULL;
- }
-
- wcscpy(KeyNameBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
- wcscat(KeyNameBuffer, DeviceInstance->Buffer);
-
- RtlInitUnicodeString(&KeyName,
- KeyNameBuffer);
- InitializeObjectAttributes(&ObjectAttributes,
- &KeyName,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = ZwOpenKey(&InstanceKeyHandle,
- KEY_READ,
- &ObjectAttributes);
- ExFreePool(KeyNameBuffer);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to open the instance key (Status %lx)\n", Status);
- return NULL;
- }
-
- /* Open the 'Control' subkey */
- RtlInitUnicodeString(&KeyName,
- L"Control");
- InitializeObjectAttributes(&ObjectAttributes,
- &KeyName,
- OBJ_CASE_INSENSITIVE,
- InstanceKeyHandle,
- NULL);
-
- Status = ZwOpenKey(&ControlKeyHandle,
- KEY_READ,
- &ObjectAttributes);
- ZwClose(InstanceKeyHandle);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to open the 'Control' key (Status %lx)\n", Status);
- return NULL;
- }
-
- /* Query the 'DeviceReference' value */
- RtlInitUnicodeString(&ValueName,
- L"DeviceReference");
- ValueInformationLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,
- Data[0]) + sizeof(ULONG);
- ValueInformation = ExAllocatePool(PagedPool, ValueInformationLength);
- if (ValueInformation == NULL)
- {
- DPRINT1("Failed to allocate the name information buffer!\n");
- ZwClose(ControlKeyHandle);
- return NULL;
- }
-
- Status = ZwQueryValueKey(ControlKeyHandle,
- &ValueName,
- KeyValuePartialInformation,
- ValueInformation,
- ValueInformationLength,
- &ValueInformationLength);
- ZwClose(ControlKeyHandle);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to query the 'DeviceReference' value (Status %lx)\n", Status);
- return NULL;
- }
-
- /* Check the device object */
- RtlCopyMemory(&DeviceObject,
- ValueInformation->Data,
- sizeof(PDEVICE_OBJECT));
-
- DPRINT("DeviceObject: %p\n", DeviceObject);
-
- if (DeviceObject->Type != IO_TYPE_DEVICE ||
- DeviceObject->DeviceObjectExtension == NULL ||
- DeviceObject->DeviceObjectExtension->DeviceNode == NULL ||
- !RtlEqualUnicodeString(&DeviceObject->DeviceObjectExtension->DeviceNode->InstancePath,
- DeviceInstance, TRUE))
- {
- DPRINT1("Invalid object type!\n");
- return NULL;
- }
-
- DPRINT("Instance path: %wZ\n", &DeviceObject->DeviceObjectExtension->DeviceNode->InstancePath);
-
- ObReferenceObject(DeviceObject);
-
- DPRINT("IopGetDeviceObjectFromDeviceInstance() done\n");
-
- return DeviceObject;
-#endif
-
if (IopRootDeviceNode == NULL)
return NULL;
}
/* Get the device object */
- DeviceObject = IopGetDeviceObjectFromDeviceInstance(&PropertyData->DeviceInstance);
+ DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
ExFreePool(DeviceInstance.Buffer);
if (DeviceObject == NULL)
{
break;
case PNP_GET_SIBLING_DEVICE:
- RelatedDeviceNode = DeviceNode->NextSibling;
+ RelatedDeviceNode = DeviceNode->Sibling;
break;
default:
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("IopDeviceStatus() called\n");
- DPRINT("Device name: %wZ\n", &StatusData->DeviceInstance);
Status = IopCaptureUnicodeString(&DeviceInstance, &StatusData->DeviceInstance);
if (!NT_SUCCESS(Status))
- {
- return Status;
- }
+ return Status;
+ DPRINT("Device name: '%wZ'\n", &DeviceInstance);
_SEH_TRY
{
if (!NT_SUCCESS(Status))
{
- if (DeviceInstance.Buffer)
- {
- ExFreePool(DeviceInstance.Buffer);
- }
- return Status;
+ if (DeviceInstance.Buffer)
+ ExFreePool(DeviceInstance.Buffer);
+ return Status;
}
/* Get the device object */
- DeviceObject = IopGetDeviceObjectFromDeviceInstance(&StatusData->DeviceInstance);
+ DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
ExFreePool(DeviceInstance.Buffer);
if (DeviceObject == NULL)
return STATUS_NO_SUCH_DEVICE;
- DeviceNode = ((PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension)->DeviceNode;
+ DeviceNode = IopGetDeviceNode(DeviceObject);
switch (Operation)
{
}
/* Get the device object */
- DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DepthData->DeviceInstance);
+ DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
ExFreePool(DeviceInstance.Buffer);
if (DeviceObject == NULL)
return STATUS_NO_SUCH_DEVICE;
DeviceNode = IopGetDeviceNode(DeviceObject);
- DepthData->Depth = DeviceNode->Level;
-
- ObDereferenceObject(DeviceObject);
-
_SEH_TRY
{
DepthData->Depth = DeviceNode->Level;
}
_SEH_END;
+ ObDereferenceObject(DeviceObject);
+
return Status;
}
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING DeviceInstance;
- DPRINT("IopResetDevice() called\n");
- DPRINT("Device name: %wZ\n", &ResetDeviceData->DeviceInstance);
-
Status = IopCaptureUnicodeString(&DeviceInstance, &ResetDeviceData->DeviceInstance);
if (!NT_SUCCESS(Status))
- {
- return Status;
- }
+ return Status;
+
+ DPRINT("IopResetDevice(%wZ)\n", &DeviceInstance);
/* Get the device object */
DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
Status = IopActionConfigureChildServices(DeviceNode, DeviceNode->Parent);
if (NT_SUCCESS(Status))
- Status = IopActionInitChildServices(DeviceNode, DeviceNode->Parent, FALSE);
+ Status = IopActionInitChildServices(DeviceNode, DeviceNode->Parent);
ObDereferenceObject(DeviceObject);
return Status;
}
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * Plug and Play event structure used by NtGetPlugPlayEvent.
+ *
+ * EventGuid
+ * Can be one of the following values:
+ * GUID_HWPROFILE_QUERY_CHANGE
+ * GUID_HWPROFILE_CHANGE_CANCELLED
+ * GUID_HWPROFILE_CHANGE_COMPLETE
+ * GUID_TARGET_DEVICE_QUERY_REMOVE
+ * GUID_TARGET_DEVICE_REMOVE_CANCELLED
+ * GUID_TARGET_DEVICE_REMOVE_COMPLETE
+ * GUID_PNP_CUSTOM_NOTIFICATION
+ * GUID_PNP_POWER_NOTIFICATION
+ * GUID_DEVICE_* (see above)
+ *
+ * EventCategory
+ * Type of the event that happened.
+ *
+ * Result
+ * ?
+ *
+ * Flags
+ * ?
+ *
+ * TotalSize
+ * Size of the event block including the device IDs and other
+ * per category specific fields.
+ */
+
+/*
+ * NtGetPlugPlayEvent
+ *
+ * Returns one Plug & Play event from a global queue.
+ *
+ * Parameters
+ * Reserved1
+ * Reserved2
+ * Always set to zero.
+ *
+ * Buffer
+ * The buffer that will be filled with the event information on
+ * successful return from the function.
+ *
+ * BufferSize
+ * Size of the buffer pointed by the Buffer parameter. If the
+ * buffer size is not large enough to hold the whole event
+ * information, error STATUS_BUFFER_TOO_SMALL is returned and
+ * the buffer remains untouched.
+ *
+ * Return Values
+ * STATUS_PRIVILEGE_NOT_HELD
+ * STATUS_BUFFER_TOO_SMALL
+ * STATUS_SUCCESS
+ *
+ * Remarks
+ * This function isn't multi-thread safe!
+ *
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+NtGetPlugPlayEvent(IN ULONG Reserved1,
+ IN ULONG Reserved2,
+ OUT PPLUGPLAY_EVENT_BLOCK Buffer,
+ IN ULONG BufferSize)
+{
+ PPNP_EVENT_ENTRY Entry;
+ NTSTATUS Status;
+
+ DPRINT("NtGetPlugPlayEvent() called\n");
+
+ /* Function can only be called from user-mode */
+ if (KeGetPreviousMode() == KernelMode)
+ {
+ DPRINT1("NtGetPlugPlayEvent cannot be called from kernel mode!\n");
+ return STATUS_ACCESS_DENIED;
+ }
+
+ /* Check for Tcb privilege */
+ if (!SeSinglePrivilegeCheck(SeTcbPrivilege,
+ UserMode))
+ {
+ DPRINT1("NtGetPlugPlayEvent: Caller does not hold the SeTcbPrivilege privilege!\n");
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
+
+ /* Wait for a PnP event */
+ DPRINT("Waiting for pnp notification event\n");
+ Status = KeWaitForSingleObject(&IopPnpNotifyEvent,
+ UserRequest,
+ KernelMode,
+ FALSE,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("KeWaitForSingleObject() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ /* Get entry from the tail of the queue */
+ Entry = CONTAINING_RECORD(IopPnpEventQueueHead.Blink,
+ PNP_EVENT_ENTRY,
+ ListEntry);
+
+ /* Check the buffer size */
+ if (BufferSize < 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_SUCCESS;
+}
/*
* NtPlugPlayControl
*
* @unimplemented
*/
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass,
IN OUT PVOID Buffer,
IN ULONG BufferLength)
return STATUS_NOT_IMPLEMENTED;
}
-
-/* EOF */