Fix 2 setupapi:devclass tests
[reactos.git] / reactos / dll / win32 / setupapi / devinst.c
index 5875d25..e3272b4 100644 (file)
@@ -33,6 +33,7 @@ static const WCHAR DotHW[]  = {'.','H','W',0};
 static const WCHAR DotServices[]  = {'.','S','e','r','v','i','c','e','s',0};
 static const WCHAR InfDirectory[] = {'i','n','f','\\',0};
 static const WCHAR InstanceKeyFormat[] = {'%','0','4','l','u',0};
+static const WCHAR Version[]  = {'V','e','r','s','i','o','n',0};
 static const WCHAR VersionFormat[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
 
 static const WCHAR REGSTR_DRIVER_DATE[]  = {'D','r','i','v','e','r','D','a','t','e',0};
@@ -78,46 +79,17 @@ struct GetSectionCallbackInfo
 };
 
 
-/***********************************************************************
- *             SetupDiCreateDeviceInfoList (SETUPAPI.@)
- */
-HDEVINFO WINAPI
-SetupDiCreateDeviceInfoList(
-    IN CONST GUID *ClassGuid OPTIONAL,
-    IN HWND hwndParent OPTIONAL)
-{
-    return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
-}
 
-/***********************************************************************
- *             SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
- */
-HDEVINFO WINAPI
-SetupDiCreateDeviceInfoListExA(
-    IN CONST GUID *ClassGuid OPTIONAL,
-    IN HWND hwndParent OPTIONAL,
-    IN PCSTR MachineName OPTIONAL,
-    IN PVOID Reserved)
+static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
 {
-    LPWSTR MachineNameW = NULL;
-    HDEVINFO hDevInfo;
-
-    TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
-      debugstr_a(MachineName), Reserved);
-
-    if (MachineName)
-    {
-        MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
-        if (MachineNameW == NULL)
-            return (HDEVINFO)INVALID_HANDLE_VALUE;
-    }
-
-    hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
-                                              MachineNameW, Reserved);
-
-    MyFree(MachineNameW);
-
-    return hDevInfo;
+    static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
+        '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
+        'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
+        '0','2','X','}',0};
+
+    sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
+        guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
+        guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
 }
 
 static DWORD
@@ -148,256 +120,6 @@ GetErrorCodeFromCrCode(const IN CONFIGRET cr)
   /* Does not happen */
 }
 
-/***********************************************************************
- *             SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
- *
- * Create an empty DeviceInfoSet list.
- *
- * PARAMS
- *   ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
- *                 with this list.
- *   hwndParent [I] hwnd needed for interface related actions.
- *   MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
- *                   local regestry will be used.
- *   Reserved [I] must be NULL
- *
- * RETURNS
- *   Success: empty list.
- *   Failure: INVALID_HANDLE_VALUE.
- */
-HDEVINFO WINAPI
-SetupDiCreateDeviceInfoListExW(
-    IN CONST GUID *ClassGuid OPTIONAL,
-    IN HWND hwndParent OPTIONAL,
-    IN PCWSTR MachineName OPTIONAL,
-    IN PVOID Reserved)
-{
-    struct DeviceInfoSet *list = NULL;
-    DWORD size;
-    DWORD rc;
-    CONFIGRET cr;
-    HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE;
-
-    TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
-        debugstr_w(MachineName), Reserved);
-
-    if (Reserved != NULL)
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        goto cleanup;
-    }
-
-    size = FIELD_OFFSET(struct DeviceInfoSet, szData);
-    if (MachineName)
-    {
-        SIZE_T len = strlenW(MachineName);
-        if (len >= SP_MAX_MACHINENAME_LENGTH - 4)
-        {
-            SetLastError(ERROR_INVALID_MACHINENAME);
-            goto cleanup;
-        }
-        size += (len + 3) * sizeof(WCHAR);
-    }
-    list = MyMalloc(size);
-    if (!list)
-    {
-        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        goto cleanup;
-    }
-    ZeroMemory(list, FIELD_OFFSET(struct DeviceInfoSet, szData));
-
-    list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
-    memcpy(
-        &list->ClassGuid,
-        ClassGuid ? ClassGuid : &GUID_NULL,
-        sizeof(list->ClassGuid));
-    list->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
-    list->InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
-    list->InstallParams.hwndParent = hwndParent;
-    if (MachineName)
-    {
-        rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &list->HKLM);
-        if (rc != ERROR_SUCCESS)
-        {
-            SetLastError(ERROR_INVALID_MACHINENAME);
-            goto cleanup;
-        }
-
-        list->szData[0] = list->szData[1] = '\\';
-        strcpyW(list->szData + 2, MachineName);
-        list->MachineName = list->szData;
-    }
-    else
-    {
-        list->HKLM = HKEY_LOCAL_MACHINE;
-        list->MachineName = NULL;
-    }
-    cr = CM_Connect_MachineW(list->MachineName, &list->hMachine);
-    if (cr != CR_SUCCESS)
-    {
-        SetLastError(GetErrorCodeFromCrCode(cr));
-        goto cleanup;
-    }
-    InitializeListHead(&list->DriverListHead);
-    InitializeListHead(&list->ListHead);
-
-    ret = (HDEVINFO)list;
-
-cleanup:
-    if (ret == INVALID_HANDLE_VALUE)
-    {
-        if (list)
-        {
-            if (list->HKLM != NULL && list->HKLM != HKEY_LOCAL_MACHINE)
-                RegCloseKey(list->HKLM);
-            MyFree(list);
-        }
-    }
-    return ret;
-}
-
-/***********************************************************************
- *             SetupDiEnumDeviceInfo (SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiEnumDeviceInfo(
-    IN HDEVINFO DeviceInfoSet,
-    IN DWORD MemberIndex,
-    OUT PSP_DEVINFO_DATA DeviceInfoData)
-{
-    BOOL ret = FALSE;
-
-    TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet, MemberIndex, DeviceInfoData);
-    if (!DeviceInfoData)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
-    {
-        struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
-
-        if (list->magic != SETUP_DEVICE_INFO_SET_MAGIC)
-            SetLastError(ERROR_INVALID_HANDLE);
-        else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
-            SetLastError(ERROR_INVALID_USER_BUFFER);
-        else
-        {
-            PLIST_ENTRY ItemList = list->ListHead.Flink;
-            while (ItemList != &list->ListHead && MemberIndex-- > 0)
-                ItemList = ItemList->Flink;
-            if (ItemList == &list->ListHead)
-                SetLastError(ERROR_NO_MORE_ITEMS);
-            else
-            {
-                struct DeviceInfo *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
-                memcpy(&DeviceInfoData->ClassGuid,
-                    &DevInfo->ClassGuid,
-                    sizeof(GUID));
-                DeviceInfoData->DevInst = DevInfo->dnDevInst;
-                DeviceInfoData->Reserved = (ULONG_PTR)DevInfo;
-                ret = TRUE;
-            }
-        }
-    }
-    else
-        SetLastError(ERROR_INVALID_HANDLE);
-    return ret;
-}
-
-/***********************************************************************
- *             SetupDiGetActualSectionToInstallA (SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiGetActualSectionToInstallA(
-    IN HINF InfHandle,
-    IN PCSTR InfSectionName,
-    OUT PSTR InfSectionWithExt OPTIONAL,
-    IN DWORD InfSectionWithExtSize,
-    OUT PDWORD RequiredSize OPTIONAL,
-    OUT PSTR *Extension OPTIONAL)
-{
-    return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName,
-        NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
-        Extension, NULL);
-}
-
-/***********************************************************************
- *             SetupDiGetActualSectionToInstallW (SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiGetActualSectionToInstallW(
-    IN HINF InfHandle,
-    IN PCWSTR InfSectionName,
-    OUT PWSTR InfSectionWithExt OPTIONAL,
-    IN DWORD InfSectionWithExtSize,
-    OUT PDWORD RequiredSize OPTIONAL,
-    OUT PWSTR *Extension OPTIONAL)
-{
-    return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName,
-        NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
-        Extension, NULL);
-}
-
-/***********************************************************************
- *             SetupDiGetActualSectionToInstallExA  (SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiGetActualSectionToInstallExA(
-    IN HINF InfHandle,
-    IN PCSTR InfSectionName,
-    IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
-    OUT PSTR InfSectionWithExt OPTIONAL,
-    IN DWORD InfSectionWithExtSize,
-    OUT PDWORD RequiredSize OPTIONAL,
-    OUT PSTR* Extension OPTIONAL,
-    IN PVOID Reserved)
-{
-    LPWSTR InfSectionNameW = NULL;
-    LPWSTR InfSectionWithExtW = NULL;
-    PWSTR ExtensionW;
-    BOOL bResult = FALSE;
-
-    TRACE("\n");
-
-    if (InfSectionName)
-    {
-        InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
-        if (InfSectionNameW == NULL)
-            goto cleanup;
-    }
-    if (InfSectionWithExt)
-    {
-        InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR));
-        if (InfSectionWithExtW == NULL)
-            goto cleanup;
-    }
-
-    bResult = SetupDiGetActualSectionToInstallExW(
-        InfHandle, InfSectionNameW, AlternatePlatformInfo,
-        InfSectionWithExt ? InfSectionWithExtW : NULL,
-        InfSectionWithExtSize,
-        RequiredSize,
-        Extension ? &ExtensionW : NULL,
-        Reserved);
-
-    if (bResult && InfSectionWithExt)
-    {
-         bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt,
-             InfSectionWithExtSize, NULL, NULL) != 0;
-    }
-    if (bResult && Extension)
-    {
-        if (ExtensionW == NULL)
-            *Extension = NULL;
-         else
-            *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW];
-    }
-
-cleanup:
-    MyFree(InfSectionNameW);
-    MyFree(InfSectionWithExtW);
-
-    return bResult;
-}
-
 /* Lower scores are best ones */
 static BOOL
 CheckSectionValid(
@@ -837,7 +559,7 @@ CreateDeviceInfo(
     deviceInfo->set = list;
     deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
     strcpyW(deviceInfo->Data, InstancePath);
-    deviceInfo->DeviceName = deviceInfo->Data;
+    deviceInfo->instanceId = deviceInfo->Data;
     deviceInfo->UniqueId = strrchrW(deviceInfo->Data, '\\');
     deviceInfo->DeviceDescription = NULL;
     memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
@@ -904,552 +626,3049 @@ DestroyDeviceInfoSet(struct DeviceInfoSet* list)
 }
 
 /***********************************************************************
- *             SetupDiGetDeviceInfoListDetailA  (SETUPAPI.@)
+ *              SetupDiBuildClassInfoList  (SETUPAPI.@)
+ *
+ * Returns a list of setup class GUIDs that identify the classes
+ * that are installed on a local machine.
+ *
+ * PARAMS
+ *   Flags [I] control exclusion of classes from the list.
+ *   ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
+ *   ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
+ *   RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
+ *
+ * RETURNS
+ *   Success: TRUE.
+ *   Failure: FALSE.
  */
-BOOL WINAPI SetupDiGetDeviceInfoListDetailA(
-        HDEVINFO DeviceInfoSet,
-        PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData )
+BOOL WINAPI SetupDiBuildClassInfoList(
+        DWORD Flags,
+        LPGUID ClassGuidList,
+        DWORD ClassGuidListSize,
+        PDWORD RequiredSize)
 {
-    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+    TRACE("\n");
+    return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
+                                        ClassGuidListSize, RequiredSize,
+                                        NULL, NULL);
+}
 
-    TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
+/***********************************************************************
+ *              SetupDiBuildClassInfoListExA  (SETUPAPI.@)
+ *
+ * Returns a list of setup class GUIDs that identify the classes
+ * that are installed on a local or remote macine.
+ *
+ * PARAMS
+ *   Flags [I] control exclusion of classes from the list.
+ *   ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
+ *   ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
+ *   RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
+ *   MachineName [I] name of a remote machine.
+ *   Reserved [I] must be NULL.
+ *
+ * RETURNS
+ *   Success: TRUE.
+ *   Failure: FALSE.
+ */
+BOOL WINAPI SetupDiBuildClassInfoListExA(
+        DWORD Flags,
+        LPGUID ClassGuidList,
+        DWORD ClassGuidListSize,
+        PDWORD RequiredSize,
+        LPCSTR MachineName,
+        PVOID Reserved)
+{
+    LPWSTR MachineNameW = NULL;
+    BOOL bResult;
+
+    TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
+        ClassGuidListSize, RequiredSize, debugstr_a(MachineName), Reserved);
 
-    if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
+    if (MachineName)
     {
-        SetLastError(ERROR_INVALID_HANDLE);
-        return FALSE;
+        MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
+        if (MachineNameW == NULL) return FALSE;
     }
-    if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+
+    bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
+                                           ClassGuidListSize, RequiredSize,
+                                           MachineNameW, Reserved);
+
+    MyFree(MachineNameW);
+
+    return bResult;
+}
+
+/***********************************************************************
+ *              SetupDiBuildClassInfoListExW  (SETUPAPI.@)
+ *
+ * Returns a list of setup class GUIDs that identify the classes
+ * that are installed on a local or remote macine.
+ *
+ * PARAMS
+ *   Flags [I] control exclusion of classes from the list.
+ *   ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
+ *   ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
+ *   RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
+ *   MachineName [I] name of a remote machine.
+ *   Reserved [I] must be NULL.
+ *
+ * RETURNS
+ *   Success: TRUE.
+ *   Failure: FALSE.
+ */
+BOOL WINAPI SetupDiBuildClassInfoListExW(
+        DWORD Flags,
+        LPGUID ClassGuidList,
+        DWORD ClassGuidListSize,
+        PDWORD RequiredSize,
+        LPCWSTR MachineName,
+        PVOID Reserved)
+{
+    WCHAR szKeyName[40];
+    HKEY hClassesKey = INVALID_HANDLE_VALUE;
+    HKEY hClassKey;
+    DWORD dwLength;
+    DWORD dwIndex;
+    LONG lError;
+    DWORD dwGuidListIndex = 0;
+
+    TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
+        ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
+
+    if (!RequiredSize)
     {
-        SetLastError(ERROR_INVALID_HANDLE);
+        SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
-    if (!DevInfoData ||
-            DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A))
+    else if (!ClassGuidList && ClassGuidListSize > 0)
     {
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
-    memcpy(
-        &DevInfoData->ClassGuid,
-        &set->ClassGuid,
-        sizeof(GUID));
-    DevInfoData->RemoteMachineHandle = set->hMachine;
-    if (set->MachineName)
+
+    hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
+                                            KEY_ENUMERATE_SUB_KEYS,
+                                            DIOCR_INSTALLER,
+                                            MachineName,
+                                            Reserved);
+    if (hClassesKey == INVALID_HANDLE_VALUE)
     {
-        FIXME("Stub\n");
-        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-        return FALSE;
+       return FALSE;
+    }
+
+    for (dwIndex = 0; ; dwIndex++)
+    {
+       dwLength = 40;
+       lError = RegEnumKeyExW(hClassesKey,
+                              dwIndex,
+                              szKeyName,
+                              &dwLength,
+                              NULL,
+                              NULL,
+                              NULL,
+                              NULL);
+       TRACE("RegEnumKeyExW() returns %d\n", lError);
+       if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
+       {
+           TRACE("Key name: %s\n", debugstr_w(szKeyName));
+
+           if (RegOpenKeyExW(hClassesKey,
+                             szKeyName,
+                             0,
+                             KEY_QUERY_VALUE,
+                             &hClassKey))
+           {
+               RegCloseKey(hClassesKey);
+               return FALSE;
+           }
+
+           if (!RegQueryValueExW(hClassKey,
+                                 REGSTR_VAL_NOUSECLASS,
+                                 NULL,
+                                 NULL,
+                                 NULL,
+                                 NULL))
+           {
+               TRACE("'NoUseClass' value found!\n");
+               RegCloseKey(hClassKey);
+               continue;
+           }
+
+           if ((Flags & DIBCI_NOINSTALLCLASS) &&
+               (!RegQueryValueExW(hClassKey,
+                                  REGSTR_VAL_NOINSTALLCLASS,
+                                  NULL,
+                                  NULL,
+                                  NULL,
+                                  NULL)))
+           {
+               TRACE("'NoInstallClass' value found!\n");
+               RegCloseKey(hClassKey);
+               continue;
+           }
+
+           if ((Flags & DIBCI_NODISPLAYCLASS) &&
+               (!RegQueryValueExW(hClassKey,
+                                  REGSTR_VAL_NODISPLAYCLASS,
+                                  NULL,
+                                  NULL,
+                                  NULL,
+                                  NULL)))
+           {
+               TRACE("'NoDisplayClass' value found!\n");
+               RegCloseKey(hClassKey);
+               continue;
+           }
+
+           RegCloseKey(hClassKey);
+
+           TRACE("Guid: %s\n", debugstr_w(szKeyName));
+           if (dwGuidListIndex < ClassGuidListSize)
+           {
+               if (szKeyName[0] == '{' && szKeyName[37] == '}')
+               {
+                   szKeyName[37] = 0;
+               }
+               TRACE("Guid: %p\n", &szKeyName[1]);
+
+               UuidFromStringW(&szKeyName[1],
+                               &ClassGuidList[dwGuidListIndex]);
+           }
+
+           dwGuidListIndex++;
+       }
+
+       if (lError != ERROR_SUCCESS)
+           break;
+    }
+
+    RegCloseKey(hClassesKey);
+
+    if (RequiredSize != NULL)
+       *RequiredSize = dwGuidListIndex;
+
+    if (ClassGuidListSize < dwGuidListIndex)
+    {
+       SetLastError(ERROR_INSUFFICIENT_BUFFER);
+       return FALSE;
     }
-    else
-        DevInfoData->RemoteMachineName[0] = 0;
 
     return TRUE;
 }
 
 /***********************************************************************
- *             SetupDiGetDeviceInfoListDetailW  (SETUPAPI.@)
+ *             SetupDiClassGuidsFromNameA  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
-        HDEVINFO DeviceInfoSet,
-        PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData )
+BOOL WINAPI SetupDiClassGuidsFromNameA(
+        LPCSTR ClassName,
+        LPGUID ClassGuidList,
+        DWORD ClassGuidListSize,
+        PDWORD RequiredSize)
 {
-    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+  return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
+                                      ClassGuidListSize, RequiredSize,
+                                      NULL, NULL);
+}
 
-    TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
+/***********************************************************************
+ *             SetupDiClassGuidsFromNameW  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiClassGuidsFromNameW(
+        LPCWSTR ClassName,
+        LPGUID ClassGuidList,
+        DWORD ClassGuidListSize,
+        PDWORD RequiredSize)
+{
+  return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
+                                      ClassGuidListSize, RequiredSize,
+                                      NULL, NULL);
+}
+
+/***********************************************************************
+ *             SetupDiClassGuidsFromNameExA  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiClassGuidsFromNameExA(
+        LPCSTR ClassName,
+        LPGUID ClassGuidList,
+        DWORD ClassGuidListSize,
+        PDWORD RequiredSize,
+        LPCSTR MachineName,
+        PVOID Reserved)
+{
+    LPWSTR ClassNameW = NULL;
+    LPWSTR MachineNameW = NULL;
+    BOOL bResult;
+
+    TRACE("%s %p %lu %p %s %p\n", debugstr_a(ClassName), ClassGuidList,
+        ClassGuidListSize, RequiredSize, debugstr_a(MachineName), Reserved);
 
-    if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
+    if (!ClassName)
     {
-        SetLastError(ERROR_INVALID_HANDLE);
+        SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
-    if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
-    {
-        SetLastError(ERROR_INVALID_HANDLE);
+
+    ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
+    if (ClassNameW == NULL)
         return FALSE;
-    }
-    if (!DevInfoData ||
-            DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
+
+    if (MachineName)
     {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return FALSE;
+        MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
+        if (MachineNameW == NULL)
+        {
+            MyFree(ClassNameW);
+            return FALSE;
+        }
     }
-    memcpy(
-        &DevInfoData->ClassGuid,
-        &set->ClassGuid,
-        sizeof(GUID));
-    DevInfoData->RemoteMachineHandle = set->hMachine;
-    if (set->MachineName)
-        strcpyW(DevInfoData->RemoteMachineName, set->MachineName + 2);
-    else
-        DevInfoData->RemoteMachineName[0] = 0;
 
-    return TRUE;
+    bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
+                                           ClassGuidListSize, RequiredSize,
+                                           MachineNameW, Reserved);
+
+    MyFree(MachineNameW);
+    MyFree(ClassNameW);
+
+    return bResult;
 }
 
 /***********************************************************************
- *             SetupDiDestroyDeviceInfoList (SETUPAPI.@)
+ *             SetupDiClassGuidsFromNameExW  (SETUPAPI.@)
  */
