Use UNICODE_STRING and Rtl functions instead of LPWSTR variables (can prevent some...
authorHervé Poussineau <hpoussin@reactos.org>
Thu, 27 Dec 2007 19:02:32 +0000 (19:02 +0000)
committerHervé Poussineau <hpoussin@reactos.org>
Thu, 27 Dec 2007 19:02:32 +0000 (19:02 +0000)
Remove assumption that UNICODE_STRING buffers are always NULL terminated
Remove some intermediate buffers
Do not define multiple times PnP parent key

svn path=/trunk/; revision=31467

reactos/ntoskrnl/io/pnpmgr/pnpmgr.c

index 810d77a..89edacd 100644 (file)
@@ -19,6 +19,8 @@
 
 /* GLOBALS *******************************************************************/
 
+#define ENUM_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum"
+
 PDEVICE_NODE IopRootDeviceNode;
 KSPIN_LOCK IopDeviceTreeLock;
 ERESOURCE PpRegistryDeviceResource;
@@ -403,12 +405,13 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
       case DevicePropertyLocationInformation:
       case DevicePropertyUINumber:
       {
-         LPWSTR RegistryPropertyName, KeyNameBuffer;
-         UNICODE_STRING KeyName, ValueName;
+         LPCWSTR RegistryPropertyName;
+         UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT);
+         UNICODE_STRING ValueName;
          OBJECT_ATTRIBUTES ObjectAttributes;
          KEY_VALUE_PARTIAL_INFORMATION *ValueInformation;
          ULONG ValueInformationLength;
-         HANDLE KeyHandle;
+         HANDLE hEnum, KeyHandle;
          NTSTATUS Status;
 
          switch (DeviceProperty)
@@ -434,62 +437,70 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
             case DevicePropertyUINumber:
                RegistryPropertyName = L"UINumber"; break;
             default:
-               RegistryPropertyName = NULL; break;
-         }
-
-         KeyNameBuffer = ExAllocatePool(PagedPool,
-            (49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length);
-
-         DPRINT("KeyNameBuffer: 0x%p, value %S\n", KeyNameBuffer, RegistryPropertyName);
-
-         if (KeyNameBuffer == NULL)
-            return STATUS_INSUFFICIENT_RESOURCES;
-
-         wcscpy(KeyNameBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
-         wcscat(KeyNameBuffer, DeviceNode->InstancePath.Buffer);
-         RtlInitUnicodeString(&KeyName, KeyNameBuffer);
-         InitializeObjectAttributes(&ObjectAttributes, &KeyName,
-                                    OBJ_CASE_INSENSITIVE, NULL, NULL);
-
-         Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
-         ExFreePool(KeyNameBuffer);
-         if (!NT_SUCCESS(Status))
-            return Status;
-
-         RtlInitUnicodeString(&ValueName, RegistryPropertyName);
-         ValueInformationLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,
-                                               Data[0]) + BufferLength;
-         ValueInformation = ExAllocatePool(PagedPool, ValueInformationLength);
-         if (ValueInformation == NULL)
-         {
-            ZwClose(KeyHandle);
-            return STATUS_INSUFFICIENT_RESOURCES;
-         }
-
-         Status = ZwQueryValueKey(KeyHandle, &ValueName,
-                                  KeyValuePartialInformation, ValueInformation,
-                                  ValueInformationLength,
-                                  &ValueInformationLength);
-         *ResultLength = ValueInformation->DataLength;
-         ZwClose(KeyHandle);
-
-         if (!NT_SUCCESS(Status))
-         {
-            ExFreePool(ValueInformation);
-            if (Status == STATUS_BUFFER_OVERFLOW)
-               return STATUS_BUFFER_TOO_SMALL;
-            else
-               return Status;
+               /* Should not happen */
+               ASSERT(FALSE);
+               return STATUS_UNSUCCESSFUL;
          }
 
-         /* FIXME: Verify the value (NULL-terminated, correct format). */
+            DPRINT("Registry property %S\n", RegistryPropertyName);
 
-         RtlCopyMemory(PropertyBuffer, ValueInformation->Data,
-                       ValueInformation->DataLength);
-         ExFreePool(ValueInformation);
+            /* Open Enum key */
+            InitializeObjectAttributes(&ObjectAttributes, &EnumU,
+                                       OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
+            Status = ZwOpenKey(&hEnum, 0, &ObjectAttributes);
+            if (!NT_SUCCESS(Status))
+                return Status;
 
-         return STATUS_SUCCESS;
-      }
+            /* Open instance key */
+            InitializeObjectAttributes(&ObjectAttributes, &DeviceNode->InstancePath,
+                                       OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, hEnum, NULL);
+            Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
+            ZwClose(hEnum);
+            if (!NT_SUCCESS(Status))
+                return Status;
+
+             /* Allocate buffer to read as much data as required by the caller */
+             ValueInformationLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,
+                                                   Data[0]) + BufferLength;
+             ValueInformation = ExAllocatePool(PagedPool, ValueInformationLength);
+             if (!ValueInformation)
+             {
+                 ZwClose(KeyHandle);
+                 return STATUS_INSUFFICIENT_RESOURCES;
+             }
+
+             /* Read the value */
+             RtlInitUnicodeString(&ValueName, RegistryPropertyName);
+             Status = ZwQueryValueKey(KeyHandle, &ValueName,
+                                      KeyValuePartialInformation, ValueInformation,
+                                      ValueInformationLength,
+                                      &ValueInformationLength);
+             ZwClose(KeyHandle);
+
+             if (!NT_SUCCESS(Status))
+             {
+                 ExFreePool(ValueInformation);
+                 if (Status == STATUS_BUFFER_OVERFLOW)
+                 {
+                     *ResultLength = ValueInformation->DataLength;
+                     return STATUS_BUFFER_TOO_SMALL;
+                 }
+                 else
+                 {
+                     *ResultLength = 0;
+                     return Status;
+                 }
+             }
+
+             /* Return data */
+             *ResultLength = ValueInformation->DataLength;
+             /* FIXME: Verify the value (NULL-terminated, correct format). */
+             RtlCopyMemory(PropertyBuffer, ValueInformation->Data,
+                           ValueInformation->DataLength);
+             ExFreePool(ValueInformation);
+
+             return STATUS_SUCCESS;
+        }
 
    case DevicePropertyBootConfiguration:
       Length = 0;
