Fix some whitespaces
[reactos.git] / reactos / dll / win32 / setupapi / devinst.c
index 6c61be4..a0c94b5 100644 (file)
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#define INITGUID
 #include "setupapi_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
 
 /* Unicode constants */
+static const WCHAR AddInterface[]  = {'A','d','d','I','n','t','e','r','f','a','c','e',0};
 static const WCHAR ClassGUID[]  = {'C','l','a','s','s','G','U','I','D',0};
 static const WCHAR Class[]  = {'C','l','a','s','s',0};
 static const WCHAR ClassInstall32[]  = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
 static const WCHAR Control[]  = {'C','o','n','t','r','o','l',0};
 static const WCHAR DeviceInstance[]  = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
 static const WCHAR DotCoInstallers[]  = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
+static const WCHAR DotHW[]  = {'.','H','W',0};
+static const WCHAR DotInterfaces[]  = {'.','I','n','t','e','r','f','a','c','e','s',0};
 static const WCHAR DotServices[]  = {'.','S','e','r','v','i','c','e','s',0};
 static const WCHAR InterfaceInstall32[]  = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
 static const WCHAR Linked[]  = {'L','i','n','k','e','d',0};
 static const WCHAR SymbolicLink[]  = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
 static const WCHAR Version[]  = {'V','e','r','s','i','o','n',0};
 
-/* FIXME: header mess */
-DEFINE_GUID(GUID_NULL,
-  0x00000000L, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+static const WCHAR REGSTR_DRIVER_DATE[]  = {'D','r','i','v','e','r','D','a','t','e',0};
+static const WCHAR REGSTR_DRIVER_DATE_DATA[]  = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
+static const WCHAR REGSTR_DRIVER_VERSION[]  = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
+static const WCHAR REGSTR_SECURITY[]  = {'S','e','c','u','r','i','t','y',0};
+static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT[]  = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0};
+
+static const WCHAR INF_MANUFACTURER[]  = {'M','a','n','u','f','a','c','t','u','r','e','r',0};
+static const WCHAR INF_PROVIDER[]  = {'P','r','o','v','i','d','e','r',0};
+static const WCHAR INF_DRIVER_VER[]  = {'D','r','i','v','e','r','V','e','r',0};
+
 typedef DWORD
 (CALLBACK* CLASS_INSTALL_PROC) (
     IN DI_FUNCTION InstallFunction,
@@ -77,6 +86,15 @@ struct CoInstallerElement
     PVOID PrivateData;
 };
 