-BOOL WINAPI
-SetupDiDestroyDeviceInfoList(
-    IN HDEVINFO DeviceInfoSet)
+BOOL WINAPI SetupDiClassGuidsFromNameExW(
+        LPCWSTR ClassName,
+        LPGUID ClassGuidList,
+        DWORD ClassGuidListSize,
+        PDWORD RequiredSize,
+        LPCWSTR MachineName,
+        PVOID Reserved)
 {
-    BOOL ret = FALSE;
+    WCHAR szKeyName[40];
+    WCHAR szClassName[MAX_CLASS_NAME_LEN];
+    HKEY hClassesKey;
+    HKEY hClassKey;
+    DWORD dwLength;
+    DWORD dwIndex;
+    LONG lError;
+    DWORD dwGuidListIndex = 0;
+
+    TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName), ClassGuidList,
+        ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
+
+    if (!ClassName || !RequiredSize)
+     {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    if (!ClassGuidList && ClassGuidListSize > 0)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+       *RequiredSize = 0;
+
+    hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
+                                            KEY_ENUMERATE_SUB_KEYS,
+                                            DIOCR_INSTALLER,
+                                            MachineName,
+                                            Reserved);
+    if (hClassesKey == INVALID_HANDLE_VALUE)
+    {
+       return FALSE;
+    }
 
-    TRACE("%p\n", DeviceInfoSet);
-    if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
+    for (dwIndex = 0; ; dwIndex++)
     {
-        struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
+       dwLength = 40;
+       lError = RegEnumKeyExW(hClassesKey,
+                              dwIndex,
+                              szKeyName,
+                              &dwLength,
+                              NULL,
+                              NULL,
+                              NULL,
+                              NULL);
+       TRACE("RegEnumKeyExW() returns %d\n", lError);
+       if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
+       {
+           TRACE("Key name: %p\n", szKeyName);
+
+           if (RegOpenKeyExW(hClassesKey,
+                             szKeyName,
+                             0,
+                             KEY_QUERY_VALUE,
+                             &hClassKey))
+           {
+               RegCloseKey(hClassesKey);
+               return FALSE;
+           }
+
+           dwLength = MAX_CLASS_NAME_LEN * sizeof(WCHAR);
+           if (!RegQueryValueExW(hClassKey,
+                                 Class,
+                                 NULL,
+                                 NULL,
+                                 (LPBYTE)szClassName,
+                                 &dwLength))
+           {
+               TRACE("Class name: %p\n", szClassName);
+
+               if (strcmpiW(szClassName, ClassName) == 0)
+               {
+                   TRACE("Found matching class name\n");
+
+                   TRACE("Guid: %p\n", szKeyName);
+                   if (dwGuidListIndex < ClassGuidListSize)
+                   {
+                       if (szKeyName[0] == '{' && szKeyName[37] == '}')
+                       {
+                           szKeyName[37] = 0;
+                       }
+                       TRACE("Guid: %p\n", &szKeyName[1]);
+
+                       UuidFromStringW(&szKeyName[1],
+                                       &ClassGuidList[dwGuidListIndex]);
+                   }
+
+                   dwGuidListIndex++;
+               }
+           }
+
+           RegCloseKey(hClassKey);
+       }
+
+       if (lError != ERROR_SUCCESS)
+           break;
+    }
 
-        if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
-            ret = DestroyDeviceInfoSet(list);
-        else
-            SetLastError(ERROR_INVALID_HANDLE);
+    RegCloseKey(hClassesKey);
+
+    if (RequiredSize != NULL)
+       *RequiredSize = dwGuidListIndex;
+
+    if (ClassGuidListSize < dwGuidListIndex)
+    {
+       SetLastError(ERROR_INSUFFICIENT_BUFFER);
+       return FALSE;
     }
-    else
-        SetLastError(ERROR_INVALID_HANDLE);
 
-    TRACE("Returning %d\n", ret);
-    return ret;
+    return TRUE;
 }
 
 /***********************************************************************
- *             SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
+ *              SetupDiClassNameFromGuidA  (SETUPAPI.@)
  */
-BOOL WINAPI
-SetupDiGetDeviceRegistryPropertyA(
-    IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData,
-    IN DWORD Property,
-    OUT PDWORD PropertyRegDataType OPTIONAL,
-    OUT PBYTE PropertyBuffer OPTIONAL,
-    IN DWORD PropertyBufferSize,
-    OUT PDWORD  RequiredSize OPTIONAL)
+BOOL WINAPI SetupDiClassNameFromGuidA(
+        const GUID* ClassGuid,
+        PSTR ClassName,
+        DWORD ClassNameSize,
+        PDWORD RequiredSize)
 {
-    BOOL bResult;
-    BOOL bIsStringProperty;
-    DWORD RegType;
-    DWORD RequiredSizeA, RequiredSizeW;
-    DWORD PropertyBufferSizeW = 0;
-    PBYTE PropertyBufferW = NULL;
+  return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
+                                     ClassNameSize, RequiredSize,
+                                     NULL, NULL);
+}
 
-    TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet, DeviceInfoData,
-        Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
-        RequiredSize);
+/***********************************************************************
+ *              SetupDiClassNameFromGuidW  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiClassNameFromGuidW(
+        const GUID* ClassGuid,
+        PWSTR ClassName,
+        DWORD ClassNameSize,
+        PDWORD RequiredSize)
+{
+  return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
+                                     ClassNameSize, RequiredSize,
+                                     NULL, NULL);
+}
 
-    if (PropertyBufferSize != 0)
+/***********************************************************************
+ *              SetupDiClassNameFromGuidExA  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiClassNameFromGuidExA(
+        const GUID* ClassGuid,
+        PSTR ClassName,
+        DWORD ClassNameSize,
+        PDWORD RequiredSize,
+        PCSTR MachineName,
+        PVOID Reserved)
+{
+    WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
+    LPWSTR MachineNameW = NULL;
+    BOOL ret;
+
+    if (MachineName)
+        MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
+    ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
+     NULL, MachineNameW, Reserved);
+    if (ret)
     {
-        PropertyBufferSizeW = PropertyBufferSize * 2;
-        PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
-        if (!PropertyBufferW)
+        int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
+         ClassNameSize, NULL, NULL);
+        if (len == 0 || len > ClassNameSize)
         {
-            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            return FALSE;
+            SetLastError(ERROR_INSUFFICIENT_BUFFER);
+            ret = FALSE;
         }
+        else if (RequiredSize)
+            *RequiredSize = len;
     }
+    MyFree(MachineNameW);
+    return ret;
+}
 
-    bResult = SetupDiGetDeviceRegistryPropertyW(
-        DeviceInfoSet,
-        DeviceInfoData,
-        Property,
-        &RegType,
-        PropertyBufferW,
-        PropertyBufferSizeW,
-        &RequiredSizeW);
+/***********************************************************************
+ *             SetupDiClassNameFromGuidExW  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiClassNameFromGuidExW(
+        const GUID* ClassGuid,
+        PWSTR ClassName,
+        DWORD ClassNameSize,
+        PDWORD RequiredSize,
+        PCWSTR MachineName,
+        PVOID Reserved)
+{
+    HKEY hKey;
+    DWORD dwLength;
+    DWORD dwRegType;
+    LONG rc;
 
-    if (bResult || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+    TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName,
+        ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved);
+
+    hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
+                                     KEY_QUERY_VALUE,
+                                     DIOCR_INSTALLER,
+                                     MachineName,
+                                     Reserved);
+    if (hKey == INVALID_HANDLE_VALUE)
     {
-        bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
+       return FALSE;
+    }
 
-        if (bIsStringProperty)
-           RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
-        else
-            RequiredSizeA = RequiredSizeW;
-        if (RequiredSize)
-            *RequiredSize = RequiredSizeA;
-        if (PropertyRegDataType)
-            *PropertyRegDataType = RegType;
+    if (RequiredSize != NULL)
+    {
+       dwLength = 0;
+       if (RegQueryValueExW(hKey,
+                            Class,
+                            NULL,
+                            NULL,
+                            NULL,
+                            &dwLength))
+       {
+           RegCloseKey(hKey);
+           return FALSE;
+       }
+
+       *RequiredSize = dwLength / sizeof(WCHAR) + 1;
     }
 
-    if (!bResult)
+    if (!ClassGuid)
     {
-        HeapFree(GetProcessHeap(), 0, PropertyBufferW);
-        return bResult;
+        SetLastError(ERROR_INVALID_CLASS);
+        RegCloseKey(hKey);
+        return FALSE;
+    }
+    if (!ClassName && ClassNameSize > 0)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        RegCloseKey(hKey);
+        return FALSE;
     }
 
-    if (RequiredSizeA <= PropertyBufferSize)
+    dwLength = ClassNameSize * sizeof(WCHAR) - sizeof(UNICODE_NULL);
+    rc = RegQueryValueExW(hKey,
+                        Class,
+                        NULL,
+                        &dwRegType,
+                        (LPBYTE)ClassName,
+                        &dwLength);
+    if (rc != ERROR_SUCCESS)
     {
-        if (bIsStringProperty && PropertyBufferSize > 0)
-        {
-            if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0)
-            {
-                /* Last error is already set by WideCharToMultiByte */
-                bResult = FALSE;
-            }
-        }
-        else
-            memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA);
+       SetLastError(rc);
+       RegCloseKey(hKey);
+       return FALSE;
     }
-    else
+    if (dwRegType != REG_SZ)
     {
-        SetLastError(ERROR_INSUFFICIENT_BUFFER);
-        bResult = FALSE;
+        SetLastError(ERROR_GEN_FAILURE);
+        RegCloseKey(hKey);
+        return FALSE;
     }
+    
+    if (ClassNameSize > 1)
+        ClassName[ClassNameSize] = UNICODE_NULL;
+    RegCloseKey(hKey);
 
-    HeapFree(GetProcessHeap(), 0, PropertyBufferW);
-    return bResult;
+    return TRUE;
 }
 
 /***********************************************************************
- *             SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
+ *             SetupDiCreateDeviceInfoList (SETUPAPI.@)
  */
-BOOL WINAPI
-SetupDiGetDeviceRegistryPropertyW(
-    IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData,
-    IN DWORD Property,
-    OUT PDWORD PropertyRegDataType OPTIONAL,
-    OUT PBYTE PropertyBuffer OPTIONAL,
-    IN DWORD PropertyBufferSize,
-    OUT PDWORD  RequiredSize OPTIONAL)
-{
-    HKEY hEnumKey, hKey;
-    DWORD rc;
-    BOOL ret = FALSE;
-
-    TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet, DeviceInfoData,
-        Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
-        RequiredSize);
+HDEVINFO WINAPI
+SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
+                           HWND hwndParent)
+{
+  return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
+}
 