@@ -510,43 +521,36 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
       Data = &DeviceNode->BootResources;
       break;
 
-   case DevicePropertyEnumeratorName:
-      Ptr = wcschr(DeviceNode->InstancePath.Buffer, L'\\');
-      if (Ptr != NULL)
-      {
-         Length = (ULONG)((ULONG_PTR)Ptr - (ULONG_PTR)DeviceNode->InstancePath.Buffer) + sizeof(WCHAR);
-         Data = DeviceNode->InstancePath.Buffer;
-      }
-      else
-      {
-         Length = 0;
-         Data = NULL;
-      }
-      break;
-
-   case DevicePropertyPhysicalDeviceObjectName:
-      Length = DeviceNode->InstancePath.Length + sizeof(WCHAR);
-      Data = DeviceNode->InstancePath.Buffer;
-      break;
-
-   default:
-      return STATUS_INVALID_PARAMETER_2;
-  }
+        case DevicePropertyEnumeratorName:
+            /* A buffer overflow can't happen here, since InstancePath
+             * always contains the enumerator name followed by \\ */
+            Ptr = wcschr(DeviceNode->InstancePath.Buffer, L'\\');
+            ASSERT(Ptr);
+            Length = (Ptr - DeviceNode->InstancePath.Buffer + 1) * sizeof(WCHAR);
+            Data = DeviceNode->InstancePath.Buffer;
+            break;
+
+        case DevicePropertyPhysicalDeviceObjectName:
+            /* InstancePath buffer is NULL terminated, so we can do this */
+            Length = DeviceNode->InstancePath.MaximumLength;
+            Data = DeviceNode->InstancePath.Buffer;
+            break;
+
+        default:
+            return STATUS_INVALID_PARAMETER_2;
+    }
 
-  *ResultLength = Length;
-  if (BufferLength < Length)
-     return STATUS_BUFFER_TOO_SMALL;
-  RtlCopyMemory(PropertyBuffer, Data, Length);
+    /* Prepare returned values */
+    *ResultLength = Length;
+    if (BufferLength < Length)
+        return STATUS_BUFFER_TOO_SMALL;
+    RtlCopyMemory(PropertyBuffer, Data, Length);
 