+struct GetSectionCallbackInfo
+{
+    PSP_ALTPLATFORM_INFO PlatformInfo;
+    BYTE ProductType;
+    WORD SuiteMask;
+    WCHAR BestSection[LINE_LEN + 1];
+    DWORD BestScore1, BestScore2, BestScore3, BestScore4, BestScore5;
+};
+
 static BOOL
 PropertyChangeHandler(
     IN HDEVINFO DeviceInfoSet,
@@ -84,7 +102,7 @@ PropertyChangeHandler(
     IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
     IN DWORD ClassInstallParamsSize);
 
-static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers[] = {
+static const UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers[] = {
     NULL, /* DIF_SELECTDEVICE */
     NULL, /* DIF_INSTALLDEVICE */
     NULL, /* DIF_ASSIGNRESOURCES */
@@ -132,11 +150,12 @@ static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers[] = {
 /***********************************************************************
  *              SetupDiBuildClassInfoList  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiBuildClassInfoList(
-        DWORD Flags,
-        LPGUID ClassGuidList,
-        DWORD ClassGuidListSize,
-        PDWORD RequiredSize)
+BOOL WINAPI
+SetupDiBuildClassInfoList(
+    IN DWORD Flags,
+    OUT LPGUID ClassGuidList OPTIONAL,
+    IN DWORD ClassGuidListSize,
+    OUT PDWORD RequiredSize)
 {
     TRACE("\n");
     return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
@@ -147,13 +166,14 @@ BOOL WINAPI SetupDiBuildClassInfoList(
 /***********************************************************************
  *              SetupDiBuildClassInfoListExA  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiBuildClassInfoListExA(
-        DWORD Flags,
-        LPGUID ClassGuidList,
-        DWORD ClassGuidListSize,
-        PDWORD RequiredSize,
-        LPCSTR MachineName,
-        PVOID Reserved)
+BOOL WINAPI
+SetupDiBuildClassInfoListExA(
+    IN DWORD Flags,
+    OUT LPGUID ClassGuidList OPTIONAL,
+    IN DWORD ClassGuidListSize,
+    OUT PDWORD RequiredSize,
+    IN PCSTR MachineName OPTIONAL,
+    IN PVOID Reserved)
 {
     LPWSTR MachineNameW = NULL;
     BOOL bResult;
@@ -179,27 +199,29 @@ BOOL WINAPI SetupDiBuildClassInfoListExA(
 /***********************************************************************
  *             SetupDiBuildClassInfoListExW  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiBuildClassInfoListExW(
-        DWORD Flags,
-        LPGUID ClassGuidList,
-        DWORD ClassGuidListSize,
-        PDWORD RequiredSize,
-        LPCWSTR MachineName,
-        PVOID Reserved)
+BOOL WINAPI
+SetupDiBuildClassInfoListExW(
+    IN DWORD Flags,
+    OUT LPGUID ClassGuidList OPTIONAL,
+    IN DWORD ClassGuidListSize,
+    OUT PDWORD RequiredSize,
+    IN PCWSTR MachineName OPTIONAL,
+    IN PVOID Reserved)
 {
     WCHAR szKeyName[MAX_GUID_STRING_LEN + 1];
-    HKEY hClassesKey;
-    HKEY hClassKey;
+    HKEY hClassesKey = INVALID_HANDLE_VALUE;
+    HKEY hClassKey = NULL;
     DWORD dwLength;
     DWORD dwIndex;
     LONG lError;
     DWORD dwGuidListIndex = 0;
+    BOOL ret = FALSE;
 
     TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
         ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
 
     if (RequiredSize != NULL)
-       *RequiredSize = 0;
+        *RequiredSize = 0;
 
     hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
                                             KEY_ENUMERATE_SUB_KEYS,
@@ -207,118 +229,113 @@ BOOL WINAPI SetupDiBuildClassInfoListExW(
                                             MachineName,
                                             Reserved);
     if (hClassesKey == INVALID_HANDLE_VALUE)
-    {
-       return FALSE;
-    }
+        goto cleanup;
 
     for (dwIndex = 0; ; dwIndex++)
     {
-       dwLength = MAX_GUID_STRING_LEN + 1;
-       lError = RegEnumKeyExW(hClassesKey,
-                              dwIndex,
-                              szKeyName,
-                              &dwLength,
-                              NULL,
-                              NULL,
-                              NULL,
-                              NULL);
-       TRACE("RegEnumKeyExW() returns %ld\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] == L'{' && szKeyName[37] == L'}')
-               {
-                   szKeyName[37] = 0;
-               }
-               TRACE("Guid: %s\n", debugstr_w(&szKeyName[1]));
-
-               UuidFromStringW(&szKeyName[1],
-                               &ClassGuidList[dwGuidListIndex]);
-           }
-
-           dwGuidListIndex++;
-       }
-
-       if (lError != ERROR_SUCCESS)
-           break;
-    }
-
-    RegCloseKey(hClassesKey);
+        dwLength = MAX_GUID_STRING_LEN + 1;
+        lError = RegEnumKeyExW(hClassesKey,
+                               dwIndex,
+                               szKeyName,
+                               &dwLength,
+                               NULL,
+                               NULL,
+                               NULL,
+                               NULL);
+        TRACE("RegEnumKeyExW() returns %ld\n", lError);
+        if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
+        {
+            TRACE("Key name: %s\n", debugstr_w(szKeyName));
+
+            if (hClassKey != NULL)
+                RegCloseKey(hClassKey);
+            if (RegOpenKeyExW(hClassesKey,
+                              szKeyName,
+                              0,
+                              KEY_QUERY_VALUE,
+                              &hClassKey) != ERROR_SUCCESS)
+            {
+                goto cleanup;
+            }
+
+            if (RegQueryValueExW(hClassKey,
+                                 REGSTR_VAL_NOUSECLASS,
+                                 NULL,
+                                 NULL,
+                                 NULL,
+                                 NULL) == ERROR_SUCCESS)
+            {
+                TRACE("'NoUseClass' value found!\n");
+                continue;
+            }
+
+            if ((Flags & DIBCI_NOINSTALLCLASS) &&
+                (!RegQueryValueExW(hClassKey,
+                                   REGSTR_VAL_NOINSTALLCLASS,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   NULL)))
+            {
+                TRACE("'NoInstallClass' value found!\n");
+                continue;
+            }
+
+            if ((Flags & DIBCI_NODISPLAYCLASS) &&
+                (!RegQueryValueExW(hClassKey,
+                                   REGSTR_VAL_NODISPLAYCLASS,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   NULL)))
+            {
+                TRACE("'NoDisplayClass' value found!\n");
+                continue;
+            }
+
+            TRACE("Guid: %s\n", debugstr_w(szKeyName));
+            if (dwGuidListIndex < ClassGuidListSize)
+            {
+                if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
+                    szKeyName[37] = 0;
+                TRACE("Guid: %s\n", debugstr_w(&szKeyName[1]));
+
+                UuidFromStringW(&szKeyName[1],
+                    &ClassGuidList[dwGuidListIndex]);
+            }
+
+            dwGuidListIndex++;
+        }
+
+        if (lError != ERROR_SUCCESS)
+        break;
+    }
 
     if (RequiredSize != NULL)
-       *RequiredSize = dwGuidListIndex;
+        *RequiredSize = dwGuidListIndex;
 
     if (ClassGuidListSize < dwGuidListIndex)
-    {
-       SetLastError(ERROR_INSUFFICIENT_BUFFER);
-       return FALSE;
-    }
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    else
+        ret = TRUE;
 
-    return TRUE;
+cleanup:
+    if (hClassesKey != INVALID_HANDLE_VALUE)
+        RegCloseKey(hClassesKey);
+    if (hClassKey != NULL)
+        RegCloseKey(hClassKey);
+    return ret;
 }
 
 /***********************************************************************
  *             SetupDiClassGuidsFromNameA  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiClassGuidsFromNameA(
-        LPCSTR ClassName,
-        LPGUID ClassGuidList,
-        DWORD ClassGuidListSize,
-        PDWORD RequiredSize)
+BOOL WINAPI
+SetupDiClassGuidsFromNameA(
+    IN PCSTR ClassName,
+    OUT LPGUID ClassGuidList,
+    IN DWORD ClassGuidListSize,
+    OUT PDWORD RequiredSize)
 {
   return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
                                       ClassGuidListSize, RequiredSize,
@@ -329,10 +346,10 @@ BOOL WINAPI SetupDiClassGuidsFromNameA(
  *             SetupDiClassGuidsFromNameW  (SETUPAPI.@)
  */
 BOOL WINAPI SetupDiClassGuidsFromNameW(
-        LPCWSTR ClassName,
-        LPGUID ClassGuidList,
-        DWORD ClassGuidListSize,
-        PDWORD RequiredSize)
+        IN PCWSTR ClassName,
+        OUT LPGUID ClassGuidList,
+        IN DWORD ClassGuidListSize,
+        OUT PDWORD RequiredSize)
 {
   return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
                                       ClassGuidListSize, RequiredSize,
@@ -342,13 +359,14 @@ BOOL WINAPI SetupDiClassGuidsFromNameW(
 /***********************************************************************
  *             SetupDiClassGuidsFromNameExA  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiClassGuidsFromNameExA(
-        LPCSTR ClassName,
-        LPGUID ClassGuidList,
-        DWORD ClassGuidListSize,
-        PDWORD RequiredSize,
-        LPCSTR MachineName,
-        PVOID Reserved)
+BOOL WINAPI
+SetupDiClassGuidsFromNameExA(
+    IN PCSTR ClassName,
+    OUT LPGUID ClassGuidList,
+    IN DWORD ClassGuidListSize,
+    OUT PDWORD RequiredSize,
+    IN PCSTR MachineName OPTIONAL,
+    IN PVOID Reserved)
 {
     LPWSTR ClassNameW = NULL;
     LPWSTR MachineNameW = NULL;
@@ -385,28 +403,30 @@ BOOL WINAPI SetupDiClassGuidsFromNameExA(
 /***********************************************************************
  *             SetupDiClassGuidsFromNameExW  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiClassGuidsFromNameExW(
-        LPCWSTR ClassName,
-        LPGUID ClassGuidList,
-        DWORD ClassGuidListSize,
-        PDWORD RequiredSize,
-        LPCWSTR MachineName,
-        PVOID Reserved)
+BOOL WINAPI
+SetupDiClassGuidsFromNameExW(
+    IN PCWSTR ClassName,
+    OUT LPGUID ClassGuidList,
+    IN DWORD ClassGuidListSize,
+    OUT PDWORD RequiredSize,
+    IN PCWSTR MachineName OPTIONAL,
+    IN PVOID Reserved)
 {
     WCHAR szKeyName[MAX_GUID_STRING_LEN + 1];
     WCHAR szClassName[256];
-    HKEY hClassesKey;
-    HKEY hClassKey;
+    HKEY hClassesKey = INVALID_HANDLE_VALUE;
+    HKEY hClassKey = NULL;
     DWORD dwLength;
     DWORD dwIndex;
     LONG lError;
     DWORD dwGuidListIndex = 0;
+    BOOL ret = FALSE;
 
     TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName), ClassGuidList,
         ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
 
     if (RequiredSize != NULL)
-       *RequiredSize = 0;
+        *RequiredSize = 0;
 
     hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
                                             KEY_ENUMERATE_SUB_KEYS,
@@ -414,96 +434,94 @@ BOOL WINAPI SetupDiClassGuidsFromNameExW(
                                             MachineName,
                                             Reserved);
     if (hClassesKey == INVALID_HANDLE_VALUE)
-    {
-       return FALSE;
-    }
+        goto cleanup;
 
     for (dwIndex = 0; ; dwIndex++)
     {
-       dwLength = MAX_GUID_STRING_LEN + 1;
-       lError = RegEnumKeyExW(hClassesKey,
-                              dwIndex,
-                              szKeyName,
-                              &dwLength,
-                              NULL,
-                              NULL,
-                              NULL,
-                              NULL);
-       TRACE("RegEnumKeyExW() returns %ld\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;
-           }
-
-           dwLength = 256 * sizeof(WCHAR);
-           if (!RegQueryValueExW(hClassKey,
-                                 Class,
-                                 NULL,
-                                 NULL,
-                                 (LPBYTE)szClassName,
-                                 &dwLength))
-           {
-               TRACE("Class name: %s\n", debugstr_w(szClassName));
-
-               if (strcmpiW(szClassName, ClassName) == 0)
-               {
-                   TRACE("Found matching class name\n");
-
-                   TRACE("Guid: %s\n", debugstr_w(szKeyName));
-                   if (dwGuidListIndex < ClassGuidListSize)
-                   {
-                       if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
-                       {
-                           szKeyName[37] = 0;
-                       }
-                       TRACE("Guid: %s\n", debugstr_w(&szKeyName[1]));
-
-                       UuidFromStringW(&szKeyName[1],
-                                       &ClassGuidList[dwGuidListIndex]);
-                   }
-
-                   dwGuidListIndex++;
-               }
-           }
-
-           RegCloseKey(hClassKey);
-       }
-
-       if (lError != ERROR_SUCCESS)
-           break;
-    }
-
-    RegCloseKey(hClassesKey);
+        dwLength = MAX_GUID_STRING_LEN + 1;
+        lError = RegEnumKeyExW(hClassesKey,
+                               dwIndex,
+                               szKeyName,
+                               &dwLength,
+                               NULL,
+                               NULL,
+                               NULL,
+                               NULL);
+        TRACE("RegEnumKeyExW() returns %ld\n", lError);
+        if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
+        {
+            TRACE("Key name: %s\n", debugstr_w(szKeyName));
+
+            if (hClassKey != NULL)
+                RegCloseKey(hClassKey);
+            if (RegOpenKeyExW(hClassesKey,
+                              szKeyName,
+                              0,
+                              KEY_QUERY_VALUE,
+                              &hClassKey) != ERROR_SUCCESS)
+            {
+                goto cleanup;
+            }
+
+            dwLength = 256 * sizeof(WCHAR);
+            if (RegQueryValueExW(hClassKey,
+                                 Class,
+                                 NULL,
+                                 NULL,
+                                 (LPBYTE)szClassName,
+                                 &dwLength) == ERROR_SUCCESS)
+            {
+                TRACE("Class name: %s\n", debugstr_w(szClassName));
+
+                if (strcmpiW(szClassName, ClassName) == 0)
+                {
+                    TRACE("Found matching class name\n");
+
+                    TRACE("Guid: %s\n", debugstr_w(szKeyName));
+                    if (dwGuidListIndex < ClassGuidListSize)
+                    {
+                        if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
+                            szKeyName[37] = 0;
+                        TRACE("Guid: %s\n", debugstr_w(&szKeyName[1]));
+
+                        UuidFromStringW(&szKeyName[1],
+                            &ClassGuidList[dwGuidListIndex]);
+                    }
+
+                    dwGuidListIndex++;
+                }
+            }
+        }
+
+        if (lError != ERROR_SUCCESS)
+            break;
+    }
 
     if (RequiredSize != NULL)
-       *RequiredSize = dwGuidListIndex;
+        *RequiredSize = dwGuidListIndex;
 
     if (ClassGuidListSize < dwGuidListIndex)
-    {
-       SetLastError(ERROR_INSUFFICIENT_BUFFER);
-       return FALSE;
-    }
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    else
+        ret = TRUE;
 
-    return TRUE;
+cleanup:
+    if (hClassesKey != INVALID_HANDLE_VALUE)
+        RegCloseKey(hClassesKey);
+    if (hClassKey != NULL)
+        RegCloseKey(hClassKey);
+    return ret;
 }
 
 /***********************************************************************
  *              SetupDiClassNameFromGuidA  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiClassNameFromGuidA(
-        const GUID* ClassGuid,
-        PSTR ClassName,
-        DWORD ClassNameSize,
-        PDWORD RequiredSize)
+BOOL WINAPI
+SetupDiClassNameFromGuidA(
+    IN CONST GUID* ClassGuid,
+    OUT PSTR ClassName,
+    IN DWORD ClassNameSize,
+    OUT PDWORD RequiredSize OPTIONAL)
 {
   return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
                                      ClassNameSize, RequiredSize,
@@ -513,11 +531,12 @@ BOOL WINAPI SetupDiClassNameFromGuidA(
 /***********************************************************************
  *              SetupDiClassNameFromGuidW  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiClassNameFromGuidW(
-        const GUID* ClassGuid,
-        PWSTR ClassName,
-        DWORD ClassNameSize,
-        PDWORD RequiredSize)
+BOOL WINAPI
+SetupDiClassNameFromGuidW(
+    IN CONST GUID* ClassGuid,
+    OUT PWSTR ClassName,
+    IN DWORD ClassNameSize,
+    OUT PDWORD RequiredSize OPTIONAL)
 {
   return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
                                      ClassNameSize, RequiredSize,
@@ -527,13 +546,14 @@ BOOL WINAPI SetupDiClassNameFromGuidW(
 /***********************************************************************
  *              SetupDiClassNameFromGuidExA  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiClassNameFromGuidExA(
-        const GUID* ClassGuid,
-        PSTR ClassName,
-        DWORD ClassNameSize,
-        PDWORD RequiredSize,
-        PCSTR MachineName,
-        PVOID Reserved)
+BOOL WINAPI
+SetupDiClassNameFromGuidExA(
+    IN CONST GUID* ClassGuid,
+    OUT PSTR ClassName,
+    IN DWORD ClassNameSize,
+    OUT PDWORD RequiredSize OPTIONAL,
+    IN PCSTR MachineName OPTIONAL,
+    IN PVOID Reserved)
 {
     WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
     LPWSTR MachineNameW = NULL;
@@ -542,7 +562,7 @@ BOOL WINAPI SetupDiClassNameFromGuidExA(
     if (MachineName)
         MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
     ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
-     NULL, MachineNameW, Reserved);
+        NULL, MachineNameW, Reserved);
     if (ret)
     {
         int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
@@ -558,17 +578,19 @@ BOOL WINAPI SetupDiClassNameFromGuidExA(
 /***********************************************************************
  *             SetupDiClassNameFromGuidExW  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiClassNameFromGuidExW(
-        const GUID* ClassGuid,
-        PWSTR ClassName,
-        DWORD ClassNameSize,
-        PDWORD RequiredSize,
-        PCWSTR MachineName,
-        PVOID Reserved)
+BOOL WINAPI
+SetupDiClassNameFromGuidExW(
+    IN CONST GUID* ClassGuid,
+    OUT PWSTR ClassName,
+    IN DWORD ClassNameSize,
+    OUT PDWORD RequiredSize OPTIONAL,
+    IN PCWSTR MachineName OPTIONAL,
+    IN PVOID Reserved)
 {
     HKEY hKey;
     DWORD dwLength;
     LONG rc;
+    BOOL ret = FALSE;
 
     TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName,
         ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved);
@@ -579,54 +601,54 @@ BOOL WINAPI SetupDiClassNameFromGuidExW(
                                      MachineName,
                                      Reserved);
     if (hKey == INVALID_HANDLE_VALUE)
-    {
-       return FALSE;
-    }
+        goto cleanup;
 
     if (RequiredSize != NULL)
     {
-       dwLength = 0;
-       rc = RegQueryValueExW(hKey,
-                            Class,
-                            NULL,
-                            NULL,
-                            NULL,
-                            &dwLength);
-       if (rc != ERROR_SUCCESS)
-       {
-           SetLastError(rc);
-           RegCloseKey(hKey);
-           return FALSE;
-       }
+        dwLength = 0;
+        rc = RegQueryValueExW(hKey,
+                              Class,
+                              NULL,
+                              NULL,
+                              NULL,
+                              &dwLength);
+        if (rc != ERROR_SUCCESS)
+        {
+            SetLastError(rc);
+            goto cleanup;
+        }
 
-       *RequiredSize = dwLength / sizeof(WCHAR);
+        *RequiredSize = dwLength / sizeof(WCHAR);
     }
 
     dwLength = ClassNameSize * sizeof(WCHAR);
     rc = RegQueryValueExW(hKey,
-                        Class,
-                        NULL,
-                        NULL,
-                        (LPBYTE)ClassName,
-                        &dwLength);
+                          Class,
+                          NULL,
+                          NULL,
+                          (LPBYTE)ClassName,
+                          &dwLength);
     if (rc != ERROR_SUCCESS)
     {
-       SetLastError(rc);
-       RegCloseKey(hKey);
-       return FALSE;
+        SetLastError(rc);
+        goto cleanup;
     }
 
-    RegCloseKey(hKey);
+    ret = TRUE;
 
-    return TRUE;
+cleanup:
+    if (hKey != INVALID_HANDLE_VALUE)
+        RegCloseKey(hKey);
+    return ret;
 }
 
 /***********************************************************************
  *             SetupDiCreateDeviceInfoList (SETUPAPI.@)
  */
 HDEVINFO WINAPI
-SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
-                           HWND hwndParent)
+SetupDiCreateDeviceInfoList(
+    IN CONST GUID *ClassGuid OPTIONAL,
+    IN HWND hwndParent OPTIONAL)
 {
   return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
 }
@@ -635,10 +657,11 @@ SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
  *             SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
  */
 HDEVINFO WINAPI
-SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
-                              HWND hwndParent,
-                              PCSTR MachineName,
-                              PVOID Reserved)
+SetupDiCreateDeviceInfoListExA(
+    IN CONST GUID *ClassGuid OPTIONAL,
+    IN HWND hwndParent OPTIONAL,
+    IN PCSTR MachineName OPTIONAL,
+    IN PVOID Reserved)
 {
     LPWSTR MachineNameW = NULL;
     HDEVINFO hDevInfo;
@@ -667,12 +690,24 @@ GetErrorCodeFromCrCode(const IN CONFIGRET cr)
 {
   switch (cr)
   {
-    case CR_INVALID_MACHINENAME: return ERROR_INVALID_COMPUTERNAME;
-    case CR_OUT_OF_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
-    case CR_SUCCESS: return ERROR_SUCCESS;
-    default:
-      /* FIXME */
-      return ERROR_GEN_FAILURE;
+    case CR_ACCESS_DENIED:        return ERROR_ACCESS_DENIED;
+    case CR_BUFFER_SMALL:         return ERROR_INSUFFICIENT_BUFFER;
+    case CR_CALL_NOT_IMPLEMENTED: return ERROR_CALL_NOT_IMPLEMENTED;
+    case CR_FAILURE:              return ERROR_GEN_FAILURE;
+    case CR_INVALID_DATA:         return ERROR_INVALID_USER_BUFFER;
+    case CR_INVALID_DEVICE_ID:    return ERROR_INVALID_PARAMETER;
+    case CR_INVALID_MACHINENAME:  return ERROR_INVALID_COMPUTERNAME;
+    case CR_INVALID_DEVNODE:      return ERROR_INVALID_PARAMETER;
+    case CR_INVALID_FLAG:         return ERROR_INVALID_FLAGS;
+    case CR_INVALID_POINTER:      return ERROR_INVALID_PARAMETER;
+    case CR_INVALID_PROPERTY:     return ERROR_INVALID_PARAMETER;
+    case CR_NO_SUCH_DEVNODE:      return ERROR_FILE_NOT_FOUND;
+    case CR_NO_SUCH_REGISTRY_KEY: return ERROR_FILE_NOT_FOUND;
+    case CR_NO_SUCH_VALUE:        return ERROR_FILE_NOT_FOUND;
+    case CR_OUT_OF_MEMORY:        return ERROR_NOT_ENOUGH_MEMORY;
+    case CR_REGISTRY_ERROR:       return ERROR_GEN_FAILURE;
+    case CR_SUCCESS:              return ERROR_SUCCESS;
+    default:                      return ERROR_GEN_FAILURE;
   }
 
   /* Does not happen */
@@ -682,10 +717,11 @@ GetErrorCodeFromCrCode(const IN CONFIGRET cr)
  *             SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
  */
 HDEVINFO WINAPI
-SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
-                              HWND hwndParent,
-                              PCWSTR MachineName,
-                              PVOID Reserved)
+SetupDiCreateDeviceInfoListExW(
+    IN CONST GUID *ClassGuid OPTIONAL,
+    IN HWND hwndParent OPTIONAL,
+    IN PCWSTR MachineName OPTIONAL,
+    IN PVOID Reserved)
 {
   struct DeviceInfoSet *list;
   LPWSTR UNCServerName = NULL;
@@ -699,7 +735,7 @@ SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
 
   size = FIELD_OFFSET(struct DeviceInfoSet, szData);
   if (MachineName)
-    size += (wcslen(MachineName) + 3) * sizeof(WCHAR);
+    size += (strlenW(MachineName) + 3) * sizeof(WCHAR);
   list = HeapAlloc(GetProcessHeap(), 0, size);
   if (!list)
   {
@@ -767,21 +803,26 @@ SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
 cleanup:
   if (ret == INVALID_HANDLE_VALUE)
   {
-    if (list && list->HKLM != 0 && list->HKLM != HKEY_LOCAL_MACHINE)
-      RegCloseKey(list->HKLM);
+    if (list)
+    {
+      if (list->HKLM != NULL && list->HKLM != HKEY_LOCAL_MACHINE)
+        RegCloseKey(list->HKLM);
+    }
     HeapFree(GetProcessHeap(), 0, list);
   }
-  HeapFree(GetProcessHeap(), 0, UNCServerName);
+  if (UNCServerName)
+    HeapFree(GetProcessHeap(), 0, UNCServerName);
   return ret;
 }
 
 /***********************************************************************
  *             SetupDiEnumDeviceInfo (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiEnumDeviceInfo(
-        HDEVINFO DeviceInfoSet,
-        DWORD MemberIndex,
-        PSP_DEVINFO_DATA DeviceInfoData)
+BOOL WINAPI
+SetupDiEnumDeviceInfo(
+    IN HDEVINFO DeviceInfoSet,
+    IN DWORD MemberIndex,
+    OUT PSP_DEVINFO_DATA DeviceInfoData)
 {
     BOOL ret = FALSE;
 
@@ -805,7 +846,7 @@ BOOL WINAPI SetupDiEnumDeviceInfo(
                 SetLastError(ERROR_NO_MORE_ITEMS);
             else
             {
-                struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)ItemList;
+                struct DeviceInfoElement *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfoElement, ListEntry);
                 memcpy(&DeviceInfoData->ClassGuid,
                     &DevInfo->ClassGuid,
                     sizeof(GUID));
@@ -825,12 +866,12 @@ BOOL WINAPI SetupDiEnumDeviceInfo(
  */
 BOOL WINAPI
 SetupDiGetActualSectionToInstallA(
-        IN HINF InfHandle,
-        IN PCSTR InfSectionName,
-        OUT PSTR InfSectionWithExt OPTIONAL,
-        IN DWORD InfSectionWithExtSize,
-        OUT PDWORD RequiredSize OPTIONAL,
-        OUT PSTR *Extension OPTIONAL)
+    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,
@@ -842,12 +883,12 @@ SetupDiGetActualSectionToInstallA(
  */
 BOOL WINAPI
 SetupDiGetActualSectionToInstallW(
-        IN HINF InfHandle,
-        IN PCWSTR InfSectionName,
-        OUT PWSTR InfSectionWithExt OPTIONAL,
-        IN DWORD InfSectionWithExtSize,
-        OUT PDWORD RequiredSize OPTIONAL,
-        OUT PWSTR *Extension OPTIONAL)
+    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,
@@ -859,14 +900,14 @@ SetupDiGetActualSectionToInstallW(
  */
 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)
+    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;
@@ -916,19 +957,304 @@ cleanup:
     return bResult;
 }
 
+/* Lower scores are best ones */
+static BOOL
+CheckSectionValid(
+    IN LPCWSTR SectionName,
+    IN PSP_ALTPLATFORM_INFO PlatformInfo,
+    IN BYTE ProductType,
+    IN WORD SuiteMask,
+    OUT PDWORD ScorePlatform,
+    OUT PDWORD ScoreMajorVersion,
+    OUT PDWORD ScoreMinorVersion,
+    OUT PDWORD ScoreProductType,
+    OUT PDWORD ScoreSuiteMask)
+{
+    LPWSTR Section = NULL;
+    LPCWSTR pExtensionPlatform, pExtensionArchitecture;
+    LPWSTR Fields[6];
+    DWORD i;
+    BOOL ret = FALSE;
+
+    TRACE("%s %p 0x%x 0x%x\n",
+        debugstr_w(SectionName), PlatformInfo, ProductType, SuiteMask);
+
+    static const WCHAR ExtensionPlatformNone[]  = {'.',0};
+    static const WCHAR ExtensionPlatformNT[]  = {'.','N','T',0};
+    static const WCHAR ExtensionPlatformWindows[]  = {'.','W','i','n',0};
+
+    static const WCHAR ExtensionArchitectureNone[]  = {0};
+    static const WCHAR ExtensionArchitecturealpha[]  = {'a','l','p','h','a',0};
+    static const WCHAR ExtensionArchitectureamd64[]  = {'a','m','d','6','4',0};
+    static const WCHAR ExtensionArchitectureia64[]  = {'i','a','6','4',0};
+    static const WCHAR ExtensionArchitecturemips[]  = {'m','i','p','s',0};
+    static const WCHAR ExtensionArchitectureppc[]  = {'p','p','c',0};
+    static const WCHAR ExtensionArchitecturex86[]  = {'x','8','6',0};
+
+    *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = 0;
+
+    Section = DuplicateString(SectionName);
+    if (!Section)
+    {
+        TRACE("DuplicateString() failed\n");
+        goto cleanup;
+    }
+
+    /* Set various extensions values */
+    switch (PlatformInfo->Platform)
+    {
+        case VER_PLATFORM_WIN32_WINDOWS:
+            pExtensionPlatform = ExtensionPlatformWindows;
+            break;
+        case VER_PLATFORM_WIN32_NT:
+            pExtensionPlatform = ExtensionPlatformNT;
+            break;
+        default:
+            ERR("Unkown platform 0x%lx\n", PlatformInfo->Platform);
+            pExtensionPlatform = ExtensionPlatformNone;
+            break;
+    }
+    switch (PlatformInfo->ProcessorArchitecture)
+    {
+        case PROCESSOR_ARCHITECTURE_ALPHA:
+            pExtensionArchitecture = ExtensionArchitecturealpha;
+            break;
+        case PROCESSOR_ARCHITECTURE_AMD64:
+            pExtensionArchitecture = ExtensionArchitectureamd64;
+            break;
+        case PROCESSOR_ARCHITECTURE_IA64:
+            pExtensionArchitecture = ExtensionArchitectureia64;
+            break;
+        case PROCESSOR_ARCHITECTURE_INTEL:
+            pExtensionArchitecture = ExtensionArchitecturex86;
+            break;
+        case PROCESSOR_ARCHITECTURE_MIPS:
+            pExtensionArchitecture = ExtensionArchitecturemips;
+            break;
+        case PROCESSOR_ARCHITECTURE_PPC:
+            pExtensionArchitecture = ExtensionArchitectureppc;
+            break;
+        default:
+            ERR("Unknown processor architecture 0x%x\n", PlatformInfo->ProcessorArchitecture);
+        case PROCESSOR_ARCHITECTURE_UNKNOWN:
+            pExtensionArchitecture = ExtensionArchitectureNone;
+            break;
+    }
+
+    /*
+     * Field[0] Platform
+     * Field[1] Architecture
+     * Field[2] Major version
+     * Field[3] Minor version
+     * Field[4] Product type
+     * Field[5] Suite mask
+     * Remark: lastests fields may be NULL if the information is not provided
+     */
+    Fields[0] = strchrW(Section, '.');
+    if (Fields[0] == NULL)
+    {
+        TRACE("No extension found\n");
+        *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = ULONG_MAX;
+        ret = TRUE;
+        goto cleanup;
+    }
+    Fields[1] = Fields[0] + 1;
+    Fields[2] = Fields[3] = Fields[4] = Fields[5] = NULL;
+    for (i = 2; Fields[i - 1] != NULL && i < 6; i++)
+    {
+        Fields[i] = wcschr(Fields[i - 1], '.');
+        if (Fields[i])
+        {
+            Fields[i]++;
+            *(Fields[i] - 1) = L'\0';
+        }
+    }
+    /* Take care of first 2 fields */
+    if (strncmpiW(Fields[0], ExtensionPlatformWindows, strlenW(ExtensionPlatformWindows)) == 0)
+    {
+        if (PlatformInfo->Platform != VER_PLATFORM_WIN32_WINDOWS)
+        {
+            TRACE("Mismatch on platform field\n");
+            goto cleanup;
+        }
+        Fields[1] += wcslen(ExtensionPlatformWindows) - 1;
+    }
+    else if (strncmpiW(Fields[0], ExtensionPlatformNT, strlenW(ExtensionPlatformNT)) == 0)
+    {
+        if (PlatformInfo->Platform != VER_PLATFORM_WIN32_NT)
+        {
+            TRACE("Mismatch on platform field\n");
+            goto cleanup;
+        }
+        Fields[1] += wcslen(ExtensionPlatformNT) - 1;
+    }
+    else
+    {
+        /* No platform specified */
+        *ScorePlatform |= 0x02;
+    }
+    if (strcmpiW(Fields[1], ExtensionArchitectureNone) == 0)
+    {
+        /* No architecture specified */
+        *ScorePlatform |= 0x01;
+    }
+    else if (strcmpiW(Fields[1], pExtensionArchitecture) != 0)
+    {
+        TRACE("Mismatch on architecture field ('%s' and '%s')\n",
+            debugstr_w(Fields[1]), debugstr_w(pExtensionArchitecture));
+        goto cleanup;
+    }
+
+    /* Check if informations are matching */
+    if (Fields[2] && *Fields[2])
+    {
+        DWORD MajorVersion, MinorVersion = 0;
+        MajorVersion = strtoulW(Fields[2], NULL, 0);
+        if ((MajorVersion == 0 || MajorVersion == ULONG_MAX) &&
+            (errno == ERANGE || errno == EINVAL))
+        {
+            TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields[2]));
+            goto cleanup;
+        }
+        if (Fields[3] && *Fields[3])
+        {
+            MinorVersion = strtoulW(Fields[3], NULL, 0);
+            if ((MinorVersion == 0 || MinorVersion == ULONG_MAX) &&
+                (errno == ERANGE || errno == EINVAL))
+            {
+                TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields[3]));
+                goto cleanup;
+            }
+        }
+        if (PlatformInfo->MajorVersion < MajorVersion ||
+            (PlatformInfo->MajorVersion == MajorVersion && PlatformInfo->MinorVersion < MinorVersion))
+        {
+            TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
+                MajorVersion, MinorVersion, PlatformInfo->MajorVersion, PlatformInfo->MinorVersion);
+            goto cleanup;
+        }
+        *ScoreMajorVersion = MajorVersion - PlatformInfo->MajorVersion;
+        if (MajorVersion == PlatformInfo->MajorVersion)
+            *ScoreMinorVersion = MinorVersion - PlatformInfo->MinorVersion;
+        else
+            *ScoreMinorVersion = MinorVersion;
+    }
+    else if (Fields[3] && *Fields[3])
+    {
+        TRACE("Minor version found without major version\n");
+        goto cleanup;
+    }
+    else
+    {
+        *ScoreMajorVersion = PlatformInfo->MajorVersion;
+        *ScoreMinorVersion = PlatformInfo->MinorVersion;
+    }
+
+    if (Fields[4] && *Fields[4])
+    {
+        DWORD CurrentProductType;
+        CurrentProductType = strtoulW(Fields[4], NULL, 0);
+        if ((CurrentProductType == 0 || CurrentProductType == ULONG_MAX) &&
+            (errno == ERANGE || errno == EINVAL))
+        {
+            TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields[4]));
+            goto cleanup;
+        }
+        if (CurrentProductType != ProductType)
+        {
+            TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
+                CurrentProductType, ProductType);
+            goto cleanup;
+        }
+    }
+    else
+        *ScoreProductType = 1;
+
+    if (Fields[5] && *Fields[5])
+    {
+        DWORD CurrentSuiteMask;
+        CurrentSuiteMask = strtoulW(Fields[5], NULL, 0);
+        if ((CurrentSuiteMask == 0 || CurrentSuiteMask == ULONG_MAX) &&
+            (errno == ERANGE || errno == EINVAL))
+        {
+            TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields[5]));
+            goto cleanup;
+        }
+        if ((CurrentSuiteMask & ~SuiteMask) != 0)
+        {
+            TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
+                CurrentSuiteMask, SuiteMask);
+            goto cleanup;
+        }
+        *ScoreSuiteMask = SuiteMask & ~CurrentSuiteMask;
+    }
+    else
+        *ScoreSuiteMask = SuiteMask;
+
+    ret = TRUE;
+
+cleanup:
+    MyFree(Section);
+    return ret;
+}
+
+static BOOL
+GetSectionCallback(
+    IN LPCWSTR SectionName,
+    IN PVOID Context)
+{
+    struct GetSectionCallbackInfo *info = Context;
+    DWORD Score1, Score2, Score3, Score4, Score5;
+    BOOL ret;
+
+    ret = CheckSectionValid(
+        SectionName,
+        info->PlatformInfo,
+        info->ProductType,
+        info->SuiteMask,
+        &Score1, &Score2, &Score3, &Score4, &Score5);
+    if (!ret)
+    {
+        TRACE("Section %s not compatible\n", debugstr_w(SectionName));
+        return TRUE;
+    }
+    if (Score1 > info->BestScore1) goto done;
+    if (Score1 < info->BestScore1) goto bettersection;
+    if (Score2 > info->BestScore2) goto done;
+    if (Score2 < info->BestScore2) goto bettersection;
+    if (Score3 > info->BestScore3) goto done;
+    if (Score3 < info->BestScore3) goto bettersection;
+    if (Score4 > info->BestScore4) goto done;
+    if (Score4 < info->BestScore4) goto bettersection;
+    if (Score5 > info->BestScore5) goto done;
+    if (Score5 < info->BestScore5) goto bettersection;
+    goto done;
+
+bettersection:
+    strcpyW(info->BestSection, SectionName);
+    info->BestScore1 = Score1;
+    info->BestScore2 = Score2;
+    info->BestScore3 = Score3;
+    info->BestScore4 = Score4;
+    info->BestScore5 = Score5;
+
+done:
+    return TRUE;
+}
+
 /***********************************************************************
  *             SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
  */
 BOOL WINAPI
 SetupDiGetActualSectionToInstallExW(
-        IN HINF InfHandle,
-        IN PCWSTR InfSectionName,
-        IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
-        OUT PWSTR InfSectionWithExt OPTIONAL,
-        IN DWORD InfSectionWithExtSize,
-        OUT PDWORD RequiredSize OPTIONAL,
-        OUT PWSTR* Extension OPTIONAL,
-        IN PVOID Reserved)
+    IN HINF InfHandle,
+    IN PCWSTR InfSectionName,
+    IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
+    OUT PWSTR InfSectionWithExt OPTIONAL,
+    IN DWORD InfSectionWithExtSize,
+    OUT PDWORD RequiredSize OPTIONAL,
+    OUT PWSTR* Extension OPTIONAL,
+    IN PVOID Reserved)
 {
     BOOL ret = FALSE;
 
@@ -947,154 +1273,84 @@ SetupDiGetActualSectionToInstallExW(
     else
     {
         static SP_ALTPLATFORM_INFO CurrentPlatform = { 0, };
+        static BYTE CurrentProductType = 0;
+        static WORD CurrentSuiteMask = 0;
         PSP_ALTPLATFORM_INFO pPlatformInfo = &CurrentPlatform;
-        LPCWSTR pExtensionPlatform, pExtensionArchitecture;
-        WCHAR SectionName[LINE_LEN + 1];
-        LONG lLineCount = -1;
+        struct GetSectionCallbackInfo CallbackInfo;
         DWORD dwFullLength;
+        BYTE ProductType;
+        WORD SuiteMask;
 
         /* Fill platform info if needed */
         if (AlternatePlatformInfo)
-            pPlatformInfo = AlternatePlatformInfo;
-        else if (CurrentPlatform.cbSize != sizeof(SP_ALTPLATFORM_INFO))
         {
-            /* That's the first time we go here. We need to fill in the structure */
-            OSVERSIONINFO VersionInfo;
-            SYSTEM_INFO SystemInfo;
-            VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-            ret = GetVersionEx(&VersionInfo);
-            if (!ret)
-                goto done;
-            GetSystemInfo(&SystemInfo);
-            CurrentPlatform.cbSize = sizeof(SP_ALTPLATFORM_INFO);
-            CurrentPlatform.Platform = VersionInfo.dwPlatformId;
-            CurrentPlatform.MajorVersion = VersionInfo.dwMajorVersion;
-            CurrentPlatform.MinorVersion = VersionInfo.dwMinorVersion;
-            CurrentPlatform.ProcessorArchitecture = SystemInfo.wProcessorArchitecture;
-            CurrentPlatform.Reserved = 0;
-        }
-
-static const WCHAR ExtensionPlatformNone[]  = {'.',0};
-static const WCHAR ExtensionPlatformNT[]  = {'.','N','T',0};
-static const WCHAR ExtensionPlatformWindows[]  = {'.','W','i','n',0};
-
-static const WCHAR ExtensionArchitectureNone[]  = {0};
-static const WCHAR ExtensionArchitecturealpha[]  = {'a','l','p','h','a',0};
-static const WCHAR ExtensionArchitectureamd64[]  = {'a','m','d','6','4',0};
-static const WCHAR ExtensionArchitectureia64[]  = {'i','a','6','4',0};
-static const WCHAR ExtensionArchitecturemips[]  = {'m','i','p','s',0};
-static const WCHAR ExtensionArchitectureppc[]  = {'p','p','c',0};
-static const WCHAR ExtensionArchitecturex86[]  = {'x','8','6',0};
-
-        /* Set various extensions values */
-        switch (pPlatformInfo->Platform)
-        {
-            case VER_PLATFORM_WIN32_WINDOWS:
-                pExtensionPlatform = ExtensionPlatformWindows;
-                break;
-            case VER_PLATFORM_WIN32_NT:
-                pExtensionPlatform = ExtensionPlatformNT;
-                break;
-            default:
-                ERR("Unkown platform 0x%lx\n", pPlatformInfo->Platform);
-                pExtensionPlatform = ExtensionPlatformNone;
-                break;
+            pPlatformInfo = AlternatePlatformInfo;
+            ProductType = 0;
+            SuiteMask = 0;
         }
-        switch (pPlatformInfo->ProcessorArchitecture)
+        else
         {
-            case PROCESSOR_ARCHITECTURE_ALPHA:
-                pExtensionArchitecture = ExtensionArchitecturealpha;
-                break;
-            case PROCESSOR_ARCHITECTURE_AMD64:
-                pExtensionArchitecture = ExtensionArchitectureamd64;
-                break;
-            case PROCESSOR_ARCHITECTURE_IA64:
-                pExtensionArchitecture = ExtensionArchitectureia64;
-                break;
-            case PROCESSOR_ARCHITECTURE_INTEL:
-                pExtensionArchitecture = ExtensionArchitecturex86;
-                break;
-            case PROCESSOR_ARCHITECTURE_MIPS:
-                pExtensionArchitecture = ExtensionArchitecturemips;
-                break;
-            case PROCESSOR_ARCHITECTURE_PPC:
-                pExtensionArchitecture = ExtensionArchitectureppc;
-                break;
-            default:
-                ERR("Unknown processor architecture 0x%x\n", pPlatformInfo->ProcessorArchitecture);
-            case PROCESSOR_ARCHITECTURE_UNKNOWN:
-                pExtensionArchitecture = ExtensionArchitectureNone;
-                break;
+            if (CurrentPlatform.cbSize != sizeof(SP_ALTPLATFORM_INFO))
+            {
+                /* That's the first time we go here. We need to fill in the structure */
+                OSVERSIONINFOEX VersionInfo;
+                SYSTEM_INFO SystemInfo;
+                VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+                ret = GetVersionEx((POSVERSIONINFO)&VersionInfo);
+                if (!ret)
+                    goto done;
+                GetSystemInfo(&SystemInfo);
+                CurrentPlatform.cbSize = sizeof(SP_ALTPLATFORM_INFO);
+                CurrentPlatform.Platform = VersionInfo.dwPlatformId;
+                CurrentPlatform.MajorVersion = VersionInfo.dwMajorVersion;
+                CurrentPlatform.MinorVersion = VersionInfo.dwMinorVersion;
+                CurrentPlatform.ProcessorArchitecture = SystemInfo.wProcessorArchitecture;
+                CurrentPlatform.Reserved = 0;
+                CurrentProductType = VersionInfo.wProductType;
+                CurrentSuiteMask = VersionInfo.wSuiteMask;
+            }
+            ProductType = CurrentProductType;
+            SuiteMask = CurrentSuiteMask;
+        }
+
+        CallbackInfo.PlatformInfo = pPlatformInfo;
+        CallbackInfo.ProductType = ProductType;
+        CallbackInfo.SuiteMask = SuiteMask;
+        CallbackInfo.BestScore1 = ULONG_MAX;
+        CallbackInfo.BestScore2 = ULONG_MAX;
+        CallbackInfo.BestScore3 = ULONG_MAX;
+        CallbackInfo.BestScore4 = ULONG_MAX;
+        CallbackInfo.BestScore5 = ULONG_MAX;
+        strcpyW(CallbackInfo.BestSection, InfSectionName);
+        if (!EnumerateSectionsStartingWith(
+            InfHandle,
+            InfSectionName,
+            GetSectionCallback,
+            &CallbackInfo))
+        {
+            SetLastError(ERROR_GEN_FAILURE);
+            goto done;
         }
 
-        SectionName[LINE_LEN] = UNICODE_NULL;
-
-        /* Test with platform.architecture.major.minor extension */
-        snprintfW(SectionName, LINE_LEN, L"%s%s%s.%lu.%lu", InfSectionName,
-            pExtensionPlatform, pExtensionArchitecture, pPlatformInfo->MajorVersion, pPlatformInfo->MinorVersion);
-        lLineCount = SetupGetLineCountW(InfHandle, SectionName);
-        if (lLineCount != -1) goto sectionfound;
-
-        /* Test with platform.major.minor extension */
-        snprintfW(SectionName, LINE_LEN, L"%s%s.%lu.%lu", InfSectionName,
-            pExtensionPlatform, pPlatformInfo->MajorVersion, pPlatformInfo->MinorVersion);
-        lLineCount = SetupGetLineCountW(InfHandle, SectionName);
-        if (lLineCount != -1) goto sectionfound;
-
-        /* Test with platform.architecture.major extension */
-        snprintfW(SectionName, LINE_LEN, L"%s%s%s.%lu", InfSectionName,
-            pExtensionPlatform, pExtensionArchitecture, pPlatformInfo->MajorVersion);
-        lLineCount = SetupGetLineCountW(InfHandle, SectionName);
-        if (lLineCount != -1) goto sectionfound;
-
-        /* Test with platform.major extension */
-        snprintfW(SectionName, LINE_LEN, L"%s%s.%lu", InfSectionName,
-            pExtensionPlatform, pPlatformInfo->MajorVersion);
-        lLineCount = SetupGetLineCountW(InfHandle, SectionName);
-        if (lLineCount != -1) goto sectionfound;
-
-        /* Test with platform.architecture extension */
-        snprintfW(SectionName, LINE_LEN, L"%s%s%s", InfSectionName,
-            pExtensionPlatform, pExtensionArchitecture);
-        lLineCount = SetupGetLineCountW(InfHandle, SectionName);
-        if (lLineCount != -1) goto sectionfound;
-
-        /* Test with platform extension */
-        snprintfW(SectionName, LINE_LEN, L"%s%s", InfSectionName,
-            pExtensionPlatform);
-        lLineCount = SetupGetLineCountW(InfHandle, SectionName);
-        if (lLineCount != -1) goto sectionfound;
-
-        /* Test without extension */
-        snprintfW(SectionName, LINE_LEN, L"%s", InfSectionName);
-        lLineCount = SetupGetLineCountW(InfHandle, SectionName);
-        if (lLineCount != -1) goto sectionfound;
-
-        /* No appropriate section found */
-        SetLastError(ERROR_INVALID_PARAMETER);
-        goto done;
+        dwFullLength = lstrlenW(CallbackInfo.BestSection);
+        if (RequiredSize != NULL)
+            *RequiredSize = dwFullLength + 1;
 
-sectionfound:
-        dwFullLength = lstrlenW(SectionName);
-        if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
+        if (InfSectionWithExtSize > 0)
         {
-            if (InfSectionWithExtSize < (dwFullLength + 1))
+            if (InfSectionWithExtSize < dwFullLength + 1)
             {
                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
                 goto done;
             }
-
-            lstrcpyW(InfSectionWithExt, SectionName);
-            if (Extension != NULL)
+            strcpyW(InfSectionWithExt, CallbackInfo.BestSection);
+            if (Extension)
             {
-                DWORD dwLength = lstrlenW(SectionName);
+                DWORD dwLength = lstrlenW(InfSectionName);
                 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
             }
         }
 
-        if (RequiredSize != NULL)
-            *RequiredSize = dwFullLength + 1;
-
         ret = TRUE;
     }
 
@@ -1107,11 +1363,12 @@ done:
 /***********************************************************************
  *             SetupDiGetClassDescriptionA  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetClassDescriptionA(
-        const GUID* ClassGuid,
-        PSTR ClassDescription,
-        DWORD ClassDescriptionSize,
-        PDWORD RequiredSize)
+BOOL WINAPI
+SetupDiGetClassDescriptionA(
+    IN CONST GUID *ClassGuid,
+    OUT PSTR ClassDescription,
+    IN DWORD ClassDescriptionSize,
+    OUT PDWORD RequiredSize OPTIONAL)
 {
   return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
                                        ClassDescriptionSize,
@@ -1121,11 +1378,12 @@ BOOL WINAPI SetupDiGetClassDescriptionA(
 /***********************************************************************
  *             SetupDiGetClassDescriptionW  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetClassDescriptionW(
-        const GUID* ClassGuid,
-        PWSTR ClassDescription,
-        DWORD ClassDescriptionSize,
-        PDWORD RequiredSize)
+BOOL WINAPI
+SetupDiGetClassDescriptionW(
+    IN CONST GUID *ClassGuid,
+    OUT PWSTR ClassDescription,
+    IN DWORD ClassDescriptionSize,
+    OUT PDWORD RequiredSize OPTIONAL)
 {
   return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
                                        ClassDescriptionSize,
@@ -1135,13 +1393,14 @@ BOOL WINAPI SetupDiGetClassDescriptionW(
 /***********************************************************************
  *             SetupDiGetClassDescriptionExA  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetClassDescriptionExA(
-        const GUID* ClassGuid,
-        PSTR ClassDescription,
-        DWORD ClassDescriptionSize,
-        PDWORD RequiredSize,
-        PCSTR MachineName,
-        PVOID Reserved)
+BOOL WINAPI
+SetupDiGetClassDescriptionExA(
+    IN CONST GUID *ClassGuid,
+    OUT PSTR ClassDescription,
+    IN DWORD ClassDescriptionSize,
+    OUT PDWORD RequiredSize OPTIONAL,
+    IN PCSTR MachineName OPTIONAL,
+    IN PVOID Reserved)
 {
     PWCHAR ClassDescriptionW;
     LPWSTR MachineNameW = NULL;
@@ -1192,16 +1451,18 @@ end:
 /***********************************************************************
  *             SetupDiGetClassDescriptionExW  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetClassDescriptionExW(
-        const GUID* ClassGuid,
-        PWSTR ClassDescription,
-        DWORD ClassDescriptionSize,
-        PDWORD RequiredSize,
-        PCWSTR MachineName,
-        PVOID Reserved)
+BOOL WINAPI
+SetupDiGetClassDescriptionExW(
+    IN CONST GUID *ClassGuid,
+    OUT PWSTR ClassDescription,
+    IN DWORD ClassDescriptionSize,
+    OUT PDWORD RequiredSize OPTIONAL,
+    IN PCWSTR MachineName OPTIONAL,
+    IN PVOID Reserved)
 {
-    HKEY hKey;
+    HKEY hKey = INVALID_HANDLE_VALUE;
     DWORD dwLength;
+    BOOL ret = FALSE;
 
     TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
         ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved);
@@ -1213,109 +1474,114 @@ BOOL WINAPI SetupDiGetClassDescriptionExW(
                                      Reserved);
     if (hKey == INVALID_HANDLE_VALUE)
     {
-       WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
-       return FALSE;
+        WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
+        goto cleanup;
     }
 
     if (RequiredSize != NULL)
     {
-       dwLength = 0;
-       if (RegQueryValueExW(hKey,
-                            NULL,
-                            NULL,
-                            NULL,
-                            NULL,
-                            &dwLength))
-       {
-           RegCloseKey(hKey);
-           return FALSE;
-       }
+        dwLength = 0;
+        if (RegQueryValueExW(hKey,
+                             NULL,
+                             NULL,
+                             NULL,
+                             NULL,
+                             &dwLength) != ERROR_SUCCESS)
+        {
+            goto cleanup;
+        }
 
-       *RequiredSize = dwLength / sizeof(WCHAR);
+        *RequiredSize = dwLength / sizeof(WCHAR);
     }
 
     dwLength = ClassDescriptionSize * sizeof(WCHAR);
     if (RegQueryValueExW(hKey,
-                        NULL,
-                        NULL,
-                        NULL,
-                        (LPBYTE)ClassDescription,
-                        &dwLength))
+                         NULL,
+                         NULL,
+                         NULL,
+                         (LPBYTE)ClassDescription,
+                         &dwLength) != ERROR_SUCCESS)
     {
-       RegCloseKey(hKey);
-       return FALSE;
+        goto cleanup;
     }
 
-    RegCloseKey(hKey);
+    ret = TRUE;
 
-    return TRUE;
+cleanup:
+    if (hKey != INVALID_HANDLE_VALUE)
+        RegCloseKey(hKey);
+
+    return ret;
 }
 
 /***********************************************************************
  *             SetupDiGetClassDevsA (SETUPAPI.@)
  */
-HDEVINFO WINAPI SetupDiGetClassDevsA(
-       CONST GUID *class,
-       LPCSTR enumstr,
-       HWND parent,
-       DWORD flags)
+HDEVINFO WINAPI
+SetupDiGetClassDevsA(
+    IN CONST GUID *ClassGuid OPTIONAL,
+    IN PCSTR Enumerator OPTIONAL,
+    IN HWND hwndParent OPTIONAL,
+    IN DWORD Flags)
 {
-    return SetupDiGetClassDevsExA(class, enumstr, parent,
-                                  flags, NULL, NULL, NULL);
+    return SetupDiGetClassDevsExA(ClassGuid, Enumerator, hwndParent,
+                                  Flags, NULL, NULL, NULL);
 }
 
 /***********************************************************************
  *             SetupDiGetClassDevsW (SETUPAPI.@)
  */
-HDEVINFO WINAPI SetupDiGetClassDevsW(
-       CONST GUID *class,
-       LPCWSTR enumstr,
-       HWND parent,
-       DWORD flags)
+HDEVINFO WINAPI
+SetupDiGetClassDevsW(
+    IN CONST GUID *ClassGuid OPTIONAL,
+    IN PCWSTR Enumerator OPTIONAL,
+    IN HWND hwndParent OPTIONAL,
+    IN DWORD Flags)
 {
-    return SetupDiGetClassDevsExW(class, enumstr, parent,
-                                  flags, NULL, NULL, NULL);
+    return SetupDiGetClassDevsExW(ClassGuid, Enumerator, hwndParent,
+                                  Flags, NULL, NULL, NULL);
 }
 
 /***********************************************************************
  *             SetupDiGetClassDevsExA (SETUPAPI.@)
  */
-HDEVINFO WINAPI SetupDiGetClassDevsExA(
-       CONST GUID *class,
-       LPCSTR enumstr,
-       HWND parent,
-       DWORD flags,
-       HDEVINFO deviceset,
-       LPCSTR machine,
-       PVOID reserved)
+HDEVINFO WINAPI
+SetupDiGetClassDevsExA(
+    IN CONST GUID *ClassGuid OPTIONAL,
+    IN PCSTR Enumerator OPTIONAL,
+    IN HWND hwndParent OPTIONAL,
+    IN DWORD Flags,
+    IN HDEVINFO DeviceInfoSet OPTIONAL,
+    IN PCSTR MachineName OPTIONAL,
+    IN PVOID Reserved)
 {
     HDEVINFO ret;
     LPWSTR enumstrW = NULL;
     LPWSTR machineW = NULL;
 
-    if (enumstr)
+    if (Enumerator)
     {
-        int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
+        int len = MultiByteToWideChar(CP_ACP, 0, Enumerator, -1, NULL, 0);
         enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
         if (!enumstrW)
         {
             ret = (HDEVINFO)INVALID_HANDLE_VALUE;
             goto end;
         }
-        MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
+        MultiByteToWideChar(CP_ACP, 0, Enumerator, -1, enumstrW, len);
     }
-    if (machine)
+    if (MachineName)
     {
-        int len = MultiByteToWideChar(CP_ACP, 0, machine, -1, NULL, 0);
+        int len = MultiByteToWideChar(CP_ACP, 0, MachineName, -1, NULL, 0);
         machineW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
         if (!machineW)
         {
             ret = (HDEVINFO)INVALID_HANDLE_VALUE;
             goto end;
         }
-        MultiByteToWideChar(CP_ACP, 0, machine, -1, machineW, len);
+        MultiByteToWideChar(CP_ACP, 0, MachineName, -1, machineW, len);
     }
-    ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset, machineW, reserved);
+    ret = SetupDiGetClassDevsExW(ClassGuid, enumstrW, hwndParent, Flags, DeviceInfoSet, machineW, Reserved);
 
 end:
     HeapFree(GetProcessHeap(), 0, enumstrW);
@@ -1336,7 +1602,7 @@ CreateDeviceInfoElement(
 
     *pDeviceInfo = NULL;
 
-    size = FIELD_OFFSET(struct DeviceInfoElement, Data) + (wcslen(InstancePath) + 1) * sizeof(WCHAR);
+    size = FIELD_OFFSET(struct DeviceInfoElement, Data) + (strlenW(InstancePath) + 1) * sizeof(WCHAR);
     deviceInfo = HeapAlloc(GetProcessHeap(), 0, size);
     if (!deviceInfo)
     {
@@ -1353,9 +1619,9 @@ CreateDeviceInfoElement(
     }
 
     deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
-    wcscpy(deviceInfo->Data, InstancePath);
+    strcpyW(deviceInfo->Data, InstancePath);
     deviceInfo->DeviceName = deviceInfo->Data;
-    deviceInfo->UniqueId = wcsrchr(deviceInfo->Data, '\\');
+    deviceInfo->UniqueId = strrchrW(deviceInfo->Data, '\\');
     deviceInfo->DeviceDescription = NULL;
     memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
     deviceInfo->CreationFlags = 0;
@@ -1378,28 +1644,29 @@ CreateDeviceInterface(
     *pDeviceInterface = NULL;
 
     deviceInterface = HeapAlloc(GetProcessHeap(), 0,
-        FIELD_OFFSET(struct DeviceInterface, SymbolicLink) + (wcslen(SymbolicLink) + 1) * sizeof(WCHAR));
+        FIELD_OFFSET(struct DeviceInterface, SymbolicLink) + (strlenW(SymbolicLink) + 1) * sizeof(WCHAR));
     if (!deviceInterface)
     {
         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return FALSE;
     }
     deviceInterface->DeviceInfo = deviceInfo;
-    wcscpy(deviceInterface->SymbolicLink, SymbolicLink);
-    deviceInterface->Flags = 0; /* FIXME */
+    strcpyW(deviceInterface->SymbolicLink, SymbolicLink);
+    deviceInterface->Flags = 0; /* Flags will be updated later */
     memcpy(&deviceInterface->InterfaceClassGuid, pInterfaceGuid, sizeof(GUID));
 
     *pDeviceInterface = deviceInterface;
     return TRUE;
 }
 
-static LONG SETUP_CreateDevListFromEnumerator(
-       struct DeviceInfoSet *list,
-       LPCGUID pClassGuid OPTIONAL,
-       LPCWSTR Enumerator,
-       HKEY hEnumeratorKey) /* handle to Enumerator registry key */
+static LONG
+SETUP_CreateDevListFromEnumerator(
+    struct DeviceInfoSet *list,
+    CONST GUID *pClassGuid OPTIONAL,
+    LPCWSTR Enumerator,
+    HKEY hEnumeratorKey) /* handle to Enumerator registry key */
 {
-    HKEY hDeviceIdKey, hInstanceIdKey;
+    HKEY hDeviceIdKey = NULL, hInstanceIdKey;
     WCHAR KeyBuffer[MAX_PATH];
     WCHAR InstancePath[MAX_PATH];
     LPWSTR pEndOfInstancePath; /* Pointer into InstancePath buffer */
@@ -1416,18 +1683,20 @@ static LONG SETUP_CreateDevListFromEnumerator(
         if (rc == ERROR_NO_MORE_ITEMS)
             break;
         if (rc != ERROR_SUCCESS)
-            return rc;
+            goto cleanup;
         i++;
 
         /* Open device id sub key */
+        if (hDeviceIdKey != NULL)
+            RegCloseKey(hDeviceIdKey);
         rc = RegOpenKeyExW(hEnumeratorKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hDeviceIdKey);
         if (rc != ERROR_SUCCESS)
-            return rc;
-        wcscpy(InstancePath, Enumerator);
-        wcscat(InstancePath, L"\\");
-        wcscat(InstancePath, KeyBuffer);
-        wcscat(InstancePath, L"\\");
-        pEndOfInstancePath = &InstancePath[wcslen(InstancePath)];
+            goto cleanup;
+        strcpyW(InstancePath, Enumerator);
+        strcatW(InstancePath, L"\\");
+        strcatW(InstancePath, KeyBuffer);
+        strcatW(InstancePath, L"\\");
+        pEndOfInstancePath = &InstancePath[strlenW(InstancePath)];
 
         /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
         j = 0;
@@ -1440,21 +1709,15 @@ static LONG SETUP_CreateDevListFromEnumerator(
             if (rc == ERROR_NO_MORE_ITEMS)
                 break;
             if (rc != ERROR_SUCCESS)
-            {
-                RegCloseKey(hDeviceIdKey);
-                return rc;
-            }
+                goto cleanup;
             j++;
 
             /* Open instance id sub key */
             rc = RegOpenKeyExW(hDeviceIdKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hInstanceIdKey);
             if (rc != ERROR_SUCCESS)
-            {
-                RegCloseKey(hDeviceIdKey);
-                return rc;
-            }
+                goto cleanup;
             *pEndOfInstancePath = '\0';
-            wcscat(InstancePath, KeyBuffer);
+            strcatW(InstancePath, KeyBuffer);
 
             /* Read ClassGUID value */
             dwLength = sizeof(KeyBuffer) - sizeof(WCHAR);
@@ -1470,13 +1733,12 @@ static LONG SETUP_CreateDevListFromEnumerator(
             }
             else if (rc != ERROR_SUCCESS)
             {
-                RegCloseKey(hDeviceIdKey);
-                return rc;
+                goto cleanup;
             }
             else if (dwRegType != REG_SZ)
             {
-                RegCloseKey(hDeviceIdKey);
-                return ERROR_GEN_FAILURE;
+                rc = ERROR_GEN_FAILURE;
+                goto cleanup;
             }
             else
             {
@@ -1495,25 +1757,32 @@ static LONG SETUP_CreateDevListFromEnumerator(
             /* Add the entry to the list */
             if (!CreateDeviceInfoElement(list, InstancePath, &KeyGuid, &deviceInfo))
             {
-                RegCloseKey(hDeviceIdKey);
-                return GetLastError();
+                rc = GetLastError();
+                goto cleanup;
             }
-            TRACE("Adding '%S' to device info set %p\n", InstancePath, list);
+            TRACE("Adding '%s' to device info set %p\n", debugstr_w(InstancePath), list);
             InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
         }
-        RegCloseKey(hDeviceIdKey);
     }
 
-    return ERROR_SUCCESS;
+    rc = ERROR_SUCCESS;
+
+cleanup:
+    if (hDeviceIdKey != NULL)
+        RegCloseKey(hDeviceIdKey);
+    return rc;
 }
 
-static LONG SETUP_CreateDevList(
-       struct DeviceInfoSet *list,
-       PCWSTR MachineName OPTIONAL,
-       LPGUID class OPTIONAL,
-       PCWSTR Enumerator OPTIONAL)
+static LONG
+SETUP_CreateDevList(
+    struct DeviceInfoSet *list,
+    PCWSTR MachineName OPTIONAL,
+    CONST GUID *class OPTIONAL,
+    PCWSTR Enumerator OPTIONAL)
 {
-    HKEY HKLM, hEnumKey, hEnumeratorKey;
+    HKEY HKLM = HKEY_LOCAL_MACHINE;
+    HKEY hEnumKey = NULL;
+    HKEY hEnumeratorKey = NULL;
     WCHAR KeyBuffer[MAX_PATH];
     DWORD i;
     DWORD dwLength;
@@ -1522,24 +1791,22 @@ static LONG SETUP_CreateDevList(
     if (class && IsEqualIID(class, &GUID_NULL))
         class = NULL;
 
-    /* Open Enum key */
+    /* Open Enum key (if applicable) */
     if (MachineName != NULL)
     {
         rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM);
         if (rc != ERROR_SUCCESS)
-            return rc;
+            goto cleanup;
     }
-    else
-        HKLM = HKEY_LOCAL_MACHINE;
 
-    rc = RegOpenKeyExW(HKLM,
+    rc = RegOpenKeyExW(
+        HKLM,
         REGSTR_PATH_SYSTEMENUM,
         0,
         KEY_ENUMERATE_SUB_KEYS,
         &hEnumKey);
-    if (MachineName != NULL) RegCloseKey(HKLM);
     if (rc != ERROR_SUCCESS)
-        return rc;
+        goto cleanup;
 
     /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
      * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
@@ -1553,12 +1820,9 @@ static LONG SETUP_CreateDevList(
             0,
             KEY_ENUMERATE_SUB_KEYS,
             &hEnumeratorKey);
-        RegCloseKey(hEnumKey);
         if (rc != ERROR_SUCCESS)
-            return rc;
+            goto cleanup;
         rc = SETUP_CreateDevListFromEnumerator(list, class, Enumerator, hEnumeratorKey);
-        RegCloseKey(hEnumeratorKey);
-        return rc;
     }
     else
     {
@@ -1567,43 +1831,52 @@ static LONG SETUP_CreateDevList(
         while (TRUE)
         {
             dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
-            rc = RegEnumKeyExW(hEnumKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
-            if (rc == ERROR_NO_MORE_ITEMS)
-                break;
-            if (rc != ERROR_SUCCESS)
-            {
-                RegCloseKey(hEnumKey);
-                return rc;
-            }
+            rc = RegEnumKeyExW(hEnumKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
+            if (rc == ERROR_NO_MORE_ITEMS)
+                break;
+            else if (rc != ERROR_SUCCESS)
+                goto cleanup;
             i++;
 
             /* Open sub key */
+            if (hEnumeratorKey != NULL)
+                RegCloseKey(hEnumeratorKey);
             rc = RegOpenKeyExW(hEnumKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hEnumeratorKey);
             if (rc != ERROR_SUCCESS)
-            {
-                RegCloseKey(hEnumKey);
-                return rc;
-            }
+                goto cleanup;
 
             /* Call SETUP_CreateDevListFromEnumerator */
             rc = SETUP_CreateDevListFromEnumerator(list, class, KeyBuffer, hEnumeratorKey);
-            RegCloseKey(hEnumeratorKey);
             if (rc != ERROR_SUCCESS)
-            {
-                RegCloseKey(hEnumKey);
-                return rc;
-            }
+                goto cleanup;
         }
-        RegCloseKey(hEnumKey);
-        return ERROR_SUCCESS;
+        rc = ERROR_SUCCESS;
     }
+
+cleanup:
+    if (HKLM != HKEY_LOCAL_MACHINE)
+        RegCloseKey(HKLM);
+    if (hEnumKey != NULL)
+        RegCloseKey(hEnumKey);
+    if (hEnumeratorKey != NULL)
+        RegCloseKey(hEnumeratorKey);
+    return rc;
+}
+
+static BOOL
+DestroyDeviceInterface(
+    struct DeviceInterface* deviceInterface)
+{
+    return HeapFree(GetProcessHeap(), 0, deviceInterface);
 }
 
-static LONG SETUP_CreateInterfaceList(
-       struct DeviceInfoSet *list,
-       PCWSTR MachineName,
-       LPGUID InterfaceGuid,
-       PCWSTR DeviceInstanceW /* OPTIONAL */)
+static LONG
+SETUP_CreateInterfaceList(
+    struct DeviceInfoSet *list,
+    PCWSTR MachineName,
+    CONST GUID *InterfaceGuid,
+    PCWSTR DeviceInstanceW /* OPTIONAL */,
+    BOOL OnlyPresentInterfaces)
 {
     HKEY hInterfaceKey;      /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
     HKEY hDeviceInstanceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
@@ -1613,7 +1886,8 @@ static LONG SETUP_CreateInterfaceList(
     HKEY hKey;               /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
     LONG rc;
     WCHAR KeyBuffer[max(MAX_PATH, MAX_GUID_STRING_LEN) + 1];
-    PWSTR InstancePath;
+    PWSTR pSymbolicLink = NULL;
+    PWSTR InstancePath = NULL;
     DWORD i, j;
     DWORD dwLength, dwInstancePathLength;
     DWORD dwRegType;
@@ -1621,10 +1895,17 @@ static LONG SETUP_CreateInterfaceList(
     GUID ClassGuid;
     struct DeviceInfoElement *deviceInfo;
 
+    hInterfaceKey = INVALID_HANDLE_VALUE;
+    hDeviceInstanceKey = NULL;
+    hReferenceKey = NULL;
+
     /* Open registry key related to this interface */
     hInterfaceKey = SetupDiOpenClassRegKeyExW(InterfaceGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, MachineName, NULL);
     if (hInterfaceKey == INVALID_HANDLE_VALUE)
-        return GetLastError();
+    {
+        rc = GetLastError();
+        goto cleanup;
+    }
 
     /* Enumerate sub keys of hInterfaceKey */
     i = 0;
@@ -1635,61 +1916,43 @@ static LONG SETUP_CreateInterfaceList(
         if (rc == ERROR_NO_MORE_ITEMS)
             break;
         if (rc != ERROR_SUCCESS)
-        {
-            RegCloseKey(hInterfaceKey);
-            return rc;
-        }
+            goto cleanup;
         i++;
 
         /* Open sub key */
+        if (hDeviceInstanceKey != NULL)
+            RegCloseKey(hDeviceInstanceKey);
         rc = RegOpenKeyExW(hInterfaceKey, KeyBuffer, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hDeviceInstanceKey);
         if (rc != ERROR_SUCCESS)
-        {
-            RegCloseKey(hInterfaceKey);
-            return rc;
-        }
+            goto cleanup;
 
         /* Read DeviceInstance */
         rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, &dwRegType, NULL, &dwInstancePathLength);
-        if (rc != ERROR_SUCCESS )
-        {
-            RegCloseKey(hDeviceInstanceKey);
-            RegCloseKey(hInterfaceKey);
-            return rc;
-        }
+        if (rc != ERROR_SUCCESS)
+            goto cleanup;
         if (dwRegType != REG_SZ)
         {
-            RegCloseKey(hDeviceInstanceKey);
-            RegCloseKey(hInterfaceKey);
-            return ERROR_GEN_FAILURE;
+            rc = ERROR_GEN_FAILURE;
+            goto cleanup;
         }
+        HeapFree(GetProcessHeap(), 0, InstancePath);
         InstancePath = HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength + sizeof(WCHAR));
         if (!InstancePath)
         {
-            RegCloseKey(hDeviceInstanceKey);
-            RegCloseKey(hInterfaceKey);
-            return ERROR_NOT_ENOUGH_MEMORY;
+            rc = ERROR_NOT_ENOUGH_MEMORY;
+            goto cleanup;
         }
         rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, NULL, (LPBYTE)InstancePath, &dwInstancePathLength);
         if (rc != ERROR_SUCCESS)
-        {
-            HeapFree(GetProcessHeap(), 0, InstancePath);
-            RegCloseKey(hDeviceInstanceKey);
-            RegCloseKey(hInterfaceKey);
-            return rc;
-        }
+            goto cleanup;
         InstancePath[dwInstancePathLength / sizeof(WCHAR)] = '\0';
         TRACE("DeviceInstance %s\n", debugstr_w(InstancePath));
 
         if (DeviceInstanceW)
         {
             /* Check if device enumerator is not the right one */
-            if (wcscmp(DeviceInstanceW, InstancePath) != 0)
-            {
-                HeapFree(GetProcessHeap(), 0, InstancePath);
-                RegCloseKey(hDeviceInstanceKey);
+            if (strcmpW(DeviceInstanceW, InstancePath) != 0)
                 continue;
-            }
         }
 
         /* Find class GUID associated to the device instance */
@@ -1700,12 +1963,7 @@ static LONG SETUP_CreateInterfaceList(
             0,
             &hEnumKey);
         if (rc != ERROR_SUCCESS)
-        {
-            HeapFree(GetProcessHeap(), 0, InstancePath);
-            RegCloseKey(hDeviceInstanceKey);
-            RegCloseKey(hInterfaceKey);
-            return rc;
-        }
+            goto cleanup;
         rc = RegOpenKeyExW(
             hEnumKey,
             InstancePath,
@@ -1714,46 +1972,29 @@ static LONG SETUP_CreateInterfaceList(
             &hKey);
         RegCloseKey(hEnumKey);
         if (rc != ERROR_SUCCESS)
-        {
-            HeapFree(GetProcessHeap(), 0, InstancePath);
-            RegCloseKey(hDeviceInstanceKey);
-            RegCloseKey(hInterfaceKey);
-            return rc;
-        }
+            goto cleanup;
         dwLength = sizeof(KeyBuffer) - sizeof(WCHAR);
         rc = RegQueryValueExW(hKey, ClassGUID, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
         RegCloseKey(hKey);
         if (rc != ERROR_SUCCESS)
-        {
-            HeapFree(GetProcessHeap(), 0, InstancePath);
-            RegCloseKey(hDeviceInstanceKey);
-            RegCloseKey(hInterfaceKey);
-            return rc;
-        }
+            goto cleanup;
         KeyBuffer[dwLength / sizeof(WCHAR)] = '\0';
         KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */
         if (UuidFromStringW(&KeyBuffer[1], &ClassGuid) != RPC_S_OK)
         {
-            HeapFree(GetProcessHeap(), 0, InstancePath);
-            RegCloseKey(hDeviceInstanceKey);
-            RegCloseKey(hInterfaceKey);
-            return ERROR_GEN_FAILURE;
+            rc = ERROR_GEN_FAILURE;
+            goto cleanup;
         }
         TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid));
 
         /* If current device doesn't match the list GUID (if any), skip this entry */
         if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
-        {
-            HeapFree(GetProcessHeap(), 0, InstancePath);
-            RegCloseKey(hDeviceInstanceKey);
             continue;
-        }
 
         /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
         j = 0;
         while (TRUE)
         {
-            LPWSTR pSymbolicLink;
             struct DeviceInterface *interfaceInfo;
 
             dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
@@ -1761,88 +2002,71 @@ static LONG SETUP_CreateInterfaceList(
             if (rc == ERROR_NO_MORE_ITEMS)
                 break;
             if (rc != ERROR_SUCCESS)
-            {
-                HeapFree(GetProcessHeap(), 0, InstancePath);
-                RegCloseKey(hDeviceInstanceKey);
-                RegCloseKey(hInterfaceKey);
-                return rc;
-            }
+                goto cleanup;
             j++;
             if (KeyBuffer[0] != '#')
                 /* This entry doesn't represent an interesting entry */
                 continue;
 
             /* Open sub key */
+            if (hReferenceKey != NULL)
+                RegCloseKey(hReferenceKey);
             rc = RegOpenKeyExW(hDeviceInstanceKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hReferenceKey);
             if (rc != ERROR_SUCCESS)
-            {
-                RegCloseKey(hDeviceInstanceKey);
-                RegCloseKey(hInterfaceKey);
-                return rc;
-            }
+                goto cleanup;
 
             /* Read SymbolicLink value */
             rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, &dwRegType, NULL, &dwLength);
             if (rc != ERROR_SUCCESS )
-            {
-                RegCloseKey(hReferenceKey);
-                RegCloseKey(hDeviceInstanceKey);
-                RegCloseKey(hInterfaceKey);
-                return rc;
-            }
+                goto cleanup;
             if (dwRegType != REG_SZ)
             {
-                RegCloseKey(hReferenceKey);
-                RegCloseKey(hDeviceInstanceKey);
-                RegCloseKey(hInterfaceKey);
-                return ERROR_GEN_FAILURE;
+                rc = ERROR_GEN_FAILURE;
+                goto cleanup;
             }
 
             /* We have found a device */
             /* Step 1. Create a device info element */
             if (!CreateDeviceInfoElement(list, InstancePath, &ClassGuid, &deviceInfo))
             {
-                RegCloseKey(hReferenceKey);
-                RegCloseKey(hDeviceInstanceKey);
-                RegCloseKey(hInterfaceKey);
-                return GetLastError();
+                rc = GetLastError();
+                goto cleanup;
             }
             TRACE("Adding device %s to list\n", debugstr_w(InstancePath));
             InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
 
             /* Step 2. Create an interface list for this element */
+            HeapFree(GetProcessHeap(), 0, pSymbolicLink);
             pSymbolicLink = HeapAlloc(GetProcessHeap(), 0, (dwLength + 1) * sizeof(WCHAR));
             if (!pSymbolicLink)
             {
-                RegCloseKey(hReferenceKey);
-                RegCloseKey(hDeviceInstanceKey);
-                RegCloseKey(hInterfaceKey);
-                return ERROR_NOT_ENOUGH_MEMORY;
+                rc = ERROR_NOT_ENOUGH_MEMORY;
+                goto cleanup;
             }
             rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, NULL, (LPBYTE)pSymbolicLink, &dwLength);
             pSymbolicLink[dwLength / sizeof(WCHAR)] = '\0';
-            RegCloseKey(hReferenceKey);
             if (rc != ERROR_SUCCESS)
-            {
-                HeapFree(GetProcessHeap(), 0, pSymbolicLink);
-                RegCloseKey(hDeviceInstanceKey);
-                RegCloseKey(hInterfaceKey);
-                return rc;
-            }
+                goto cleanup;
             if (!CreateDeviceInterface(deviceInfo, pSymbolicLink, InterfaceGuid, &interfaceInfo))
             {
-                HeapFree(GetProcessHeap(), 0, pSymbolicLink);
-                RegCloseKey(hDeviceInstanceKey);
-                RegCloseKey(hInterfaceKey);
-                return GetLastError();
+                rc = GetLastError();
+                goto cleanup;
             }
 
             /* Step 3. Update flags */
             if (KeyBuffer[1] == '\0')
                 interfaceInfo->Flags |= SPINT_DEFAULT;
             rc = RegOpenKeyExW(hReferenceKey, Control, 0, KEY_QUERY_VALUE, &hControlKey);
-            if (!rc)
-                interfaceInfo->Flags |= SPINT_REMOVED;
+            if (rc != ERROR_SUCCESS)
+            {
+                if (OnlyPresentInterfaces)
+                {
+                    DestroyDeviceInterface(interfaceInfo);
+                    continue;
+                }
+                else
+                    interfaceInfo->Flags |= SPINT_REMOVED;
+            }
             else
             {
                 dwLength = sizeof(DWORD);
@@ -1853,53 +2077,63 @@ static LONG SETUP_CreateInterfaceList(
             }
 
             TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink));
-            HeapFree(GetProcessHeap(), 0, pSymbolicLink);
             InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry);
         }
-        RegCloseKey(hDeviceInstanceKey);
     }
-    RegCloseKey(hInterfaceKey);
-    return ERROR_SUCCESS;
+    rc = ERROR_SUCCESS;
+
+cleanup:
+    if (hReferenceKey != NULL)
+        RegCloseKey(hReferenceKey);
+    if (hDeviceInstanceKey != NULL)
+        RegCloseKey(hDeviceInstanceKey);
+    if (hInterfaceKey != INVALID_HANDLE_VALUE)
+        RegCloseKey(hInterfaceKey);
+    HeapFree(GetProcessHeap(), 0, InstancePath);
+    HeapFree(GetProcessHeap(), 0, pSymbolicLink);
+    return rc;
 }
 
 /***********************************************************************
  *             SetupDiGetClassDevsExW (SETUPAPI.@)
  */
-HDEVINFO WINAPI SetupDiGetClassDevsExW(
-       CONST GUID *class,
-       LPCWSTR enumstr,
-       HWND parent,
-       DWORD flags,
-       HDEVINFO deviceset,
-       LPCWSTR machine,
-       PVOID reserved)
+HDEVINFO WINAPI
+SetupDiGetClassDevsExW(
+    IN CONST GUID *ClassGuid OPTIONAL,
+    IN PCWSTR Enumerator OPTIONAL,
+    IN HWND hwndParent OPTIONAL,
+    IN DWORD Flags,
+    IN HDEVINFO DeviceInfoSet OPTIONAL,
+    IN PCWSTR MachineName OPTIONAL,
+    IN PVOID Reserved)
 {
     HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
     struct DeviceInfoSet *list;
-    LPGUID pClassGuid;
+    CONST GUID *pClassGuid;
     LONG rc;
+    HDEVINFO ret = INVALID_HANDLE_VALUE;
 
-    TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr),
-     parent, flags, deviceset, debugstr_w(machine), reserved);
+    TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(ClassGuid), debugstr_w(Enumerator),
+        hwndParent, Flags, DeviceInfoSet, debugstr_w(MachineName), Reserved);
 
     /* Create the deviceset if not set */
-    if (deviceset)
+    if (DeviceInfoSet)
     {
-        list = (struct DeviceInfoSet *)deviceset;
+        list = (struct DeviceInfoSet *)DeviceInfoSet;
         if (list->magic != SETUP_DEV_INFO_SET_MAGIC)
         {
             SetLastError(ERROR_INVALID_HANDLE);
-            return INVALID_HANDLE_VALUE;
+            goto cleanup;
         }
-        hDeviceInfo = deviceset;
+        hDeviceInfo = DeviceInfoSet;
     }
     else
     {
          hDeviceInfo = SetupDiCreateDeviceInfoListExW(
-             flags & DIGCF_DEVICEINTERFACE ? NULL : class,
-             NULL, machine, NULL);
+             Flags & DIGCF_DEVICEINTERFACE ? NULL : ClassGuid,
+             NULL, MachineName, NULL);
          if (hDeviceInfo == INVALID_HANDLE_VALUE)
-             return INVALID_HANDLE_VALUE;
+             goto cleanup;
          list = (struct DeviceInfoSet *)hDeviceInfo;
     }
 
@@ -1908,64 +2142,60 @@ HDEVINFO WINAPI SetupDiGetClassDevsExW(
     else
         pClassGuid = &list->ClassGuid;
 
-    if (flags & DIGCF_PRESENT)
-        FIXME(": flag DIGCF_PRESENT ignored\n");
-    if (flags & DIGCF_PROFILE)
+    if (Flags & DIGCF_PROFILE)
         FIXME(": flag DIGCF_PROFILE ignored\n");
 
-    if (flags & DIGCF_ALLCLASSES)
+    if (Flags & DIGCF_ALLCLASSES)
     {
-        rc = SETUP_CreateDevList(list, machine, pClassGuid, enumstr);
+        rc = SETUP_CreateDevList(list, MachineName, pClassGuid, Enumerator);
         if (rc != ERROR_SUCCESS)
         {
             SetLastError(rc);
-            if (!deviceset)
-                SetupDiDestroyDeviceInfoList(hDeviceInfo);
-            return INVALID_HANDLE_VALUE;
+            goto cleanup;
         }
-        return hDeviceInfo;
+        ret = hDeviceInfo;
     }
-    else if (flags & DIGCF_DEVICEINTERFACE)
+    else if (Flags & DIGCF_DEVICEINTERFACE)
     {
-        if (class == NULL)
+        if (ClassGuid == NULL)
         {
             SetLastError(ERROR_INVALID_PARAMETER);
-            if (!deviceset)
-                SetupDiDestroyDeviceInfoList(hDeviceInfo);
-            return INVALID_HANDLE_VALUE;
+            goto cleanup;
         }
 
-        rc = SETUP_CreateInterfaceList(list, machine, (LPGUID)class, enumstr);
+        rc = SETUP_CreateInterfaceList(list, MachineName, ClassGuid, Enumerator, Flags & DIGCF_PRESENT);
         if (rc != ERROR_SUCCESS)
         {
             SetLastError(rc);
-            if (!deviceset)
-                SetupDiDestroyDeviceInfoList(hDeviceInfo);
-            return INVALID_HANDLE_VALUE;
+            goto cleanup;
         }
-        return hDeviceInfo;
+        ret = hDeviceInfo;
     }
     else
     {
-        rc = SETUP_CreateDevList(list, machine, (LPGUID)class, enumstr);
+        rc = SETUP_CreateDevList(list, MachineName, ClassGuid, Enumerator);
         if (rc != ERROR_SUCCESS)
         {
             SetLastError(rc);
-            if (!deviceset)
-                SetupDiDestroyDeviceInfoList(hDeviceInfo);
-            return INVALID_HANDLE_VALUE;
+            goto cleanup;
         }
-        return hDeviceInfo;
+        ret = hDeviceInfo;
     }
+
+cleanup:
+    if (!DeviceInfoSet && hDeviceInfo != INVALID_HANDLE_VALUE && hDeviceInfo != ret)
+        SetupDiDestroyDeviceInfoList(hDeviceInfo);
+    return ret;
 }
 
 /***********************************************************************
  *             SetupDiGetClassImageIndex (SETUPAPI.@)
  */
 
-static BOOL GetIconIndex(
-       IN HKEY hClassKey,
-       OUT PINT ImageIndex)
+static BOOL
+GetIconIndex(
+    IN HKEY hClassKey,
+    OUT PINT ImageIndex)
 {
     LPWSTR Buffer = NULL;
     DWORD dwRegType, dwLength;
@@ -2007,10 +2237,11 @@ cleanup:
     return ret;
 }
 
-BOOL WINAPI SetupDiGetClassImageIndex(
-       IN PSP_CLASSIMAGELIST_DATA ClassImageListData,
-       IN CONST GUID *ClassGuid,
-       OUT PINT ImageIndex)
+BOOL WINAPI
+SetupDiGetClassImageIndex(
+    IN PSP_CLASSIMAGELIST_DATA ClassImageListData,
+    IN CONST GUID *ClassGuid,
+    OUT PINT ImageIndex)
 {
     struct ClassImageList *list;
     BOOL ret = FALSE;
@@ -2060,8 +2291,9 @@ cleanup:
 /***********************************************************************
  *             SetupDiGetClassImageList(SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetClassImageList(
-       OUT PSP_CLASSIMAGELIST_DATA ClassImageListData)
+BOOL WINAPI
+SetupDiGetClassImageList(
+    OUT PSP_CLASSIMAGELIST_DATA ClassImageListData)
 {
     return SetupDiGetClassImageListExW(ClassImageListData, NULL, NULL);
 }
@@ -2069,10 +2301,11 @@ BOOL WINAPI SetupDiGetClassImageList(
 /***********************************************************************
  *             SetupDiGetClassImageListExA(SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetClassImageListExA(
-       OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
-       IN PCSTR MachineName OPTIONAL,
-       IN PVOID Reserved)
+BOOL WINAPI
+SetupDiGetClassImageListExA(
+    OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
+    IN PCSTR MachineName OPTIONAL,
+    IN PVOID Reserved)
 {
     PWSTR MachineNameW = NULL;
     BOOL ret;
@@ -2095,10 +2328,11 @@ BOOL WINAPI SetupDiGetClassImageListExA(
 /***********************************************************************
  *             SetupDiGetClassImageListExW(SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetClassImageListExW(
-       OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
-       IN PCWSTR MachineName OPTIONAL,
-       IN PVOID Reserved)
+BOOL WINAPI
+SetupDiGetClassImageListExW(
+    OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
+    IN PCWSTR MachineName OPTIONAL,
+    IN PVOID Reserved)
 {
     BOOL ret = FALSE;
 
@@ -2117,7 +2351,7 @@ BOOL WINAPI SetupDiGetClassImageListExW(
 
         size = FIELD_OFFSET(struct ClassImageList, szData);
         if (MachineName)
-            size += (wcslen(MachineName) + 3) * sizeof(WCHAR);
+            size += (strlenW(MachineName) + 3) * sizeof(WCHAR);
         list = HeapAlloc(GetProcessHeap(), 0, size);
         if (!list)
         {
@@ -2136,7 +2370,7 @@ BOOL WINAPI SetupDiGetClassImageListExW(
             list->MachineName = NULL;
         }
 
-        ClassImageListData->Reserved = (DWORD)list; /* FIXME: 64 bit portability issue */
+        ClassImageListData->Reserved = (ULONG_PTR)list;
         ret = TRUE;
 
 cleanup:
@@ -2151,10 +2385,11 @@ cleanup:
 /***********************************************************************
  *             SetupDiLoadClassIcon(SETUPAPI.@)
  */
-BOOL WINAPI SetupDiLoadClassIcon(
-       IN CONST GUID *ClassGuid,
-       OUT HICON *LargeIcon OPTIONAL,
-       OUT PINT MiniIconIndex OPTIONAL)
+BOOL WINAPI
+SetupDiLoadClassIcon(
+    IN CONST GUID *ClassGuid,
+    OUT HICON *LargeIcon OPTIONAL,
+    OUT PINT MiniIconIndex OPTIONAL)
 {
     BOOL ret = FALSE;
 
@@ -2265,12 +2500,13 @@ cleanup:
 /***********************************************************************
  *             SetupDiEnumDeviceInterfaces (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiEnumDeviceInterfaces(
-       HDEVINFO DeviceInfoSet,
-       PSP_DEVINFO_DATA DeviceInfoData,
-       CONST GUID * InterfaceClassGuid,
-       DWORD MemberIndex,
-       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
+BOOL WINAPI
+SetupDiEnumDeviceInterfaces(
+    IN HDEVINFO DeviceInfoSet,
+    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+    IN CONST GUID *InterfaceClassGuid,
+    IN DWORD MemberIndex,
+    OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
 {
     BOOL ret = FALSE;
 
@@ -2292,7 +2528,7 @@ BOOL WINAPI SetupDiEnumDeviceInterfaces(
             while (ItemList != &list->ListHead && !Found)
             {
                 PLIST_ENTRY InterfaceListEntry;
-                struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)ItemList;
+                struct DeviceInfoElement *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfoElement, ListEntry);
                 if (DeviceInfoData && (struct DeviceInfoElement *)DeviceInfoData->Reserved != DevInfo)
                 {
                     /* We are not searching for this element */
@@ -2302,7 +2538,7 @@ BOOL WINAPI SetupDiEnumDeviceInterfaces(
                 InterfaceListEntry = DevInfo->InterfaceListHead.Flink;
                 while (InterfaceListEntry != &DevInfo->InterfaceListHead && !Found)
                 {
-                    struct DeviceInterface *DevItf = (struct DeviceInterface *)InterfaceListEntry;
+                    struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
                     if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
                     {
                         InterfaceListEntry = InterfaceListEntry->Flink;
@@ -2335,12 +2571,14 @@ BOOL WINAPI SetupDiEnumDeviceInterfaces(
     return ret;
 }
 
-static VOID ReferenceInfFile(struct InfFileDetails* infFile)
+static VOID
+ReferenceInfFile(struct InfFileDetails* infFile)
 {
     InterlockedIncrement(&infFile->References);
 }
 
-static VOID DereferenceInfFile(struct InfFileDetails* infFile)
+static VOID
+DereferenceInfFile(struct InfFileDetails* infFile)
 {
     if (InterlockedDecrement(&infFile->References) == 0)
     {
@@ -2349,7 +2587,8 @@ static VOID DereferenceInfFile(struct InfFileDetails* infFile)
     }
 }
 
-static BOOL DestroyDriverInfoElement(struct DriverInfoElement* driverInfo)
+static BOOL
+DestroyDriverInfoElement(struct DriverInfoElement* driverInfo)
 {
     DereferenceInfFile(driverInfo->InfFileDetails);
     HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
@@ -2357,35 +2596,39 @@ static BOOL DestroyDriverInfoElement(struct DriverInfoElement* driverInfo)
     return TRUE;
 }
 
-static BOOL DestroyClassInstallParams(struct ClassInstallParams* installParams)
+static BOOL
+DestroyClassInstallParams(struct ClassInstallParams* installParams)
 {
-    HeapFree(GetProcessHeap(), 0, installParams->PropChange);
-    return TRUE;
+    return HeapFree(GetProcessHeap(), 0, installParams->PropChange);
 }
 
-static BOOL DestroyDeviceInfoElement(struct DeviceInfoElement* deviceInfo)
+static BOOL
+DestroyDeviceInfoElement(struct DeviceInfoElement* deviceInfo)
 {
     PLIST_ENTRY ListEntry;
     struct DriverInfoElement *driverInfo;
+    struct DeviceInterface *deviceInterface;
 
     while (!IsListEmpty(&deviceInfo->DriverListHead))
     {
         ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
-        driverInfo = (struct DriverInfoElement *)ListEntry;
+        driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry);
         if (!DestroyDriverInfoElement(driverInfo))
             return FALSE;
     }
     while (!IsListEmpty(&deviceInfo->InterfaceListHead))
     {
         ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
-        HeapFree(GetProcessHeap(), 0, ListEntry);
+        deviceInterface = CONTAINING_RECORD(ListEntry, struct DeviceInterface, ListEntry);
+        if (!DestroyDeviceInterface(deviceInterface))
+            return FALSE;
     }
     DestroyClassInstallParams(&deviceInfo->ClassInstallParams);
-    HeapFree(GetProcessHeap(), 0, deviceInfo);
-    return TRUE;
+    return HeapFree(GetProcessHeap(), 0, deviceInfo);
 }
 
-static BOOL DestroyDeviceInfoSet(struct DeviceInfoSet* list)
+static BOOL
+DestroyDeviceInfoSet(struct DeviceInfoSet* list)
 {
     PLIST_ENTRY ListEntry;
     struct DeviceInfoElement *deviceInfo;
@@ -2393,7 +2636,7 @@ static BOOL DestroyDeviceInfoSet(struct DeviceInfoSet* list)
     while (!IsListEmpty(&list->ListHead))
     {
         ListEntry = RemoveHeadList(&list->ListHead);
-        deviceInfo = (struct DeviceInfoElement *)ListEntry;
+        deviceInfo = CONTAINING_RECORD(ListEntry, struct DeviceInfoElement, ListEntry);
         if (!DestroyDeviceInfoElement(deviceInfo))
             return FALSE;
     }
@@ -2401,21 +2644,22 @@ static BOOL DestroyDeviceInfoSet(struct DeviceInfoSet* list)
         RegCloseKey(list->HKLM);
     CM_Disconnect_Machine(list->hMachine);
     DestroyClassInstallParams(&list->ClassInstallParams);
-    HeapFree(GetProcessHeap(), 0, list);
-    return TRUE;
+    return HeapFree(GetProcessHeap(), 0, list);
 }
 
 /***********************************************************************
  *             SetupDiDestroyDeviceInfoList (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
+BOOL WINAPI
+SetupDiDestroyDeviceInfoList(
+    IN HDEVINFO DeviceInfoSet)
 {
     BOOL ret = FALSE;
 
-    TRACE("%p\n", devinfo);
-    if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
+    TRACE("%p\n", DeviceInfoSet);
+    if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
     {
-        struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
+        struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
 
         if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
             ret = DestroyDeviceInfoSet(list);
@@ -2432,13 +2676,14 @@ BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
 /***********************************************************************
  *             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)
+BOOL WINAPI
+SetupDiGetDeviceInterfaceDetailA(
+    IN HDEVINFO DeviceInfoSet,
+    IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
+    OUT PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData OPTIONAL,
+    IN DWORD DeviceInterfaceDetailDataSize,
+    OUT PDWORD RequiredSize OPTIONAL,
+    OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
 {
     PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL;
     DWORD sizeW = 0, sizeA;
@@ -2502,13 +2747,14 @@ BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
 /***********************************************************************
  *             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)
+BOOL WINAPI
+SetupDiGetDeviceInterfaceDetailW(
+    IN HDEVINFO DeviceInfoSet,
+    IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
+    OUT PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData OPTIONAL,
+    IN DWORD DeviceInterfaceDetailDataSize,
+    OUT PDWORD RequiredSize OPTIONAL,
+    OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
 {
     BOOL ret = FALSE;
 
@@ -2547,7 +2793,7 @@ BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
         }
         else
         {
-            wcscpy(DeviceInterfaceDetailData->DevicePath, devName);
+            strcpyW(DeviceInterfaceDetailData->DevicePath, devName);
             TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath));
             if (DeviceInfoData)
             {
@@ -2568,31 +2814,40 @@ BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
 /***********************************************************************
  *             SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
-        HDEVINFO  devinfo,
-        PSP_DEVINFO_DATA  DeviceInfoData,
-        DWORD   Property,
-        PDWORD  PropertyRegDataType,
-        PBYTE   PropertyBuffer,
-        DWORD   PropertyBufferSize,
-        PDWORD  RequiredSize)
+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 bResult;
     BOOL bIsStringProperty;
     DWORD RegType;
     DWORD RequiredSizeA, RequiredSizeW;
-    DWORD PropertyBufferSizeW;
-    PBYTE PropertyBufferW;
+    DWORD PropertyBufferSizeW = 0;
+    PBYTE PropertyBufferW = NULL;
 
-    TRACE("%p %p %ld %p %p %ld %p\n", devinfo, DeviceInfoData,
+    TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet, DeviceInfoData,
         Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
         RequiredSize);
 
-    PropertyBufferSizeW = PropertyBufferSize * 2;
-    PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
+    if (PropertyBufferSize != 0)
+    {
+        PropertyBufferSizeW = PropertyBufferSize * 2;
+        PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
+        if (!PropertyBufferW)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            return FALSE;
+        }
+    }
 
     bResult = SetupDiGetDeviceRegistryPropertyW(
-        devinfo,
+        DeviceInfoSet,
         DeviceInfoData,
         Property,
         &RegType,
@@ -2646,14 +2901,15 @@ BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
 /***********************************************************************
  *             SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
-        HDEVINFO  DeviceInfoSet,
-        PSP_DEVINFO_DATA  DeviceInfoData,
-        DWORD   Property,
-        PDWORD  PropertyRegDataType,
-        PBYTE   PropertyBuffer,
-        DWORD   PropertyBufferSize,
-        PDWORD  RequiredSize)
+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;
@@ -2728,13 +2984,13 @@ BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
                     case SPDRP_MFG:
                         RegistryPropertyName = REGSTR_VAL_MFG; break;
                     case SPDRP_SECURITY:
-                        RegistryPropertyName = L"Security"; break;
+                        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 = L"UINumberDescFormat"; break;
+                        RegistryPropertyName = REGSTR_UI_NUMBER_DESC_FORMAT; break;
                     case SPDRP_UPPERFILTERS:
                         RegistryPropertyName = REGSTR_VAL_UPPERFILTERS; break;
                     default:
@@ -2796,7 +3052,7 @@ BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
 
             case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME:
             {
-                DWORD required = (wcslen(DevInfo->Data) + 1) * sizeof(WCHAR);
+                DWORD required = (strlenW(DevInfo->Data) + 1) * sizeof(WCHAR);
 
                 if (PropertyRegDataType)
                     *PropertyRegDataType = REG_SZ;
@@ -2804,7 +3060,7 @@ BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
                     *RequiredSize = required;
                 if (PropertyBufferSize >= required)
                 {
-                    wcscpy((LPWSTR)PropertyBuffer, DevInfo->Data);
+                    strcpyW((LPWSTR)PropertyBuffer, DevInfo->Data);
                     ret = TRUE;
                 }
                 else
@@ -2844,12 +3100,13 @@ BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
 /***********************************************************************
  *             SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
-        IN HDEVINFO DeviceInfoSet,
-        IN OUT PSP_DEVINFO_DATA DeviceInfoData,
-        IN DWORD Property,
-        IN CONST BYTE *PropertyBuffer,
-        IN DWORD PropertyBufferSize)
+BOOL WINAPI
+SetupDiSetDeviceRegistryPropertyA(
+    IN HDEVINFO DeviceInfoSet,
+    IN OUT PSP_DEVINFO_DATA DeviceInfoData,
+    IN DWORD Property,
+    IN CONST BYTE *PropertyBuffer OPTIONAL,
+    IN DWORD PropertyBufferSize)
 {
     FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
         Property, PropertyBuffer, PropertyBufferSize);
@@ -2860,12 +3117,13 @@ BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
 /***********************************************************************
  *             SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
-        IN HDEVINFO DeviceInfoSet,
-        IN OUT PSP_DEVINFO_DATA DeviceInfoData,
-        IN DWORD Property,
-        IN const BYTE *PropertyBuffer,
-        IN DWORD PropertyBufferSize)
+BOOL WINAPI
+SetupDiSetDeviceRegistryPropertyW(
+    IN HDEVINFO DeviceInfoSet,
+    IN OUT PSP_DEVINFO_DATA DeviceInfoData,
+    IN DWORD Property,
+    IN CONST BYTE *PropertyBuffer OPTIONAL,
+    IN DWORD PropertyBufferSize)
 {
     struct DeviceInfoSet *list;
     BOOL ret = FALSE;
@@ -2928,7 +3186,7 @@ BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
                         RegistryDataType = REG_MULTI_SZ;
                         break;
                     case SPDRP_SECURITY:
-                        RegistryPropertyName = L"Security";
+                        RegistryPropertyName = REGSTR_SECURITY;
                         RegistryDataType = REG_BINARY;
                         break;
                     case SPDRP_SERVICE:
@@ -2936,7 +3194,7 @@ BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
                         RegistryDataType = REG_SZ;
                         break;
                     case SPDRP_UI_NUMBER_DESC_FORMAT:
-                        RegistryPropertyName = L"UINumberDescFormat";
+                        RegistryPropertyName = REGSTR_UI_NUMBER_DESC_FORMAT;
                         RegistryDataType = REG_SZ;
                         break;
                     case SPDRP_UPPERFILTERS:
@@ -2994,11 +3252,12 @@ BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
 /***********************************************************************
  *             SetupDiInstallClassA (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiInstallClassA(
-        IN HWND hwndParent OPTIONAL,
-        IN PCSTR InfFileName,
-        IN DWORD Flags,
-        IN HSPFILEQ FileQueue OPTIONAL)
+BOOL WINAPI
+SetupDiInstallClassA(
+    IN HWND hwndParent OPTIONAL,
+    IN PCSTR InfFileName,
+    IN DWORD Flags,
+    IN HSPFILEQ FileQueue OPTIONAL)
 {
     return SetupDiInstallClassExA(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
 }
@@ -3007,11 +3266,12 @@ BOOL WINAPI SetupDiInstallClassA(
 /***********************************************************************
  *             SetupDiInstallClassW (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiInstallClassW(
-        IN HWND hwndParent OPTIONAL,
-        IN PCWSTR InfFileName,
-        IN DWORD Flags,
-        IN HSPFILEQ FileQueue OPTIONAL)
+BOOL WINAPI
+SetupDiInstallClassW(
+    IN HWND hwndParent OPTIONAL,
+    IN PCWSTR InfFileName,
+    IN DWORD Flags,
+    IN HSPFILEQ FileQueue OPTIONAL)
 {
     return SetupDiInstallClassExW(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
 }
@@ -3020,14 +3280,15 @@ BOOL WINAPI SetupDiInstallClassW(
 /***********************************************************************
  *             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)
+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;
@@ -3051,90 +3312,100 @@ BOOL WINAPI SetupDiInstallClassExA(
 }
 
 
-static HKEY CreateClassKey(HINF hInf)
+static HKEY
+CreateClassKey(HINF hInf)
 {
     WCHAR FullBuffer[MAX_PATH];
     WCHAR Buffer[MAX_PATH];
     DWORD RequiredSize;
-    HKEY hClassKey;
+    HKEY hClassKey = NULL;
+    HKEY ret = INVALID_HANDLE_VALUE;
 
+    FullBuffer[0] = '\0';
     Buffer[0] = '\\';
     if (!SetupGetLineTextW(NULL,
-                          hInf,
-                          Version,
-                          ClassGUID,
-                          &Buffer[1],
-                          MAX_PATH - 1,
-                          &RequiredSize))
+                           hInf,
+                           Version,
+                           ClassGUID,
+                           &Buffer[1],
+                           MAX_PATH - 1,
+                           &RequiredSize))
     {
-        return INVALID_HANDLE_VALUE;
+        goto cleanup;
     }
 
     lstrcpyW(FullBuffer, REGSTR_PATH_CLASS_NT);
     lstrcatW(FullBuffer, Buffer);
 
-
     if (!SetupGetLineTextW(NULL,
-                              hInf,
-                              Version,
-                              Class,
-                              Buffer,
-                              MAX_PATH,
-                              &RequiredSize))
+                           hInf,
+                           Version,
+                           Class,
+                           Buffer,
+                           MAX_PATH,
+                           &RequiredSize))
     {
         RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
-        return INVALID_HANDLE_VALUE;
+        goto cleanup;
     }
 
     if (ERROR_SUCCESS != RegCreateKeyExW(HKEY_LOCAL_MACHINE,
-                           FullBuffer,
-                           0,
-                           NULL,
-                           REG_OPTION_NON_VOLATILE,
-                           KEY_SET_VALUE,
-                           NULL,
-                           &hClassKey,
-             NULL))
+                                         FullBuffer,
+                                         0,
+                                         NULL,
+                                         REG_OPTION_NON_VOLATILE,
+                                         KEY_SET_VALUE,
+                                         NULL,
+                                         &hClassKey,
+                                         NULL))
     {
-        RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
-        return INVALID_HANDLE_VALUE;
+        goto cleanup;
     }
 
     if (ERROR_SUCCESS != RegSetValueExW(hClassKey,
-                      Class,
-                      0,
-                      REG_SZ,
-                      (LPBYTE)Buffer,
-             RequiredSize * sizeof(WCHAR)))
+                                        Class,
+                                        0,
+                                        REG_SZ,
+                                        (LPBYTE)Buffer,
+                                        RequiredSize * sizeof(WCHAR)))
     {
-        RegCloseKey(hClassKey);
-        RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
-        return INVALID_HANDLE_VALUE;
+        goto cleanup;
     }
 
-    return hClassKey;
+    ret = hClassKey;
+
+cleanup:
+    if (hClassKey != NULL && hClassKey != ret)
+        RegCloseKey(hClassKey);
+    if (ret == INVALID_HANDLE_VALUE && FullBuffer[0] != '\0')
+        RegDeleteKeyW(HKEY_LOCAL_MACHINE, FullBuffer);
+    return ret;
 }
 
 
 /***********************************************************************
  *             SetupDiInstallClassExW (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiInstallClassExW(
-        IN HWND hwndParent OPTIONAL,
-        IN PCWSTR InfFileName OPTIONAL,
-        IN DWORD Flags,
-        IN HSPFILEQ FileQueue OPTIONAL,
-        IN const GUID* InterfaceClassGuid OPTIONAL,
-        IN PVOID Reserved1,
-        IN PVOID Reserved2)
+BOOL WINAPI
+SetupDiInstallClassExW(
+    IN HWND hwndParent OPTIONAL,
+    IN PCWSTR InfFileName OPTIONAL,
+    IN DWORD Flags,
+    IN HSPFILEQ FileQueue OPTIONAL,
+    IN CONST GUID *InterfaceClassGuid OPTIONAL,
+    IN PVOID Reserved1,
+    IN PVOID Reserved2)
 {
     BOOL ret = FALSE;
 
     TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent, debugstr_w(InfFileName), Flags,
         FileQueue, debugstr_guid(InterfaceClassGuid), Reserved1, Reserved2);
 
-    if (!InfFileName && !InterfaceClassGuid)
-        SetLastError(ERROR_INVALID_PARAMETER);
+    if (!InfFileName)
+    {
+        FIXME("Case not implemented: InfFileName NULL\n");
+        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    }
     else if (Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL))
     {
         TRACE("Unknown flags: 0x%08lx\n", Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL));
@@ -3148,41 +3419,67 @@ BOOL WINAPI SetupDiInstallClassExW(
         SetLastError(ERROR_INVALID_PARAMETER);
     else
     {
+        HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
+        SP_DEVINSTALL_PARAMS_W InstallParams;
         WCHAR SectionName[MAX_PATH];
         HINF hInf = INVALID_HANDLE_VALUE;
-        HKEY hClassKey = INVALID_HANDLE_VALUE;
+        HKEY hRootKey = INVALID_HANDLE_VALUE;
         PVOID callback_context = NULL;
 
+        hDeviceInfo = SetupDiCreateDeviceInfoList(NULL, NULL);
+
+        InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
+        if (!SetupDiGetDeviceInstallParamsW(hDeviceInfo, NULL, &InstallParams))
+            goto cleanup;
+        InstallParams.Flags &= ~(DI_NOVCP | DI_NOBROWSE | DI_QUIETINSTALL);
+        InstallParams.Flags |= Flags & (DI_NOVCP | DI_NOBROWSE | DI_QUIETINSTALL);
+        if (Flags & DI_NOVCP)
+            InstallParams.FileQueue = FileQueue;
+        if (!SetupDiSetDeviceInstallParamsW(hDeviceInfo, NULL, &InstallParams))
+            goto cleanup;
+
+        /* Open the .inf file */
+        hInf = SetupOpenInfFileW(
+            InfFileName,
+            NULL,
+            INF_STYLE_WIN4,
+            NULL);
+        if (hInf == INVALID_HANDLE_VALUE)
+            goto cleanup;
+
+        /* Try to append a layout file */
+        ret = SetupOpenAppendInfFileW(NULL, hInf, NULL);
+        if (!ret)
+            goto cleanup;
+
         if (InterfaceClassGuid)
         {
+            /* Retrieve the actual section name */
+            ret = SetupDiGetActualSectionToInstallW(
+                hInf,
+                InterfaceInstall32,
+                SectionName,
+                MAX_PATH,
+                NULL,
+                NULL);
+            if (!ret)
+                goto cleanup;
+
+            /* Open registry key related to this interface */
+            /* FIXME: What happens if the key doesn't exist? */
+            hRootKey = SetupDiOpenClassRegKeyExW(InterfaceClassGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, NULL, NULL);
+            if (hRootKey == INVALID_HANDLE_VALUE)
+                goto cleanup;
+
             /* SetupDiCreateDeviceInterface??? */
             FIXME("Installing an interface is not implemented\n");
             SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
         }
         else
         {
-            if (Flags & DI_NOVCP)
-                FIXME("FileQueue argument ignored\n");
-            if (Flags & (DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL))
-                FIXME("Flags 0x%lx ignored\n", Flags & (DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL));
-
-            /* Open the .inf file */
-            hInf = SetupOpenInfFileW(
-                InfFileName,
-                NULL,
-                INF_STYLE_WIN4,
-                NULL);
-            if (hInf == INVALID_HANDLE_VALUE)
-                goto cleanup;
-
             /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
-            hClassKey = CreateClassKey(hInf);
-            if (hClassKey == INVALID_HANDLE_VALUE)
-                goto cleanup;
-
-            /* Try to append a layout file */
-            ret = SetupOpenAppendInfFileW(NULL, hInf, NULL);
-            if (!ret)
+            hRootKey = CreateClassKey(hInf);
+            if (hRootKey == INVALID_HANDLE_VALUE)
                 goto cleanup;
 
             /* Retrieve the actual section name */
@@ -3190,7 +3487,7 @@ BOOL WINAPI SetupDiInstallClassExW(
                 hInf,
                 ClassInstall32,
                 SectionName,
-                MAX_PATH - wcslen(DotServices),
+                MAX_PATH - strlenW(DotServices),
                 NULL,
                 NULL);
             if (!ret)
@@ -3205,19 +3502,26 @@ BOOL WINAPI SetupDiInstallClassExW(
                 hInf,
                 SectionName,
                 SPINST_REGISTRY | SPINST_FILES | SPINST_BITREG | SPINST_INIFILES | SPINST_INI2REG,
-                hClassKey,
-                NULL, /* SourceRootPath */
-                0, /* CopyFlags */
+                hRootKey,
+                NULL, /* FIXME: SourceRootPath */
+                !(Flags & DI_NOVCP) && (Flags & DI_FORCECOPY) ? SP_COPY_FORCE_IN_USE : 0, /* CopyFlags */
                 SetupDefaultQueueCallbackW,
                 callback_context,
-                NULL,
+                hDeviceInfo,
                 NULL);
             if (!ret)
                 goto cleanup;
 
             /* Install .Services section */
             lstrcatW(SectionName, DotServices);
-            ret = SetupInstallServicesFromInfSectionW(hInf, SectionName, 0);
+            ret = SetupInstallServicesFromInfSectionExW(
+                hInf,
+                SectionName,
+                0,
+                hDeviceInfo,
+                NULL,
+                NULL,
+                NULL);
             if (!ret)
                 goto cleanup;
 
@@ -3225,10 +3529,12 @@ BOOL WINAPI SetupDiInstallClassExW(
         }
 
 cleanup:
+        if (hDeviceInfo != INVALID_HANDLE_VALUE)
+            SetupDiDestroyDeviceInfoList(hDeviceInfo);
         if (hInf != INVALID_HANDLE_VALUE)
             SetupCloseInfFile(hInf);
-        if (hClassKey != INVALID_HANDLE_VALUE)
-            RegCloseKey(hClassKey);
+        if (hRootKey != INVALID_HANDLE_VALUE)
+            RegCloseKey(hRootKey);
         SetupTermDefaultQueueCallback(callback_context);
     }
 
@@ -3240,9 +3546,10 @@ cleanup:
 /***********************************************************************
  *             SetupDiOpenClassRegKey  (SETUPAPI.@)
  */
-HKEY WINAPI SetupDiOpenClassRegKey(
-        const GUID* ClassGuid,
-        REGSAM samDesired)
+HKEY WINAPI
+SetupDiOpenClassRegKey(
+    IN CONST GUID *ClassGuid OPTIONAL,
+    IN REGSAM samDesired)
 {
     return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
                                      DIOCR_INSTALLER, NULL, NULL);
@@ -3252,12 +3559,13 @@ HKEY WINAPI SetupDiOpenClassRegKey(
 /***********************************************************************
  *             SetupDiOpenClassRegKeyExA  (SETUPAPI.@)
  */
-HKEY WINAPI SetupDiOpenClassRegKeyExA(
-        const GUID* ClassGuid OPTIONAL,
-        REGSAM samDesired,
-        DWORD Flags,
-        PCSTR MachineName OPTIONAL,
-        PVOID Reserved)
+HKEY WINAPI
+SetupDiOpenClassRegKeyExA(
+    IN CONST GUID *ClassGuid OPTIONAL,
+    IN REGSAM samDesired,
+    IN DWORD Flags,
+    IN PCSTR MachineName OPTIONAL,
+    IN PVOID Reserved)
 {
     PWSTR MachineNameW = NULL;
     HKEY hKey;
@@ -3284,19 +3592,21 @@ HKEY WINAPI SetupDiOpenClassRegKeyExA(
 /***********************************************************************
  *             SetupDiOpenClassRegKeyExW  (SETUPAPI.@)
  */
-HKEY WINAPI SetupDiOpenClassRegKeyExW(
-        const GUID* ClassGuid OPTIONAL,
-        REGSAM samDesired,
-        DWORD Flags,
-        PCWSTR MachineName OPTIONAL,
-        PVOID Reserved)
+HKEY WINAPI
+SetupDiOpenClassRegKeyExW(
+    IN CONST GUID* ClassGuid OPTIONAL,
+    IN REGSAM samDesired,
+    IN DWORD Flags,
+    IN PCWSTR MachineName OPTIONAL,
+    IN PVOID Reserved)
 {
-    LPWSTR lpGuidString;
-    LPWSTR lpFullGuidString;
+    LPWSTR lpGuidString = NULL;
+    LPWSTR lpFullGuidString = NULL;
     DWORD dwLength;
     HKEY HKLM;
-    HKEY hClassesKey;
-    HKEY hClassKey;
+    HKEY hClassesKey = NULL;
+    HKEY hClassKey = NULL;
+    HKEY ret = INVALID_HANDLE_VALUE;
     DWORD rc;
     LPCWSTR lpKeyName;
 
@@ -3304,18 +3614,14 @@ HKEY WINAPI SetupDiOpenClassRegKeyExW(
         Flags, debugstr_w(MachineName), Reserved);
 
     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);
-        return INVALID_HANDLE_VALUE;
+        goto cleanup;
     }
 
     if (MachineName != NULL)
@@ -3324,32 +3630,35 @@ HKEY WINAPI SetupDiOpenClassRegKeyExW(
         if (rc != ERROR_SUCCESS)
         {
             SetLastError(rc);
-            return INVALID_HANDLE_VALUE;
+            goto cleanup;
         }
     }
     else
         HKLM = HKEY_LOCAL_MACHINE;
 
     rc = RegOpenKeyExW(HKLM,
-                     lpKeyName,
-                     0,
-                     ClassGuid ? 0 : samDesired,
-                     &hClassesKey);
+                      lpKeyName,
+                      0,
+                      ClassGuid ? 0 : samDesired,
+                      &hClassesKey);
     if (MachineName != NULL) RegCloseKey(HKLM);
     if (rc != ERROR_SUCCESS)
     {
-       SetLastError(rc);
-       return INVALID_HANDLE_VALUE;
+        SetLastError(rc);
+        goto cleanup;
     }
 
     if (ClassGuid == NULL)
-        return hClassesKey;
+    {
+        /* Stop here. We don't need to open a subkey */
+        ret = hClassesKey;
+        goto cleanup;
+    }
 
     if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK)
     {
-       SetLastError(ERROR_GEN_FAILURE);
-       RegCloseKey(hClassesKey);
-       return INVALID_HANDLE_VALUE;
+        SetLastError(ERROR_GEN_FAILURE);
+        goto cleanup;
     }
 
     dwLength = lstrlenW(lpGuidString);
@@ -3357,42 +3666,46 @@ HKEY WINAPI SetupDiOpenClassRegKeyExW(
     if (!lpFullGuidString)
     {
         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        RpcStringFreeW(&lpGuidString);
-        return INVALID_HANDLE_VALUE;
+        goto cleanup;
     }
     lpFullGuidString[0] = '{';
     memcpy(&lpFullGuidString[1], lpGuidString, dwLength * sizeof(WCHAR));
     lpFullGuidString[dwLength + 1] = '}';
     lpFullGuidString[dwLength + 2] = '\0';
-    RpcStringFreeW(&lpGuidString);
 
     rc = RegOpenKeyExW(hClassesKey,
-                     lpFullGuidString,
-                     0,
-                     samDesired,
-                     &hClassKey);
+                       lpFullGuidString,
+                       0,
+                       samDesired,
+                       &hClassKey);
     if (rc != ERROR_SUCCESS)
     {
-       SetLastError(rc);
-       HeapFree(GetProcessHeap(), 0, lpFullGuidString);
-       RegCloseKey(hClassesKey);
-       return INVALID_HANDLE_VALUE;
+        SetLastError(rc);
+        goto cleanup;
     }
+    ret = hClassKey;
 
+cleanup:
+    if (hClassKey != NULL && hClassKey != ret)
+        RegCloseKey(hClassKey);
+    if (hClassesKey != NULL && hClassesKey != ret)
+        RegCloseKey(hClassesKey);
+    if (lpGuidString)
+        RpcStringFreeW(&lpGuidString);
     HeapFree(GetProcessHeap(), 0, lpFullGuidString);
-    RegCloseKey(hClassesKey);
 
-    return hClassKey;
+    return ret;
 }
 
 /***********************************************************************
  *             SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiOpenDeviceInterfaceW(
-       HDEVINFO DeviceInfoSet,
-       PCWSTR DevicePath,
-       DWORD OpenFlags,
-       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
+BOOL WINAPI
+SetupDiOpenDeviceInterfaceW(
+    IN HDEVINFO DeviceInfoSet,
+    IN PCWSTR DevicePath,
+    IN DWORD OpenFlags,
+    OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData OPTIONAL)
 {
     FIXME("%p %s %08lx %p\n",
         DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
@@ -3402,11 +3715,12 @@ BOOL WINAPI SetupDiOpenDeviceInterfaceW(
 /***********************************************************************
  *             SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiOpenDeviceInterfaceA(
-       HDEVINFO DeviceInfoSet,
-       PCSTR DevicePath,
-       DWORD OpenFlags,
-       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
+BOOL WINAPI
+SetupDiOpenDeviceInterfaceA(
+    IN HDEVINFO DeviceInfoSet,
+    IN PCSTR DevicePath,
+    IN DWORD OpenFlags,
+    OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData OPTIONAL)
 {
     LPWSTR DevicePathW = NULL;
     BOOL bResult;
@@ -3428,11 +3742,12 @@ BOOL WINAPI SetupDiOpenDeviceInterfaceA(
 /***********************************************************************
  *             SetupDiSetClassInstallParamsA (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiSetClassInstallParamsA(
-       HDEVINFO  DeviceInfoSet,
-       PSP_DEVINFO_DATA DeviceInfoData,
-       PSP_CLASSINSTALL_HEADER ClassInstallParams,
-       DWORD ClassInstallParamsSize)
+BOOL WINAPI
+SetupDiSetClassInstallParamsA(
+    IN HDEVINFO  DeviceInfoSet,
+    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+    IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
+    IN DWORD ClassInstallParamsSize)
 {
     FIXME("%p %p %x %lu\n",DeviceInfoSet, DeviceInfoData,
           ClassInstallParams->InstallFunction, ClassInstallParamsSize);
@@ -3442,11 +3757,12 @@ BOOL WINAPI SetupDiSetClassInstallParamsA(
 /***********************************************************************
  *             SetupDiSetClassInstallParamsW (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiSetClassInstallParamsW(
-       IN HDEVINFO DeviceInfoSet,
-       IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
-       IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
-       IN DWORD ClassInstallParamsSize)
+BOOL WINAPI
+SetupDiSetClassInstallParamsW(
+    IN HDEVINFO DeviceInfoSet,
+    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+    IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
+    IN DWORD ClassInstallParamsSize)
 {
     struct DeviceInfoSet *list;
     BOOL ret = FALSE;
@@ -3511,11 +3827,12 @@ done:
     return ret;
 }
 
-static BOOL PropertyChangeHandler(
-       IN HDEVINFO DeviceInfoSet,
-       IN PSP_DEVINFO_DATA DeviceInfoData,
-       IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
-       IN DWORD ClassInstallParamsSize)
+static BOOL
+PropertyChangeHandler(
+    IN HDEVINFO DeviceInfoSet,
+    IN PSP_DEVINFO_DATA DeviceInfoData,
+    IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
+    IN DWORD ClassInstallParamsSize)
 {
     PSP_PROPCHANGE_PARAMS PropChangeParams = (PSP_PROPCHANGE_PARAMS)ClassInstallParams;
     BOOL ret = FALSE;
@@ -3572,9 +3889,9 @@ done:
 
 static DWORD
 GetFunctionPointer(
-        IN PWSTR InstallerName,
-        OUT HMODULE* ModulePointer,
-        OUT PVOID* FunctionPointer)
+    IN PWSTR InstallerName,
+    OUT HMODULE* ModulePointer,
+    OUT PVOID* FunctionPointer)
 {
     HMODULE hModule = NULL;
     LPSTR FunctionNameA = NULL;
@@ -3633,8 +3950,8 @@ cleanup:
 
 static DWORD
 FreeFunctionPointer(
-        IN HMODULE ModulePointer,
-        IN PVOID FunctionPointer)
+    IN HMODULE ModulePointer,
+    IN PVOID FunctionPointer)
 {
     if (ModulePointer == NULL)
         return ERROR_SUCCESS;
@@ -3655,10 +3972,11 @@ IntSetupDiRegisterDeviceInfo(
 /***********************************************************************
  *             SetupDiCallClassInstaller (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiCallClassInstaller(
-       IN DI_FUNCTION InstallFunction,
-       IN HDEVINFO DeviceInfoSet,
-       IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
+BOOL WINAPI
+SetupDiCallClassInstaller(
+    IN DI_FUNCTION InstallFunction,
+    IN HDEVINFO DeviceInfoSet,
+    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
 {
     BOOL ret = FALSE;
 
@@ -3903,7 +4221,8 @@ BOOL WINAPI SetupDiCallClassInstaller(
             ListEntry = ClassCoInstallersListHead.Flink;
             while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead)
             {
-                struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
+                struct CoInstallerElement *coinstaller;
+                coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
                 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
                 coinstaller->PrivateData = Context.PrivateData;
                 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
@@ -3918,7 +4237,8 @@ BOOL WINAPI SetupDiCallClassInstaller(
             ListEntry = DeviceCoInstallersListHead.Flink;
             while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead)
             {
-                struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
+                struct CoInstallerElement *coinstaller;
+                coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
                 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
                 coinstaller->PrivateData = Context.PrivateData;
                 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
@@ -3957,7 +4277,8 @@ BOOL WINAPI SetupDiCallClassInstaller(
             ListEntry = ClassCoInstallersListHead.Flink;
             while (ListEntry != &ClassCoInstallersListHead)
             {
-                struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
+                struct CoInstallerElement *coinstaller;
+                coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
                 if (coinstaller->DoPostProcessing)
                 {
                     Context.InstallResult = rc;
@@ -3972,7 +4293,8 @@ BOOL WINAPI SetupDiCallClassInstaller(
             ListEntry = DeviceCoInstallersListHead.Flink;
             while (ListEntry != &DeviceCoInstallersListHead)
             {
-                struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry;
+                struct CoInstallerElement *coinstaller;
+                coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
                 if (coinstaller->DoPostProcessing)
                 {
                     Context.InstallResult = rc;
@@ -3987,12 +4309,12 @@ BOOL WINAPI SetupDiCallClassInstaller(
             while (!IsListEmpty(&ClassCoInstallersListHead))
             {
                 ListEntry = RemoveHeadList(&ClassCoInstallersListHead);
-                HeapFree(GetProcessHeap(), 0, ListEntry);
+                HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry));
             }
             while (!IsListEmpty(&DeviceCoInstallersListHead))
             {
                 ListEntry = RemoveHeadList(&DeviceCoInstallersListHead);
-                HeapFree(GetProcessHeap(), 0, ListEntry);
+                HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry));
             }
 
             ret = (rc == NO_ERROR);
@@ -4006,9 +4328,10 @@ BOOL WINAPI SetupDiCallClassInstaller(
 /***********************************************************************
  *             SetupDiGetDeviceInfoListClass  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetDeviceInfoListClass(
-        IN HDEVINFO DeviceInfoSet,
-        OUT LPGUID ClassGuid)
+BOOL WINAPI
+SetupDiGetDeviceInfoListClass(
+    IN HDEVINFO DeviceInfoSet,
+    OUT LPGUID ClassGuid)
 {
     struct DeviceInfoSet *list;
     BOOL ret = FALSE;
@@ -4035,9 +4358,10 @@ BOOL WINAPI SetupDiGetDeviceInfoListClass(
 /***********************************************************************
  *             SetupDiGetDeviceInfoListDetailW  (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
-        IN HDEVINFO DeviceInfoSet,
-        OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData)
+BOOL WINAPI
+SetupDiGetDeviceInfoListDetailW(
+    IN HDEVINFO DeviceInfoSet,
+    OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData)
 {
     struct DeviceInfoSet *list;
     BOOL ret = FALSE;
@@ -4074,10 +4398,11 @@ BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
 /***********************************************************************
  *             SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetDeviceInstallParamsA(
-       IN HDEVINFO DeviceInfoSet,
-       IN PSP_DEVINFO_DATA DeviceInfoData,
-       OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
+BOOL WINAPI
+SetupDiGetDeviceInstallParamsA(
+    IN HDEVINFO DeviceInfoSet,
+    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+    OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
 {
     SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
     BOOL ret = FALSE;
@@ -4116,10 +4441,11 @@ BOOL WINAPI SetupDiGetDeviceInstallParamsA(
 /***********************************************************************
  *             SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetDeviceInstallParamsW(
-       IN HDEVINFO DeviceInfoSet,
-       IN PSP_DEVINFO_DATA DeviceInfoData,
-       OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
+BOOL WINAPI
+SetupDiGetDeviceInstallParamsW(
+    IN HDEVINFO DeviceInfoSet,
+    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+    OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
 {
     struct DeviceInfoSet *list;
     BOOL ret = FALSE;
@@ -4154,7 +4480,7 @@ BOOL WINAPI SetupDiGetDeviceInstallParamsW(
 
 static BOOL
 CheckDeviceInstallParameters(
-       IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
+    IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
 {
     DWORD SupportedFlags =
         DI_NOVCP |                            /* 0x00000008 */
@@ -4167,6 +4493,7 @@ CheckDeviceInstallParameters(
         DI_ENUMSINGLEINF |                    /* 0x00010000 */
         DI_CLASSINSTALLPARAMS |               /* 0x00100000 */
         DI_NODI_DEFAULTACTION |               /* 0x00200000 */
+        DI_QUIETINSTALL |                     /* 0x00800000 */
         DI_NOFILECOPY |                       /* 0x01000000 */
         DI_DRIVERPAGE_ADDED;                  /* 0x04000000 */
     DWORD SupportedFlagsEx =
@@ -4208,10 +4535,11 @@ CheckDeviceInstallParameters(
 /***********************************************************************
  *             SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiSetDeviceInstallParamsW(
-       IN HDEVINFO DeviceInfoSet,
-       IN PSP_DEVINFO_DATA DeviceInfoData,
-       IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
+BOOL WINAPI
+SetupDiSetDeviceInstallParamsW(
+    IN HDEVINFO DeviceInfoSet,
+    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+    IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
 {
     struct DeviceInfoSet *list;
     BOOL ret = FALSE;
@@ -4247,12 +4575,13 @@ BOOL WINAPI SetupDiSetDeviceInstallParamsW(
 /***********************************************************************
  *             SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetDeviceInstanceIdA(
-        IN HDEVINFO DeviceInfoSet,
-        IN PSP_DEVINFO_DATA DeviceInfoData,
-        OUT PSTR DeviceInstanceId OPTIONAL,
-        IN DWORD DeviceInstanceIdSize,
-        OUT PDWORD RequiredSize OPTIONAL)
+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;
@@ -4293,12 +4622,13 @@ BOOL WINAPI SetupDiGetDeviceInstanceIdA(
 /***********************************************************************
  *             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 WINAPI
+SetupDiGetDeviceInstanceIdW(
+    IN HDEVINFO DeviceInfoSet,
+    IN PSP_DEVINFO_DATA DeviceInfoData,
+    OUT PWSTR DeviceInstanceId OPTIONAL,
+    IN DWORD DeviceInstanceIdSize,
+    OUT PDWORD RequiredSize OPTIONAL)
 {
     BOOL ret = FALSE;
 
@@ -4322,13 +4652,13 @@ BOOL WINAPI SetupDiGetDeviceInstanceIdW(
         struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
         DWORD required;
 
-        required = (wcslen(DevInfo->DeviceName) + 1) * sizeof(WCHAR);
+        required = (strlenW(DevInfo->DeviceName) + 1) * sizeof(WCHAR);
         if (RequiredSize)
             *RequiredSize = required;
 
         if (required <= DeviceInstanceIdSize)
         {
-            wcscpy(DeviceInstanceId, DevInfo->DeviceName);
+            strcpyW(DeviceInstanceId, DevInfo->DeviceName);
             ret = TRUE;
         }
         else
@@ -4342,13 +4672,14 @@ BOOL WINAPI SetupDiGetDeviceInstanceIdW(
 /***********************************************************************
  *             SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetClassDevPropertySheetsA(
-        IN HDEVINFO DeviceInfoSet,
-        IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
-        IN LPPROPSHEETHEADERA PropertySheetHeader,
-        IN DWORD PropertySheetHeaderPageListSize,
-        OUT PDWORD RequiredSize OPTIONAL,
-        IN DWORD PropertySheetType)
+BOOL WINAPI
+SetupDiGetClassDevPropertySheetsA(
+    IN HDEVINFO DeviceInfoSet,
+    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+    IN LPPROPSHEETHEADERA PropertySheetHeader,
+    IN DWORD PropertySheetHeaderPageListSize,
+    OUT PDWORD RequiredSize OPTIONAL,
+    IN DWORD PropertySheetType)
 {
     PROPSHEETHEADERW psh;
     BOOL ret = FALSE;
@@ -4380,9 +4711,10 @@ struct ClassDevPropertySheetsData
     DWORD NumberOfPages;
 };
 
-static BOOL WINAPI GetClassDevPropertySheetsCallback(
-        IN HPROPSHEETPAGE hPropSheetPage,
-        IN OUT LPARAM lParam)
+static BOOL WINAPI
+GetClassDevPropertySheetsCallback(
+    IN HPROPSHEETPAGE hPropSheetPage,
+    IN OUT LPARAM lParam)
 {
     struct ClassDevPropertySheetsData *PropPageData;
 
@@ -4401,13 +4733,14 @@ static BOOL WINAPI GetClassDevPropertySheetsCallback(
 /***********************************************************************
  *             SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
  */
-BOOL WINAPI SetupDiGetClassDevPropertySheetsW(
-        IN HDEVINFO DeviceInfoSet,
-        IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
-        IN OUT LPPROPSHEETHEADERW PropertySheetHeader,
-        IN DWORD PropertySheetHeaderPageListSize,
-        OUT PDWORD RequiredSize OPTIONAL,
-        IN DWORD PropertySheetType)
+BOOL WINAPI
+SetupDiGetClassDevPropertySheetsW(
+    IN HDEVINFO DeviceInfoSet,
+    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+    IN OUT LPPROPSHEETHEADERW PropertySheetHeader,
+    IN DWORD PropertySheetHeaderPageListSize,
+    OUT PDWORD RequiredSize OPTIONAL,
+    IN DWORD PropertySheetType)
 {
     struct DeviceInfoSet *list;
     BOOL ret = FALSE;
@@ -4532,14 +4865,15 @@ cleanup:
 /***********************************************************************
  *             SetupDiCreateDevRegKeyA (SETUPAPI.@)
  */
-HKEY WINAPI SetupDiCreateDevRegKeyA(
-        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)
+HKEY WINAPI
+SetupDiCreateDevRegKeyA(
+    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)
 {
     PCWSTR InfSectionNameW = NULL;
     HKEY ret = INVALID_HANDLE_VALUE;
@@ -4566,12 +4900,12 @@ HKEY WINAPI SetupDiCreateDevRegKeyA(
 
 static HKEY
 OpenHardwareProfileKey(
-        IN HKEY HKLM,
-        IN DWORD HwProfile,
-        IN DWORD samDesired)
+    IN HKEY HKLM,
+    IN DWORD HwProfile,
+    IN DWORD samDesired)
 {
-    HKEY hHWProfilesKey = INVALID_HANDLE_VALUE;
-    HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
+    HKEY hHWProfilesKey = NULL;
+    HKEY hHWProfileKey = NULL;
     HKEY ret = INVALID_HANDLE_VALUE;
     LONG rc;
 
@@ -4614,9 +4948,9 @@ OpenHardwareProfileKey(
     ret = hHWProfileKey;
 
 cleanup:
-    if (hHWProfilesKey != INVALID_HANDLE_VALUE)
+    if (hHWProfilesKey != NULL)
         RegCloseKey(hHWProfilesKey);
-    if (hHWProfileKey != INVALID_HANDLE_VALUE && hHWProfileKey != ret)
+    if (hHWProfileKey != NULL && hHWProfileKey != ret)
         RegCloseKey(hHWProfileKey);
     return ret;
 }
@@ -4624,14 +4958,15 @@ cleanup:
 /***********************************************************************
  *             SetupDiCreateDevRegKeyW (SETUPAPI.@)
  */
-HKEY WINAPI SetupDiCreateDevRegKeyW(
-        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)
+HKEY WINAPI
+SetupDiCreateDevRegKeyW(
+    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)
 {
     struct DeviceInfoSet *list;
     HKEY ret = INVALID_HANDLE_VALUE;
@@ -4663,10 +4998,10 @@ HKEY WINAPI SetupDiCreateDevRegKeyW(
         DWORD Index; /* Index used in the DriverKey name */
         DWORD rc;
         HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
-        HKEY hEnumKey = INVALID_HANDLE_VALUE;
-        HKEY hClassKey = INVALID_HANDLE_VALUE;
+        HKEY hEnumKey = NULL;
+        HKEY hClassKey = NULL;
         HKEY hDeviceKey = INVALID_HANDLE_VALUE;
-        HKEY hKey = INVALID_HANDLE_VALUE;
+        HKEY hKey = NULL;
         HKEY RootKey;
 
         if (Scope == DICS_FLAG_GLOBAL)
@@ -4723,16 +5058,16 @@ HKEY WINAPI SetupDiCreateDevRegKeyW(
             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, (wcslen(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_STRING));
+            DriverKey = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_STRING));
             if (!DriverKey)
             {
                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
                 goto cleanup;
             }
-            wcscpy(DriverKey, L"{");
-            wcscat(DriverKey, lpGuidString);
-            wcscat(DriverKey, L"}\\");
-            pDeviceInstance = &DriverKey[wcslen(DriverKey)];
+            strcpyW(DriverKey, L"{");
+            strcatW(DriverKey, lpGuidString);
+            strcatW(DriverKey, L"}\\");
+            pDeviceInstance = &DriverKey[strlenW(DriverKey)];
             rc = RegOpenKeyExW(RootKey,
                 REGSTR_PATH_CLASS_NT,
                 0,
@@ -4771,7 +5106,7 @@ HKEY WINAPI SetupDiCreateDevRegKeyW(
                 if (Disposition == REG_CREATED_NEW_KEY)
                     break;
                 RegCloseKey(hKey);
-                hKey = INVALID_HANDLE_VALUE;
+                hKey = NULL;
                 Index++;
             }
             if (Index > 9999)
@@ -4785,7 +5120,7 @@ HKEY WINAPI SetupDiCreateDevRegKeyW(
             hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_SET_VALUE);
             if (hDeviceKey == INVALID_HANDLE_VALUE)
                 goto cleanup;
-            rc = RegSetValueEx(hDeviceKey, REGSTR_VAL_DRIVER, 0, REG_SZ, (const BYTE *)DriverKey, (wcslen(DriverKey) + 1) * sizeof(WCHAR));
+            rc = RegSetValueEx(hDeviceKey, REGSTR_VAL_DRIVER, 0, REG_SZ, (const BYTE *)DriverKey, (strlenW(DriverKey) + 1) * sizeof(WCHAR));
             if (rc != ERROR_SUCCESS)
             {
                 SetLastError(rc);
@@ -4807,13 +5142,13 @@ cleanup:
         HeapFree(GetProcessHeap(), 0, DriverKey);
         if (hHWProfileKey != INVALID_HANDLE_VALUE)
             RegCloseKey(hHWProfileKey);
-        if (hEnumKey != INVALID_HANDLE_VALUE)
+        if (hEnumKey != NULL)
             RegCloseKey(hEnumKey);
-        if (hClassKey != INVALID_HANDLE_VALUE)
+        if (hClassKey != NULL)
             RegCloseKey(hClassKey);
         if (hDeviceKey != INVALID_HANDLE_VALUE)
             RegCloseKey(hDeviceKey);
-        if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
+        if (hKey != NULL && hKey != ret)
             RegCloseKey(hKey);
     }
 
@@ -4824,13 +5159,14 @@ cleanup:
 /***********************************************************************
  *             SetupDiOpenDevRegKey (SETUPAPI.@)
  */
-HKEY WINAPI SetupDiOpenDevRegKey(
-       HDEVINFO DeviceInfoSet,
-       PSP_DEVINFO_DATA DeviceInfoData,
-       DWORD Scope,
-       DWORD HwProfile,
-       DWORD KeyType,
-       REGSAM samDesired)
+HKEY WINAPI
+SetupDiOpenDevRegKey(
+    IN HDEVINFO DeviceInfoSet,
+    IN PSP_DEVINFO_DATA DeviceInfoData,
+    IN DWORD Scope,
+    IN DWORD HwProfile,
+    IN DWORD KeyType,
+    IN REGSAM samDesired)
 {
     struct DeviceInfoSet *list;
     HKEY ret = INVALID_HANDLE_VALUE;
@@ -4858,8 +5194,8 @@ HKEY WINAPI SetupDiOpenDevRegKey(
         DWORD dwRegType;
         DWORD rc;
         HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
-        HKEY hEnumKey = INVALID_HANDLE_VALUE;
-        HKEY hKey = INVALID_HANDLE_VALUE;
+        HKEY hEnumKey = NULL;
+        HKEY hKey = NULL;
         HKEY RootKey;
 
         if (Scope == DICS_FLAG_GLOBAL)
@@ -4890,7 +5226,7 @@ HKEY WINAPI SetupDiOpenDevRegKey(
             KeyType == DIREG_DEV ? samDesired : KEY_QUERY_VALUE,
             &hKey);
         RegCloseKey(hEnumKey);
-        hEnumKey = INVALID_HANDLE_VALUE;
+        hEnumKey = NULL;
         if (rc != ERROR_SUCCESS)
         {
             SetLastError(rc);
@@ -4927,7 +5263,7 @@ HKEY WINAPI SetupDiOpenDevRegKey(
             goto cleanup;
         }
         RegCloseKey(hKey);
-        hKey = INVALID_HANDLE_VALUE;
+        hKey = NULL;
         /* Need to open the driver key */
         rc = RegOpenKeyExW(
             RootKey,
@@ -4956,9 +5292,9 @@ HKEY WINAPI SetupDiOpenDevRegKey(
 cleanup:
         if (hHWProfileKey != INVALID_HANDLE_VALUE)
             RegCloseKey(hHWProfileKey);
-        if (hEnumKey != INVALID_HANDLE_VALUE)
+        if (hEnumKey != NULL)
             RegCloseKey(hEnumKey);
-        if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
+        if (hKey != NULL && hKey != ret)
             RegCloseKey(hKey);
     }
 
@@ -4969,14 +5305,15 @@ cleanup:
 /***********************************************************************
  *             SetupDiCreateDeviceInfoA (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiCreateDeviceInfoA(
-       HDEVINFO DeviceInfoSet,
-       PCSTR DeviceName,
-       CONST GUID *ClassGuid,
-       PCSTR DeviceDescription,
-       HWND hwndParent,
-       DWORD CreationFlags,
-       PSP_DEVINFO_DATA DeviceInfoData)
+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)
 {
     LPWSTR DeviceNameW = NULL;
     LPWSTR DeviceDescriptionW = NULL;
@@ -5013,20 +5350,21 @@ BOOL WINAPI SetupDiCreateDeviceInfoA(
 /***********************************************************************
  *             SetupDiCreateDeviceInfoW (SETUPAPI.@)
  */
-BOOL WINAPI SetupDiCreateDeviceInfoW(
-       HDEVINFO DeviceInfoSet,
-       PCWSTR DeviceName,
-       CONST GUID *ClassGuid,
-       PCWSTR DeviceDescription,
-       HWND hwndParent,
-       DWORD CreationFlags,
-       PSP_DEVINFO_DATA DeviceInfoData)
+BOOL WINAPI
+SetupDiCreateDeviceInfoW(
+    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)
 {
     struct DeviceInfoSet *list;
     BOOL ret = FALSE;
 
-    TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet, DeviceName,
-        debugstr_guid(ClassGuid), DeviceDescription,
+    TRACE("%p %s %s %s %p %lx %p\n", DeviceInfoSet, debugstr_w(DeviceName),
+        debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
         hwndParent, CreationFlags, DeviceInfoData);
 
     if (!DeviceInfoSet)
@@ -5143,7 +5481,7 @@ AddDriverToList(
     driverInfo->Details.Reserved = (ULONG_PTR)driverInfo;
 
     /* Copy InfFileName field */
-    wcsncpy(driverInfo->Details.InfFileName, InfFile, MAX_PATH - 1);
+    strncpyW(driverInfo->Details.InfFileName, InfFile, MAX_PATH - 1);
     driverInfo->Details.InfFileName[MAX_PATH - 1] = '\0';
 
     /* Fill InfDate field */
@@ -5175,13 +5513,13 @@ AddDriverToList(
     /* Copy MatchingId information */
     if (MatchingId)
     {
-        driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
+        driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (strlenW(MatchingId) + 1) * sizeof(WCHAR));
         if (!driverInfo->MatchingId)
         {
             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
             goto cleanup;
         }
-        RtlCopyMemory(driverInfo->MatchingId, MatchingId, (wcslen(MatchingId) + 1) * sizeof(WCHAR));
+        RtlCopyMemory(driverInfo->MatchingId, MatchingId, (strlenW(MatchingId) + 1) * sizeof(WCHAR));
     }
     else
         driverInfo->MatchingId = NULL;
@@ -5205,21 +5543,22 @@ AddDriverToList(
     if (!Result)
         goto cleanup;
 
-    TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
-        driverInfo->Details.DrvDescription, InfFile, InfInstallSection, Rank);
+    TRACE("Adding driver '%s' [%s/%s] (Rank 0x%lx)\n",
+        debugstr_w(driverInfo->Details.DrvDescription), debugstr_w(InfFile),
+        debugstr_w(InfInstallSection), Rank);
 
     driverInfo->DriverRank = Rank;
     memcpy(&driverInfo->DriverDate, &DriverDate, sizeof(FILETIME));
     memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID));
     driverInfo->Info.DriverType = DriverType;
     driverInfo->Info.Reserved = (ULONG_PTR)driverInfo;
-    wcsncpy(driverInfo->Info.Description, driverInfo->Details.DrvDescription, LINE_LEN - 1);
+    strncpyW(driverInfo->Info.Description, driverInfo->Details.DrvDescription, LINE_LEN - 1);
     driverInfo->Info.Description[LINE_LEN - 1] = '\0';
-    wcsncpy(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1);
+    strncpyW(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1);
     driverInfo->Info.MfgName[LINE_LEN - 1] = '\0';
     if (ProviderName)
     {
-        wcsncpy(driverInfo->Info.ProviderName, ProviderName, LINE_LEN - 1);
+        strncpyW(driverInfo->Info.ProviderName, ProviderName, LINE_LEN - 1);
         driverInfo->Info.ProviderName[LINE_LEN - 1] = '\0';
     }
     else
@@ -5288,7 +5627,7 @@ GetVersionInformationFromInfFile(
     if (!SetupGetLineTextW(
         NULL, /* Context */
         hInf,
-        L"Version", L"ClassGUID",
+        Version, ClassGUID,
         guidW, sizeof(guidW),
         NULL /* Required size */))
     {
@@ -5304,7 +5643,7 @@ GetVersionInformationFromInfFile(
     /* Get provider name */
     Result = SetupGetLineTextW(
         NULL, /* Context */
-        hInf, L"Version", L"Provider",
+        hInf, Version, INF_PROVIDER,
         NULL, 0,
         &RequiredSize);
     if (Result)
@@ -5318,7 +5657,7 @@ GetVersionInformationFromInfFile(
         }
         Result = SetupGetLineTextW(
             NULL, /* Context */
-            hInf, L"Version", L"Provider",
+            hInf, Version, INF_PROVIDER,
             ProviderName, RequiredSize,
             &RequiredSize);
     }
@@ -5329,7 +5668,7 @@ GetVersionInformationFromInfFile(
     /* Read the "DriverVer" value */
     Result = SetupGetLineTextW(
         NULL, /* Context */
-        hInf, L"Version", L"DriverVer",
+        hInf, Version, INF_DRIVER_VER,
         NULL, 0,
         &RequiredSize);
     if (Result)
@@ -5343,7 +5682,7 @@ GetVersionInformationFromInfFile(
         }
         Result = SetupGetLineTextW(
             NULL, /* Context */
-            hInf, L"Version", L"DriverVer",
+            hInf, Version, INF_DRIVER_VER,
             DriverVer, RequiredSize,
             &RequiredSize);
     }
@@ -5351,7 +5690,7 @@ GetVersionInformationFromInfFile(
         goto cleanup;
 
     /* Get driver date and driver version, by analyzing the "DriverVer" value */
-    pComma = wcschr(DriverVer, ',');
+    pComma = strchrW(DriverVer, ',');
     if (pComma != NULL)
     {
         *pComma = UNICODE_NULL;
@@ -5359,7 +5698,7 @@ GetVersionInformationFromInfFile(
     }
     /* Get driver date version. Invalid date = 00/00/00 */
     memset(DriverDate, 0, sizeof(FILETIME));
-    if (wcslen(DriverVer) == 10
+    if (strlenW(DriverVer) == 10
         && (DriverVer[2] == '-' || DriverVer[2] == '/')
         && (DriverVer[5] == '-' || DriverVer[5] == '/'))
     {
@@ -5413,6 +5752,150 @@ cleanup:
     return ret;
 }
 
+static BOOL
+GetHardwareAndCompatibleIDsLists(
+    IN HDEVINFO DeviceInfoSet,
+    IN OUT PSP_DEVINFO_DATA DeviceInfoData,
+    OUT LPWSTR *pHardwareIDs OPTIONAL,
+    OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL,
+    OUT LPWSTR *pCompatibleIDs OPTIONAL,
+    OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL)
+{
+    LPWSTR HardwareIDs = NULL;
+    LPWSTR CompatibleIDs = NULL;
+    DWORD RequiredSize;
+    BOOL Result;
+
+    /* Get hardware IDs list */
+    Result = FALSE;
+    RequiredSize = 512; /* Initial buffer size */
+    SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+    {
+        MyFree(HardwareIDs);
+        HardwareIDs = MyMalloc(RequiredSize);
+        if (!HardwareIDs)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            goto done;
+        }
+        Result = SetupDiGetDeviceRegistryPropertyW(
+            DeviceInfoSet,
+            DeviceInfoData,
+            SPDRP_HARDWAREID,
+            NULL,
+            (PBYTE)HardwareIDs,
+            RequiredSize,
+            &RequiredSize);
+    }
+    if (!Result)
+    {
+        if (GetLastError() == ERROR_FILE_NOT_FOUND)
+        {
+            /* No hardware ID for this device */
+            MyFree(HardwareIDs);
+            HardwareIDs = NULL;
+            RequiredSize = 0;
+        }
+        else
+            goto done;
+    }
+    if (pHardwareIDs)
+        *pHardwareIDs = HardwareIDs;
+    if (pHardwareIDsRequiredSize)
+        *pHardwareIDsRequiredSize = RequiredSize;
+
+    /* Get compatible IDs list */
+    Result = FALSE;
+    RequiredSize = 512; /* Initial buffer size */
+    SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+    {
+        MyFree(CompatibleIDs);
+        CompatibleIDs = MyMalloc(RequiredSize);
+        if (!CompatibleIDs)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            goto done;
+        }
+        Result = SetupDiGetDeviceRegistryPropertyW(
+            DeviceInfoSet,
+            DeviceInfoData,
+            SPDRP_COMPATIBLEIDS,
+            NULL,
+            (PBYTE)CompatibleIDs,
+            RequiredSize,
+            &RequiredSize);
+    }
+    if (!Result)
+    {
+        if (GetLastError() == ERROR_FILE_NOT_FOUND)
+        {
+            /* No compatible ID for this device */
+            MyFree(CompatibleIDs);
+            CompatibleIDs = NULL;
+            RequiredSize = 0;
+        }
+        else
+            goto done;
+    }
+    if (pCompatibleIDs)
+        *pCompatibleIDs = CompatibleIDs;
+    if (pCompatibleIDsRequiredSize)
+        *pCompatibleIDsRequiredSize = RequiredSize;
+
+    Result = TRUE;
+
+done:
+    if (!Result)
+    {
+        MyFree(HardwareIDs);
+        MyFree(CompatibleIDs);
+    }
+    return Result;
+}
+
+static struct InfFileDetails *
+CreateInfFileDetails(
+    IN LPCWSTR InfFileName)
+{
+    struct InfFileDetails *details;
+    PWCHAR last;
+    DWORD Needed;
+
+    last = strrchrW(InfFileName, '\\');
+    Needed = FIELD_OFFSET(struct InfFileDetails, szData)
+        + strlenW(InfFileName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
+    if (last != NULL)
+    Needed += (last - InfFileName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
+
+    details = HeapAlloc(GetProcessHeap(), 0, Needed);
+    if (!details)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return NULL;
+    }
+
+    memset(details, 0, Needed);
+    if (last)
+    {
+        details->DirectoryName = details->szData;
+        details->FullInfFileName = &details->szData[last - InfFileName + 1];
+        strncpyW(details->DirectoryName, InfFileName, last - InfFileName);
+    }
+    else
+        details->FullInfFileName = details->szData;
+    strcpyW(details->FullInfFileName, InfFileName);
+    ReferenceInfFile(details);
+    details->hInf = SetupOpenInfFileW(InfFileName, NULL, INF_STYLE_WIN4, NULL);
+    if (details->hInf == INVALID_HANDLE_VALUE)
+    {
+        HeapFree(GetProcessHeap(), 0, details);
+        return NULL;
+    }
+    return details;
+}
+
 /***********************************************************************
  *             SetupDiBuildDriverInfoList (SETUPAPI.@)
  */
@@ -5471,75 +5954,34 @@ SetupDiBuildDriverInfoList(
 
         if (DriverType == SPDIT_COMPATDRIVER)
         {
-            /* Get hardware IDs list */
-            Result = FALSE;
-            RequiredSize = 512; /* Initial buffer size */
-            SetLastError(ERROR_INSUFFICIENT_BUFFER);
-            while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
-            {
-                HeapFree(GetProcessHeap(), 0, HardwareIDs);
-                HardwareIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
-                if (!HardwareIDs)
-                {
-                    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-                    goto done;
-                }
-                Result = SetupDiGetDeviceRegistryPropertyW(
-                    DeviceInfoSet,
-                    DeviceInfoData,
-                    SPDRP_HARDWAREID,
-                    NULL,
-                    (PBYTE)HardwareIDs,
-                    RequiredSize,
-                    &RequiredSize);
-            }
+            /* Get hardware and compatible IDs lists */
+            Result = GetHardwareAndCompatibleIDsLists(
+                DeviceInfoSet,
+                DeviceInfoData,
+                &HardwareIDs,
+                NULL,
+                &CompatibleIDs,
+                NULL);
             if (!Result)
                 goto done;
-
-            /* Get compatible IDs list */
-            Result = FALSE;
-            RequiredSize = 512; /* Initial buffer size */
-            SetLastError(ERROR_INSUFFICIENT_BUFFER);
-            while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+            if (!HardwareIDs && !CompatibleIDs)
             {
-                HeapFree(GetProcessHeap(), 0, CompatibleIDs);
-                CompatibleIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
-                if (!CompatibleIDs)
-                {
-                    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-                    goto done;
-                }
-                Result = SetupDiGetDeviceRegistryPropertyW(
-                    DeviceInfoSet,
-                    DeviceInfoData,
-                    SPDRP_COMPATIBLEIDS,
-                    NULL,
-                    (PBYTE)CompatibleIDs,
-                    RequiredSize,
-                    &RequiredSize);
-                if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
-                {
-                    /* No compatible ID for this device */
-                    HeapFree(GetProcessHeap(), 0, CompatibleIDs);
-                    CompatibleIDs = NULL;
-                    Result = TRUE;
-                }
-            }
-            if (!Result)
+                SetLastError(ERROR_FILE_NOT_FOUND);
                 goto done;
+            }
         }
 
         if (InstallParams.Flags & DI_ENUMSINGLEINF)
         {
             /* InstallParams.DriverPath contains the name of a .inf file */
-            RequiredSize = wcslen(InstallParams.DriverPath) + 2;
+            RequiredSize = strlenW(InstallParams.DriverPath) + 2;
             Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
             if (!Buffer)
             {
                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
                 goto done;
             }
-            wcscpy(Buffer, InstallParams.DriverPath);
+            strcpyW(Buffer, InstallParams.DriverPath);
             ((LPWSTR)Buffer)[RequiredSize - 1] = 0;
             Result = TRUE;
         }
@@ -5598,9 +6040,9 @@ SetupDiBuildDriverInfoList(
                 len = GetFullPathNameW(InstallParams.DriverPath, len, FullInfFileName, NULL);
                 if (len == 0)
                     goto done;
-                if (*FullInfFileName && FullInfFileName[wcslen(FullInfFileName) - 1] != '\\')
-                    wcscat(FullInfFileName, L"\\");
-                pFullFilename = &FullInfFileName[wcslen(FullInfFileName)];
+                if (*FullInfFileName && FullInfFileName[strlenW(FullInfFileName) - 1] != '\\')
+                    strcatW(FullInfFileName, L"\\");
+                pFullFilename = &FullInfFileName[strlenW(FullInfFileName)];
             }
             else
             {
@@ -5610,31 +6052,17 @@ SetupDiBuildDriverInfoList(
                 pFullFilename = &FullInfFileName[0];
             }
 
-            for (filename = (LPCWSTR)Buffer; *filename; filename += wcslen(filename) + 1)
+            for (filename = (LPCWSTR)Buffer; *filename; filename += strlenW(filename) + 1)
             {
                 INFCONTEXT ContextManufacturer, ContextDevice;
                 GUID ClassGuid;
 
-                wcscpy(pFullFilename, filename);
-                TRACE("Opening file %S\n", FullInfFileName);
+                strcpyW(pFullFilename, filename);
+                TRACE("Opening file %s\n", debugstr_w(FullInfFileName));
 
-                currentInfFileDetails = HeapAlloc(
-                    GetProcessHeap(),
-                    0,
-                    FIELD_OFFSET(struct InfFileDetails, FullInfFileName) + wcslen(FullInfFileName) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
+                currentInfFileDetails = CreateInfFileDetails(FullInfFileName);
                 if (!currentInfFileDetails)
                     continue;
-                memset(currentInfFileDetails, 0, sizeof(struct InfFileDetails));
-                wcscpy(currentInfFileDetails->FullInfFileName, FullInfFileName);
-
-                currentInfFileDetails->hInf = SetupOpenInfFileW(FullInfFileName, NULL, INF_STYLE_WIN4, NULL);
-                ReferenceInfFile(currentInfFileDetails);
-                if (currentInfFileDetails->hInf == INVALID_HANDLE_VALUE)
-                {
-                    HeapFree(GetProcessHeap(), 0, currentInfFileDetails);
-                    currentInfFileDetails = NULL;
-                    continue;
-                }
 
                 if (!GetVersionInformationFromInfFile(
                     currentInfFileDetails->hInf,
@@ -5643,8 +6071,7 @@ SetupDiBuildDriverInfoList(
                     &DriverDate,
                     &DriverVersion))
                 {
-                    SetupCloseInfFile(currentInfFileDetails->hInf);
-                    HeapFree(GetProcessHeap(), 0, currentInfFileDetails->hInf);
+                    DereferenceInfFile(currentInfFileDetails);
                     currentInfFileDetails = NULL;
                     continue;
                 }
@@ -5667,7 +6094,7 @@ SetupDiBuildDriverInfoList(
                     FIXME("ExcludeFromSelect list ignored\n");
 
                 /* Get the manufacturers list */
-                Result = SetupFindFirstLineW(currentInfFileDetails->hInf, L"Manufacturer", NULL, &ContextManufacturer);
+                Result = SetupFindFirstLineW(currentInfFileDetails->hInf, INF_MANUFACTURER, NULL, &ContextManufacturer);
                 while (Result)
                 {
                     Result = SetupGetStringFieldW(
@@ -5704,7 +6131,7 @@ SetupDiBuildDriverInfoList(
                             currentInfFileDetails->hInf, ManufacturerSection, ManufacturerSection, LINE_LEN, NULL, NULL);
                         if (Result)
                         {
-                            TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection);
+                            TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection));
                             Result = SetupFindFirstLineW(currentInfFileDetails->hInf, ManufacturerSection, NULL, &ContextDevice);
                         }
                     }
@@ -5766,9 +6193,9 @@ SetupDiBuildDriverInfoList(
                                 }
                                 /* FIXME: Check ExcludeFromSelect list */
                                 DriverAlreadyAdded = FALSE;
-                                for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
+                                for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += strlenW(currentId) + 1, DriverRank++)
                                 {
-                                    if (wcsicmp(DeviceId, currentId) == 0)
+                                    if (strcmpiW(DeviceId, currentId) == 0)
                                     {
                                         AddDriverToList(
                                             pDriverListHead,
@@ -5787,9 +6214,9 @@ SetupDiBuildDriverInfoList(
                                 }
                                 if (CompatibleIDs)
                                 {
-                                    for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
+                                    for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += strlenW(currentId) + 1, DriverRank++)
                                     {
-                                        if (wcsicmp(DeviceId, currentId) == 0)
+                                        if (strcmpiW(DeviceId, currentId) == 0)
                                         {
                                             AddDriverToList(
                                                 pDriverListHead,
@@ -5849,8 +6276,8 @@ done:
 
     HeapFree(GetProcessHeap(), 0, ProviderName);
     HeapFree(GetProcessHeap(), 0, ManufacturerName);
-    HeapFree(GetProcessHeap(), 0, HardwareIDs);
-    HeapFree(GetProcessHeap(), 0, CompatibleIDs);
+    MyFree(HardwareIDs);
+    MyFree(CompatibleIDs);
     HeapFree(GetProcessHeap(), 0, FullInfFileName);
     HeapFree(GetProcessHeap(), 0, ExcludeFromSelect);
     if (currentInfFileDetails)
@@ -5883,7 +6310,7 @@ SetupDiDeleteDeviceInfo(
 BOOL WINAPI
 SetupDiDestroyDriverInfoList(
     IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData,
+    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
     IN DWORD DriverType)
 {
     struct DeviceInfoSet *list;
@@ -5920,7 +6347,7 @@ SetupDiDestroyDriverInfoList(
             while (!IsListEmpty(&list->DriverListHead))
             {
                  ListEntry = RemoveHeadList(&list->DriverListHead);
-                 driverInfo = (struct DriverInfoElement *)ListEntry;
+                 driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry);
                  DestroyDriverInfoElement(driverInfo);
             }
             InstallParams.Reserved = 0;
@@ -5940,7 +6367,7 @@ SetupDiDestroyDriverInfoList(
             while (!IsListEmpty(&deviceInfo->DriverListHead))
             {
                  ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
-                 driverInfo = (struct DriverInfoElement *)ListEntry;
+                 driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry);
                  if ((PVOID)InstallParamsSet.Reserved == driverInfo)
                  {
                      InstallParamsSet.Reserved = 0;
@@ -6002,11 +6429,13 @@ SetupDiOpenDeviceInfoW(
     OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
 {
     struct DeviceInfoSet *list;
-    HKEY hEnumKey, hKey;
+    HKEY hEnumKey, hKey = NULL;
     DWORD rc;
     BOOL ret = FALSE;
 
-    TRACE("%p %S %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
+    TRACE("%p %s %p %lx %p\n",
+        DeviceInfoSet, debugstr_w(DeviceInstanceId),
+        hwndParent, OpenFlags, DeviceInfoData);
 
     if (OpenFlags & DIOD_CANCEL_REMOVE)
         FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
@@ -6058,7 +6487,7 @@ SetupDiOpenDeviceInfoW(
             if (rc != ERROR_SUCCESS)
             {
                 SetLastError(rc);
-                return FALSE;
+                goto cleanup;
             }
             rc = RegOpenKeyExW(
                 hEnumKey,
@@ -6072,20 +6501,16 @@ SetupDiOpenDeviceInfoW(
                 if (rc == ERROR_FILE_NOT_FOUND)
                     rc = ERROR_NO_SUCH_DEVINST;
                 SetLastError(rc);
-                return FALSE;
+                goto cleanup;
             }
 
             /* FIXME: try to get ClassGUID from registry, instead of
              * sending GUID_NULL to CreateDeviceInfoElement
              */
             if (!CreateDeviceInfoElement(list, DeviceInstanceId, &GUID_NULL, &deviceInfo))
-            {
-                RegCloseKey(hKey);
-                return FALSE;
-            }
+                goto cleanup;
             InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
 
-            RegCloseKey(hKey);
             ret = TRUE;
         }
 
@@ -6097,6 +6522,9 @@ SetupDiOpenDeviceInfoW(
         }
     }
 
+cleanup:
+    if (hKey != NULL)
+        RegCloseKey(hKey);
     return ret;
 }
 
@@ -6216,7 +6644,7 @@ SetupDiEnumDriverInfoW(
             SetLastError(ERROR_NO_MORE_ITEMS);
         else
         {
-            struct DriverInfoElement *DrvInfo = (struct DriverInfoElement *)ItemList;
+            struct DriverInfoElement *DrvInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry);
 
             memcpy(
                 &DriverInfoData->DriverType,
@@ -6419,7 +6847,7 @@ SetupDiSetSelectedDevice(
 BOOL WINAPI
 SetupDiSetSelectedDriverA(
     IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+    IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
     IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL)
 {
     SP_DRVINFO_DATA_V1_W DriverInfoDataW;
@@ -6482,7 +6910,7 @@ SetupDiSetSelectedDriverA(
 BOOL WINAPI
 SetupDiSetSelectedDriverW(
     IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+    IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
     IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL)
 {
     BOOL ret = FALSE;
@@ -6536,8 +6964,8 @@ SetupDiSetSelectedDriverW(
                     /* The caller wants to compare only DriverType, Description and ProviderName fields */
                     struct DriverInfoElement *driverInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry);
                     if (driverInfo->Info.DriverType == DriverInfoData->DriverType
-                        && wcscmp(driverInfo->Info.Description, DriverInfoData->Description) == 0
-                        && wcscmp(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0)
+                        && strcmpW(driverInfo->Info.Description, DriverInfoData->Description) == 0
+                        && strcmpW(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0)
                     {
                         break;
                     }
@@ -6548,11 +6976,11 @@ SetupDiSetSelectedDriverW(
                 SetLastError(ERROR_INVALID_PARAMETER);
             else
             {
-                *pDriverInfo = (struct DriverInfoElement *)ItemList;
+                *pDriverInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry);
                 DriverInfoData->Reserved = (ULONG_PTR)ItemList;
                 ret = TRUE;
                 TRACE("Choosing driver whose rank is 0x%lx\n",
-                    ((struct DriverInfoElement *)ItemList)->DriverRank);
+                    (*pDriverInfo)->DriverRank);
                 if (DeviceInfoData)
                     memcpy(&DeviceInfoData->ClassGuid, &(*pDriverInfo)->ClassGuid, sizeof(GUID));
             }
@@ -6571,7 +6999,7 @@ SetupDiGetDriverInfoDetailA(
     IN HDEVINFO DeviceInfoSet,
     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
     IN PSP_DRVINFO_DATA_A DriverInfoData,
-    OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL,
+    IN OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL,
     IN DWORD DriverInfoDetailDataSize,
     OUT PDWORD RequiredSize OPTIONAL)
 {
@@ -6772,7 +7200,7 @@ SetupDiGetDriverInfoDetailW(
     IN HDEVINFO DeviceInfoSet,
     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
     IN PSP_DRVINFO_DATA_W DriverInfoData,
-    OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL,
+    IN OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL,
     IN DWORD DriverInfoDetailDataSize,
     OUT PDWORD RequiredSize OPTIONAL)
 {
@@ -6803,16 +7231,88 @@ SetupDiGetDriverInfoDetailW(
     else
     {
         struct DriverInfoElement *driverInfoElement;
+        LPWSTR HardwareIDs = NULL;
+        LPWSTR CompatibleIDs = NULL;
+        LPWSTR pBuffer = NULL;
+        LPCWSTR DeviceID = NULL;
+        ULONG HardwareIDsSize, CompatibleIDsSize;
+        ULONG sizeNeeded, sizeLeft, size;
+        BOOL Result;
+
         driverInfoElement = (struct DriverInfoElement *)DriverInfoData->Reserved;
 
+        /* Get hardware and compatible IDs lists */
+        Result = GetHardwareAndCompatibleIDsLists(
+            DeviceInfoSet,
+            DeviceInfoData,
+            &HardwareIDs, &HardwareIDsSize,
+            &CompatibleIDs, &CompatibleIDsSize);
+        if (!Result)
+            goto done;
+
+        sizeNeeded = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)
+            + HardwareIDsSize + CompatibleIDsSize;
+        if (RequiredSize)
+            *RequiredSize = sizeNeeded;
+
+        if (!DriverInfoDetailData)
+        {
+            ret = TRUE;
+            goto done;
+        }
+
         memcpy(
             DriverInfoDetailData,
             &driverInfoElement->Details,
             driverInfoElement->Details.cbSize);
-        /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
-         * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
-         */
-        ret = TRUE;
+        DriverInfoDetailData->CompatIDsOffset = 0;
+        DriverInfoDetailData->CompatIDsLength = 0;
+
+        sizeLeft = (DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR);
+        pBuffer = DriverInfoDetailData->HardwareID;
+        /* Add as many as possible HardwareIDs in the list */
+        DeviceID = HardwareIDs;
+        while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft)
+        {
+            TRACE("Adding %s to list\n", debugstr_w(DeviceID));
+            wcscpy(pBuffer, DeviceID);
+            DeviceID += size + 1;
+            pBuffer += size + 1;
+            sizeLeft -= size + 1;
+            DriverInfoDetailData->CompatIDsOffset += size + 1;
+        }
+        if (sizeLeft > 0)
+        {
+            *pBuffer = UNICODE_NULL;
+            sizeLeft--;
+            DriverInfoDetailData->CompatIDsOffset++;
+        }
+        /* Add as many as possible CompatibleIDs in the list */
+        DeviceID = CompatibleIDs;
+        while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft)
+        {
+            TRACE("Adding %s to list\n", debugstr_w(DeviceID));
+            wcscpy(pBuffer, DeviceID);
+            DeviceID += size + 1;
+            pBuffer += size + 1;
+            sizeLeft -= size + 1;
+            DriverInfoDetailData->CompatIDsLength += size + 1;
+        }
+        if (sizeLeft > 0)
+        {
+            *pBuffer = UNICODE_NULL;
+            sizeLeft--;
+            DriverInfoDetailData->CompatIDsLength++;
+        }
+
+        if (sizeNeeded > DriverInfoDetailDataSize)
+            SetLastError(ERROR_INSUFFICIENT_BUFFER);
+        else
+            ret = TRUE;
+
+done:
+        MyFree(HardwareIDs);
+        MyFree(CompatibleIDs);
     }
 
     TRACE("Returning %d\n", ret);
@@ -6824,7 +7324,7 @@ static DWORD
 GetCurrentHwProfile(
     IN HDEVINFO DeviceInfoSet)
 {
-    HKEY hKey = INVALID_HANDLE_VALUE;
+    HKEY hKey = NULL;
     DWORD dwRegType, dwLength;
     DWORD hwProfile;
     LONG rc;
@@ -6863,7 +7363,7 @@ GetCurrentHwProfile(
     ret = hwProfile;
 
 cleanup:
-    if (hKey != INVALID_HANDLE_VALUE)
+    if (hKey != NULL)
         RegCloseKey(hKey);
 
     return hwProfile;
@@ -6874,6 +7374,7 @@ ResetDevice(
     IN HDEVINFO DeviceInfoSet,
     IN PSP_DEVINFO_DATA DeviceInfoData)
 {
+#ifndef __WINESRC__
     PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
     struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
     NTSTATUS Status;
@@ -6889,13 +7390,17 @@ ResetDevice(
     Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
     SetLastError(RtlNtStatusToDosError(Status));
     return NT_SUCCESS(Status);
+#else
+    FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData);
+    return TRUE;
+#endif
 }
 
 static BOOL StopDevice(
     IN HDEVINFO DeviceInfoSet,
     IN PSP_DEVINFO_DATA DeviceInfoData)
 {
-    FIXME("Stub %p %p\n", DeviceInfoSet, DeviceInfoData);
+    FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData);
     return TRUE;
 }
 
@@ -6905,7 +7410,7 @@ static BOOL StopDevice(
 BOOL WINAPI
 SetupDiChangeState(
     IN HDEVINFO DeviceInfoSet,
-    IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
+    IN OUT PSP_DEVINFO_DATA DeviceInfoData)
 {
     PSP_PROPCHANGE_PARAMS PropChange;
     HKEY hKey = INVALID_HANDLE_VALUE;
@@ -7017,7 +7522,7 @@ cleanup:
 BOOL WINAPI
 SetupDiSelectBestCompatDrv(
     IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData)
+    IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
 {
     SP_DRVINFO_DATA_W drvInfoData;
     BOOL ret;
@@ -7053,7 +7558,7 @@ SetupDiSelectBestCompatDrv(
 BOOL WINAPI
 SetupDiInstallDriverFiles(
     IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
+    IN PSP_DEVINFO_DATA DeviceInfoData)
 {
     BOOL ret = FALSE;
 
@@ -7115,7 +7620,7 @@ SetupDiInstallDriverFiles(
         }
         ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
             SelectedDriver->InfFileDetails->hInf, SectionName,
-            SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
+            SPINST_FILES, NULL, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
             InstallMsgHandler, InstallMsgHandlerContext,
             DeviceInfoSet, DeviceInfoData);
         if (!ret)
@@ -7125,7 +7630,7 @@ SetupDiInstallDriverFiles(
         lstrcatW(SectionName, DotCoInstallers);
         ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
             SelectedDriver->InfFileDetails->hInf, SectionName,
-            SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
+            SPINST_FILES, NULL, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
             InstallMsgHandler, InstallMsgHandlerContext,
             DeviceInfoSet, DeviceInfoData);
         if (!ret)
@@ -7222,7 +7727,7 @@ SetupDiRegisterCoDeviceInstallers(
         }
         Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
             SelectedDriver->InfFileDetails->hInf, SectionName,
-            DoAction, hKey, NULL, SP_COPY_NEWER,
+            DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
             SetupDefaultQueueCallback, Context,
             DeviceInfoSet, DeviceInfoData);
         if (!Result)
@@ -7254,7 +7759,7 @@ InstallOneInterface(
         return FALSE;
     }
 
-    FIXME("Need to AddInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid),
+    FIXME("Need to InstallOneInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid),
         debugstr_w(ReferenceString), debugstr_w(InterfaceSection), InterfaceFlags);
     return TRUE;
 }
@@ -7314,15 +7819,15 @@ SetupDiInstallDeviceInterfaces(
             SelectedDriver->InfFileDetails->hInf,
             SelectedDriver->Details.SectionName,
             SectionName, MAX_PATH, &SectionNameLength, NULL);
-        if (!Result || SectionNameLength > MAX_PATH - wcslen(L".Interfaces") - 1)
+        if (!Result || SectionNameLength > MAX_PATH - strlenW(DotInterfaces) - 1)
             goto cleanup;
-        wcscat(SectionName, L".Interfaces");
+        strcatW(SectionName, DotInterfaces);
 
         ret = TRUE;
         Result = SetupFindFirstLineW(
             SelectedDriver->InfFileDetails->hInf,
             SectionName,
-            L"AddInterface",
+            AddInterface,
             &ContextInterface);
         while (ret && Result)
         {
@@ -7377,7 +7882,7 @@ cleanup:
             MyFree(ReferenceString);
             MyFree(InterfaceSection);
             InterfaceGuidString = ReferenceString = InterfaceSection = NULL;
-            Result = SetupFindNextMatchLineW(&ContextInterface, L"AddInterface", &ContextInterface);
+            Result = SetupFindNextMatchLineW(&ContextInterface, AddInterface, &ContextInterface);
         }
     }
 
@@ -7385,7 +7890,7 @@ cleanup:
     return ret;
 }
 
-BOOL
+static BOOL
 InfIsFromOEMLocation(
     IN PCWSTR FullName,
     OUT LPBOOL IsOEMLocation)
@@ -7412,7 +7917,7 @@ InfIsFromOEMLocation(
 
         if (strncmpW(FullName, Windir, last - FullName) == 0)
         {
-            /* The path is %SYSTEMROOT%\Inf */
+            /* The path is %WINDIR%\Inf */
             *IsOEMLocation = FALSE;
         }
         else
@@ -7430,7 +7935,7 @@ InfIsFromOEMLocation(
 BOOL WINAPI
 SetupDiInstallDevice(
     IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData)
+    IN OUT PSP_DEVINFO_DATA DeviceInfoData)
 {
     SP_DEVINSTALL_PARAMS_W InstallParams;
     struct DriverInfoElement *SelectedDriver;
@@ -7447,7 +7952,6 @@ SetupDiInstallDevice(
     LPWSTR lpGuidString = NULL, lpFullGuidString = NULL;
     BOOL RebootRequired = FALSE;
     HKEY hKey = INVALID_HANDLE_VALUE;
-    HKEY hClassKey = INVALID_HANDLE_VALUE;
     BOOL NeedtoCopyFile;
     LARGE_INTEGER fullVersion;
     LONG rc;
@@ -7480,7 +7984,35 @@ SetupDiInstallDevice(
 
     if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)
     {
-        /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
+        /* Set FAILEDINSTALL in ConfigFlags registry value */
+        DWORD ConfigFlags, regType;
+        Result = SetupDiGetDeviceRegistryPropertyW(
+            DeviceInfoSet,
+            DeviceInfoData,
+            SPDRP_CONFIGFLAGS,
+            &regType,
+            (PBYTE)&ConfigFlags,
+            sizeof(ConfigFlags),
+            NULL);
+        if (!Result || regType != REG_DWORD)
+        {
+            SetLastError(ERROR_GEN_FAILURE);
+            goto cleanup;
+        }
+        ConfigFlags |= DNF_DISABLED;
+        Result = SetupDiSetDeviceRegistryPropertyW(
+            DeviceInfoSet,
+            DeviceInfoData,
+            SPDRP_CONFIGFLAGS,
+            (PBYTE)&ConfigFlags,
+            sizeof(ConfigFlags));
+        if (!Result)
+        {
+            SetLastError(ERROR_GEN_FAILURE);
+            goto cleanup;
+        }
+
+        ret = TRUE;
         goto cleanup;
     }
 
@@ -7497,12 +8029,12 @@ SetupDiInstallDevice(
         SelectedDriver->InfFileDetails->hInf,
         SelectedDriver->Details.SectionName,
         SectionName, MAX_PATH, &SectionNameLength, NULL);
-    if (!Result || SectionNameLength > MAX_PATH - wcslen(DotServices))
+    if (!Result || SectionNameLength > MAX_PATH - strlenW(DotServices))
         goto cleanup;
-    pSectionName = &SectionName[wcslen(SectionName)];
+    pSectionName = &SectionName[strlenW(SectionName)];
 
     /* Get information from [Version] section */
-    if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize))
+    if (!SetupDiGetINFClassW(SelectedDriver->InfFileDetails->FullInfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize))
         goto cleanup;
     /* Format ClassGuid to a string */
     if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK)
@@ -7544,7 +8076,7 @@ SetupDiInstallDevice(
     *pSectionName = '\0';
     Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
         SelectedDriver->InfFileDetails->hInf, SectionName,
-        DoAction, hKey, NULL, SP_COPY_NEWER,
+        DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
         SetupDefaultQueueCallback, Context,
         DeviceInfoSet, DeviceInfoData);
     if (!Result)
@@ -7557,34 +8089,34 @@ SetupDiInstallDevice(
     memcpy(&fullVersion, &SelectedDriver->Info.DriverVersion, sizeof(LARGE_INTEGER));
     TRACE("Write information to driver key\n");
     TRACE("DriverDate      : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
-    TRACE("DriverDesc      : '%S'\n", SelectedDriver->Info.Description);
+    TRACE("DriverDesc      : '%s'\n", debugstr_w(SelectedDriver->Info.Description));
     TRACE("DriverVersion   : '%u.%u.%u.%u'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
-    TRACE("InfPath         : '%S'\n", SelectedDriver->Details.InfFileName);
-    TRACE("InfSection      : '%S'\n", SelectedDriver->Details.SectionName);
-    TRACE("InfSectionExt   : '%S'\n", &SectionName[wcslen(SelectedDriver->Details.SectionName)]);
-    TRACE("MatchingDeviceId: '%S'\n", SelectedDriver->MatchingId);
-    TRACE("ProviderName    : '%S'\n", SelectedDriver->Info.ProviderName);
-    swprintf(Buffer, L"%u-%u-%u", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
-    rc = RegSetValueEx(hKey, L"DriverDate", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
+    TRACE("InfPath         : '%s'\n", debugstr_w(SelectedDriver->Details.InfFileName));
+    TRACE("InfSection      : '%s'\n", debugstr_w(SelectedDriver->Details.SectionName));
+    TRACE("InfSectionExt   : '%s'\n", debugstr_w(&SectionName[strlenW(SelectedDriver->Details.SectionName)]));
+    TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver->MatchingId));
+    TRACE("ProviderName    : '%s'\n", debugstr_w(SelectedDriver->Info.ProviderName));
+    sprintfW(Buffer, L"%u-%u-%u", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
+    rc = RegSetValueEx(hKey, REGSTR_DRIVER_DATE, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR));
     if (rc == ERROR_SUCCESS)
-        rc = RegSetValueEx(hKey, L"DriverDateData", 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME));
+        rc = RegSetValueEx(hKey, REGSTR_DRIVER_DATE_DATA, 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME));
     if (rc == ERROR_SUCCESS)
-        rc = RegSetValueEx(hKey, REGSTR_VAL_DRVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
+        rc = RegSetValueEx(hKey, REGSTR_VAL_DRVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
     if (rc == ERROR_SUCCESS)
     {
-        swprintf(Buffer, L"%u.%u.%u.%u", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
-        rc = RegSetValueEx(hKey, L"DriverVersion", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
+        sprintfW(Buffer, L"%u.%u.%u.%u", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
+        rc = RegSetValueEx(hKey, REGSTR_DRIVER_VERSION, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR));
     }
     if (rc == ERROR_SUCCESS)
-        rc = RegSetValueEx(hKey, REGSTR_VAL_INFPATH, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.InfFileName, (wcslen(SelectedDriver->Details.InfFileName) + 1) * sizeof(WCHAR));
+        rc = RegSetValueEx(hKey, REGSTR_VAL_INFPATH, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.InfFileName, (strlenW(SelectedDriver->Details.InfFileName) + 1) * sizeof(WCHAR));
     if (rc == ERROR_SUCCESS)
-        rc = RegSetValueEx(hKey, REGSTR_VAL_INFSECTION, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (wcslen(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
+        rc = RegSetValueEx(hKey, REGSTR_VAL_INFSECTION, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
     if (rc == ERROR_SUCCESS)
-        rc = RegSetValueEx(hKey, REGSTR_VAL_INFSECTIONEXT, 0, REG_SZ, (const BYTE *)&SectionName[wcslen(SelectedDriver->Details.SectionName)], (wcslen(SectionName) - wcslen(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
+        rc = RegSetValueEx(hKey, REGSTR_VAL_INFSECTIONEXT, 0, REG_SZ, (const BYTE *)&SectionName[strlenW(SelectedDriver->Details.SectionName)], (strlenW(SectionName) - strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
     if (rc == ERROR_SUCCESS)
-        rc = RegSetValueEx(hKey, REGSTR_VAL_MATCHINGDEVID, 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (wcslen(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR));
+        rc = RegSetValueEx(hKey, REGSTR_VAL_MATCHINGDEVID, 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (strlenW(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR));
     if (rc == ERROR_SUCCESS)
-        rc = RegSetValueEx(hKey, REGSTR_VAL_PROVIDER_NAME, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (wcslen(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR));
+        rc = RegSetValueEx(hKey, REGSTR_VAL_PROVIDER_NAME, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (strlenW(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR));
     if (rc != ERROR_SUCCESS)
     {
        SetLastError(rc);
@@ -7596,7 +8128,7 @@ SetupDiInstallDevice(
     /* FIXME: Process .LogConfigOverride section */
 
     /* Install .Services section */
-    wcscpy(pSectionName, DotServices);
+    strcpyW(pSectionName, DotServices);
     Result = SetupInstallServicesFromInfSectionExW(
         SelectedDriver->InfFileDetails->hInf,
         SectionName,
@@ -7639,7 +8171,7 @@ SetupDiInstallDevice(
     DoAction = 0;
     if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY))
         DoAction |= SPINST_REGISTRY;
-    wcscpy(pSectionName, L".HW");
+    strcpyW(pSectionName, DotHW);
     Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
         SelectedDriver->InfFileDetails->hInf, SectionName,
         DoAction, hKey, NULL, 0,
@@ -7650,17 +8182,17 @@ SetupDiInstallDevice(
 
     /* Write information to enum key */
     TRACE("Write information to enum key\n");
-    TRACE("Class           : '%S'\n", ClassName);
-    TRACE("ClassGUID       : '%S'\n", lpFullGuidString);
-    TRACE("DeviceDesc      : '%S'\n", SelectedDriver->Info.Description);
-    TRACE("Mfg             : '%S'\n", SelectedDriver->Info.MfgName);
-    rc = RegSetValueEx(hKey, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE *)ClassName, (wcslen(ClassName) + 1) * sizeof(WCHAR));
+    TRACE("Class           : '%s'\n", debugstr_w(ClassName));
+    TRACE("ClassGUID       : '%s'\n", debugstr_w(lpFullGuidString));
+    TRACE("DeviceDesc      : '%s'\n", debugstr_w(SelectedDriver->Info.Description));
+    TRACE("Mfg             : '%s'\n", debugstr_w(SelectedDriver->Info.MfgName));
+    rc = RegSetValueEx(hKey, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE *)ClassName, (strlenW(ClassName) + 1) * sizeof(WCHAR));
     if (rc == ERROR_SUCCESS)
-        rc = RegSetValueEx(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (wcslen(lpFullGuidString) + 1) * sizeof(WCHAR));
+        rc = RegSetValueEx(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (strlenW(lpFullGuidString) + 1) * sizeof(WCHAR));
     if (rc == ERROR_SUCCESS)
-        rc = RegSetValueEx(hKey, REGSTR_VAL_DEVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
+        rc = RegSetValueEx(hKey, REGSTR_VAL_DEVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
     if (rc == ERROR_SUCCESS)
-        rc = RegSetValueEx(hKey, REGSTR_VAL_MFG, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (wcslen(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR));
+        rc = RegSetValueEx(hKey, REGSTR_VAL_MFG, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (strlenW(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR));
     if (rc != ERROR_SUCCESS)
     {
        SetLastError(rc);
@@ -7675,8 +8207,6 @@ SetupDiInstallDevice(
 
 cleanup:
     /* End of installation */
-    if (hClassKey != INVALID_HANDLE_VALUE)
-        RegCloseKey(hClassKey);
     if (hKey != INVALID_HANDLE_VALUE)
         RegCloseKey(hKey);
     if (lpGuidString)