-    if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
-        SetLastError(ERROR_INVALID_HANDLE);
-    else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
-        SetLastError(ERROR_INVALID_HANDLE);
-    else if (!DeviceInfoData)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
-        SetLastError(ERROR_INVALID_USER_BUFFER);
-    else if (Property >= SPDRP_MAXIMUM_PROPERTY)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else
-    {
-        struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
-        struct DeviceInfo *DevInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
-
-        switch (Property)
-        {
-            case SPDRP_CAPABILITIES:
-            case SPDRP_CLASS:
-            case SPDRP_CLASSGUID:
-            case SPDRP_COMPATIBLEIDS:
-            case SPDRP_CONFIGFLAGS:
-            case SPDRP_DEVICEDESC:
-            case SPDRP_DRIVER:
-            case SPDRP_FRIENDLYNAME:
-            case SPDRP_HARDWAREID:
-            case SPDRP_LOCATION_INFORMATION:
-            case SPDRP_LOWERFILTERS:
-            case SPDRP_MFG:
-            case SPDRP_SECURITY:
-            case SPDRP_SERVICE:
-            case SPDRP_UI_NUMBER:
-            case SPDRP_UI_NUMBER_DESC_FORMAT:
-            case SPDRP_UPPERFILTERS:
-            {
-                LPCWSTR RegistryPropertyName;
-                DWORD BufferSize;
+/***********************************************************************
+ *             SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
+ */
+HDEVINFO WINAPI
+SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
+                              HWND hwndParent,
+                              PCSTR MachineName,
+                              PVOID Reserved)
+{
+    LPWSTR MachineNameW = NULL;
+    HDEVINFO hDevInfo;
 
-                switch (Property)
-                {
-                    case SPDRP_CAPABILITIES:
-                        RegistryPropertyName = REGSTR_VAL_CAPABILITIES; break;
-                    case SPDRP_CLASS:
-                        RegistryPropertyName = REGSTR_VAL_CLASS; break;
-                    case SPDRP_CLASSGUID:
-                        RegistryPropertyName = REGSTR_VAL_CLASSGUID; break;
-                    case SPDRP_COMPATIBLEIDS:
-                        RegistryPropertyName = REGSTR_VAL_COMPATIBLEIDS; break;
-                    case SPDRP_CONFIGFLAGS:
-                        RegistryPropertyName = REGSTR_VAL_CONFIGFLAGS; break;
-                    case SPDRP_DEVICEDESC:
-                        RegistryPropertyName = REGSTR_VAL_DEVDESC; break;
-                    case SPDRP_DRIVER:
-                        RegistryPropertyName = REGSTR_VAL_DRIVER; break;
-                    case SPDRP_FRIENDLYNAME:
-                        RegistryPropertyName = REGSTR_VAL_FRIENDLYNAME; break;
-                    case SPDRP_HARDWAREID:
-                        RegistryPropertyName = REGSTR_VAL_HARDWAREID; break;
-                    case SPDRP_LOCATION_INFORMATION:
-                        RegistryPropertyName = REGSTR_VAL_LOCATION_INFORMATION; break;
-                    case SPDRP_LOWERFILTERS:
-                        RegistryPropertyName = REGSTR_VAL_LOWERFILTERS; break;
-                    case SPDRP_MFG:
-                        RegistryPropertyName = REGSTR_VAL_MFG; break;
-                    case SPDRP_SECURITY:
-                        RegistryPropertyName = REGSTR_SECURITY; break;
-                    case SPDRP_SERVICE:
-                        RegistryPropertyName = REGSTR_VAL_SERVICE; break;
-                    case SPDRP_UI_NUMBER:
-                        RegistryPropertyName = REGSTR_VAL_UI_NUMBER; break;
-                    case SPDRP_UI_NUMBER_DESC_FORMAT:
-                        RegistryPropertyName = REGSTR_UI_NUMBER_DESC_FORMAT; break;
-                    case SPDRP_UPPERFILTERS:
-                        RegistryPropertyName = REGSTR_VAL_UPPERFILTERS; break;
-                    default:
-                        /* Should not happen */
-                        RegistryPropertyName = NULL; break;
-                }
+    TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
+      debugstr_a(MachineName), Reserved);
 
-                /* Open registry key name */
-                rc = RegOpenKeyExW(
-                    list->HKLM,
-                    REGSTR_PATH_SYSTEMENUM,
-                    0, /* Options */
+    if (MachineName)
+    {
+        MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
+        if (MachineNameW == NULL)
+            return INVALID_HANDLE_VALUE;
+    }
+
+    hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
+                                              MachineNameW, Reserved);
+
+    MyFree(MachineNameW);
+
+    return hDevInfo;
+}
+
+/***********************************************************************
+ *             SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
+ *
+ * Create an empty DeviceInfoSet list.
+ *
+ * PARAMS
+ *   ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
+ *                 with this list.
+ *   hwndParent [I] hwnd needed for interface related actions.
+ *   MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
+ *                   local registry will be used.
+ *   Reserved [I] must be NULL
+ *
+ * RETURNS
+ *   Success: empty list.
+ *   Failure: INVALID_HANDLE_VALUE.
+ */
+HDEVINFO WINAPI
+SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
+                              HWND hwndParent,
+                              PCWSTR MachineName,
+                              PVOID Reserved)
+{
+    struct DeviceInfoSet *list = NULL;
+    DWORD size = FIELD_OFFSET(struct DeviceInfoSet, szData);
+    DWORD rc;
+    CONFIGRET cr;
+    HDEVINFO ret = INVALID_HANDLE_VALUE;
+
+    TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
+      debugstr_w(MachineName), Reserved);
+
+    if (MachineName != NULL)
+    {
+        SIZE_T len = strlenW(MachineName);
+        if (len >= SP_MAX_MACHINENAME_LENGTH - 4)
+        {
+            SetLastError(ERROR_INVALID_MACHINENAME);
+            goto cleanup;
+        }
+        size += (len + 3) * sizeof(WCHAR);
+    }
+
+    if (Reserved != NULL)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return INVALID_HANDLE_VALUE;
+    }
+
+    list = MyMalloc(size);
+    if (!list)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return INVALID_HANDLE_VALUE;
+    }
+    ZeroMemory(list, FIELD_OFFSET(struct DeviceInfoSet, szData));
+
+    list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
+    memcpy(&list->ClassGuid,
+            ClassGuid ? ClassGuid : &GUID_NULL,
+            sizeof(list->ClassGuid));
+    list->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+    list->InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
+    list->InstallParams.hwndParent = hwndParent;
+    if (MachineName)
+    {
+        rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &list->HKLM);
+        if (rc != ERROR_SUCCESS)
+        {
+            SetLastError(ERROR_INVALID_MACHINENAME);
+            goto cleanup;
+        }
+
+        list->szData[0] = list->szData[1] = '\\';
+        strcpyW(list->szData + 2, MachineName);
+        list->MachineName = list->szData;
+    }
+    else
+    {
+        list->HKLM = HKEY_LOCAL_MACHINE;
+        list->MachineName = NULL;
+    }
+    cr = CM_Connect_MachineW(list->MachineName, &list->hMachine);
+    if (cr != CR_SUCCESS)
+    {
+        SetLastError(GetErrorCodeFromCrCode(cr));
+        goto cleanup;
+    }
+    InitializeListHead(&list->DriverListHead);
+    InitializeListHead(&list->ListHead);
+
+    return (HDEVINFO)list;
+
+cleanup:
+    if (ret == INVALID_HANDLE_VALUE)
+    {
+        if (list)
+        {
+            if (list->HKLM != NULL && list->HKLM != HKEY_LOCAL_MACHINE)
+                RegCloseKey(list->HKLM);
+            MyFree(list);
+        }
+    }
+    return ret;
+}
+
+/***********************************************************************
+ *              SetupDiCreateDevRegKeyA (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiCreateDevRegKeyA(
+        HDEVINFO DeviceInfoSet,
+        PSP_DEVINFO_DATA DeviceInfoData,
+        DWORD Scope,
+        DWORD HwProfile,
+        DWORD KeyType,
+        HINF InfHandle,
+        PCSTR InfSectionName)
+{
+    PWSTR InfSectionNameW = NULL;
+    HKEY key;
+
+    TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
+            HwProfile, KeyType, InfHandle, debugstr_a(InfSectionName));
+
+    if (InfHandle)
+    {
+        if (!InfSectionName)
+        {
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return INVALID_HANDLE_VALUE;
+        }
+        else
+        {
+            InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
+            if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
+        }
+    }
+    key = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, Scope,
+            HwProfile, KeyType, InfHandle, InfSectionNameW);
+    MyFree(InfSectionNameW);
+    return key;
+}
+
+static HKEY
+OpenHardwareProfileKey(
+    IN HKEY HKLM,
+    IN DWORD HwProfile,
+    IN DWORD samDesired);
+
+/***********************************************************************
+ *              SetupDiCreateDevRegKeyW (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiCreateDevRegKeyW(
+        HDEVINFO DeviceInfoSet,
+        PSP_DEVINFO_DATA DeviceInfoData,
+        DWORD Scope,
+        DWORD HwProfile,
+        DWORD KeyType,
+        HINF InfHandle,
+        PCWSTR InfSectionName)
+{
+    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+    HKEY key = INVALID_HANDLE_VALUE;
+
+    TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
+            HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
+
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return INVALID_HANDLE_VALUE;
+    }
+    if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return INVALID_HANDLE_VALUE;
+    }
+    if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
+            || !DeviceInfoData->Reserved)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return INVALID_HANDLE_VALUE;
+    }
+    if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
+    {
+        SetLastError(ERROR_INVALID_FLAGS);
+        return INVALID_HANDLE_VALUE;
+    }
+    if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
+    {
+        SetLastError(ERROR_INVALID_FLAGS);
+        return INVALID_HANDLE_VALUE;
+    }
+    if (InfHandle && !InfSectionName)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return INVALID_HANDLE_VALUE;
+    }
+    if (!InfHandle && InfSectionName)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return INVALID_HANDLE_VALUE;
+    }
+
+        LPWSTR lpGuidString = NULL;
+        LPWSTR DriverKey = NULL; /* {GUID}\Index */
+        LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
+        DWORD Index; /* Index used in the DriverKey name */
+        DWORD rc;
+        HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
+        HKEY hEnumKey = NULL;
+        HKEY hClassKey = NULL;
+        HKEY hDeviceKey = INVALID_HANDLE_VALUE;
+        HKEY hKey = NULL;
+        HKEY RootKey;
+
+        if (Scope == DICS_FLAG_GLOBAL)
+            RootKey = set->HKLM;
+        else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
+        {
+            hHWProfileKey = OpenHardwareProfileKey(set->HKLM, HwProfile, KEY_CREATE_SUB_KEY);
+            if (hHWProfileKey == INVALID_HANDLE_VALUE)
+                goto cleanup;
+            RootKey = hHWProfileKey;
+        }
+
+        if (KeyType == DIREG_DEV)
+        {
+            struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
+
+            rc = RegCreateKeyExW(
+                RootKey,
+                REGSTR_PATH_SYSTEMENUM,
+                0,
+                NULL,
+                REG_OPTION_NON_VOLATILE,
+                KEY_CREATE_SUB_KEY,
+                NULL,
+                &hEnumKey,
+                NULL);
+            if (rc != ERROR_SUCCESS)
+            {
+                SetLastError(rc);
+                goto cleanup;
+            }
+            rc = RegCreateKeyExW(
+                hEnumKey,
+                deviceInfo->instanceId,
+                0,
+                NULL,
+                REG_OPTION_NON_VOLATILE,
+#if _WIN32_WINNT >= 0x502
+                KEY_READ | KEY_WRITE,
+#else
+                KEY_ALL_ACCESS,
+#endif
+                NULL,
+                &hKey,
+                NULL);
+            if (rc != ERROR_SUCCESS)
+            {
+                SetLastError(rc);
+                goto cleanup;
+            }
+        }
+        else /* KeyType == DIREG_DRV */
+        {
+            if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
+                goto cleanup;
+            /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
+            DriverKey = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
+            if (!DriverKey)
+            {
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                goto cleanup;
+            }
+            DriverKey[0] = '{';
+            strcpyW(&DriverKey[1], lpGuidString);
+            pDeviceInstance = &DriverKey[strlenW(DriverKey)];
+            *pDeviceInstance++ = '}';
+            *pDeviceInstance++ = '\\';
+            rc = RegOpenKeyExW(RootKey,
+                REGSTR_PATH_CLASS_NT,
+                0,
+                KEY_CREATE_SUB_KEY,
+                &hClassKey);
+            if (rc != ERROR_SUCCESS)
+            {
+                SetLastError(rc);
+                goto cleanup;
+            }
+
+            /* Try all values for Index between 0 and 9999 */
+            Index = 0;
+            while (Index <= 9999)
+            {
+                DWORD Disposition;
+                sprintfW(pDeviceInstance, InstanceKeyFormat, Index);
+                rc = RegCreateKeyExW(hClassKey,
+                    DriverKey,
                     0,
-                    &hEnumKey);
+                    NULL,
+                    REG_OPTION_NON_VOLATILE,
+#if _WIN32_WINNT >= 0x502
+                    KEY_READ | KEY_WRITE,
+#else
+                    KEY_ALL_ACCESS,
+#endif
+                    NULL,
+                    &hKey,
+                    &Disposition);
                 if (rc != ERROR_SUCCESS)
                 {
-                    SetLastError(rc);
-                    break;
+                    SetLastError(rc);
+                    goto cleanup;
+                }
+                if (Disposition == REG_CREATED_NEW_KEY)
+                    break;
+                RegCloseKey(hKey);
+                hKey = NULL;
+                Index++;
+            }
+            if (Index > 9999)
+            {
+                /* Unable to create more than 9999 devices within the same class */
+                SetLastError(ERROR_GEN_FAILURE);
+                goto cleanup;
+            }
+
+            /* Open device key, to write Driver value */
+            hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_SET_VALUE);
+            if (hDeviceKey == INVALID_HANDLE_VALUE)
+                goto cleanup;
+            rc = RegSetValueExW(hDeviceKey, REGSTR_VAL_DRIVER, 0, REG_SZ, (const BYTE *)DriverKey, (strlenW(DriverKey) + 1) * sizeof(WCHAR));
+            if (rc != ERROR_SUCCESS)
+            {
+                SetLastError(rc);
+                goto cleanup;
+            }
+        }
+
+        /* Do installation of the specified section */
+        if (InfHandle)
+        {
+            FIXME("Need to install section %s in file %p\n",
+                debugstr_w(InfSectionName), InfHandle);
+        }
+        key = hKey;
+
+cleanup:
+        if (lpGuidString)
+            RpcStringFreeW(&lpGuidString);
+        HeapFree(GetProcessHeap(), 0, DriverKey);
+        if (hHWProfileKey != INVALID_HANDLE_VALUE)
+            RegCloseKey(hHWProfileKey);
+        if (hEnumKey != NULL)
+            RegCloseKey(hEnumKey);
+        if (hClassKey != NULL)
+            RegCloseKey(hClassKey);
+        if (hDeviceKey != INVALID_HANDLE_VALUE)
+            RegCloseKey(hDeviceKey);
+        if (hKey != NULL && hKey != key)
+            RegCloseKey(hKey);
+
+    TRACE("Returning 0x%p\n", key);
+    return key;
+}
+
+/***********************************************************************
+ *              SetupDiCreateDeviceInfoA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiCreateDeviceInfoA(
+       HDEVINFO DeviceInfoSet,
+       PCSTR DeviceName,
+       CONST GUID *ClassGuid,
+       PCSTR DeviceDescription,
+       HWND hwndParent,
+       DWORD CreationFlags,
+       PSP_DEVINFO_DATA DeviceInfoData)
+{
+    BOOL ret;
+    LPWSTR DeviceNameW = NULL;
+    LPWSTR DeviceDescriptionW = NULL;
+
+    TRACE("\n");
+
+    if (DeviceName)
+    {
+        DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
+        if (DeviceNameW == NULL) return FALSE;
+    }
+    if (DeviceDescription)
+    {
+        DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
+        if (DeviceDescriptionW == NULL)
+        {
+            MyFree(DeviceNameW);
+            return FALSE;
+        }
+    }
+
+    ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
+            hwndParent, CreationFlags, DeviceInfoData);
+
+    MyFree(DeviceNameW);
+    MyFree(DeviceDescriptionW);
+
+    return ret;
+}
+
+/***********************************************************************
+ *              SetupDiCreateDeviceInfoW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiCreateDeviceInfoW(
+       HDEVINFO DeviceInfoSet,
+       PCWSTR DeviceName,
+       CONST GUID *ClassGuid,
+       PCWSTR DeviceDescription,
+       HWND hwndParent,
+       DWORD CreationFlags,
+       PSP_DEVINFO_DATA DeviceInfoData)
+{
+    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+    BOOL ret = FALSE;
+
+    TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
+        debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
+        hwndParent, CreationFlags, DeviceInfoData);
+
+    if (!DeviceName)
+    {
+        SetLastError(ERROR_INVALID_DEVINST_NAME);
+        return FALSE;
+    }
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (!ClassGuid)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
+        !IsEqualGUID(ClassGuid, &set->ClassGuid))
+    {
+        SetLastError(ERROR_CLASS_MISMATCH);
+        return FALSE;
+    }
+    if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
+    {
+        TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
+        SetLastError(ERROR_INVALID_FLAGS);
+        return FALSE;
+    }
+
+        SP_DEVINFO_DATA DevInfo;
+
+        if (CreationFlags & DICD_GENERATE_ID)
+        {
+            /* Generate a new unique ID for this device */
+            SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+            FIXME("not implemented\n");
+        }
+        else
+        {
+            /* Device name is fully qualified. Try to open it */
+            BOOL rc;
+
+            DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
+            rc = SetupDiOpenDeviceInfoW(
+                DeviceInfoSet,
+                DeviceName,
+                NULL, /* hwndParent */
+                CreationFlags & DICD_INHERIT_CLASSDRVS ? DIOD_INHERIT_CLASSDRVS : 0,
+                &DevInfo);
+
+            if (rc)
+            {
+                /* SetupDiOpenDeviceInfoW has already added
+                 * the device info to the device info set
+                 */
+                SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
+            }
+            else if (GetLastError() == ERROR_FILE_NOT_FOUND)
+            {
+                struct DeviceInfo *deviceInfo;
+
+                if (CreateDeviceInfo(set, DeviceName, ClassGuid, &deviceInfo))
+                {
+                    InsertTailList(&set->ListHead, &deviceInfo->ListEntry);
+
+                    if (!DeviceInfoData)
+                        ret = TRUE;
+                    else
+                    {
+                        if (DeviceInfoData->cbSize != sizeof(PSP_DEVINFO_DATA))
+                        {
+                            SetLastError(ERROR_INVALID_USER_BUFFER);
+                        }
+                        else
+                        {
+                            memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
+                            DeviceInfoData->DevInst = deviceInfo->dnDevInst;
+                            DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
+                            ret = TRUE;
+                        }
+                    }
+                }
+            }
+        }
+
+    TRACE("Returning %d\n", ret);
+    return ret;
+}
+
+/***********************************************************************
+ *             SetupDiRegisterDeviceInfo (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiRegisterDeviceInfo(
+        HDEVINFO DeviceInfoSet,
+        PSP_DEVINFO_DATA DeviceInfoData,
+        DWORD Flags,
+        PSP_DETSIG_CMPPROC CompareProc,
+        PVOID CompareContext,
+        PSP_DEVINFO_DATA DupDeviceInfoData)
+{
+    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+
+    TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
+            CompareProc, CompareContext, DupDeviceInfoData);
+
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
+            || !DeviceInfoData->Reserved)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    FIXME("Stub %p %p 0x%lx %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
+            CompareProc, CompareContext, DupDeviceInfoData);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
+
+/***********************************************************************
+ *             SetupDiEnumDeviceInfo (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiEnumDeviceInfo(
+        HDEVINFO  devinfo,
+        DWORD  index,
+        PSP_DEVINFO_DATA info)
+{
+    BOOL ret = FALSE;
+
+    TRACE("%p %d %p\n", devinfo, index, info);
+
+    if(info==NULL)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    if (devinfo && devinfo != INVALID_HANDLE_VALUE)
+    {
+        struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
+        if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
+        {
+            if (info->cbSize != sizeof(SP_DEVINFO_DATA))
+                SetLastError(ERROR_INVALID_USER_BUFFER);
+            else
+            {
+                PLIST_ENTRY ItemList = list->ListHead.Flink;
+                while (ItemList != &list->ListHead && index-- > 0)
+                    ItemList = ItemList->Flink;
+                if (ItemList == &list->ListHead)
+                    SetLastError(ERROR_NO_MORE_ITEMS);
+                else
+                {
+                    struct DeviceInfo *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
+                    memcpy(&info->ClassGuid,
+                        &DevInfo->ClassGuid,
+                        sizeof(GUID));
+                    info->DevInst = DevInfo->dnDevInst;
+                    info->Reserved = (ULONG_PTR)DevInfo;
+                    ret = TRUE;
+                }
+            }
+        }
+        else
+            SetLastError(ERROR_INVALID_HANDLE);
+    }
+    else
+        SetLastError(ERROR_INVALID_HANDLE);
+    return ret;
+}
+
+/***********************************************************************
+ *             SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInstanceIdA(
+       HDEVINFO DeviceInfoSet,
+       PSP_DEVINFO_DATA DeviceInfoData,
+       PSTR DeviceInstanceId,
+       DWORD DeviceInstanceIdSize,
+       PDWORD RequiredSize)
+{
+    BOOL ret = FALSE;
+    DWORD size;
+    PWSTR instanceId;
+
+    TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
+           DeviceInstanceIdSize, RequiredSize);
+
+    if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
+                                DeviceInfoData,
+                                NULL,
+                                0,
+                                &size);
+    if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+        return FALSE;
+    instanceId = MyMalloc(size * sizeof(WCHAR));
+    if (instanceId)
+    {
+        ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
+                                          DeviceInfoData,
+                                          instanceId,
+                                          size,
+                                          &size);
+        if (ret)
+        {
+            int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
+                                          DeviceInstanceId,
+                                          DeviceInstanceIdSize, NULL, NULL);
+
+            if (!len)
+                ret = FALSE;
+            else
+            {
+                if (len > DeviceInstanceIdSize)
+                {
+                    SetLastError(ERROR_INSUFFICIENT_BUFFER);
+                    ret = FALSE;
+                }
+                if (RequiredSize)
+                    *RequiredSize = len;
+            }
+        }
+        MyFree(instanceId);
+    }
+    else
+    {
+        if (RequiredSize)
+            *RequiredSize = size;
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+        ret = FALSE;
+    }
+    return ret;
+}
+
+/***********************************************************************
+ *             SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInstanceIdW(
+       HDEVINFO DeviceInfoSet,
+       PSP_DEVINFO_DATA DeviceInfoData,
+       PWSTR DeviceInstanceId,
+       DWORD DeviceInstanceIdSize,
+       PDWORD RequiredSize)
+{
+    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+    struct DeviceInfo *devInfo;
+
+    TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
+           DeviceInstanceIdSize, RequiredSize);
+
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
+            || !DeviceInfoData->Reserved)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
+    if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    if (DeviceInstanceId && DeviceInstanceIdSize == 0)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
+    if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
+    {
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+        if (RequiredSize)
+            *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
+        return FALSE;
+    }
+    lstrcpyW(DeviceInstanceId, devInfo->instanceId);
+    if (RequiredSize)
+        *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
+    return TRUE;
+}
+
+/***********************************************************************
+ *             SetupDiGetActualSectionToInstallA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetActualSectionToInstallA(
+        HINF InfHandle,
+        PCSTR InfSectionName,
+        PSTR InfSectionWithExt,
+        DWORD InfSectionWithExtSize,
+        PDWORD RequiredSize,
+        PSTR *Extension)
+{
+    return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName,
+        NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
+        Extension, NULL);
+}
+
+/***********************************************************************
+ *             SetupDiGetActualSectionToInstallW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetActualSectionToInstallW(
+        HINF InfHandle,
+        PCWSTR InfSectionName,
+        PWSTR InfSectionWithExt,
+        DWORD InfSectionWithExtSize,
+        PDWORD RequiredSize,
+        PWSTR *Extension)
+{
+    return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName,
+        NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
+        Extension, NULL);
+}
+
+/***********************************************************************
+ *             SetupDiGetActualSectionToInstallExA  (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiGetActualSectionToInstallExA(
+    IN HINF InfHandle,
+    IN PCSTR InfSectionName,
+    IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
+    OUT PSTR InfSectionWithExt OPTIONAL,
+    IN DWORD InfSectionWithExtSize,
+    OUT PDWORD RequiredSize OPTIONAL,
+    OUT PSTR* Extension OPTIONAL,
+    IN PVOID Reserved)
+{
+    LPWSTR InfSectionNameW = NULL;
+    LPWSTR InfSectionWithExtW = NULL;
+    PWSTR ExtensionW;
+    BOOL bResult = FALSE;
+
+    TRACE("\n");
+
+    if (InfSectionName)
+    {
+        InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
+        if (InfSectionNameW == NULL)
+            goto cleanup;
+    }
+    if (InfSectionWithExt)
+    {
+        InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR));
+        if (InfSectionWithExtW == NULL)
+            goto cleanup;
+    }
+
+    bResult = SetupDiGetActualSectionToInstallExW(
+        InfHandle, InfSectionNameW, AlternatePlatformInfo,
+        InfSectionWithExt ? InfSectionWithExtW : NULL,
+        InfSectionWithExtSize,
+        RequiredSize,
+        Extension ? &ExtensionW : NULL,
+        Reserved);
+
+    if (bResult && InfSectionWithExt)
+    {
+         bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt,
+             InfSectionWithExtSize, NULL, NULL) != 0;
+    }
+    if (bResult && Extension)
+    {
+        if (ExtensionW == NULL)
+            *Extension = NULL;
+         else
+            *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW];
+    }
+
+cleanup:
+    MyFree(InfSectionNameW);
+    MyFree(InfSectionWithExtW);
+
+    return bResult;
+}
+
+/***********************************************************************
+ *             SetupDiGetClassDescriptionA  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassDescriptionA(
+        const GUID* ClassGuid,
+        PSTR ClassDescription,
+        DWORD ClassDescriptionSize,
+        PDWORD RequiredSize)
+{
+  return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
+                                       ClassDescriptionSize,
+                                       RequiredSize, NULL, NULL);
+}
+
+/***********************************************************************
+ *             SetupDiGetClassDescriptionW  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassDescriptionW(
+        const GUID* ClassGuid,
+        PWSTR ClassDescription,
+        DWORD ClassDescriptionSize,
+        PDWORD RequiredSize)
+{
+  return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
+                                       ClassDescriptionSize,
+                                       RequiredSize, NULL, NULL);
+}
+
+/***********************************************************************
+ *             SetupDiGetClassDescriptionExA  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassDescriptionExA(
+        const GUID* ClassGuid,
+        PSTR ClassDescription,
+        DWORD ClassDescriptionSize,
+        PDWORD RequiredSize,
+        PCSTR MachineName,
+        PVOID Reserved)
+{
+    PWCHAR ClassDescriptionW = NULL;
+    LPWSTR MachineNameW = NULL;
+    BOOL ret = FALSE;
+
+    TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
+        ClassDescriptionSize, RequiredSize, debugstr_a(MachineName), Reserved);
+
+    if (ClassDescriptionSize > 0)
+    {
+        ClassDescriptionW = MyMalloc(ClassDescriptionSize * sizeof(WCHAR));
+        if (!ClassDescriptionW)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            goto cleanup;
+        }
+    }
+
+    if (MachineName)
+    {
+        MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
+        if (!MachineNameW)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            goto cleanup;
+        }
+    }
+
+    ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW,
+        ClassDescriptionSize * sizeof(WCHAR), RequiredSize, MachineNameW, Reserved);
+    if (ret)
+    {
+        DWORD len = (DWORD)WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription,
+            ClassDescriptionSize, NULL, NULL);
+        if (len == 0 || len > ClassDescriptionSize)
+        {
+            SetLastError(ERROR_INSUFFICIENT_BUFFER);
+            ret = FALSE;
+        }
+    }
+
+cleanup:
+    MyFree(ClassDescriptionW);
+    MyFree(MachineNameW);
+    return ret;
+}
+
+/***********************************************************************
+ *             SetupDiGetClassDescriptionExW  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassDescriptionExW(
+        const GUID* ClassGuid,
+        PWSTR ClassDescription,
+        DWORD ClassDescriptionSize,
+        PDWORD RequiredSize,
+        PCWSTR MachineName,
+        PVOID Reserved)
+{
+    HKEY hKey;
+    DWORD dwLength;
+    DWORD dwRegType;
+    LONG rc;
+
+    TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
+        ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved);
+
+    if (!ClassGuid)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    else if (!ClassDescription && ClassDescriptionSize > 0)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
+                                     KEY_QUERY_VALUE,
+                                     DIOCR_INSTALLER,
+                                     MachineName,
+                                     Reserved);
+    if (hKey == INVALID_HANDLE_VALUE)
+    {
+       WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
+       return FALSE;
+    }
+
+    if (ClassDescriptionSize < sizeof(UNICODE_NULL) || !ClassDescription)
+        dwLength = 0;
+    else
+        dwLength = ClassDescriptionSize * sizeof(WCHAR) - sizeof(UNICODE_NULL);
+
+    rc = RegQueryValueExW(hKey,
+                          NULL,
+                          NULL,
+                          &dwRegType,
+                          (LPBYTE)ClassDescription,
+                          &dwLength);
+    RegCloseKey(hKey);
+    if (rc != ERROR_MORE_DATA && rc != ERROR_SUCCESS)
+    {
+        SetLastError(rc);
+        return FALSE;
+    }
+    else if (dwRegType != REG_SZ)
+    {
+        SetLastError(ERROR_GEN_FAILURE);
+        return FALSE;
+    }
+
+    if (RequiredSize)
+        *RequiredSize = dwLength / sizeof(WCHAR) + 1;
+
+    if (ClassDescriptionSize * sizeof(WCHAR) >= dwLength + sizeof(UNICODE_NULL))
+    {
+        if (ClassDescriptionSize > sizeof(UNICODE_NULL))
+            ClassDescription[ClassDescriptionSize / sizeof(WCHAR)] = UNICODE_NULL;
+        return TRUE;
+    }
+    else
+    {
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+        return FALSE;
+    }
+}
+
+/***********************************************************************
+ *             SetupDiGetClassDevsA (SETUPAPI.@)
+ */
+HDEVINFO WINAPI SetupDiGetClassDevsA(
+       CONST GUID *class,
+       LPCSTR enumstr,
+       HWND parent,
+       DWORD flags)
+{
+    return SetupDiGetClassDevsExA(class, enumstr, parent,
+                                  flags, NULL, NULL, NULL);
+}
+
+/***********************************************************************
+ *               SetupDiGetClassDevsExA (SETUPAPI.@)
+ */
+HDEVINFO WINAPI SetupDiGetClassDevsExA(
+        const GUID *class,
+        PCSTR enumstr,
+        HWND parent,
+        DWORD flags,
+        HDEVINFO deviceset,
+        PCSTR machine,
+        PVOID reserved)
+{
+    HDEVINFO ret;
+    LPWSTR enumstrW = NULL, machineW = NULL;
+
+    if (enumstr)
+    {
+        enumstrW = MultiByteToUnicode(enumstr, CP_ACP);
+        if (!enumstrW)
+        {
+            ret = INVALID_HANDLE_VALUE;
+            goto end;
+        }
+    }
+    if (machine)
+    {
+        machineW = MultiByteToUnicode(machine, CP_ACP);
+        if (!machineW)
+        {
+            MyFree(enumstrW);
+            ret = INVALID_HANDLE_VALUE;
+            goto end;
+        }
+    }
+    ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset,
+            machineW, reserved);
+    MyFree(enumstrW);
+    MyFree(machineW);
+
+end:
+    return ret;
+}
+
+/***********************************************************************
+ *             SetupDiGetClassDevsW (SETUPAPI.@)
+ */
+HDEVINFO WINAPI SetupDiGetClassDevsW(
+       CONST GUID *class,
+       LPCWSTR enumstr,
+       HWND parent,
+       DWORD flags)
+{
+    return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL,
+            NULL);
+}
+
+/***********************************************************************
+ *              SetupDiGetClassDevsExW (SETUPAPI.@)
+ */
+HDEVINFO WINAPI SetupDiGetClassDevsExW(
+        CONST GUID *class,
+        PCWSTR enumstr,
+        HWND parent,
+        DWORD flags,
+        HDEVINFO deviceset,
+        PCWSTR machine,
+        PVOID reserved)
+{
+    HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
+    struct DeviceInfoSet *list;
+    CONST GUID *pClassGuid;
+    LONG rc;
+    HDEVINFO set = INVALID_HANDLE_VALUE;
+
+    TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
+            debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine),
+            reserved);
+
+    if (!(flags & DIGCF_ALLCLASSES) && !class)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return NULL;
+    }
+
+    /* Create the deviceset if not set */
+    if (deviceset)
+    {
+        list = (struct DeviceInfoSet *)deviceset;
+        if (list->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+        {
+            SetLastError(ERROR_INVALID_HANDLE);
+            goto cleanup;
+        }
+        hDeviceInfo = deviceset;
+    }
+    else
+    {
+         hDeviceInfo = SetupDiCreateDeviceInfoListExW(
+             flags & (DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES) ? NULL : class,
+             NULL, machine, NULL);
+         if (hDeviceInfo == INVALID_HANDLE_VALUE)
+             goto cleanup;
+         list = (struct DeviceInfoSet *)hDeviceInfo;
+    }
+
+    if (flags & DIGCF_PROFILE)
+        FIXME(": flag DIGCF_PROFILE ignored\n");
+
+    if (flags & DIGCF_DEVICEINTERFACE)
+    {
+        if (!class)
+        {
+            SetLastError(ERROR_INVALID_PARAMETER);
+            goto cleanup;
+        }
+        rc = SETUP_CreateInterfaceList(list, machine, class, enumstr, flags & DIGCF_PRESENT);
+    }
+    else
+    {
+        /* Determine which class(es) should be included in the deviceset */
+        if (flags & DIGCF_ALLCLASSES)
+        {
+            /* The caller wants all classes. Check if
+             * the deviceset limits us to one class */
+            if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
+                pClassGuid = NULL;
+            else
+                pClassGuid = &list->ClassGuid;
+        }
+        else if (class)
+        {
+            /* The caller wants one class. Check if it matches deviceset class */
+            if (IsEqualIID(&list->ClassGuid, class)
+             || IsEqualIID(&list->ClassGuid, &GUID_NULL))
+            {
+                pClassGuid = class;
+            }
+            else
+            {
+                SetLastError(ERROR_INVALID_PARAMETER);
+                goto cleanup;
+            }
+        }
+        else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL))
+        {
+            /* No class specified. Try to use the one of the deviceset */
+            if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
+                pClassGuid = &list->ClassGuid;
+            else
+            {
+                SetLastError(ERROR_INVALID_PARAMETER);
+                goto cleanup;
+            }
+        }
+        else
+        {
+            SetLastError(ERROR_INVALID_PARAMETER);
+            goto cleanup;
+        }
+        rc = SETUP_CreateDevicesList(list, machine, pClassGuid, enumstr);
+    }
+    if (rc != ERROR_SUCCESS)
+    {
+        SetLastError(rc);
+        goto cleanup;
+    }
+    set = hDeviceInfo;
+
+cleanup:
+    if (!deviceset && hDeviceInfo != INVALID_HANDLE_VALUE && hDeviceInfo != set)
+        SetupDiDestroyDeviceInfoList(hDeviceInfo);
+    return set;
+}
+
+/***********************************************************************
+ *             SetupDiGetDeviceInfoListDetailA  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInfoListDetailA(
+        HDEVINFO DeviceInfoSet,
+        PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData )
+{
+    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+
+    TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
+
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (!DevInfoData ||
+            DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
+    DevInfoData->RemoteMachineHandle = set->hMachine;
+    if (set->MachineName)
+    {
+        FIXME("Stub\n");
+        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+        return FALSE;
+    }
+    else
+        DevInfoData->RemoteMachineName[0] = 0;
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *             SetupDiGetDeviceInfoListDetailW  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
+        HDEVINFO DeviceInfoSet,
+        PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData )
+{
+    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+
+    TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
+
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (!DevInfoData ||
+            DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
+    DevInfoData->RemoteMachineHandle = set->hMachine;
+    if (set->MachineName)
+        strcpyW(DevInfoData->RemoteMachineName, set->MachineName + 2);
+    else
+        DevInfoData->RemoteMachineName[0] = 0;
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *             SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiCreateDeviceInterfaceA(
+        HDEVINFO DeviceInfoSet,
+        PSP_DEVINFO_DATA DeviceInfoData,
+        const GUID *InterfaceClassGuid,
+        PCSTR ReferenceString,
+        DWORD CreationFlags,
+        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
+{
+    BOOL ret;
+    LPWSTR ReferenceStringW = NULL;
+
+    TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
+            debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
+            CreationFlags, DeviceInterfaceData);
+
+    if (ReferenceString)
+    {
+        ReferenceStringW = MultiByteToUnicode(ReferenceString, CP_ACP);
+        if (ReferenceStringW == NULL) return FALSE;
+    }
+
+    ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData,
+            InterfaceClassGuid, ReferenceStringW, CreationFlags,
+            DeviceInterfaceData);
+
+    MyFree(ReferenceStringW);
+
+    return ret;
+}
+
+/***********************************************************************
+ *             SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiCreateDeviceInterfaceW(
+        HDEVINFO DeviceInfoSet,
+        PSP_DEVINFO_DATA DeviceInfoData,
+        const GUID *InterfaceClassGuid,
+        PCWSTR ReferenceString,
+        DWORD CreationFlags,
+        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
+{
+    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+    TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
+            debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
+            CreationFlags, DeviceInterfaceData);
+
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
+            || !DeviceInfoData->Reserved)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    if (!InterfaceClassGuid)
+    {
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+        return FALSE;
+    }
+
+    FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
+            debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
+            CreationFlags, DeviceInterfaceData);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
+
+/***********************************************************************
+ *             SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(
+        HDEVINFO DeviceInfoSet,
+        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
+        DWORD Reserved,
+        REGSAM samDesired,
+        HINF InfHandle,
+        PCSTR InfSectionName)
+{
+    HKEY key;
+    PWSTR InfSectionNameW = NULL;
+
+    TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
+            samDesired, InfHandle, InfSectionName);
+    if (InfHandle)
+    {
+        if (!InfSectionName)
+        {
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return INVALID_HANDLE_VALUE;
+        }
+        InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
+        if (!InfSectionNameW)
+            return INVALID_HANDLE_VALUE;
+    }
+    key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet,
+            DeviceInterfaceData, Reserved, samDesired, InfHandle,
+            InfSectionNameW);
+    MyFree(InfSectionNameW);
+    return key;
+}
+
+/***********************************************************************
+ *             SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(
+        HDEVINFO DeviceInfoSet,
+        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
+        DWORD Reserved,
+        REGSAM samDesired,
+        HINF InfHandle,
+        PCWSTR InfSectionName)
+{
+    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+    TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
+            samDesired, InfHandle, InfSectionName);
+
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
+            set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return INVALID_HANDLE_VALUE;
+    }
+    if (!DeviceInterfaceData ||
+            DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
+            !DeviceInterfaceData->Reserved)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return INVALID_HANDLE_VALUE;
+    }
+    if (InfHandle && !InfSectionName)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return INVALID_HANDLE_VALUE;
+    }
+    
+    FIXME("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
+            samDesired, InfHandle, InfSectionName);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return INVALID_HANDLE_VALUE;
+}
+
+/***********************************************************************
+ *             SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey(
+        HDEVINFO DeviceInfoSet,
+        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
+        DWORD Reserved)
+{
+    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+    BOOL ret = FALSE;
+
+    TRACE("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
+
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
+            set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (!DeviceInterfaceData ||
+            DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
+            !DeviceInterfaceData->Reserved)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    FIXME("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return ret;
+}
+
+/***********************************************************************
+ *             SetupDiEnumDeviceInterfaces (SETUPAPI.@)
+ *
+ * PARAMS
+ *   DeviceInfoSet      [I]    Set of devices from which to enumerate
+ *                             interfaces
+ *   DeviceInfoData     [I]    (Optional) If specified, a specific device
+ *                             instance from which to enumerate interfaces.
+ *                             If it isn't specified, all interfaces for all
+ *                             devices in the set are enumerated.
+ *   InterfaceClassGuid [I]    The interface class to enumerate.
+ *   MemberIndex        [I]    An index of the interface instance to enumerate.
+ *                             A caller should start with MemberIndex set to 0,
+ *                             and continue until the function fails with
+ *                             ERROR_NO_MORE_ITEMS.
+ *   DeviceInterfaceData [I/O] Returns an enumerated interface.  Its cbSize
+ *                             member must be set to
+ *                             sizeof(SP_DEVICE_INTERFACE_DATA).
+ *
+ * RETURNS
+ *   Success: non-zero value.
+ *   Failure: FALSE.  Call GetLastError() for more info.
+ */
+BOOL WINAPI SetupDiEnumDeviceInterfaces(
+       HDEVINFO DeviceInfoSet,
+       PSP_DEVINFO_DATA DeviceInfoData,
+       CONST GUID * InterfaceClassGuid,
+       DWORD MemberIndex,
+       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
+{
+    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+    BOOL ret = FALSE;
+
+    TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData,
+     debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
+
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
+            set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
+                !DeviceInfoData->Reserved))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    if (!DeviceInterfaceData ||
+            DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    if (DeviceInfoData)
+    {
+        struct DeviceInfo *devInfo =
+            (struct DeviceInfo *)DeviceInfoData->Reserved;
+        BOOL found = FALSE;
+        PLIST_ENTRY InterfaceListEntry = devInfo->InterfaceListHead.Flink;
+        while (InterfaceListEntry != &devInfo->InterfaceListHead && !found)
+        {
+            struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
+            if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
+            {
+                InterfaceListEntry = InterfaceListEntry->Flink;
+                continue;
+            }
+            if (MemberIndex-- == 0)
+            {
+                /* return this item */
+                memcpy(&DeviceInterfaceData->InterfaceClassGuid,
+                    &DevItf->InterfaceClassGuid,
+                    sizeof(GUID));
+                DeviceInterfaceData->Flags = DevItf->Flags;
+                DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
+                found = TRUE;
+                ret = TRUE;
+            }
+            InterfaceListEntry = InterfaceListEntry->Flink;
+        }
+        if (!found)
+            SetLastError(ERROR_NO_MORE_ITEMS);
+    }
+    else
+    {
+        BOOL found = FALSE;
+        PLIST_ENTRY ItemList = set->ListHead.Flink;
+        while (ItemList != &set->ListHead && !found)
+        {
+            PLIST_ENTRY InterfaceListEntry;
+            struct DeviceInfo *devInfo =
+                CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
+            InterfaceListEntry = devInfo->InterfaceListHead.Flink;
+            while (InterfaceListEntry != &devInfo->InterfaceListHead && !found)
+            {
+                struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
+                if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
+                {
+                    InterfaceListEntry = InterfaceListEntry->Flink;
+                    continue;
                 }
-                rc = RegOpenKeyExW(
-                    hEnumKey,
-                    DevInfo->Data,
-                    0, /* Options */
-                    KEY_QUERY_VALUE,
-                    &hKey);
-                RegCloseKey(hEnumKey);
-                if (rc != ERROR_SUCCESS)
+                if (MemberIndex-- == 0)
                 {
-                    SetLastError(rc);
-                    break;
-                }
-                /* Read registry entry */
-                BufferSize = PropertyBufferSize;
-                rc = RegQueryValueExW(
-                    hKey,
-                    RegistryPropertyName,
-                    NULL, /* Reserved */
-                    PropertyRegDataType,
-                    PropertyBuffer,
-                    &BufferSize);
-                if (RequiredSize)
-                    *RequiredSize = BufferSize;
-                switch(rc) {
-                    case ERROR_SUCCESS:
-                        if (PropertyBuffer != NULL || BufferSize == 0)
-                            ret = TRUE;
-                        else
-                            SetLastError(ERROR_INSUFFICIENT_BUFFER);
-                        break;
-                    case ERROR_MORE_DATA:
-                        SetLastError(ERROR_INSUFFICIENT_BUFFER);
-                        break;
-                    default:
-                        SetLastError(rc);
+                    /* return this item */
+                    memcpy(&DeviceInterfaceData->InterfaceClassGuid,
+                        &DevItf->InterfaceClassGuid,
+                        sizeof(GUID));
+                    DeviceInterfaceData->Flags = DevItf->Flags;
+                    DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
+                    found = TRUE;
+                    ret = TRUE;
                 }
-                RegCloseKey(hKey);
-                break;
+                InterfaceListEntry = InterfaceListEntry->Flink;
+            }
+            ItemList = ItemList->Flink;
+
+        }
+        if (!found)
+            SetLastError(ERROR_NO_MORE_ITEMS);
+    }
+    return ret;
+}
+
+/***********************************************************************
+ *             SetupDiDestroyDeviceInfoList (SETUPAPI.@)
+  *
+ * Destroy a DeviceInfoList and free all used memory of the list.
+ *
+ * PARAMS
+ *   devinfo [I] DeviceInfoList pointer to list to destroy
+ *
+ * RETURNS
+ *   Success: non zero value.
+ *   Failure: zero value.
+ */
+BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
+{
+    BOOL ret = FALSE;
+
+    TRACE("%p\n", devinfo);
+    if (devinfo && devinfo != INVALID_HANDLE_VALUE)
+    {
+        struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
+
+        if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
+        {
+            ret = DestroyDeviceInfoSet(list);
+        }
+    }
+
+    if (ret == FALSE)
+        SetLastError(ERROR_INVALID_HANDLE);
+
+    return ret;
+}
+
+/***********************************************************************
+ *             SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
+      HDEVINFO DeviceInfoSet,
+      PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
+      PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
+      DWORD DeviceInterfaceDetailDataSize,
+      PDWORD RequiredSize,
+      PSP_DEVINFO_DATA DeviceInfoData)
+{
+    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+    PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL;
+    DWORD sizeW = 0, bytesNeeded;
+    BOOL ret = FALSE;
+
+    TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
+     DeviceInterfaceData, DeviceInterfaceDetailData,
+     DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
+
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
+            set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (!DeviceInterfaceData ||
+            DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
+            !DeviceInterfaceData->Reserved)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
+            FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + 1 ||
+            DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)))
+    {
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+        return FALSE;
+    }
+    if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
+    {
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+        return FALSE;
+    }
+
+
+    if (DeviceInterfaceDetailData != NULL)
+    {
+        sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
+            + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR);
+        DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)MyMalloc(sizeW);
+        if (!DeviceInterfaceDetailDataW)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        }
+    }
+    if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW))
+    {
+        DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
+        ret = SetupDiGetDeviceInterfaceDetailW(
+            DeviceInfoSet,
+            DeviceInterfaceData,
+            DeviceInterfaceDetailDataW,
+            sizeW,
+            &sizeW,
+            DeviceInfoData);
+        bytesNeeded = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR)
+            + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath);
+        if (RequiredSize)
+            *RequiredSize = bytesNeeded;
+        if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize <= bytesNeeded)
+        {
+            if (!WideCharToMultiByte(
+                CP_ACP, 0,
+                DeviceInterfaceDetailDataW->DevicePath, -1,
+                DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
+                NULL, NULL))
+            {
+                ret = FALSE;
+            }
+        }
+    }
+    MyFree(DeviceInterfaceDetailDataW);
+
+    return ret;
+}
+
+/***********************************************************************
+ *             SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
+      HDEVINFO DeviceInfoSet,
+      PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
+      PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
+      DWORD DeviceInterfaceDetailDataSize,
+      PDWORD RequiredSize,
+      PSP_DEVINFO_DATA DeviceInfoData)
+{
+    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+    BOOL ret = FALSE;
+
+    TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
+     DeviceInterfaceData, DeviceInterfaceDetailData,
+     DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
+
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
+            set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (!DeviceInterfaceData ||
+            DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
+            !DeviceInterfaceData->Reserved)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    if (DeviceInterfaceDetailData && DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W))
+    {
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+        return FALSE;
+    }
+    if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
+    {
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+        return FALSE;
+    }
+    if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    else
+    {
+        struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
+        LPCWSTR devName = deviceInterface->SymbolicLink;
+        DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) +
+            (lstrlenW(devName) + 1) * sizeof(WCHAR);
+
+        if (sizeRequired > DeviceInterfaceDetailDataSize)
+        {
+            SetLastError(ERROR_INSUFFICIENT_BUFFER);
+            if (RequiredSize)
+                *RequiredSize = sizeRequired;
+        }
+        else
+        {
+            strcpyW(DeviceInterfaceDetailData->DevicePath, devName);
+            TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath));
+            if (DeviceInfoData)
+            {
+                memcpy(&DeviceInfoData->ClassGuid,
+                    &deviceInterface->DeviceInfo->ClassGuid,
+                    sizeof(GUID));
+                DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst;
+                DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo;
+            }
+            ret = TRUE;
+        }
+    }
+    return ret;
+}
+
+struct PropertyMapEntry
+{
+    DWORD   regType;
+    LPCSTR  nameA;
+    LPCWSTR nameW;
+};
+
+static struct PropertyMapEntry PropertyMap[] = {
+    { REG_SZ, "DeviceDesc", REGSTR_VAL_DEVDESC },
+    { REG_MULTI_SZ, "HardwareId", REGSTR_VAL_HARDWAREID },
+    { REG_MULTI_SZ, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS },
+    { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
+    { REG_SZ, "Service", REGSTR_VAL_SERVICE },
+    { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
+    { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
+    { REG_SZ, "Class", REGSTR_VAL_CLASS },
+    { REG_SZ, "ClassGUID", REGSTR_VAL_CLASSGUID },
+    { REG_SZ, "Driver", REGSTR_VAL_DRIVER },
+    { REG_DWORD, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS },
+    { REG_SZ, "Mfg", REGSTR_VAL_MFG },
+    { REG_SZ, "FriendlyName", REGSTR_VAL_FRIENDLYNAME },
+    { REG_SZ, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION },
+    { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
+    { REG_DWORD, "Capabilities", REGSTR_VAL_CAPABILITIES },
+    { REG_DWORD, "UINumber", REGSTR_VAL_UI_NUMBER },
+    { REG_MULTI_SZ, "UpperFilters", REGSTR_VAL_UPPERFILTERS },
+    { REG_MULTI_SZ, "LowerFilters", REGSTR_VAL_LOWERFILTERS },
+    { 0, NULL, NULL }, /* SPDRP_BUSTYPEGUID */
+    { 0, NULL, NULL }, /* SPDRP_LEGACYBUSTYPE */
+    { 0, NULL, NULL }, /* SPDRP_BUSNUMBER */
+    { 0, NULL, NULL }, /* SPDRP_ENUMERATOR_NAME */
+    { REG_BINARY, "Security", REGSTR_SECURITY },
+    { 0, NULL, NULL }, /* SPDRP_SECURITY_SDS */
+    { 0, NULL, NULL }, /* SPDRP_DEVTYPE */
+    { 0, NULL, NULL }, /* SPDRP_EXCLUSIVE */
+    { 0, NULL, NULL }, /* SPDRP_CHARACTERISTICS */
+    { 0, NULL, NULL }, /* SPDRP_ADDRESS */
+    { REG_SZ, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT },
+    { 0, NULL, NULL }, /* SPDRP_DEVICE_POWER_DATA */
+    { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY */
+    { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
+    { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
+    { 0, NULL, NULL }, /* SPDRP_INSTALL_STATE */
+};
+
+/***********************************************************************
+ *             SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
+        HDEVINFO  DeviceInfoSet,
+        PSP_DEVINFO_DATA  DeviceInfoData,
+        DWORD   Property,
+        PDWORD  PropertyRegDataType,
+        PBYTE   PropertyBuffer,
+        DWORD   PropertyBufferSize,
+        PDWORD  RequiredSize)
+{
+    BOOL ret;
+    BOOL bIsStringProperty;
+    DWORD RegType;
+    DWORD RequiredSizeA, RequiredSizeW;
+    DWORD PropertyBufferSizeW = 0;
+    PBYTE PropertyBufferW = NULL;
+
+    TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData,
+        Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
+        RequiredSize);
+
+    if (PropertyBufferSize != 0)
+    {
+        PropertyBufferSizeW = PropertyBufferSize * 2;
+        PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
+        if (!PropertyBufferW)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            return FALSE;
+        }
+    }
+
+    ret = SetupDiGetDeviceRegistryPropertyW(
+        DeviceInfoSet,
+        DeviceInfoData,
+        Property,
+        &RegType,
+        PropertyBufferW,
+        PropertyBufferSizeW,
+        &RequiredSizeW);
+
+    if (ret || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+    {
+        bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
+
+        if (bIsStringProperty)
+           RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
+        else
+            RequiredSizeA = RequiredSizeW;
+        if (RequiredSize)
+            *RequiredSize = RequiredSizeA;
+        if (PropertyRegDataType)
+            *PropertyRegDataType = RegType;
+    }
+
+    if (!ret)
+    {
+        HeapFree(GetProcessHeap(), 0, PropertyBufferW);
+        return ret;
+    }
+
+    if (RequiredSizeA <= PropertyBufferSize)
+    {
+        if (bIsStringProperty && PropertyBufferSize > 0)
+        {
+            if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0)
+            {
+                /* Last error is already set by WideCharToMultiByte */
+                ret = FALSE;
             }
+        }
+        else
+            memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA);
+    }
+    else
+    {
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+        ret = FALSE;
+    }
+
+    HeapFree(GetProcessHeap(), 0, PropertyBufferW);
+    return ret;
+}
 