-  /* Terminate the string */
-  if (DeviceProperty == DevicePropertyEnumeratorName
-     || DeviceProperty == DevicePropertyPhysicalDeviceObjectName)
-  {
-     Ptr = (PWSTR)PropertyBuffer;
-     Ptr[(Length / sizeof(WCHAR)) - 1] = 0;
-  }
+    /* NULL terminate the string (if required) */
+    if (DeviceProperty == DevicePropertyEnumeratorName)
+        ((LPWSTR)PropertyBuffer)[Length / sizeof(WCHAR)] = UNICODE_NULL;
 
-  return STATUS_SUCCESS;
+    return STATUS_SUCCESS;
 }
 
 /*
@@ -1062,82 +1066,110 @@ IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context)
 }
 
 
-static
+/*
+ * IopCreateDeviceKeyPath
+ *
+ * Creates a registry key
+ *
+ * Parameters
+ *    RegistryPath
+ *        Name of the key to be created.
+ *    Handle
+ *        Handle to the newly created key
+ *
+ * Remarks
+ *     This method can create nested trees, so parent of RegistryPath can
+ *     be not existant, and will be created if needed.
+ */
 NTSTATUS
-IopCreateDeviceKeyPath(PWSTR Path,
-                       PHANDLE Handle)
+NTAPI
+IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath,
+                       OUT PHANDLE Handle)
 {
-   OBJECT_ATTRIBUTES ObjectAttributes;
-   WCHAR KeyBuffer[MAX_PATH];
-   UNICODE_STRING KeyName;
-   HANDLE KeyHandle;
-   NTSTATUS Status;
-   PWCHAR Current;
-   PWCHAR Next;
+    UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT);
+    HANDLE hParent = NULL, hKey;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING KeyName;
+    LPCWSTR Current, Last;
+    ULONG dwLength;
+    NTSTATUS Status;
 
-   *Handle = NULL;
+    /* Assume failure */
+    *Handle = NULL;
 
-   if (_wcsnicmp(Path, L"\\Registry\\", 10) != 0)
-   {
-      return STATUS_INVALID_PARAMETER;
-   }
+    /* Open root key for device instances */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &EnumU,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status = ZwOpenKey(&hParent,
+                       KEY_CREATE_SUB_KEY,
+                       &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU, Status);
+        return Status;
+    }
 
-   wcsncpy (KeyBuffer, Path, MAX_PATH-1);
+    Current = KeyName.Buffer = RegistryPath->Buffer;
+    Last = &RegistryPath->Buffer[RegistryPath->Length / sizeof(WCHAR)];
 
-   /* Skip \\Registry\\ */
-   Current = KeyBuffer;
-   Current = wcschr (Current, L'\\') + 1;
-   Current = wcschr (Current, L'\\') + 1;
+    /* Go up to the end of the string */
+    while (Current <= Last)
+    {
+        if (Current != Last && *Current != '\\')
+        {
+            /* Not the end of the string and not a separator */
+            Current++;
+            continue;
+        }
 
-   while (TRUE)
-   {
-      Next = wcschr (Current, L'\\');
-      if (Next == NULL)
-      {
-         /* The end */
-      }
-      else
-      {
-         *Next = 0;
-      }
+        /* Prepare relative key name */
+        dwLength = (ULONG_PTR)Current - (ULONG_PTR)KeyName.Buffer;
+        KeyName.MaximumLength = KeyName.Length = dwLength;
+        DPRINT("Create '%wZ'\n", &KeyName);
 
-      RtlInitUnicodeString (&KeyName, KeyBuffer);
-      InitializeObjectAttributes (&ObjectAttributes,
-                                  &KeyName,
-                                  OBJ_CASE_INSENSITIVE,
-                                  NULL,
-                                  NULL);
+        /* Open key */
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &KeyName,
+                                   OBJ_CASE_INSENSITIVE,
+                                   hParent,
+                                   NULL);
+        Status = ZwCreateKey(&hKey,
+                             Current == Last ? KEY_ALL_ACCESS : KEY_CREATE_SUB_KEY,
+                             &ObjectAttributes,
+                             0,
+                             NULL,
+                             0,
+                             NULL);
 
-      DPRINT("Create '%S'\n", KeyName.Buffer);
+        /* Close parent key handle, we don't need it anymore */
+        if (hParent)
+            ZwClose(hParent);
 
-      Status = ZwCreateKey (&KeyHandle,
-                            KEY_ALL_ACCESS,
-                            &ObjectAttributes,
-                            0,
-                            NULL,
-                            0,
-                            NULL);
-      if (!NT_SUCCESS (Status))
-      {
-         DPRINT ("ZwCreateKey() failed with status %x\n", Status);
-         return Status;
-      }
+        /* Key opening/creating failed? */
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName, Status);
+            return Status;
+        }
 
