- We already do this in the SEH block. No need to do it twice.
[reactos.git] / reactos / ntoskrnl / io / pnpmgr / plugplay.c
index e44e7e0..0d7dca9 100644 (file)
@@ -1,18 +1,16 @@
 /*
- * 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)
@@ -44,32 +42,41 @@ IopInitPlugPlayEvents(VOID)
     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);
@@ -105,127 +112,6 @@ IopRemovePlugPlayEvent(VOID)
   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)
 {
@@ -242,7 +128,7 @@ 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)
@@ -258,119 +144,6 @@ IopTraverseDeviceNode(PDEVICE_NODE Node, PUNICODE_STRING DeviceInstance)
 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;
 
@@ -475,7 +248,7 @@ IopGetDeviceProperty(PPLUGPLAY_CONTROL_PROPERTY_DATA PropertyData)
     }
 
     /* Get the device object */
-    DeviceObject = IopGetDeviceObjectFromDeviceInstance(&PropertyData->DeviceInstance);
+    DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
     ExFreePool(DeviceInstance.Buffer);
     if (DeviceObject == NULL)
     {
@@ -587,7 +360,7 @@ IopGetRelatedDevice(PPLUGPLAY_CONTROL_RELATED_DEVICE_DATA RelatedDeviceData)
             break;
 
         case PNP_GET_SIBLING_DEVICE:
-            RelatedDeviceNode = DeviceNode->NextSibling;
+            RelatedDeviceNode = DeviceNode->Sibling;
             break;
 
         default:
@@ -656,13 +429,11 @@ IopDeviceStatus(PPLUGPLAY_CONTROL_STATUS_DATA StatusData)
     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
     {
@@ -681,20 +452,18 @@ IopDeviceStatus(PPLUGPLAY_CONTROL_STATUS_DATA StatusData)
 
     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)
     {
@@ -753,17 +522,13 @@ IopGetDeviceDepth(PPLUGPLAY_CONTROL_DEPTH_DATA DepthData)
     }
 
     /* 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;
@@ -774,6 +539,8 @@ IopGetDeviceDepth(PPLUGPLAY_CONTROL_DEPTH_DATA DepthData)
     }
     _SEH_END;
 
+    ObDereferenceObject(DeviceObject);
+
     return Status;
 }
 
@@ -786,14 +553,11 @@ IopResetDevice(PPLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData)
     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);
@@ -810,13 +574,135 @@ IopResetDevice(PPLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData)
     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
@@ -874,7 +760,8 @@ IopResetDevice(PPLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData)
  *
  * @unimplemented
  */
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
 NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass,
                   IN OUT PVOID Buffer,
                   IN ULONG BufferLength)
@@ -955,5 +842,3 @@ NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass,
 
     return STATUS_NOT_IMPLEMENTED;
 }
-
-/* EOF */