-            case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME:
-            {
-                DWORD required = (strlenW(DevInfo->Data) + 1) * sizeof(WCHAR);
+/***********************************************************************
+ *             SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
+        HDEVINFO  DeviceInfoSet,
+        PSP_DEVINFO_DATA  DeviceInfoData,
+        DWORD   Property,
+        PDWORD  PropertyRegDataType,
+        PBYTE   PropertyBuffer,
+        DWORD   PropertyBufferSize,
+        PDWORD  RequiredSize)
+{
+    BOOL ret = FALSE;
+    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+    struct DeviceInfo *devInfo;
 
-                if (PropertyRegDataType)
-                    *PropertyRegDataType = REG_SZ;
-                if (RequiredSize)
-                    *RequiredSize = required;
-                if (PropertyBufferSize >= required)
-                {
-                    strcpyW((LPWSTR)PropertyBuffer, DevInfo->Data);
+    TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData,
+        Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
+        RequiredSize);
+
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
+            || !DeviceInfoData->Reserved)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
+    if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
+        && PropertyMap[Property].nameW)
+    {
+        DWORD size = PropertyBufferSize;
+        HKEY hKey;
+        LONG l;
+        hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
+        if (hKey == INVALID_HANDLE_VALUE)
+            return FALSE;
+        l = RegQueryValueExW(hKey, PropertyMap[Property].nameW,
+                NULL, PropertyRegDataType, PropertyBuffer, &size);
+        RegCloseKey(hKey);
+
+        if (RequiredSize)
+            *RequiredSize = size;
+        switch(l) {
+            case ERROR_SUCCESS:
+                if (PropertyBuffer != NULL || size == 0)
                     ret = TRUE;
-                }
                 else
                     SetLastError(ERROR_INSUFFICIENT_BUFFER);
                 break;
-            }
-
-            /*case SPDRP_BUSTYPEGUID:
-            case SPDRP_LEGACYBUSTYPE:
-            case SPDRP_BUSNUMBER:
-            case SPDRP_ENUMERATOR_NAME:
-            case SPDRP_SECURITY_SDS:
-            case SPDRP_DEVTYPE:
-            case SPDRP_EXCLUSIVE:
-            case SPDRP_CHARACTERISTICS:
-            case SPDRP_ADDRESS:
-            case SPDRP_DEVICE_POWER_DATA:*/
-#if (WINVER >= 0x501)
-            /*case SPDRP_REMOVAL_POLICY:
-            case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
-            case SPDRP_REMOVAL_POLICY_OVERRIDE:
-            case SPDRP_INSTALL_STATE:*/
-#endif
-
+            case ERROR_MORE_DATA:
+                SetLastError(ERROR_INSUFFICIENT_BUFFER);
+                break;
             default:
-            {
-                ERR("Property 0x%lx not implemented\n", Property);
-                SetLastError(ERROR_NOT_SUPPORTED);
-            }
+                SetLastError(l);
         }
     }