-      if (Next == NULL)
-      {
-         *Handle = KeyHandle;
-         return STATUS_SUCCESS;
-      }
-      else
-      {
-         ZwClose (KeyHandle);
-         *Next = L'\\';
-      }
+        /* Check if it is the end of the string */
+        if (Current == Last)
+        {
+            /* Yes, return success */
+            *Handle = hKey;
+            return STATUS_SUCCESS;
+        }
 
-      Current = Next + 1;
-   }
+        /* Start with this new parent key */
+        hParent = hKey;
+        Current++;
+        KeyName.Buffer = (LPWSTR)Current;
+    }
 
-   return STATUS_UNSUCCESSFUL;
+    return STATUS_UNSUCCESSFUL;
 }
 
 
@@ -1225,41 +1257,6 @@ IopSetDeviceInstanceData(HANDLE InstanceKey,
                            sizeof(DefaultConfigFlags));
   }
 
-#if 0
-  if (DeviceNode->PhysicalDeviceObject != NULL)
-  {
-    /* Create the 'Control' key */
-    RtlInitUnicodeString(&KeyName,
-                        L"Control");
-    InitializeObjectAttributes(&ObjectAttributes,
-                              &KeyName,
-                              OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
-                              InstanceKey,
-                              NULL);
-    Status = ZwCreateKey(&LogConfKey,
-                        KEY_ALL_ACCESS,
-                        &ObjectAttributes,
-                        0,
-                        NULL,
-                        REG_OPTION_VOLATILE,
-                        NULL);
-    if (NT_SUCCESS(Status))
-    {
-      ULONG Reference = (ULONG)DeviceNode->PhysicalDeviceObject;
-      RtlInitUnicodeString(&KeyName,
-                          L"DeviceReference");
-      Status = ZwSetValueKey(LogConfKey,
-                            &KeyName,
-                            0,
-                            REG_DWORD,
-                            &Reference,
-                            sizeof(PVOID));
-
-      ZwClose(LogConfKey);
-    }
-  }
-#endif
-
   DPRINT("IopSetDeviceInstanceData() done\n");
 
   return STATUS_SUCCESS;
@@ -1606,98 +1603,96 @@ NTSTATUS
 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode,
                      PUNICODE_STRING ParentIdPrefix)
 {
-   ULONG KeyNameBufferLength;
-   PWSTR KeyNameBuffer = NULL;
-   PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation = NULL;
-   UNICODE_STRING KeyName;
-   UNICODE_STRING KeyValue;
-   UNICODE_STRING ValueName;
-   OBJECT_ATTRIBUTES ObjectAttributes;
-   HANDLE hKey = NULL;
-   ULONG crc32;
-   NTSTATUS Status;
+    ULONG BufferLength;
+    UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT);
+    PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation;
+    UNICODE_STRING KeyValue;
+    UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"ParentIdPrefix");
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    HANDLE hEnum, hKey = NULL;
+    ULONG crc32;
+    NTSTATUS Status;
 
-   /* HACK: As long as some devices have a NULL device
-    * instance path, the following test is required :(
-    */
-   if (DeviceNode->Parent->InstancePath.Length == 0)
-   {
-      DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
-          &DeviceNode->InstancePath);
-      return STATUS_UNSUCCESSFUL;
-   }
+    /* Allocate a buffer big enough to read a MAX_PATH prefix */
+    BufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MAX_PATH * sizeof(WCHAR);
+    ParentIdPrefixInformation = ExAllocatePool(PagedPool, BufferLength + sizeof(WCHAR));
 
