Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / reactos / ntoskrnl / io / pnpmgr / plugplay.c
diff --git a/reactos/ntoskrnl/io/pnpmgr/plugplay.c b/reactos/ntoskrnl/io/pnpmgr/plugplay.c
deleted file mode 100644 (file)
index 9797017..0000000
+++ /dev/null
@@ -1,1218 +0,0 @@
-/*
- * 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 <debug.h>
-
-#if defined (ALLOC_PRAGMA)
-#pragma alloc_text(INIT, IopInitPlugPlayEvents)
-#endif
-
-typedef struct _PNP_EVENT_ENTRY
-{
-    LIST_ENTRY ListEntry;
-    PLUGPLAY_EVENT_BLOCK Event;
-} PNP_EVENT_ENTRY, *PPNP_EVENT_ENTRY;
-
-
-/* GLOBALS *******************************************************************/
-
-static LIST_ENTRY IopPnpEventQueueHead;
-static KEVENT IopPnpNotifyEvent;
-
-/* FUNCTIONS *****************************************************************/
-
-NTSTATUS INIT_FUNCTION
-IopInitPlugPlayEvents(VOID)
-{
-    InitializeListHead(&IopPnpEventQueueHead);
-
-    KeInitializeEvent(&IopPnpNotifyEvent,
-                      SynchronizationEvent,
-                      FALSE);
-
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-IopQueueTargetDeviceEvent(const GUID *Guid,
-                          PUNICODE_STRING DeviceIds)
-{
-    PPNP_EVENT_ENTRY EventEntry;
-    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) +
-        Copy.MaximumLength;
-
-    EventEntry = ExAllocatePool(NonPagedPool,
-                                TotalSize + FIELD_OFFSET(PNP_EVENT_ENTRY, Event));
-    if (!EventEntry)
-        return STATUS_INSUFFICIENT_RESOURCES;
-
-    /* Fill the buffer with the event GUID */
-    RtlCopyMemory(&EventEntry->Event.EventGuid,
-                  Guid,
-                  sizeof(GUID));
-    EventEntry->Event.EventCategory = TargetDeviceChangeEvent;
-    EventEntry->Event.TotalSize = TotalSize;
-
-    /* Fill the device id */
-    Copy.Buffer = EventEntry->Event.TargetDevice.DeviceIds;
-    Status = RtlAppendUnicodeStringToString(&Copy, DeviceIds);
-    if (!NT_SUCCESS(Status))
-    {
-        ExFreePool(EventEntry);
-        return Status;
-    }
-
-    InsertHeadList(&IopPnpEventQueueHead,
-                   &EventEntry->ListEntry);
-    KeSetEvent(&IopPnpNotifyEvent,
-               0,
-               FALSE);
-
-    return STATUS_SUCCESS;
-}
-
-
-/*
- * Remove the current PnP event from the tail of the event queue
- * and signal IopPnpNotifyEvent if there is yet another event in the queue.
- */
-static NTSTATUS
-IopRemovePlugPlayEvent(VOID)
-{
-    /* Remove a pnp event entry from the tail of the queue */
-    if (!IsListEmpty(&IopPnpEventQueueHead))
-    {
-        ExFreePool(CONTAINING_RECORD(RemoveTailList(&IopPnpEventQueueHead), PNP_EVENT_ENTRY, ListEntry));
-    }
-
-    /* Signal the next pnp event in the queue */
-    if (!IsListEmpty(&IopPnpEventQueueHead))
-    {
-        KeSetEvent(&IopPnpNotifyEvent,
-                   0,
-                   FALSE);
-    }
-
-    return STATUS_SUCCESS;
-}
-
-static PDEVICE_OBJECT
-IopTraverseDeviceNode(PDEVICE_NODE Node, PUNICODE_STRING DeviceInstance)
-{
-    PDEVICE_OBJECT DeviceObject;
-    PDEVICE_NODE ChildNode;
-
-    if (RtlEqualUnicodeString(&Node->InstancePath,
-                              DeviceInstance, TRUE))
-    {
-        ObReferenceObject(Node->PhysicalDeviceObject);
-        return Node->PhysicalDeviceObject;
-    }
-
-    /* Traversal of all children nodes */
-    for (ChildNode = Node->Child;
-         ChildNode != NULL;
-         ChildNode = ChildNode->Sibling)
-    {
-        DeviceObject = IopTraverseDeviceNode(ChildNode, DeviceInstance);
-        if (DeviceObject != NULL)
-        {
-            return DeviceObject;
-        }
-    }
-
-    return NULL;
-}
-
-
-PDEVICE_OBJECT
-IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance)
-{
-    if (IopRootDeviceNode == NULL)
-        return NULL;
-
-    if (DeviceInstance == NULL ||
-        DeviceInstance->Length == 0)
-    {
-        if (IopRootDeviceNode->PhysicalDeviceObject)
-        {
-            ObReferenceObject(IopRootDeviceNode->PhysicalDeviceObject);
-            return IopRootDeviceNode->PhysicalDeviceObject;
-        }
-        else
-            return NULL;
-    }
-
-    return IopTraverseDeviceNode(IopRootDeviceNode, DeviceInstance);
-}
-
-static NTSTATUS
-IopCaptureUnicodeString(PUNICODE_STRING DstName, PUNICODE_STRING SrcName)
-{
-    NTSTATUS Status = STATUS_SUCCESS;
-    volatile UNICODE_STRING Name;
-
-    Name.Buffer = NULL;
-    _SEH2_TRY
-    {
-        Name.Length = SrcName->Length;
-        Name.MaximumLength = SrcName->MaximumLength;
-        if (Name.Length > Name.MaximumLength)
-        {
-            Status = STATUS_INVALID_PARAMETER;
-            _SEH2_LEAVE;
-        }
-
-        if (Name.MaximumLength)
-        {
-            ProbeForRead(SrcName->Buffer,
-                         Name.MaximumLength,
-                         sizeof(WCHAR));
-            Name.Buffer = ExAllocatePool(NonPagedPool, Name.MaximumLength);
-            if (Name.Buffer == NULL)
-            {
-                Status = STATUS_INSUFFICIENT_RESOURCES;
-                _SEH2_LEAVE;
-            }
-
-            memcpy(Name.Buffer, SrcName->Buffer, Name.MaximumLength);
-        }
-
-        *DstName = Name;
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        if (Name.Buffer)
-        {
-            ExFreePool(Name.Buffer);
-        }
-        Status = _SEH2_GetExceptionCode();
-    }
-    _SEH2_END;
-
-    return Status;
-}
-
-static NTSTATUS
-IopGetInterfaceDeviceList(PPLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA DeviceList)
-{
-    NTSTATUS Status;
-    PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA StackList;
-    UNICODE_STRING DeviceInstance;
-    PDEVICE_OBJECT DeviceObject = NULL;
-    GUID FilterGuid;
-    PZZWSTR SymbolicLinkList = NULL, LinkList;
-    SIZE_T TotalLength;
-
-    _SEH2_TRY
-    {
-        RtlCopyMemory(&StackList, DeviceList, sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA));
-
-        ProbeForRead(StackList.FilterGuid, sizeof(GUID), sizeof(UCHAR));
-        RtlCopyMemory(&FilterGuid, StackList.FilterGuid, sizeof(GUID));
-
-        if (StackList.Buffer != NULL && StackList.BufferSize != 0)
-        {
-            ProbeForWrite(StackList.Buffer, StackList.BufferSize, sizeof(UCHAR));
-        }
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        _SEH2_YIELD(return _SEH2_GetExceptionCode());
-    }
-    _SEH2_END;
-
-    Status = IopCaptureUnicodeString(&DeviceInstance, &StackList.DeviceInstance);
-    if (NT_SUCCESS(Status))
-    {
-        /* Get the device object */
-        DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
-        if (DeviceInstance.Buffer != NULL)
-        {
-            ExFreePool(DeviceInstance.Buffer);
-        }
-    }
-
-    Status = IoGetDeviceInterfaces(&FilterGuid, DeviceObject, StackList.Flags, &SymbolicLinkList);
-    ObDereferenceObject(DeviceObject);
-
-    if (!NT_SUCCESS(Status))
-    {
-        /* failed */
-        return Status;
-    }
-
-    LinkList = SymbolicLinkList;
-    while (*SymbolicLinkList != UNICODE_NULL)
-    {
-        SymbolicLinkList += wcslen(SymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR));
-    }
-    TotalLength = ((SymbolicLinkList - LinkList + 1) * sizeof(WCHAR));
-
-    _SEH2_TRY
-    {
-        if (StackList.Buffer != NULL &&
-            StackList.BufferSize >= TotalLength)
-        {
-            // We've already probed the buffer for writing above.
-            RtlCopyMemory(StackList.Buffer, LinkList, TotalLength);
-        }
-
-        DeviceList->BufferSize = TotalLength;
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        ExFreePool(LinkList);
-        _SEH2_YIELD(return _SEH2_GetExceptionCode());
-    }
-    _SEH2_END;
-
-    ExFreePool(LinkList);
-    return STATUS_SUCCESS;
-}
-
-static NTSTATUS
-IopGetDeviceProperty(PPLUGPLAY_CONTROL_PROPERTY_DATA PropertyData)
-{
-    PDEVICE_OBJECT DeviceObject = NULL;
-    NTSTATUS Status;
-    UNICODE_STRING DeviceInstance;
-    ULONG BufferSize;
-    ULONG Property = 0;
-    PVOID Buffer;
-
-    DPRINT("IopGetDeviceProperty() called\n");
-    DPRINT("Device name: %wZ\n", &PropertyData->DeviceInstance);
-
-    Status = IopCaptureUnicodeString(&DeviceInstance, &PropertyData->DeviceInstance);
-    if (!NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-
-    _SEH2_TRY
-    {
-        Property = PropertyData->Property;
-        BufferSize = PropertyData->BufferSize;
-        ProbeForWrite(PropertyData->Buffer,
-                      BufferSize,
-                      sizeof(UCHAR));
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        if (DeviceInstance.Buffer != NULL)
-        {
-            ExFreePool(DeviceInstance.Buffer);
-        }
-        _SEH2_YIELD(return _SEH2_GetExceptionCode());
-    }
-    _SEH2_END;
-
-    /* Get the device object */
-    DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
-    if (DeviceInstance.Buffer != NULL)
-    {
-        ExFreePool(DeviceInstance.Buffer);
-    }
-    if (DeviceObject == NULL)
-    {
-        return STATUS_NO_SUCH_DEVICE;
-    }
-
-    Buffer = ExAllocatePool(NonPagedPool, BufferSize);
-    if (Buffer == NULL)
-    {
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    Status = IoGetDeviceProperty(DeviceObject,
-                                 Property,
-                                 BufferSize,
-                                 Buffer,
-                                 &BufferSize);
-
-    ObDereferenceObject(DeviceObject);
-
-    if (NT_SUCCESS(Status))
-    {
-        _SEH2_TRY
-        {
-            RtlCopyMemory(PropertyData->Buffer, Buffer, BufferSize);
-            PropertyData->BufferSize = BufferSize;
-        }
-        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-        {
-            Status = _SEH2_GetExceptionCode();
-        }
-        _SEH2_END;
-    }
-
-    ExFreePool(Buffer);
-    return Status;
-}
-
-
-static NTSTATUS
-IopGetRelatedDevice(PPLUGPLAY_CONTROL_RELATED_DEVICE_DATA RelatedDeviceData)
-{
-    UNICODE_STRING RootDeviceName;
-    PDEVICE_OBJECT DeviceObject = NULL;
-    PDEVICE_NODE DeviceNode = NULL;
-    PDEVICE_NODE RelatedDeviceNode;
-    UNICODE_STRING TargetDeviceInstance;
-    NTSTATUS Status = STATUS_SUCCESS;
-    ULONG Relation = 0;
-    ULONG MaximumLength = 0;
-
-    DPRINT("IopGetRelatedDevice() called\n");
-    DPRINT("Device name: %wZ\n", &RelatedDeviceData->TargetDeviceInstance);
-
-    Status = IopCaptureUnicodeString(&TargetDeviceInstance, &RelatedDeviceData->TargetDeviceInstance);
-    if (!NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-
-    _SEH2_TRY
-    {
-        Relation = RelatedDeviceData->Relation;
-        MaximumLength = RelatedDeviceData->RelatedDeviceInstanceLength;
-        ProbeForWrite(RelatedDeviceData->RelatedDeviceInstance,
-                      MaximumLength,
-                      sizeof(WCHAR));
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        if (TargetDeviceInstance.Buffer != NULL)
-        {
-            ExFreePool(TargetDeviceInstance.Buffer);
-        }
-        _SEH2_YIELD(return _SEH2_GetExceptionCode());
-    }
-    _SEH2_END;
-
-    RtlInitUnicodeString(&RootDeviceName,
-                         L"HTREE\\ROOT\\0");
-    if (RtlEqualUnicodeString(&TargetDeviceInstance,
-                              &RootDeviceName,
-                              TRUE))
-    {
-        DeviceNode = IopRootDeviceNode;
-        if (TargetDeviceInstance.Buffer != NULL)
-        {
-            ExFreePool(TargetDeviceInstance.Buffer);
-        }
-    }
-    else
-    {
-        /* Get the device object */
-        DeviceObject = IopGetDeviceObjectFromDeviceInstance(&TargetDeviceInstance);
-        if (TargetDeviceInstance.Buffer != NULL)
-        {
-            ExFreePool(TargetDeviceInstance.Buffer);
-        }
-        if (DeviceObject == NULL)
-            return STATUS_NO_SUCH_DEVICE;
-
-        DeviceNode = ((PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension)->DeviceNode;
-    }
-
-    switch (Relation)
-    {
-        case PNP_GET_PARENT_DEVICE:
-            RelatedDeviceNode = DeviceNode->Parent;
-            break;
-
-        case PNP_GET_CHILD_DEVICE:
-            RelatedDeviceNode = DeviceNode->Child;
-            break;
-
-        case PNP_GET_SIBLING_DEVICE:
-            RelatedDeviceNode = DeviceNode->Sibling;
-            break;
-
-        default:
-            if (DeviceObject != NULL)
-            {
-                ObDereferenceObject(DeviceObject);
-            }
-
-            return STATUS_INVALID_PARAMETER;
-    }
-
-    if (RelatedDeviceNode == NULL)
-    {
-        if (DeviceObject)
-        {
-            ObDereferenceObject(DeviceObject);
-        }
-
-        return STATUS_NO_SUCH_DEVICE;
-    }
-
-    if (RelatedDeviceNode->InstancePath.Length > MaximumLength)
-    {
-        if (DeviceObject)
-        {
-            ObDereferenceObject(DeviceObject);
-        }
-
-        return STATUS_BUFFER_TOO_SMALL;
-    }
-
-    /* Copy related device instance name */
-    _SEH2_TRY
-    {
-        RtlCopyMemory(RelatedDeviceData->RelatedDeviceInstance,
-                      RelatedDeviceNode->InstancePath.Buffer,
-                      RelatedDeviceNode->InstancePath.Length);
-        RelatedDeviceData->RelatedDeviceInstanceLength = RelatedDeviceNode->InstancePath.Length;
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        Status = _SEH2_GetExceptionCode();
-    }
-    _SEH2_END;
-
-    if (DeviceObject != NULL)
-    {
-        ObDereferenceObject(DeviceObject);
-    }
-
-    DPRINT("IopGetRelatedDevice() done\n");
-
-    return Status;
-}
-
-static ULONG
-IopGetDeviceNodeStatus(PDEVICE_NODE DeviceNode)
-{
-    ULONG Output = 0;
-
-    if (DeviceNode->Parent == IopRootDeviceNode)
-        Output |= DN_ROOT_ENUMERATED;
-
-    if (DeviceNode->Flags & DNF_ADDED)
-        Output |= DN_DRIVER_LOADED;
-
-    /* FIXME: DN_ENUM_LOADED */
-
-    if (DeviceNode->Flags & DNF_STARTED)
-        Output |= DN_STARTED;
-
-    /* FIXME: Manual */
-
-    if (!(DeviceNode->Flags & DNF_PROCESSED))
-        Output |= DN_NEED_TO_ENUM;
-
-    /* DN_NOT_FIRST_TIME is 9x only */
-
-    /* FIXME: DN_HARDWARE_ENUM */
-
-    /* DN_LIAR and DN_HAS_MARK are 9x only */
-
-    if (DeviceNode->Problem != 0)
-        Output |= DN_HAS_PROBLEM;
-
-    /* FIXME: DN_FILTERED */
-
-    if (DeviceNode->Flags & DNF_LEGACY_DRIVER)
-        Output |= DN_LEGACY_DRIVER;
-
-    if (DeviceNode->UserFlags & DNUF_DONT_SHOW_IN_UI)
-        Output |= DN_NO_SHOW_IN_DM;
-
-    if (!(DeviceNode->UserFlags & DNUF_NOT_DISABLEABLE))
-        Output |= DN_DISABLEABLE;
-
-    /* FIXME: Implement the rest */
-
-    Output |= DN_NT_ENUMERATOR | DN_NT_DRIVER;
-
-    return Output;
-}
-
-static NTSTATUS
-IopDeviceStatus(PPLUGPLAY_CONTROL_STATUS_DATA StatusData)
-{
-    PDEVICE_OBJECT DeviceObject;
-    PDEVICE_NODE DeviceNode;
-    ULONG Operation = 0;
-    ULONG DeviceStatus = 0;
-    ULONG DeviceProblem = 0;
-    UNICODE_STRING DeviceInstance;
-    NTSTATUS Status;
-
-    DPRINT("IopDeviceStatus() called\n");
-
-    Status = IopCaptureUnicodeString(&DeviceInstance, &StatusData->DeviceInstance);
-    if (!NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-
-    DPRINT("Device name: '%wZ'\n", &DeviceInstance);
-
-    _SEH2_TRY
-    {
-        Operation = StatusData->Operation;
-        if (Operation == PNP_SET_DEVICE_STATUS)
-        {
-            DeviceStatus = StatusData->DeviceStatus;
-            DeviceProblem = StatusData->DeviceProblem;
-        }
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        if (DeviceInstance.Buffer != NULL)
-        {
-            ExFreePool(DeviceInstance.Buffer);
-        }
-        _SEH2_YIELD(return _SEH2_GetExceptionCode());
-    }
-    _SEH2_END;
-
-    /* Get the device object */
-    DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
-    if (DeviceInstance.Buffer != NULL)
-    {
-        ExFreePool(DeviceInstance.Buffer);
-    }
-    if (DeviceObject == NULL)
-    {
-        return STATUS_NO_SUCH_DEVICE;
-    }
-
-    DeviceNode = IopGetDeviceNode(DeviceObject);
-
-    switch (Operation)
-    {
-        case PNP_GET_DEVICE_STATUS:
-            DPRINT("Get status data\n");
-            DeviceStatus = IopGetDeviceNodeStatus(DeviceNode);
-            DeviceProblem = DeviceNode->Problem;
-            break;
-
-        case PNP_SET_DEVICE_STATUS:
-            DPRINT1("Set status data is NOT SUPPORTED\n");
-            break;
-
-        case PNP_CLEAR_DEVICE_STATUS:
-            DPRINT1("FIXME: Clear status data!\n");
-            break;
-    }
-
-    ObDereferenceObject(DeviceObject);
-
-    if (Operation == PNP_GET_DEVICE_STATUS)
-    {
-        _SEH2_TRY
-        {
-            StatusData->DeviceStatus = DeviceStatus;
-            StatusData->DeviceProblem = DeviceProblem;
-        }
-        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-        {
-            Status = _SEH2_GetExceptionCode();
-        }
-        _SEH2_END;
-    }
-
-    return Status;
-}
-
-static
-NTSTATUS
-IopGetDeviceRelations(PPLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA RelationsData)
-{
-    UNICODE_STRING DeviceInstance;
-    PDEVICE_OBJECT DeviceObject = NULL;
-    IO_STACK_LOCATION Stack;
-    IO_STATUS_BLOCK IoStatusBlock;
-    PDEVICE_RELATIONS DeviceRelations = NULL;
-    PDEVICE_OBJECT ChildDeviceObject;
-    PDEVICE_NODE ChildDeviceNode;
-    ULONG i;
-    ULONG Relations;
-    ULONG BufferSize, RequiredSize;
-    ULONG BufferLeft;
-    PWCHAR Buffer, Ptr;
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    DPRINT("IopGetDeviceRelations() called\n");
-    DPRINT("Device name: %wZ\n", &RelationsData->DeviceInstance);
-    DPRINT("Relations: %lu\n", RelationsData->Relations);
-    DPRINT("BufferSize: %lu\n", RelationsData->BufferSize);
-    DPRINT("Buffer: %p\n", RelationsData->Buffer);
-
-    _SEH2_TRY
-    {
-        Relations = RelationsData->Relations;
-        BufferSize = RelationsData->BufferSize;
-        Buffer = RelationsData->Buffer;
-
-        ProbeForWrite(Buffer, BufferSize, sizeof(CHAR));
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        _SEH2_YIELD(return _SEH2_GetExceptionCode());
-    }
-    _SEH2_END;
-
-    Status = IopCaptureUnicodeString(&DeviceInstance, &RelationsData->DeviceInstance);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("IopCaptureUnicodeString() failed (Status 0x%08lx)\n", Status);
-        return Status;
-    }
-
-    /* Get the device object */
-    DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
-    if (DeviceObject == NULL)
-    {
-        DPRINT1("IopGetDeviceObjectFromDeviceInstance() returned NULL\n");
-        Status = STATUS_NO_SUCH_DEVICE;
-        goto done;
-    }
-
-    switch (Relations)
-    {
-        case 0: /* EjectRelations */
-            Stack.Parameters.QueryDeviceRelations.Type = EjectionRelations;
-            break;
-
-        case 1: /* RemovalRelations */
-            Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
-            break;
-
-        case 2: /* PowerRelations */
-            Stack.Parameters.QueryDeviceRelations.Type = PowerRelations;
-            break;
-
-        case 3: /* BusRelations */
-            Stack.Parameters.QueryDeviceRelations.Type = BusRelations;
-            break;
-
-        default:
-            Status = STATUS_INVALID_PARAMETER;
-            goto done;
-    }
-
-    Status = IopInitiatePnpIrp(DeviceObject,
-                               &IoStatusBlock,
-                               IRP_MN_QUERY_DEVICE_RELATIONS,
-                               &Stack);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status);
-        goto done;
-    }
-
-    DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
-
-    DPRINT("Found %d device relations\n", DeviceRelations->Count);
-
-    _SEH2_TRY
-    {
-        RequiredSize = 0;
-        BufferLeft = BufferSize;
-        Ptr = Buffer;
-
-        for (i = 0; i < DeviceRelations->Count; i++)
-        {
-            ChildDeviceObject = DeviceRelations->Objects[i];
-
-            ChildDeviceNode = IopGetDeviceNode(ChildDeviceObject);
-            if (ChildDeviceNode)
-            {
-                DPRINT("Device instance: %wZ\n", &ChildDeviceNode->InstancePath);
-                DPRINT("RequiredSize: %hu\n", ChildDeviceNode->InstancePath.Length + sizeof(WCHAR));
-
-                if (Ptr != NULL)
-                {
-                    if (BufferLeft < ChildDeviceNode->InstancePath.Length + 2 * sizeof(WCHAR))
-                    {
-                        Status = STATUS_BUFFER_TOO_SMALL;
-                        break;
-                    }
-
-                    RtlCopyMemory(Ptr,
-                                  ChildDeviceNode->InstancePath.Buffer,
-                                  ChildDeviceNode->InstancePath.Length);
-                    Ptr = (PWCHAR)((ULONG_PTR)Ptr + ChildDeviceNode->InstancePath.Length);
-                    *Ptr = UNICODE_NULL;
-                    Ptr = (PWCHAR)((ULONG_PTR)Ptr + sizeof(WCHAR));
-
-                    BufferLeft -= (ChildDeviceNode->InstancePath.Length + sizeof(WCHAR));
-                }
-
-                RequiredSize += (ChildDeviceNode->InstancePath.Length + sizeof(WCHAR));
-            }
-        }
-
-        if (Ptr != NULL && BufferLeft >= sizeof(WCHAR))
-            *Ptr = UNICODE_NULL;
-
-        if (RequiredSize > 0)
-            RequiredSize += sizeof(WCHAR);
-
-        DPRINT("BufferSize: %lu  RequiredSize: %lu\n", RelationsData->BufferSize, RequiredSize);
-
-        RelationsData->BufferSize = RequiredSize;
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        Status = _SEH2_GetExceptionCode();
-    }
-    _SEH2_END;
-
-done:
-    if (DeviceRelations != NULL)
-        ExFreePool(DeviceRelations);
-
-    if (DeviceObject != NULL)
-        ObDereferenceObject(DeviceObject);
-
-    if (DeviceInstance.Buffer != NULL)
-        ExFreePool(DeviceInstance.Buffer);
-
-    return Status;
-}
-
-static NTSTATUS
-IopGetDeviceDepth(PPLUGPLAY_CONTROL_DEPTH_DATA DepthData)
-{
-    PDEVICE_OBJECT DeviceObject;
-    PDEVICE_NODE DeviceNode;
-    UNICODE_STRING DeviceInstance;
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    DPRINT("IopGetDeviceDepth() called\n");
-    DPRINT("Device name: %wZ\n", &DepthData->DeviceInstance);
-
-    Status = IopCaptureUnicodeString(&DeviceInstance, &DepthData->DeviceInstance);
-    if (!NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-
-    /* Get the device object */
-    DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
-    if (DeviceInstance.Buffer != NULL)
-    {
-        ExFreePool(DeviceInstance.Buffer);
-    }
-    if (DeviceObject == NULL)
-    {
-        return STATUS_NO_SUCH_DEVICE;
-    }
-
-    DeviceNode = IopGetDeviceNode(DeviceObject);
-
-    _SEH2_TRY
-    {
-        DepthData->Depth = DeviceNode->Level;
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        Status = _SEH2_GetExceptionCode();
-    }
-    _SEH2_END;
-
-    ObDereferenceObject(DeviceObject);
-
-    return Status;
-}
-
-
-static NTSTATUS
-IopResetDevice(PPLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData)
-{
-    PDEVICE_OBJECT DeviceObject;
-    PDEVICE_NODE DeviceNode;
-    NTSTATUS Status = STATUS_SUCCESS;
-    UNICODE_STRING DeviceInstance;
-
-    Status = IopCaptureUnicodeString(&DeviceInstance, &ResetDeviceData->DeviceInstance);
-    if (!NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-
-    DPRINT("IopResetDevice(%wZ)\n", &DeviceInstance);
-
-    /* Get the device object */
-    DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
-    if (DeviceInstance.Buffer != NULL)
-    {
-        ExFreePool(DeviceInstance.Buffer);
-    }
-    if (DeviceObject == NULL)
-    {
-        return STATUS_NO_SUCH_DEVICE;
-    }
-
-    /* Get the device node */
-    DeviceNode = IopGetDeviceNode(DeviceObject);
-
-    ASSERT(DeviceNode->Flags & DNF_ENUMERATED);
-    ASSERT(DeviceNode->Flags & DNF_PROCESSED);
-
-    /* Check if there's already a driver loaded for this device */
-    if (DeviceNode->Flags & DNF_ADDED)
-    {
-#if 0
-        /* Remove the device node */
-        Status = IopRemoveDevice(DeviceNode);
-        if (NT_SUCCESS(Status))
-        {
-            /* Invalidate device relations for the parent to reenumerate the device */
-            DPRINT1("A new driver will be loaded for '%wZ' (FDO above removed)\n", &DeviceNode->InstancePath);
-            Status = IoSynchronousInvalidateDeviceRelations(DeviceNode->Parent->PhysicalDeviceObject, BusRelations);
-        }
-        else
-#endif
-        {
-            /* A driver has already been loaded for this device */
-            DPRINT1("A reboot is required for the current driver for '%wZ' to be replaced\n", &DeviceNode->InstancePath);
-            DeviceNode->Problem = CM_PROB_NEED_RESTART;
-        }
-    }
-    else
-    {
-        /* FIXME: What if the device really is disabled? */
-        DeviceNode->Flags &= ~DNF_DISABLED;
-        DeviceNode->Problem = 0;
-
-        /* Load service data from the registry */
-        Status = IopActionConfigureChildServices(DeviceNode, DeviceNode->Parent);
-
-        if (NT_SUCCESS(Status))
-        {
-            /* Start the service and begin PnP initialization of the device again */
-            DPRINT1("A new driver will be loaded for '%wZ' (no FDO above)\n", &DeviceNode->InstancePath);
-            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,
-                                   UserMode,
-                                   FALSE,
-                                   NULL);
-    if (!NT_SUCCESS(Status) || Status == STATUS_USER_APC)
-    {
-        DPRINT("KeWaitForSingleObject() failed (Status %lx)\n", Status);
-        ASSERT(Status == STATUS_USER_APC);
-        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 */
-    _SEH2_TRY
-    {
-        ProbeForWrite(Buffer,
-                      Entry->Event.TotalSize,
-                      sizeof(UCHAR));
-        RtlCopyMemory(Buffer,
-                      &Entry->Event,
-                      Entry->Event.TotalSize);
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        _SEH2_YIELD(return _SEH2_GetExceptionCode());
-    }
-    _SEH2_END;
-
-    DPRINT("NtGetPlugPlayEvent() done\n");
-
-    return STATUS_SUCCESS;
-}
-
-/*
- * NtPlugPlayControl
- *
- * A function for doing various Plug & Play operations from user mode.
- *
- * Parameters
- *    PlugPlayControlClass
- *       0x00   Reenumerate device tree
- *
- *              Buffer points to UNICODE_STRING decribing the instance
- *              path (like "HTREE\ROOT\0" or "Root\ACPI_HAL\0000"). For
- *              more information about instance paths see !devnode command
- *              in kernel debugger or look at "Inside Windows 2000" book,
- *              chapter "Driver Loading, Initialization, and Installation".
- *
- *       0x01   Register new device
- *       0x02   Deregister device
- *       0x03   Initialize device
- *       0x04   Start device
- *       0x06   Query and remove device
- *       0x07   User response
- *
- *              Called after processing the message from NtGetPlugPlayEvent.
- *
- *       0x08   Generate legacy device
- *       0x09   Get interface device list
- *       0x0A   Get property data
- *       0x0B   Device class association (Registration)
- *       0x0C   Get related device
- *       0x0D   Get device interface alias
- *       0x0E   Get/set/clear device status
- *       0x0F   Get device depth
- *       0x10   Query device relations
- *       0x11   Query target device relation
- *       0x12   Query conflict list
- *       0x13   Retrieve dock data
- *       0x14   Reset device
- *       0x15   Halt device
- *       0x16   Get blocked driver data
- *
- *    Buffer
- *       The buffer contains information that is specific to each control
- *       code. The buffer is read-only.
- *
- *    BufferSize
- *       Size of the buffer pointed by the Buffer parameter. If the
- *       buffer size specifies incorrect value for specified control
- *       code, error ??? is returned.
- *
- * Return Values
- *    STATUS_PRIVILEGE_NOT_HELD
- *    STATUS_SUCCESS
- *    ...
- *
- * @unimplemented
- */
-NTSTATUS
-NTAPI
-NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass,
-                  IN OUT PVOID Buffer,
-                  IN ULONG BufferLength)
-{
-    DPRINT("NtPlugPlayControl(%d %p %lu) called\n",
-           PlugPlayControlClass, Buffer, BufferLength);
-
-    /* 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;
-    }
-
-    /* Probe the buffer */
-    _SEH2_TRY
-    {
-        ProbeForWrite(Buffer,
-                      BufferLength,
-                      sizeof(ULONG));
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        _SEH2_YIELD(return _SEH2_GetExceptionCode());
-    }
-    _SEH2_END;
-
-    switch (PlugPlayControlClass)
-    {
-//        case PlugPlayControlEnumerateDevice:
-//        case PlugPlayControlRegisterNewDevice:
-//        case PlugPlayControlDeregisterDevice:
-//        case PlugPlayControlInitializeDevice:
-//        case PlugPlayControlStartDevice:
-//        case PlugPlayControlUnlockDevice:
-//        case PlugPlayControlQueryAndRemoveDevice:
-
-        case PlugPlayControlUserResponse:
-            if (Buffer || BufferLength != 0)
-                return STATUS_INVALID_PARAMETER;
-            return IopRemovePlugPlayEvent();
-
-//        case PlugPlayControlGenerateLegacyDevice:
-
-        case PlugPlayControlGetInterfaceDeviceList:
-            if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA))
-                return STATUS_INVALID_PARAMETER;
-            return IopGetInterfaceDeviceList((PPLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA)Buffer);
-
-        case PlugPlayControlProperty:
-            if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA))
-                return STATUS_INVALID_PARAMETER;
-            return IopGetDeviceProperty((PPLUGPLAY_CONTROL_PROPERTY_DATA)Buffer);
-
-//        case PlugPlayControlDeviceClassAssociation:
-
-        case PlugPlayControlGetRelatedDevice:
-            if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA))
-                return STATUS_INVALID_PARAMETER;
-            return IopGetRelatedDevice((PPLUGPLAY_CONTROL_RELATED_DEVICE_DATA)Buffer);
-
-//        case PlugPlayControlGetInterfaceDeviceAlias:
-
-        case PlugPlayControlDeviceStatus:
-            if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_STATUS_DATA))
-                return STATUS_INVALID_PARAMETER;
-            return IopDeviceStatus((PPLUGPLAY_CONTROL_STATUS_DATA)Buffer);
-
-        case PlugPlayControlGetDeviceDepth:
-            if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_DEPTH_DATA))
-                return STATUS_INVALID_PARAMETER;
-            return IopGetDeviceDepth((PPLUGPLAY_CONTROL_DEPTH_DATA)Buffer);
-
-        case PlugPlayControlQueryDeviceRelations:
-            if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA))
-                return STATUS_INVALID_PARAMETER;
-            return IopGetDeviceRelations((PPLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA)Buffer);
-
-//        case PlugPlayControlTargetDeviceRelation:
-//        case PlugPlayControlQueryConflictList:
-//        case PlugPlayControlRetrieveDock:
-
-        case PlugPlayControlResetDevice:
-            if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA))
-                return STATUS_INVALID_PARAMETER;
-            return IopResetDevice((PPLUGPLAY_CONTROL_RESET_DEVICE_DATA)Buffer);
-
-//        case PlugPlayControlHaltDevice:
-//        case PlugPlayControlGetBlockedDriverList:
-
-        default:
-            return STATUS_NOT_IMPLEMENTED;
-    }
-
-    return STATUS_NOT_IMPLEMENTED;
-}