+    else if (Property == SPDRP_PHYSICAL_DEVICE_OBJECT_NAME)
+    {
+        DWORD required = (strlenW(devInfo->Data) + 1) * sizeof(WCHAR);
 
-    TRACE("Returning %d\n", ret);
+        if (PropertyRegDataType)
+            *PropertyRegDataType = REG_SZ;
+        if (RequiredSize)
+            *RequiredSize = required;
+        if (PropertyBufferSize >= required)
+        {
+            strcpyW((LPWSTR)PropertyBuffer, devInfo->Data);
+            ret = TRUE;
+        }
+        else
+            SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    }
+    else
+    {
+        ERR("Property 0x%lx not implemented\n", Property);
+        SetLastError(ERROR_NOT_SUPPORTED);
+    }
     return ret;
 }
 
 /***********************************************************************
  *             SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
  */
-BOOL WINAPI
-SetupDiSetDeviceRegistryPropertyA(
-    IN HDEVINFO DeviceInfoSet,
-    IN OUT PSP_DEVINFO_DATA DeviceInfoData,
-    IN DWORD Property,
-    IN CONST BYTE *PropertyBuffer OPTIONAL,
-    IN DWORD PropertyBufferSize)
+BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
+       HDEVINFO DeviceInfoSet,
+       PSP_DEVINFO_DATA DeviceInfoData,
+       DWORD Property,
+       const BYTE *PropertyBuffer,
+       DWORD PropertyBufferSize)
 {
+    BOOL ret = FALSE;
+    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+
+    TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
+        PropertyBuffer, PropertyBufferSize);
+
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
+            || !DeviceInfoData->Reserved)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
     FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
         Property, PropertyBuffer, PropertyBufferSize);
     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    return ret;
 }
 
 /***********************************************************************
  *             SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
  */