-   /* 1. Try to retrieve ParentIdPrefix from registry */
-   KeyNameBufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MAX_PATH * sizeof(WCHAR);
-   ParentIdPrefixInformation = ExAllocatePool(PagedPool, KeyNameBufferLength + sizeof(WCHAR));
-   if (!ParentIdPrefixInformation)
-   {
-       Status = STATUS_INSUFFICIENT_RESOURCES;
-       goto cleanup;
-   }
-   KeyNameBuffer = ExAllocatePool(PagedPool, (49 * sizeof(WCHAR)) + DeviceNode->Parent->InstancePath.Length);
-   if (!KeyNameBuffer)
-   {
-       Status = STATUS_INSUFFICIENT_RESOURCES;
-       goto cleanup;
-   }
-   wcscpy(KeyNameBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
-   wcscat(KeyNameBuffer, DeviceNode->Parent->InstancePath.Buffer);
-   RtlInitUnicodeString(&KeyName, KeyNameBuffer);
-   InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
-   Status = ZwOpenKey(&hKey, KEY_QUERY_VALUE | KEY_SET_VALUE, &ObjectAttributes);
-   if (!NT_SUCCESS(Status))
-      goto cleanup;
-   RtlInitUnicodeString(&ValueName, L"ParentIdPrefix");
-   Status = ZwQueryValueKey(
-      hKey, &ValueName,
-      KeyValuePartialInformation, ParentIdPrefixInformation,
-      KeyNameBufferLength, &KeyNameBufferLength);
-   if (NT_SUCCESS(Status))
-   {
-      if (ParentIdPrefixInformation->Type != REG_SZ)
-         Status = STATUS_UNSUCCESSFUL;
-      else
-      {
-         KeyValue.Length = KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength;
-         KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data;
-      }
-      goto cleanup;
-   }
-   if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
-   {
-      KeyValue.Length = KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength;
-      KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data;
-      goto cleanup;
-   }
+    /* Check if allocation succeeded */
+    if (!ParentIdPrefixInformation)
+    {
+        Status = STATUS_NO_MEMORY;
+        goto cleanup;
+    }
+
+    /* Open enum key */
+    InitializeObjectAttributes(&ObjectAttributes, &EnumU, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
+    Status = ZwOpenKey(&hEnum, 0, &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+        goto cleanup;
+
+    /* Open instance key */
+    InitializeObjectAttributes(&ObjectAttributes, &DeviceNode->Parent->InstancePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, hEnum, NULL);
+    Status = ZwOpenKey(&hKey, KEY_QUERY_VALUE | KEY_SET_VALUE, &ObjectAttributes);
+    ZwClose(hEnum);
+    if (!NT_SUCCESS(Status))
+        goto cleanup;
+
+    /* Read the prefix */
+    Status = ZwQueryValueKey(
+        hKey, &ValueName,
+        KeyValuePartialInformation, ParentIdPrefixInformation,
+        BufferLength, &BufferLength);
+    if (NT_SUCCESS(Status))
+    {
+        /* Yes, we read something */
+        if (ParentIdPrefixInformation->Type != REG_SZ)
+            /* Hm, it was of the wrong type. Fail */
+            Status = STATUS_UNSUCCESSFUL;
+        else
+        {
+            /* OK, value is correct ; prepare to return it */
+            KeyValue.Length = KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength;
+            KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data;
+        }
 
-   /* 2. Create the ParentIdPrefix value */
-   crc32 = RtlComputeCrc32(0,
-                           (PUCHAR)DeviceNode->Parent->InstancePath.Buffer,
-                           DeviceNode->Parent->InstancePath.Length);
+        /* We're done */
+        goto cleanup;
+    }
+
+    /* Check if we failed due to value not calculated */
+    if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
+        /* Another reason, fail */
+        goto cleanup;
 
-   swprintf((PWSTR)ParentIdPrefixInformation->Data, L"%lx&%lx", DeviceNode->Parent->Level, crc32);
-   RtlInitUnicodeString(&KeyValue, (PWSTR)ParentIdPrefixInformation->Data);
+    /* Compute the prefix string of the parent */
+    crc32 = RtlComputeCrc32(0,
+                            (PUCHAR)DeviceNode->Parent->InstancePath.Buffer,
+                            DeviceNode->Parent->InstancePath.Length);
 
-   /* 3. Try to write the ParentIdPrefix to registry */
-   Status = ZwSetValueKey(hKey,
-                          &ValueName,
-                          0,
-                          REG_SZ,
-                          (PVOID)KeyValue.Buffer,
-                          (wcslen(KeyValue.Buffer) + 1) * sizeof(WCHAR));
+    /* Prepare the value to return */
+    /* (yes, it's safe to reuse ParentIdPrefixInformation buffer, which is at least MAX_PATH WCHARs long */
+    swprintf((PWSTR)ParentIdPrefixInformation, L"%lx&%lx", DeviceNode->Parent->Level, crc32);
+    RtlInitUnicodeString(&KeyValue, (PWSTR)ParentIdPrefixInformation);
+
+    /* 3. Try to write the ParentIdPrefix to registry */
+    Status = ZwSetValueKey(hKey,
+                           &ValueName,
+                           0,
+                           REG_SZ,
+                           (PVOID)KeyValue.Buffer,
+                           KeyValue.MaximumLength);
 
 cleanup:
-   if (NT_SUCCESS(Status))
-   {
-      /* Duplicate the string to return it */
-      Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &KeyValue, ParentIdPrefix);
-   }
-   ExFreePool(ParentIdPrefixInformation);
-   ExFreePool(KeyNameBuffer);
-   if (hKey != NULL)
-      ZwClose(hKey);
-   return Status;
+    if (NT_SUCCESS(Status))
+    {
+        /* Duplicate the string to return it */
+        Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &KeyValue, ParentIdPrefix);
+    }
+    /* General cleanup */
+    ExFreePool(ParentIdPrefixInformation);
+    if (hKey != NULL)
+        ZwClose(hKey);
+    return Status;
 }
 
 
@@ -1727,9 +1722,9 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
    IO_STATUS_BLOCK IoStatusBlock;
    PDEVICE_NODE ParentDeviceNode;
    WCHAR InstancePath[MAX_PATH];
+   UNICODE_STRING InstancePathU = { 0, sizeof(InstancePath), InstancePath };
    IO_STACK_LOCATION Stack;
    NTSTATUS Status;
-   PWSTR KeyBuffer;
    PWSTR Ptr;
    USHORT Length;
    USHORT TotalLength;
@@ -1791,12 +1786,7 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
    if (NT_SUCCESS(Status))
    {
       /* Copy the device id string */
-      wcscpy(InstancePath, (PWSTR)IoStatusBlock.Information);
-
-      /*
-       * FIXME: Check for valid characters, if there is invalid characters
-       * then bugcheck.
-       */
+      RtlAppendUnicodeToString(&InstancePathU, (PWSTR)IoStatusBlock.Information);
    }
    else
    {
@@ -1834,21 +1824,16 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
    if (NT_SUCCESS(Status))
    {
       /* Append the instance id string */
-      wcscat(InstancePath, L"\\");
+      RtlAppendUnicodeToString(&InstancePathU, L"\\");
       if (ParentIdPrefix.Length > 0)
       {
          /* Add information from parent bus device to InstancePath */
-         wcscat(InstancePath, ParentIdPrefix.Buffer);
+         RtlAppendUnicodeStringToString(&InstancePathU, &ParentIdPrefix);
          if (IoStatusBlock.Information && *(PWSTR)IoStatusBlock.Information)
-            wcscat(InstancePath, L"&");
+            RtlAppendUnicodeToString(&InstancePathU, L"&");
       }
       if (IoStatusBlock.Information)
-         wcscat(InstancePath, (PWSTR)IoStatusBlock.Information);
-
-      /*
-       * FIXME: Check for valid characters, if there is invalid characters
-       * then bugcheck
-       */
+         RtlAppendUnicodeToString(&InstancePathU, (PWSTR)IoStatusBlock.Information);
    }
    else
    {
@@ -1856,29 +1841,25 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
    }
    RtlFreeUnicodeString(&ParentIdPrefix);
 
-   if (!RtlCreateUnicodeString(&DeviceNode->InstancePath, InstancePath))
-   {
-      DPRINT("No resources\n");
-      /* FIXME: Cleanup and disable device */
-   }
+    /*
+     * FIXME: Check for valid characters, if there is invalid characters
+     * then bugcheck.
+     */
 
-   DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
+    Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+                                       &InstancePathU, &DeviceNode->InstancePath);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("No resources\n");
+        /* FIXME: Cleanup and disable device */
+    }
 