-BOOL WINAPI
-SetupDiSetDeviceRegistryPropertyW(
-    IN HDEVINFO DeviceInfoSet,
-    IN OUT PSP_DEVINFO_DATA DeviceInfoData,
-    IN DWORD Property,
-    IN CONST BYTE *PropertyBuffer OPTIONAL,
-    IN DWORD PropertyBufferSize)
+BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
+       HDEVINFO DeviceInfoSet,
+       PSP_DEVINFO_DATA DeviceInfoData,
+       DWORD Property,
+       const BYTE *PropertyBuffer,
+       DWORD PropertyBufferSize)
 {
-    struct DeviceInfoSet *list;
     BOOL ret = FALSE;
+    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
 
-    TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
-        Property, PropertyBuffer, PropertyBufferSize);
+    TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
+        PropertyBuffer, PropertyBufferSize);
 
-    if (!DeviceInfoSet)
-        SetLastError(ERROR_INVALID_HANDLE);
-    else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+    {
         SetLastError(ERROR_INVALID_HANDLE);
-    else if (!DeviceInfoData)
+        return FALSE;
+    }
+    if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+    {
         SetLastError(ERROR_INVALID_HANDLE);
-    else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
-        SetLastError(ERROR_INVALID_USER_BUFFER);
+        return FALSE;
+    }
+    if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
+            || !DeviceInfoData->Reserved)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
+        && PropertyMap[Property].nameW)
+    {
+       HKEY hKey;
+       LONG l;
+        hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
+        if (hKey == INVALID_HANDLE_VALUE)
+            return FALSE;
+        /* Write new data */
+        l = RegSetValueExW(
+            hKey, PropertyMap[Property].nameW, 0,
+                PropertyMap[Property].regType, PropertyBuffer,
+                PropertyBufferSize);
+        if (!l)
+            ret = TRUE;
+        else
+            SetLastError(l);
+        RegCloseKey(hKey);
+    }
     else
     {
-        switch (Property)
-        {
-            case SPDRP_COMPATIBLEIDS:
-            case SPDRP_CONFIGFLAGS:
-            case SPDRP_FRIENDLYNAME:
-            case SPDRP_HARDWAREID:
-            case SPDRP_LOCATION_INFORMATION:
-            case SPDRP_LOWERFILTERS:
-            case SPDRP_SECURITY:
-            case SPDRP_SERVICE:
-            case SPDRP_UI_NUMBER_DESC_FORMAT:
-            case SPDRP_UPPERFILTERS:
-            {
-                LPCWSTR RegistryPropertyName;
-                DWORD RegistryDataType;
-                HKEY hKey;
-                LONG rc;
+        ERR("Property 0x%lx not implemented\n", Property);
+        SetLastError(ERROR_NOT_SUPPORTED);
+    }
 
-                switch (Property)
-                {
-                    case SPDRP_COMPATIBLEIDS:
-                        RegistryPropertyName = REGSTR_VAL_COMPATIBLEIDS;
-                        RegistryDataType = REG_MULTI_SZ;
-                        break;
-                    case SPDRP_CONFIGFLAGS:
-                        RegistryPropertyName = REGSTR_VAL_CONFIGFLAGS;
-                        RegistryDataType = REG_DWORD;
-                        break;
-                    case SPDRP_FRIENDLYNAME:
-                        RegistryPropertyName = REGSTR_VAL_FRIENDLYNAME;
-                        RegistryDataType = REG_SZ;
-                        break;
-                    case SPDRP_HARDWAREID:
-                        RegistryPropertyName = REGSTR_VAL_HARDWAREID;
-                        RegistryDataType = REG_MULTI_SZ;
-                        break;
-                    case SPDRP_LOCATION_INFORMATION:
-                        RegistryPropertyName = REGSTR_VAL_LOCATION_INFORMATION;
-                        RegistryDataType = REG_SZ;
-                        break;
-                    case SPDRP_LOWERFILTERS:
-                        RegistryPropertyName = REGSTR_VAL_LOWERFILTERS;
-                        RegistryDataType = REG_MULTI_SZ;
-                        break;
-                    case SPDRP_SECURITY:
-                        RegistryPropertyName = REGSTR_SECURITY;
-                        RegistryDataType = REG_BINARY;
-                        break;
-                    case SPDRP_SERVICE:
-                        RegistryPropertyName = REGSTR_VAL_SERVICE;
-                        RegistryDataType = REG_SZ;
-                        break;
-                    case SPDRP_UI_NUMBER_DESC_FORMAT:
-                        RegistryPropertyName = REGSTR_UI_NUMBER_DESC_FORMAT;
-                        RegistryDataType = REG_SZ;
-                        break;
-                    case SPDRP_UPPERFILTERS:
-                        RegistryPropertyName = REGSTR_VAL_UPPERFILTERS;
-                        RegistryDataType = REG_MULTI_SZ;
-                        break;
-                    default:
-                        /* Should not happen */
-                        RegistryPropertyName = NULL;
-                        RegistryDataType = REG_BINARY;
-                        break;
-                }
-                /* Open device registry key */
-                hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
-                if (hKey != INVALID_HANDLE_VALUE)
-                {
-                    /* Write new data */
-                    rc = RegSetValueExW(
-                        hKey,
-                        RegistryPropertyName,
-                        0, /* Reserved */
-                        RegistryDataType,
-                        PropertyBuffer,
-                        PropertyBufferSize);
-                    if (rc == ERROR_SUCCESS)
-                        ret = TRUE;
-                    else
-                        SetLastError(rc);
-                    RegCloseKey(hKey);
-                }
-                break;
+    TRACE("Returning %d\n", ret);
+    return ret;
+}
+
+/***********************************************************************
+ *             SetupDiInstallClassA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiInstallClassA(
+        HWND hwndParent,
+        PCSTR InfFileName,
+        DWORD Flags,
+        HSPFILEQ FileQueue)
+{
+    return SetupDiInstallClassExA(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
+}
+
+/***********************************************************************
+ *             SetupDiInstallClassExA (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiInstallClassExA(
+    IN HWND hwndParent OPTIONAL,
+    IN PCSTR InfFileName OPTIONAL,
+    IN DWORD Flags,
+    IN HSPFILEQ FileQueue OPTIONAL,
+    IN CONST GUID *InterfaceClassGuid OPTIONAL,
+    IN PVOID Reserved1,
+    IN PVOID Reserved2)
+{
+    PWSTR InfFileNameW = NULL;
+    BOOL Result;
+
+    if (!InfFileName)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    else
+    {
+        InfFileNameW = MultiByteToUnicode(InfFileName, CP_ACP);
+        if (InfFileNameW == NULL)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            return FALSE;
+        }
+    }
+
+    Result = SetupDiInstallClassExW(hwndParent, InfFileNameW, Flags,
+        FileQueue, InterfaceClassGuid, Reserved1, Reserved2);
+
+    MyFree(InfFileNameW);
+
+    return Result;
+}
+
+HKEY SETUP_CreateClassKey(HINF hInf)
+{
+    static const WCHAR slash[] = { '\\',0 };
+    WCHAR FullBuffer[MAX_PATH];
+    WCHAR Buffer[MAX_PATH];
+    DWORD RequiredSize;
+    HKEY hClassKey;
+
+    if (!SetupGetLineTextW(NULL,
+                          hInf,
+                          Version,
+                          ClassGUID,
+                          Buffer,
+                          MAX_PATH,
+                          &RequiredSize))
+    {
+       return INVALID_HANDLE_VALUE;
+    }
+
+    lstrcpyW(FullBuffer, REGSTR_PATH_CLASS_NT);
+    lstrcatW(FullBuffer, slash);
+    lstrcatW(FullBuffer, Buffer);
+
+    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                     FullBuffer,
+                     0,
+                     KEY_SET_VALUE,
+                     &hClassKey))
+    {
+       if (!SetupGetLineTextW(NULL,
+                              hInf,
+                              Version,
+                              Class,
+                              Buffer,
+                              MAX_PATH,
+                              &RequiredSize))
+       {
+           return INVALID_HANDLE_VALUE;
+       }
+
+       if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
+                           FullBuffer,
+                           0,
+                           NULL,
+                           REG_OPTION_NON_VOLATILE,
+                           KEY_SET_VALUE,
+                           NULL,
+                           &hClassKey,
+                           NULL))
+       {
+           return INVALID_HANDLE_VALUE;
+       }
+
+    }
+
+    if (RegSetValueExW(hClassKey,
+                      Class,
+                      0,
+                      REG_SZ,
+                      (LPBYTE)Buffer,
+                      RequiredSize * sizeof(WCHAR)))
+    {
+       RegCloseKey(hClassKey);
+       RegDeleteKeyW(HKEY_LOCAL_MACHINE,
+                     FullBuffer);
+       return INVALID_HANDLE_VALUE;
+    }
+
+    return hClassKey;
+}
+
+/***********************************************************************
+ *             SetupDiInstallClassW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiInstallClassW(
+        HWND hwndParent,
+        PCWSTR InfFileName,
+        DWORD Flags,
+        HSPFILEQ FileQueue)
+{
+    return SetupDiInstallClassExW(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
+}
+
+
+/***********************************************************************
+ *             SetupDiOpenClassRegKey  (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiOpenClassRegKey(
+        const GUID* ClassGuid,
+        REGSAM samDesired)
+{
+    return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
+                                     DIOCR_INSTALLER, NULL, NULL);
+}
+
+
+/***********************************************************************
+ *             SetupDiOpenClassRegKeyExA  (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiOpenClassRegKeyExA(
+        const GUID* ClassGuid,
+        REGSAM samDesired,
+        DWORD Flags,
+        PCSTR MachineName,
+        PVOID Reserved)
+{
+    PWSTR MachineNameW = NULL;
+    HKEY hKey;
+
+    TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired,
+        Flags, debugstr_a(MachineName), Reserved);
+
+    if (MachineName)
+    {
+        MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
+        if (MachineNameW == NULL)
+            return INVALID_HANDLE_VALUE;
+    }
+
+    hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
+                                     Flags, MachineNameW, Reserved);
+
+    MyFree(MachineNameW);
+
+    return hKey;
+}
+
+
+/***********************************************************************
+ *             SetupDiOpenClassRegKeyExW  (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiOpenClassRegKeyExW(
+        const GUID* ClassGuid,
+        REGSAM samDesired,
+        DWORD Flags,
+        PCWSTR MachineName,
+        PVOID Reserved)
+{
+    HKEY HKLM;
+    HKEY hClassesKey;
+    HKEY key;
+    LPCWSTR lpKeyName;
+    LONG l;
+
+    TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired,
+        Flags, debugstr_w(MachineName), Reserved);
+
+    if (MachineName != NULL)
+    {
+        l = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM);
+        if (l != ERROR_SUCCESS)
+        {
+            SetLastError(l);
+            return INVALID_HANDLE_VALUE;
+        }
+    }
+    else
+        HKLM = HKEY_LOCAL_MACHINE;
+
+    if (Flags == DIOCR_INSTALLER)
+    {
+        lpKeyName = REGSTR_PATH_CLASS_NT;
+    }
+    else if (Flags == DIOCR_INTERFACE)
+    {
+        lpKeyName = REGSTR_PATH_DEVICE_CLASSES;
+    }
+    else
+    {
+        ERR("Invalid Flags parameter!\n");
+        SetLastError(ERROR_INVALID_FLAGS);
+        if (MachineName != NULL) RegCloseKey(HKLM);
+        return INVALID_HANDLE_VALUE;
+    }
+
+    if (!ClassGuid)
+    {
+        if ((l = RegOpenKeyExW(HKLM,
+                          lpKeyName,
+                          0,
+                          samDesired,
+                          &hClassesKey)))
+        {
+            SetLastError(l);
+            hClassesKey = INVALID_HANDLE_VALUE;
+        }
+        if (MachineName != NULL)
+            RegCloseKey(HKLM);
+        key = hClassesKey;
+    }
+    else
+    {
+        WCHAR bracedGuidString[39];
+
+        SETUPDI_GuidToString(ClassGuid, bracedGuidString);
+
+        if (!(l = RegOpenKeyExW(HKLM,
+                          lpKeyName,
+                          0,
+                          0,
+                          &hClassesKey)))
+        {
+                if (MachineName != NULL)
+                    RegCloseKey(HKLM);
+                
+            if ((l = RegOpenKeyExW(hClassesKey,
+                              bracedGuidString,
+                              0,
+                              samDesired,
+                              &key)))
+            {
+                SetLastError(l);
+                key = INVALID_HANDLE_VALUE;
             }
+            RegCloseKey(hClassesKey);
+        }
+        else
+        {
+            if (MachineName != NULL) RegCloseKey(HKLM);
+            SetLastError(l);
+            key = INVALID_HANDLE_VALUE;
+        }
+    }
+    return key;
+}
+
+/***********************************************************************
+ *             SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiOpenDeviceInterfaceW(
+       HDEVINFO DeviceInfoSet,
+       PCWSTR DevicePath,
+       DWORD OpenFlags,
+       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
+{
+    FIXME("%p %s %08x %p\n",
+        DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
+    return FALSE;
+}
+
+/***********************************************************************
+ *             SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiOpenDeviceInterfaceA(
+       HDEVINFO DeviceInfoSet,
+       PCSTR DevicePath,
+       DWORD OpenFlags,
+       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
+{
+    LPWSTR DevicePathW = NULL;
+    BOOL bResult;
 
-            /*case SPDRP_CHARACTERISTICS:
-            case SPDRP_DEVTYPE:
-            case SPDRP_EXCLUSIVE:*/
-#if (WINVER >= 0x501)
-            //case SPDRP_REMOVAL_POLICY_OVERRIDE:
-#endif
-            //case SPDRP_SECURITY_SDS:
+    TRACE("%p %s %08lx %p\n", DeviceInfoSet, debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
 
-            default:
-            {
-                ERR("Property 0x%lx not implemented\n", Property);
-                SetLastError(ERROR_NOT_SUPPORTED);
-            }
-        }
-    }
+    DevicePathW = MultiByteToUnicode(DevicePath, CP_ACP);
+    if (DevicePathW == NULL)
+        return FALSE;
 
-    TRACE("Returning %d\n", ret);
-    return ret;
+    bResult = SetupDiOpenDeviceInterfaceW(DeviceInfoSet,
+        DevicePathW, OpenFlags, DeviceInterfaceData);
+
+    MyFree(DevicePathW);
+
+    return bResult;
 }
 
+/***********************************************************************
+ *             SetupDiSetClassInstallParamsA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiSetClassInstallParamsA(
+       HDEVINFO  DeviceInfoSet,
+       PSP_DEVINFO_DATA DeviceInfoData,
+       PSP_CLASSINSTALL_HEADER ClassInstallParams,
+       DWORD ClassInstallParamsSize)
+{
+    FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
+          ClassInstallParams->InstallFunction, ClassInstallParamsSize);
+    return FALSE;
+}
 
 static BOOL WINAPI
 IntSetupDiRegisterDeviceInfo(
@@ -1462,11 +3681,10 @@ IntSetupDiRegisterDeviceInfo(
 /***********************************************************************
  *             SetupDiCallClassInstaller (SETUPAPI.@)
  */