-   /*
-    * Create registry key for the instance id, if it doesn't exist yet
-    */
-   KeyBuffer = ExAllocatePool(
-      PagedPool,
-      (49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length);
-   wcscpy(KeyBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
-   wcscat(KeyBuffer, DeviceNode->InstancePath.Buffer);
-   Status = IopCreateDeviceKeyPath(KeyBuffer, &InstanceKey);
-   ExFreePool(KeyBuffer);
-   if (!NT_SUCCESS(Status))
-   {
-      DPRINT1("Failed to create the instance key! (Status %lx)\n", Status);
-   }
+    DPRINT("InstancePath is %wZ\n", &DeviceNode->InstancePath);
 
+    /* Create registry key for the instance id, if it doesn't exist yet */
+    Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, &InstanceKey);
+    if (!NT_SUCCESS(Status))
+        DPRINT1("IopCreateDeviceKeyPath('%wZ') failed (Status 0x%08lx)\n", &DeviceNode->InstancePath, Status);
 
    {
       /* Set 'Capabilities' value */
@@ -2329,102 +2310,106 @@ NTSTATUS
 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode,
                                 PVOID Context)
 {
-   RTL_QUERY_REGISTRY_TABLE QueryTable[3];
-   PDEVICE_NODE ParentDeviceNode;
-   PUNICODE_STRING Service;
-   UNICODE_STRING ClassGUID;
-   NTSTATUS Status;
-
-   DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode, Context);
-
-   ParentDeviceNode = (PDEVICE_NODE)Context;
-
-   /*
-    * We are called for the parent too, but we don't need to do special
-    * handling for this node
-    */
-   if (DeviceNode == ParentDeviceNode)
-   {
-      DPRINT("Success\n");
-      return STATUS_SUCCESS;
-   }
-
-   /*
-    * Make sure this device node is a direct child of the parent device node
-    * that is given as an argument
-    */
-   if (DeviceNode->Parent != ParentDeviceNode)
-   {
-      /* Stop the traversal immediately and indicate successful operation */
-      DPRINT("Stop\n");
-      return STATUS_UNSUCCESSFUL;
-   }
-
-   if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED))
-   {
-      WCHAR RegKeyBuffer[MAX_PATH];
-      UNICODE_STRING RegKey;
-
-      RegKey.Length = 0;
-      RegKey.MaximumLength = sizeof(RegKeyBuffer);
-      RegKey.Buffer = RegKeyBuffer;
-
-      /*
-       * Retrieve configuration from Enum key
-       */
+    RTL_QUERY_REGISTRY_TABLE QueryTable[4];
+    PDEVICE_NODE ParentDeviceNode;
+    PUNICODE_STRING Service;
+    UNICODE_STRING ClassGUID;
+    NTSTATUS Status;
 
-      Service = &DeviceNode->ServiceName;
+    DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode, Context);
 
-      RtlZeroMemory(QueryTable, sizeof(QueryTable));
-      RtlInitUnicodeString(Service, NULL);
-      RtlInitUnicodeString(&ClassGUID, NULL);
+    ParentDeviceNode = (PDEVICE_NODE)Context;
 
-      QueryTable[0].Name = L"Service";
-      QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
-      QueryTable[0].EntryContext = Service;
+    /*
+     * We are called for the parent too, but we don't need to do special
+     * handling for this node
+     */
+    if (DeviceNode == ParentDeviceNode)
+    {
+        DPRINT("Success\n");
+        return STATUS_SUCCESS;
+    }
 
-      QueryTable[1].Name = L"ClassGUID";
-      QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
-      QueryTable[1].EntryContext = &ClassGUID;
-      QueryTable[1].DefaultType = REG_SZ;
-      QueryTable[1].DefaultData = L"";
-      QueryTable[1].DefaultLength = 0;
+    /*
+     * Make sure this device node is a direct child of the parent device node
+     * that is given as an argument
+     */
+    ASSERT(DeviceNode->Parent == ParentDeviceNode);
 