-BOOL WINAPI
-SetupDiCallClassInstaller(
-    IN DI_FUNCTION InstallFunction,
-    IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
+BOOL WINAPI SetupDiCallClassInstaller(
+       DI_FUNCTION InstallFunction,
+       HDEVINFO DeviceInfoSet,
+       PSP_DEVINFO_DATA DeviceInfoData)
 {
     BOOL ret = FALSE;
 
@@ -1815,44 +4033,13 @@ SetupDiCallClassInstaller(
     return ret;
 }
 
-/***********************************************************************
- *             SetupDiGetDeviceInfoListClass  (SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiGetDeviceInfoListClass(
-    IN HDEVINFO DeviceInfoSet,
-    OUT LPGUID ClassGuid)
-{
-    struct DeviceInfoSet *list;
-    BOOL ret = FALSE;
-
-    TRACE("%p %p\n", DeviceInfoSet, ClassGuid);
-
-    if (!DeviceInfoSet)
-        SetLastError(ERROR_INVALID_HANDLE);
-    else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
-        SetLastError(ERROR_INVALID_HANDLE);
-    else if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
-        SetLastError(ERROR_NO_ASSOCIATED_CLASS);
-    else
-    {
-        memcpy(&ClassGuid, &list->ClassGuid, sizeof(GUID));
-
-        ret = TRUE;
-    }
-
-    TRACE("Returning %d\n", ret);
-    return ret;
-}
-
 /***********************************************************************
  *             SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
  */
-BOOL WINAPI
-SetupDiGetDeviceInstallParamsA(
-    IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
-    OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
+BOOL WINAPI SetupDiGetDeviceInstallParamsA(
+       HDEVINFO DeviceInfoSet,
+       PSP_DEVINFO_DATA DeviceInfoData,
+       PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
 {
     SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
     BOOL ret = FALSE;
@@ -1879,678 +4066,210 @@ SetupDiGetDeviceInstallParamsA(
                 DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0)
             {
                 DeviceInstallParams->DriverPath[0] = '\0';
-                ret = FALSE;
-            }
-        }
-    }
-
-    TRACE("Returning %d\n", ret);
-    return ret;
-}
-
-/***********************************************************************
- *             SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiGetDeviceInstallParamsW(
-    IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
-    OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
-{
-    struct DeviceInfoSet *list;
-    BOOL ret = FALSE;
-
-    TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
-
-    if (!DeviceInfoSet)
-        SetLastError(ERROR_INVALID_HANDLE);
-    else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
-        SetLastError(ERROR_INVALID_HANDLE);
-    else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
-        SetLastError(ERROR_INVALID_USER_BUFFER);
-    else if (!DeviceInstallParams)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
-        SetLastError(ERROR_INVALID_USER_BUFFER);
-    else
-    {
-        PSP_DEVINSTALL_PARAMS_W Source;
-
-        if (DeviceInfoData)
-            Source = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams;
-        else
-            Source = &list->InstallParams;
-        memcpy(DeviceInstallParams, Source, Source->cbSize);
-        ret = TRUE;
-    }
-
-    TRACE("Returning %d\n", ret);
-    return ret;
-}
-
-static BOOL
-CheckDeviceInstallParameters(
-    IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
-{
-    DWORD SupportedFlags =
-        DI_NOVCP |                            /* 0x00000008 */
-        DI_DIDCOMPAT |                        /* 0x00000010 */
-        DI_DIDCLASS |                         /* 0x00000020 */
-        DI_NEEDRESTART |                      /* 0x00000080 */
-        DI_NEEDREBOOT |                       /* 0x00000100 */
-        DI_RESOURCEPAGE_ADDED |               /* 0x00002000 */
-        DI_PROPERTIES_CHANGE |                /* 0x00004000 */
-        DI_ENUMSINGLEINF |                    /* 0x00010000 */
-        DI_DONOTCALLCONFIGMG |                /* 0x00020000 */
-        DI_CLASSINSTALLPARAMS |               /* 0x00100000 */
-        DI_NODI_DEFAULTACTION |               /* 0x00200000 */
-        DI_QUIETINSTALL |                     /* 0x00800000 */
-        DI_NOFILECOPY |                       /* 0x01000000 */
-        DI_DRIVERPAGE_ADDED;                  /* 0x04000000 */
-    DWORD SupportedFlagsEx =
-        DI_FLAGSEX_CI_FAILED |                /* 0x00000004 */
-        DI_FLAGSEX_DIDINFOLIST |              /* 0x00000010 */
-        DI_FLAGSEX_DIDCOMPATINFO |            /* 0x00000020 */
-        DI_FLAGSEX_ALLOWEXCLUDEDDRVS |        /* 0x00000800 */
-        DI_FLAGSEX_NO_DRVREG_MODIFY |         /* 0x00008000 */
-        DI_FLAGSEX_INSTALLEDDRIVER;           /* 0x04000000 */
-    BOOL ret = FALSE;
-
-    /* FIXME: add support for more flags */
-
-    /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
-     * It should be checked before accessing to other values
-     * of the SP_DEVINSTALL_PARAMS structure */
-
-    if (DeviceInstallParams->Flags & ~SupportedFlags)
-    {
-        FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams->Flags & ~SupportedFlags);
-        SetLastError(ERROR_INVALID_FLAGS);
-    }
-    else if (DeviceInstallParams->FlagsEx & ~SupportedFlagsEx)
-    {
-        FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams->FlagsEx & ~SupportedFlagsEx);
-        SetLastError(ERROR_INVALID_FLAGS);
-    }
-    else if ((DeviceInstallParams->Flags & DI_NOVCP)
-        && (DeviceInstallParams->FileQueue == NULL || DeviceInstallParams->FileQueue == (HSPFILEQ)INVALID_HANDLE_VALUE))
-        SetLastError(ERROR_INVALID_USER_BUFFER);
-    else
-    {
-        /* FIXME: check Reserved field */
-        ret = TRUE;
-    }
-
-    return ret;
-}
-
-/***********************************************************************
- *             SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiSetDeviceInstallParamsW(
-    IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
-    IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
-{
-    struct DeviceInfoSet *list;
-    BOOL ret = FALSE;
-
-    TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
-
-    if (!DeviceInfoSet)
-        SetLastError(ERROR_INVALID_HANDLE);
-    else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
-        SetLastError(ERROR_INVALID_HANDLE);
-    else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
-        SetLastError(ERROR_INVALID_USER_BUFFER);
-    else if (!DeviceInstallParams)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
-        SetLastError(ERROR_INVALID_USER_BUFFER);
-    else if (CheckDeviceInstallParameters(DeviceInstallParams))
-    {
-        PSP_DEVINSTALL_PARAMS_W Destination;
-
-        if (DeviceInfoData)
-            Destination = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams;
-        else
-            Destination = &list->InstallParams;
-        memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize);
-        ret = TRUE;
-    }
-
-    TRACE("Returning %d\n", ret);
-    return ret;
-}
-
-/***********************************************************************
- *             SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiGetDeviceInstanceIdA(
-    IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData,
-    OUT PSTR DeviceInstanceId OPTIONAL,
-    IN DWORD DeviceInstanceIdSize,
-    OUT PDWORD RequiredSize OPTIONAL)
-{
-    PWSTR DeviceInstanceIdW = NULL;
-    BOOL ret = FALSE;
-
-    TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
-          DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
-
-    if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else
-    {
-        if (DeviceInstanceIdSize != 0)
-        {
-            DeviceInstanceIdW = MyMalloc(DeviceInstanceIdSize * sizeof(WCHAR));
-            if (DeviceInstanceIdW == NULL)
-                return FALSE;
-        }
-
-        ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData,
-                                          DeviceInstanceIdW, DeviceInstanceIdSize,
-                                          RequiredSize);
-
-        if (ret && DeviceInstanceIdW != NULL)
-        {
-            if (WideCharToMultiByte(CP_ACP, 0, DeviceInstanceIdW, -1,
-                DeviceInstanceId, DeviceInstanceIdSize, NULL, NULL) == 0)
-            {
-                DeviceInstanceId[0] = '\0';
-                ret = FALSE;
-            }
-        }
-    }
-
-    TRACE("Returning %d\n", ret);
-    return ret;
-}
-
-/***********************************************************************
- *             SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiGetDeviceInstanceIdW(
-    IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData,
-    OUT PWSTR DeviceInstanceId OPTIONAL,
-    IN DWORD DeviceInstanceIdSize,
-    OUT PDWORD RequiredSize OPTIONAL)
-{
-    BOOL ret = FALSE;
-
-    TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
-          DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
-
-    if (!DeviceInfoSet)
-        SetLastError(ERROR_INVALID_HANDLE);
-    else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
-        SetLastError(ERROR_INVALID_HANDLE);
-    else if (!DeviceInfoData)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
-        SetLastError(ERROR_INVALID_USER_BUFFER);
-    else if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else if (DeviceInstanceId && DeviceInstanceIdSize == 0)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else
-    {
-        struct DeviceInfo *DevInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
-        DWORD required;
-
-        required = (strlenW(DevInfo->DeviceName) + 1) * sizeof(WCHAR);
-        if (RequiredSize)
-            *RequiredSize = required;
-
-        if (required <= DeviceInstanceIdSize)
-        {
-            strcpyW(DeviceInstanceId, DevInfo->DeviceName);
-            ret = TRUE;
+                ret = FALSE;
+            }
         }
-        else
-            SetLastError(ERROR_INSUFFICIENT_BUFFER);
     }
 
     TRACE("Returning %d\n", ret);
     return ret;
 }
 
-
 /***********************************************************************
- *             SetupDiCreateDevRegKeyA (SETUPAPI.@)
+ *             SetupDiGetDeviceInfoListClass  (SETUPAPI.@)
  */
-HKEY WINAPI
-SetupDiCreateDevRegKeyA(
+BOOL WINAPI
+SetupDiGetDeviceInfoListClass(
     IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData,
-    IN DWORD Scope,
-    IN DWORD HwProfile,
-    IN DWORD KeyType,
-    IN HINF InfHandle OPTIONAL,
-    IN PCSTR InfSectionName OPTIONAL)
+    OUT LPGUID ClassGuid)
 {
-    PCWSTR InfSectionNameW = NULL;
-    HKEY ret = INVALID_HANDLE_VALUE;
-
-    if (InfSectionName)
-    {
-        InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
-        if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
-    }
-
-    ret = SetupDiCreateDevRegKeyW(DeviceInfoSet,
-                                  DeviceInfoData,
-                                  Scope,
-                                  HwProfile,
-                                  KeyType,
-                                  InfHandle,
-                                  InfSectionNameW);
-
-    if (InfSectionNameW != NULL)
-        MyFree((PVOID)InfSectionNameW);
-
-    return ret;
-}
+    struct DeviceInfoSet *list;
+    BOOL ret = FALSE;
 
-static HKEY
-OpenHardwareProfileKey(
-    IN HKEY HKLM,
-    IN DWORD HwProfile,
-    IN DWORD samDesired)
-{
-    HKEY hHWProfilesKey = NULL;
-    HKEY hHWProfileKey = NULL;
-    HKEY ret = INVALID_HANDLE_VALUE;
-    LONG rc;
+    TRACE("%p %p\n", DeviceInfoSet, ClassGuid);
 
-    rc = RegOpenKeyExW(HKLM,
-        REGSTR_PATH_HWPROFILES,
-        0,
-        0,
-        &hHWProfilesKey);
-    if (rc != ERROR_SUCCESS)
-    {
-        SetLastError(rc);
-        goto cleanup;
-    }
-    if (HwProfile == 0)
-    {
-        rc = RegOpenKeyExW(
-            hHWProfilesKey,
-            REGSTR_KEY_CURRENT,
-            0,
-            KEY_CREATE_SUB_KEY,
-            &hHWProfileKey);
-    }
+    if (!DeviceInfoSet)
+        SetLastError(ERROR_INVALID_HANDLE);
+    else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+        SetLastError(ERROR_INVALID_HANDLE);
+    else if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
+        SetLastError(ERROR_NO_ASSOCIATED_CLASS);
     else
     {
-        WCHAR subKey[5];
-        snprintfW(subKey, 4, InstanceKeyFormat, HwProfile);
-        subKey[4] = '\0';
-        rc = RegOpenKeyExW(
-            hHWProfilesKey,
-            subKey,
-            0,
-            KEY_CREATE_SUB_KEY,
-            &hHWProfileKey);
-    }
-    if (rc != ERROR_SUCCESS)
-    {
-        SetLastError(rc);
-        goto cleanup;
+        memcpy(&ClassGuid, &list->ClassGuid, sizeof(GUID));
+
+        ret = TRUE;
     }
-    ret = hHWProfileKey;
 
-cleanup:
-    if (hHWProfilesKey != NULL)
-        RegCloseKey(hHWProfilesKey);
-    if (hHWProfileKey != NULL && hHWProfileKey != ret)
-        RegCloseKey(hHWProfileKey);
+    TRACE("Returning %d\n", ret);
     return ret;
 }
 
 /***********************************************************************
- *             SetupDiCreateDevRegKeyW (SETUPAPI.@)
+ *             SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
  */
-HKEY WINAPI
-SetupDiCreateDevRegKeyW(
+BOOL WINAPI
+SetupDiGetDeviceInstallParamsW(
     IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData,
-    IN DWORD Scope,
-    IN DWORD HwProfile,
-    IN DWORD KeyType,
-    IN HINF InfHandle OPTIONAL,
-    IN PCWSTR InfSectionName OPTIONAL)
+    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+    OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
 {
     struct DeviceInfoSet *list;
-    HKEY ret = INVALID_HANDLE_VALUE;
+    BOOL ret = FALSE;
 
-    TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData,
-          Scope, HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
+    TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
 
     if (!DeviceInfoSet)
         SetLastError(ERROR_INVALID_HANDLE);
     else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
         SetLastError(ERROR_INVALID_HANDLE);
-    else if (!DeviceInfoData)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+    else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
         SetLastError(ERROR_INVALID_USER_BUFFER);
-    else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else if (InfHandle && !InfSectionName)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else if (!InfHandle && InfSectionName)
+    else if (!DeviceInstallParams)
         SetLastError(ERROR_INVALID_PARAMETER);
+    else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
+        SetLastError(ERROR_INVALID_USER_BUFFER);
     else
     {
-        LPWSTR lpGuidString = NULL;
-        LPWSTR DriverKey = NULL; /* {GUID}\Index */
-        LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
-        DWORD Index; /* Index used in the DriverKey name */
-        DWORD rc;
-        HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
-        HKEY hEnumKey = NULL;
-        HKEY hClassKey = NULL;
-        HKEY hDeviceKey = INVALID_HANDLE_VALUE;
-        HKEY hKey = NULL;
-        HKEY RootKey;
-
-        if (Scope == DICS_FLAG_GLOBAL)
-            RootKey = list->HKLM;
-        else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
-        {
-            hHWProfileKey = OpenHardwareProfileKey(list->HKLM, HwProfile, KEY_CREATE_SUB_KEY);
-            if (hHWProfileKey == INVALID_HANDLE_VALUE)
-                goto cleanup;
-            RootKey = hHWProfileKey;
-        }
-
-        if (KeyType == DIREG_DEV)
-        {
-            struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
-
-            rc = RegCreateKeyExW(
-                RootKey,
-                REGSTR_PATH_SYSTEMENUM,
-                0,
-                NULL,
-                REG_OPTION_NON_VOLATILE,
-                KEY_CREATE_SUB_KEY,
-                NULL,
-                &hEnumKey,
-                NULL);
-            if (rc != ERROR_SUCCESS)
-            {
-                SetLastError(rc);
-                goto cleanup;
-            }
-            rc = RegCreateKeyExW(
-                hEnumKey,
-                deviceInfo->DeviceName,
-                0,
-                NULL,
-                REG_OPTION_NON_VOLATILE,
-#if _WIN32_WINNT >= 0x502
-                KEY_READ | KEY_WRITE,
-#else
-                KEY_ALL_ACCESS,
-#endif
-                NULL,
-                &hKey,
-                NULL);
-            if (rc != ERROR_SUCCESS)
-            {
-                SetLastError(rc);
-                goto cleanup;
-            }
-        }
-        else /* KeyType == DIREG_DRV */
-        {
-            if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
-                goto cleanup;
-            /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
-            DriverKey = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
-            if (!DriverKey)
-            {
-                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-                goto cleanup;
-            }
-            DriverKey[0] = '{';
-            strcpyW(&DriverKey[1], lpGuidString);
-            pDeviceInstance = &DriverKey[strlenW(DriverKey)];
-            *pDeviceInstance++ = '}';
-            *pDeviceInstance++ = '\\';
-            rc = RegOpenKeyExW(RootKey,
-                REGSTR_PATH_CLASS_NT,
-                0,
-                KEY_CREATE_SUB_KEY,
-                &hClassKey);
-            if (rc != ERROR_SUCCESS)
-            {
-                SetLastError(rc);
-                goto cleanup;
-            }
-
-            /* Try all values for Index between 0 and 9999 */
-            Index = 0;
-            while (Index <= 9999)
-            {
-                DWORD Disposition;
-                sprintfW(pDeviceInstance, InstanceKeyFormat, Index);
-                rc = RegCreateKeyExW(hClassKey,
-                    DriverKey,
-                    0,
-                    NULL,
-                    REG_OPTION_NON_VOLATILE,
-#if _WIN32_WINNT >= 0x502
-                    KEY_READ | KEY_WRITE,
-#else
-                    KEY_ALL_ACCESS,
-#endif
-                    NULL,
-                    &hKey,
-                    &Disposition);
-                if (rc != ERROR_SUCCESS)
-                {
-                    SetLastError(rc);
-                    goto cleanup;
-                }
-                if (Disposition == REG_CREATED_NEW_KEY)
-                    break;
-                RegCloseKey(hKey);
-                hKey = NULL;
-                Index++;
-            }
-            if (Index > 9999)
-            {
-                /* Unable to create more than 9999 devices within the same class */
-                SetLastError(ERROR_GEN_FAILURE);
-                goto cleanup;
-            }
-
-            /* Open device key, to write Driver value */
-            hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_SET_VALUE);
-            if (hDeviceKey == INVALID_HANDLE_VALUE)
-                goto cleanup;
-            rc = RegSetValueExW(hDeviceKey, REGSTR_VAL_DRIVER, 0, REG_SZ, (const BYTE *)DriverKey, (strlenW(DriverKey) + 1) * sizeof(WCHAR));
-            if (rc != ERROR_SUCCESS)
-            {
-                SetLastError(rc);
-                goto cleanup;
-            }
-        }
-
-        /* Do installation of the specified section */
-        if (InfHandle)
-        {
-            FIXME("Need to install section %s in file %p\n",
-                debugstr_w(InfSectionName), InfHandle);
-        }
-        ret = hKey;
+        PSP_DEVINSTALL_PARAMS_W Source;
 
-cleanup:
-        if (lpGuidString)
-            RpcStringFreeW(&lpGuidString);
-        HeapFree(GetProcessHeap(), 0, DriverKey);
-        if (hHWProfileKey != INVALID_HANDLE_VALUE)
-            RegCloseKey(hHWProfileKey);
-        if (hEnumKey != NULL)
-            RegCloseKey(hEnumKey);
-        if (hClassKey != NULL)
-            RegCloseKey(hClassKey);
-        if (hDeviceKey != INVALID_HANDLE_VALUE)
-            RegCloseKey(hDeviceKey);
-        if (hKey != NULL && hKey != ret)
-            RegCloseKey(hKey);
+        if (DeviceInfoData)
+            Source = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams;
+        else
+            Source = &list->InstallParams;
+        memcpy(DeviceInstallParams, Source, Source->cbSize);
+        ret = TRUE;
     }
 
-    TRACE("Returning 0x%p\n", ret);
+    TRACE("Returning %d\n", ret);
     return ret;
 }
 