-      RtlAppendUnicodeToString(&RegKey, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
-      RtlAppendUnicodeStringToString(&RegKey, &DeviceNode->InstancePath);
+    if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED))
+    {
+        OBJECT_ATTRIBUTES ObjectAttributes;
+        UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT);
+        HANDLE hEnum;
+
+        /* Open Enum key */
+        InitializeObjectAttributes(&ObjectAttributes, &EnumU,
+                                   OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL)
+        Status = ZwOpenKey(&hEnum, 0, &ObjectAttributes);
+        if (!NT_SUCCESS(Status))
+        {
+            /* FIXME: Log the error */
+            IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
+            return Status;
+        }
 
-      Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
-         RegKey.Buffer, QueryTable, NULL, NULL);
+        /* Prepare query table */
+        RtlZeroMemory(QueryTable, sizeof(QueryTable));
+        Service = &DeviceNode->ServiceName;
+        RtlInitUnicodeString(Service, NULL);
+        RtlInitUnicodeString(&ClassGUID, NULL);
+
+        /* Hopefully, this string is always NULL terminated */
+        QueryTable[0].Name = DeviceNode->InstancePath.Buffer;
+        QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
+
+        QueryTable[1].Name = L"Service";
+        QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+        QueryTable[1].EntryContext = Service;
+
+        QueryTable[2].Name = L"ClassGUID";
+        QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
+        QueryTable[2].EntryContext = &ClassGUID;
+        QueryTable[2].DefaultType = REG_SZ;
+        QueryTable[2].DefaultData = L"";
+        QueryTable[2].DefaultLength = 0;
+
+        /* Read registry */
+        Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, (PWSTR)hEnum,
+                                        QueryTable, NULL, NULL);
+        ZwClose(hEnum);
 
-      if (!NT_SUCCESS(Status))
-      {
-         /* FIXME: Log the error */
-         DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
-            &DeviceNode->InstancePath, Status);
-         IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
-         return STATUS_SUCCESS;
-      }
+        /* Check for an error */
+        if (!NT_SUCCESS(Status))
+        {
+            /* FIXME: Log the error */
+            DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
+                   &DeviceNode->InstancePath, Status);
+            IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
+            return STATUS_SUCCESS;
+        }
 
-      if (Service->Buffer == NULL)
-      {
-         IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
+        /* Check for a NULL service */
+        if (Service->Length == 0)
+        {
+            IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
 
-         if (ClassGUID.Length != 0)
-         {
-            /* Device has a ClassGUID value, but no Service value.
-             * Suppose it is using the NULL driver, so state the
-             * device is started */
-            DPRINT1("%wZ is using NULL driver\n", &DeviceNode->InstancePath);
-            IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
-            DeviceNode->Flags |= DN_STARTED;
-         }
-         return STATUS_SUCCESS;
-      }
+            if (ClassGUID.Length != 0)
+            {
+                /* Device has a ClassGUID value, but no Service value.
+                 * Suppose it is using the NULL driver, so state the
+                 * device is started */
+                DPRINT1("%wZ is using NULL driver\n", &DeviceNode->InstancePath);
+                IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
+                DeviceNode->Flags |= DN_STARTED;
+            }
+            return STATUS_SUCCESS;
+        }
 
-      DPRINT("Got Service %S\n", Service->Buffer);
-   }
+        DPRINT("Got Service %wZ\n", Service);
+    }
 
-   return STATUS_SUCCESS;
+    return STATUS_SUCCESS;
 }
 
 /*
@@ -2476,16 +2461,7 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
     * Make sure this device node is a direct child of the parent device node
     * that is given as an argument
     */
-#if 0
-   if (DeviceNode->Parent != ParentDeviceNode)
-   {
-      /*
-       * Stop the traversal immediately and indicate unsuccessful operation
-       */
-      DPRINT("Stop\n");
-      return STATUS_UNSUCCESSFUL;
-   }
-#endif
+   ASSERT(DeviceNode->Parent == ParentDeviceNode);
 
    if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED) &&
        !IopDeviceNodeHasFlag(DeviceNode, DNF_ADDED) &&
@@ -2563,8 +2539,8 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
             IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
             IopDeviceNodeSetFlag(DeviceNode, DNF_START_FAILED);
             /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
-            CPRINT("Initialization of service %S failed (Status %x)\n",
-              DeviceNode->ServiceName.Buffer, Status);
+            DPRINT("Initialization of service %wZ failed (Status %x)\n",
+              &DeviceNode->ServiceName, Status);
          }
       }
    }