-/***********************************************************************
- *             SetupDiCreateDeviceInfoA (SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiCreateDeviceInfoA(
-    IN HDEVINFO DeviceInfoSet,
-    IN PCSTR DeviceName,
-    IN CONST GUID *ClassGuid,
-    IN PCSTR DeviceDescription OPTIONAL,
-    IN HWND hwndParent OPTIONAL,
-    IN DWORD CreationFlags,
-    OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
+static BOOL
+CheckDeviceInstallParameters(
+    IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
 {
-    LPWSTR DeviceNameW = NULL;
-    LPWSTR DeviceDescriptionW = NULL;
-    BOOL bResult;
+    DWORD SupportedFlags =
+        DI_NOVCP |                            /* 0x00000008 */
+        DI_DIDCOMPAT |                        /* 0x00000010 */
+        DI_DIDCLASS |                         /* 0x00000020 */
+        DI_NEEDRESTART |                      /* 0x00000080 */
+        DI_NEEDREBOOT |                       /* 0x00000100 */
+        DI_RESOURCEPAGE_ADDED |               /* 0x00002000 */
+        DI_PROPERTIES_CHANGE |                /* 0x00004000 */
+        DI_ENUMSINGLEINF |                    /* 0x00010000 */
+        DI_DONOTCALLCONFIGMG |                /* 0x00020000 */
+        DI_CLASSINSTALLPARAMS |               /* 0x00100000 */
+        DI_NODI_DEFAULTACTION |               /* 0x00200000 */
+        DI_QUIETINSTALL |                     /* 0x00800000 */
+        DI_NOFILECOPY |                       /* 0x01000000 */
+        DI_DRIVERPAGE_ADDED;                  /* 0x04000000 */
+    DWORD SupportedFlagsEx =
+        DI_FLAGSEX_CI_FAILED |                /* 0x00000004 */
+        DI_FLAGSEX_DIDINFOLIST |              /* 0x00000010 */
+        DI_FLAGSEX_DIDCOMPATINFO |            /* 0x00000020 */
+        DI_FLAGSEX_ALLOWEXCLUDEDDRVS |        /* 0x00000800 */
+        DI_FLAGSEX_NO_DRVREG_MODIFY |         /* 0x00008000 */
+        DI_FLAGSEX_INSTALLEDDRIVER;           /* 0x04000000 */
+    BOOL ret = FALSE;
 
-    TRACE("\n");
+    /* FIXME: add support for more flags */
 
-    if (DeviceName)
+    /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
+     * It should be checked before accessing to other values
+     * of the SP_DEVINSTALL_PARAMS structure */
+
+    if (DeviceInstallParams->Flags & ~SupportedFlags)
     {
-        DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
-        if (DeviceNameW == NULL) return FALSE;
+        FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams->Flags & ~SupportedFlags);
+        SetLastError(ERROR_INVALID_FLAGS);
     }
-    if (DeviceDescription)
+    else if (DeviceInstallParams->FlagsEx & ~SupportedFlagsEx)
     {
-        DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
-        if (DeviceDescriptionW == NULL)
-        {
-            if (DeviceNameW) MyFree(DeviceNameW);
-            return FALSE;
-        }
+        FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams->FlagsEx & ~SupportedFlagsEx);
+        SetLastError(ERROR_INVALID_FLAGS);
+    }
+    else if ((DeviceInstallParams->Flags & DI_NOVCP)
+        && (DeviceInstallParams->FileQueue == NULL || DeviceInstallParams->FileQueue == (HSPFILEQ)INVALID_HANDLE_VALUE))
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+    else
+    {
+        /* FIXME: check Reserved field */
+        ret = TRUE;
     }
 
-    bResult = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW,
-                                       ClassGuid, DeviceDescriptionW,
-                                       hwndParent, CreationFlags,
-                                       DeviceInfoData);
-
-    if (DeviceNameW) MyFree(DeviceNameW);
-    if (DeviceDescriptionW) MyFree(DeviceDescriptionW);
-
-    return bResult;
+    return ret;
 }
 
 /***********************************************************************
- *             SetupDiCreateDeviceInfoW (SETUPAPI.@)
+ *             SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
  */
 BOOL WINAPI
-SetupDiCreateDeviceInfoW(
+SetupDiSetDeviceInstallParamsW(
     IN HDEVINFO DeviceInfoSet,
-    IN PCWSTR DeviceName,
-    IN CONST GUID *ClassGuid,
-    IN PCWSTR DeviceDescription OPTIONAL,
-    IN HWND hwndParent OPTIONAL,
-    IN DWORD CreationFlags,
-    OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
+    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+    IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
 {
     struct DeviceInfoSet *list;
     BOOL ret = FALSE;
 
-    TRACE("%p %s %s %s %p %lx %p\n", DeviceInfoSet, debugstr_w(DeviceName),
-        debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
-        hwndParent, CreationFlags, DeviceInfoData);
+    TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
 
     if (!DeviceInfoSet)
         SetLastError(ERROR_INVALID_HANDLE);
     else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
         SetLastError(ERROR_INVALID_HANDLE);
-    else if (!ClassGuid)
+    else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+    else if (!DeviceInstallParams)
         SetLastError(ERROR_INVALID_PARAMETER);
-    else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, ClassGuid))
-        SetLastError(ERROR_CLASS_MISMATCH);
-    else if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
+    else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+    else if (CheckDeviceInstallParameters(DeviceInstallParams))
     {
-        TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
-        SetLastError(ERROR_INVALID_FLAGS);
+        PSP_DEVINSTALL_PARAMS_W Destination;
+
+        if (DeviceInfoData)
+            Destination = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams;
+        else
+            Destination = &list->InstallParams;
+        memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize);
+        ret = TRUE;
     }
+
+    TRACE("Returning %d\n", ret);
+    return ret;
+}
+
+BOOL WINAPI SetupDiSetDeviceInstallParamsA(
+       HDEVINFO DeviceInfoSet,
+       PSP_DEVINFO_DATA DeviceInfoData,
+       PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
+{
+    SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
+    int len = 0;
+    BOOL ret = FALSE;
+
+    TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
+
+    if (DeviceInstallParams == NULL)
+        SetLastError(ERROR_INVALID_PARAMETER);
+    else if (DeviceInstallParams->cbSize < sizeof(SP_DEVINSTALL_PARAMS_A))
+        SetLastError(ERROR_INVALID_USER_BUFFER);
     else
     {
-        SP_DEVINFO_DATA DevInfo;
-
-        if (CreationFlags & DICD_GENERATE_ID)
+        memcpy(&deviceInstallParamsW, DeviceInstallParams, FIELD_OFFSET(SP_DEVINSTALL_PARAMS_A, DriverPath));
+        deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+        len = MultiByteToWideChar(CP_ACP, 0, DeviceInstallParams->DriverPath, -1, NULL, 0);
+        if (!len)
         {
-            /* Generate a new unique ID for this device */
-            SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-            FIXME("not implemented\n");
+            ERR("DrivePath is NULL\n");
+            ret = FALSE;
         }
         else
         {
-            /* Device name is fully qualified. Try to open it */
-            BOOL rc;
-
-            DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
-            rc = SetupDiOpenDeviceInfoW(
-                DeviceInfoSet,
-                DeviceName,
-                NULL, /* hwndParent */
-                CreationFlags & DICD_INHERIT_CLASSDRVS ? DIOD_INHERIT_CLASSDRVS : 0,
-                &DevInfo);
-
-            if (rc)
-            {
-                /* SetupDiOpenDeviceInfoW has already added
-                 * the device info to the device info set
-                 */
-                SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
-            }
-            else if (GetLastError() == ERROR_FILE_NOT_FOUND)
-            {
-                struct DeviceInfo *deviceInfo;
-
-                if (CreateDeviceInfo(list, DeviceName, ClassGuid, &deviceInfo))
-                {
-                    InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
-
-                    if (!DeviceInfoData)
-                        ret = TRUE;
-                    else
-                    {
-                        if (DeviceInfoData->cbSize != sizeof(PSP_DEVINFO_DATA))
-                        {
-                            SetLastError(ERROR_INVALID_USER_BUFFER);
-                        }
-                        else
-                        {
-                            memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
-                            DeviceInfoData->DevInst = deviceInfo->dnDevInst;
-                            DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
-                            ret = TRUE;
-                        }
-                    }
-                }
-            }
+            MultiByteToWideChar(CP_ACP, 0, DeviceInstallParams->DriverPath, -1, deviceInstallParamsW.DriverPath, len);
+            ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW);
         }
     }
 
@@ -2558,6 +4277,62 @@ SetupDiCreateDeviceInfoW(
     return ret;
 }
 
+static HKEY
+OpenHardwareProfileKey(
+    IN HKEY HKLM,
+    IN DWORD HwProfile,
+    IN DWORD samDesired)
+{
+    HKEY hHWProfilesKey = NULL;
+    HKEY hHWProfileKey = NULL;
+    HKEY ret = INVALID_HANDLE_VALUE;
+    LONG rc;
+
+    rc = RegOpenKeyExW(HKLM,
+        REGSTR_PATH_HWPROFILES,
+        0,
+        0,
+        &hHWProfilesKey);
+    if (rc != ERROR_SUCCESS)
+    {
+        SetLastError(rc);
+        goto cleanup;
+    }
+    if (HwProfile == 0)
+    {
+        rc = RegOpenKeyExW(
+            hHWProfilesKey,
+            REGSTR_KEY_CURRENT,
+            0,
+            KEY_CREATE_SUB_KEY,
+            &hHWProfileKey);
+    }
+    else
+    {
+        WCHAR subKey[5];
+        snprintfW(subKey, 4, InstanceKeyFormat, HwProfile);
+        subKey[4] = '\0';
+        rc = RegOpenKeyExW(
+            hHWProfilesKey,
+            subKey,
+            0,
+            KEY_CREATE_SUB_KEY,
+            &hHWProfileKey);
+    }
+    if (rc != ERROR_SUCCESS)
+    {
+        SetLastError(rc);
+        goto cleanup;
+    }
+    ret = hHWProfileKey;
+
+cleanup:
+    if (hHWProfilesKey != NULL)
+        RegCloseKey(hHWProfilesKey);
+    if (hHWProfileKey != NULL && hHWProfileKey != ret)
+        RegCloseKey(hHWProfileKey);
+    return ret;
+}
 
 /***********************************************************************
  *             SetupDiDeleteDeviceInfo (SETUPAPI.@)
@@ -2852,7 +4627,7 @@ cleanup:
     if (hKey != NULL)
         RegCloseKey(hKey);
 
-    return hwProfile;
+    return ret;
 }
 
 static BOOL
@@ -2861,21 +4636,18 @@ ResetDevice(
     IN PSP_DEVINFO_DATA DeviceInfoData)
 {
 #ifndef __WINESRC__
-    PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
+    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
     struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
-    NTSTATUS Status;
+    CONFIGRET cr;
 
-    if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
+    cr = CM_Enable_DevNode_Ex(deviceInfo->dnDevInst, 0, set->hMachine);
+    if (cr != CR_SUCCESS)
     {
-        /* At the moment, I only know how to start local devices */
-        SetLastError(ERROR_INVALID_COMPUTERNAME);
+        SetLastError(GetErrorCodeFromCrCode(cr));
         return FALSE;
     }
 
-    RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, deviceInfo->DeviceName);
-    Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
-    SetLastError(RtlNtStatusToDosError(Status));
-    return NT_SUCCESS(Status);
+    return TRUE;
 #else
     FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData);
     return TRUE;
@@ -3468,7 +5240,7 @@ static HKEY SETUPDI_OpenDevKey(HKEY RootKey, struct DeviceInfo *devInfo, REGSAM
     l = RegOpenKeyExW(RootKey, REGSTR_PATH_SYSTEMENUM, 0, 0, &enumKey);
     if (!l)
     {
-        l = RegOpenKeyExW(enumKey, devInfo->DeviceName, 0, samDesired, &key);
+        l = RegOpenKeyExW(enumKey, devInfo->instanceId, 0, samDesired, &key);
         RegCloseKey(enumKey);
     }
     if (l)
@@ -3559,7 +5331,7 @@ HKEY WINAPI SetupDiOpenDevRegKey(
        DWORD KeyType,
        REGSAM samDesired)
 {
-    struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+    struct DeviceInfoSet *set = DeviceInfoSet;
     struct DeviceInfo *devInfo;
     HKEY key = INVALID_HANDLE_VALUE;
     HKEY RootKey;
@@ -3567,7 +5339,7 @@ HKEY WINAPI SetupDiOpenDevRegKey(
     TRACE("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
           Scope, HwProfile, KeyType, samDesired);
 
-    if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
     {
         SetLastError(ERROR_INVALID_HANDLE);
         return INVALID_HANDLE_VALUE;
@@ -3620,11 +5392,21 @@ HKEY WINAPI SetupDiOpenDevRegKey(
     }
     if (RootKey != set->HKLM)
         RegCloseKey(RootKey);
-
-    TRACE("Returning 0x%p\n", key);
     return key;
 }
 
+static BOOL SETUPDI_DeleteDevKey(HKEY RootKey, struct DeviceInfo *devInfo)
+{
+    FIXME("\n");
+    return FALSE;
+}
+
+static BOOL SETUPDI_DeleteDrvKey(HKEY RootKey, struct DeviceInfo *devInfo)
+{
+    FIXME("\n");
+    return FALSE;
+}
+
 /***********************************************************************
  *             SetupDiDeleteDevRegKey (SETUPAPI.@)
  */
@@ -3638,11 +5420,12 @@ BOOL WINAPI SetupDiDeleteDevRegKey(
     struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
     struct DeviceInfo *devInfo;
     BOOL ret = FALSE;
+    HKEY RootKey;
 
     TRACE("%p %p %d %d %d\n", DeviceInfoSet, DeviceInfoData, Scope, HwProfile,
             KeyType);
 
-    if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
+    if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
     {
         SetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
@@ -3663,7 +5446,7 @@ BOOL WINAPI SetupDiDeleteDevRegKey(
         SetLastError(ERROR_INVALID_FLAGS);
         return FALSE;
     }
-    if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
+    if (KeyType != DIREG_DEV && KeyType != DIREG_DRV && KeyType != DIREG_BOTH)
     {
         SetLastError(ERROR_INVALID_FLAGS);
         return FALSE;
@@ -3674,10 +5457,31 @@ BOOL WINAPI SetupDiDeleteDevRegKey(
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
+    if (Scope != DICS_FLAG_GLOBAL)
+    {
+        RootKey = OpenHardwareProfileKey(set->HKLM, HwProfile, 0);
+        if (RootKey == INVALID_HANDLE_VALUE)
+            return FALSE;
+    }
+    else
+        RootKey = set->HKLM;
     switch (KeyType)
     {
+        case DIREG_DEV:
+            ret = SETUPDI_DeleteDevKey(RootKey, devInfo);
+            break;
+        case DIREG_DRV:
+            ret = SETUPDI_DeleteDrvKey(RootKey, devInfo);
+            break;
+        case DIREG_BOTH:
+            ret = SETUPDI_DeleteDevKey(RootKey, devInfo);
+            if (ret)
+                ret = SETUPDI_DeleteDrvKey(RootKey, devInfo);
+            break;
         default:
             WARN("unknown KeyType %d\n", KeyType);
     }
+    if (RootKey != set->HKLM)
+        RegCloseKey(RootKey);
     return ret;
 }