[SETUPAPI]
authorKamil Hornicek <kamil.hornicek@reactos.org>
Mon, 20 Oct 2014 13:08:42 +0000 (13:08 +0000)
committerKamil Hornicek <kamil.hornicek@reactos.org>
Mon, 20 Oct 2014 13:08:42 +0000 (13:08 +0000)
- actually use the icon source we get from registry instead of loading all icons from setupapi itself
CORE-8614

svn path=/trunk/; revision=64845

reactos/dll/win32/setupapi/devclass.c

index 60c92fe..cae8b66 100644 (file)
@@ -22,6 +22,7 @@
 #include "setupapi_private.h"
 
 #include <wingdi.h>
+#include <shellapi.h>
 
 /* Unicode constants */
 static const WCHAR BackSlash[] = {'\\',0};
@@ -76,6 +77,7 @@ static const INSTALL_PARAMS_DATA InstallParamsData[] = {
 };
 #undef ADD_PARAM_HANDLER
 
+#define UNKNOWN_ICON_INDEX 18
 
 /***********************************************************************
  *             SetupDiDestroyClassImageList(SETUPAPI.@)
@@ -330,9 +332,6 @@ cleanup:
     return rc;
 }
 
-/***********************************************************************
- *             SetupDiGetClassImageIndex (SETUPAPI.@)
- */
 static BOOL
 SETUP_GetIconIndex(
     IN HKEY hClassKey,
@@ -378,6 +377,9 @@ cleanup:
     return ret;
 }
 
+/***********************************************************************
+ *             SetupDiGetClassImageIndex (SETUPAPI.@)
+ */
 BOOL WINAPI
 SetupDiGetClassImageIndex(
     IN PSP_CLASSIMAGELIST_DATA ClassImageListData,
@@ -458,6 +460,102 @@ SetupDiGetClassImageListExA(
     return ret;
 }
 
+static BOOL WINAPI 
+SETUP_GetClassIconInfo(IN CONST GUID *ClassGuid, OUT PINT OutIndex, OUT LPWSTR *OutDllName)
+{
+    LPWSTR Buffer = NULL;
+    INT iconIndex = -UNKNOWN_ICON_INDEX;
+    HKEY hKey = INVALID_HANDLE_VALUE;
+    BOOL ret = FALSE;
+
+    if (ClassGuid)
+    {
+        hKey = SetupDiOpenClassRegKey(ClassGuid, KEY_QUERY_VALUE);
+        if (hKey != INVALID_HANDLE_VALUE)
+        {
+            SETUP_GetIconIndex(hKey, &iconIndex);
+        }
+    }
+
+    if (iconIndex > 0)
+    {
+        /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
+        PWCHAR Comma;
+        LONG rc;
+        DWORD dwRegType, dwLength;
+        rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
+        if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
+        {
+            Buffer = MyMalloc(dwLength + sizeof(WCHAR));
+            if (Buffer == NULL)
+            {
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                goto cleanup;
+            }
+            rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
+            if (rc != ERROR_SUCCESS)
+            {
+                SetLastError(rc);
+                goto cleanup;
+            }
+            /* make sure the returned buffer is NULL-terminated */
+            Buffer[dwLength / sizeof(WCHAR)] = 0;
+        }
+        else if
+            (ERROR_SUCCESS == (rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength))
+            && dwRegType == REG_SZ)
+        {
+            Buffer = MyMalloc(dwLength + sizeof(WCHAR));
+            if (Buffer == NULL)
+            {
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                goto cleanup;
+            }
+            rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
+            if (rc != ERROR_SUCCESS)
+            {
+                SetLastError(rc);
+                goto cleanup;
+            }
+            /* make sure the returned buffer is NULL-terminated */
+            Buffer[dwLength / sizeof(WCHAR)] = 0;
+        }
+        else
+        {
+            /* Unable to find where to load the icon */
+            SetLastError(ERROR_FILE_NOT_FOUND);
+            goto cleanup;
+        }
+        Comma = strchrW(Buffer, ',');
+        if (!Comma)
+        {
+            SetLastError(ERROR_GEN_FAILURE);
+            goto cleanup;
+        }
+        *Comma = '\0';
+        *OutDllName = Buffer;
+    }
+    else
+    {
+        /* Look up icon in setupapi.dll */
+        iconIndex = -iconIndex;
+        *OutDllName = NULL;
+    }
+
+    *OutIndex = iconIndex;
+    ret = TRUE;
+
+    TRACE("Icon index %d, dll name %s\n", iconIndex, debugstr_w(*OutDllName ? *OutDllName : SetupapiDll));
+
+cleanup:
+
+    if (hKey != INVALID_HANDLE_VALUE)
+        RegCloseKey(hKey);
+
+    return ret;
+}
+
+
 /***********************************************************************
  *             SetupDiGetClassImageListExW(SETUPAPI.@)
  */
@@ -570,24 +668,32 @@ SetupDiGetClassImageListExW(
         for (i = 0; i < list->NumberOfGuids; i++)
         {
             INT miniIconIndex;
+            LPWSTR DllName = NULL;
 
-            ret = SetupDiLoadClassIcon(
-                &list->Guids[i],
-                NULL,
-                &miniIconIndex);
-            if (ret)
+            if (SETUP_GetClassIconInfo(&list->Guids[i], &miniIconIndex, &DllName))
             {
-                hIcon = LoadImage(hInstance, MAKEINTRESOURCE(miniIconIndex), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
-                if (hIcon)
+                if (DllName && ExtractIconExW(DllName, -miniIconIndex, NULL, &hIcon, 1) == 1)
                 {
                     list->IconIndexes[i] = ImageList_AddIcon(ClassImageListData->ImageList, hIcon);
-                    DestroyIcon(hIcon);
                 }
+                else if(!DllName)
+                {
+                    hIcon = LoadImage(hInstance, MAKEINTRESOURCE(miniIconIndex), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
+                    list->IconIndexes[i] = ImageList_AddIcon(ClassImageListData->ImageList, hIcon);
+                }
+
+                if(hIcon)
+                    DestroyIcon(hIcon);
                 else
                     list->IconIndexes[i] = -1;
+
+                if(DllName)
+                    MyFree(DllName);
             }
             else
+            {
                 list->IconIndexes[i] = -1; /* Special value to indicate that the icon is unavailable */
+            }
         }
 
         /* Finally, add the overlay icons to the image list */
@@ -660,105 +766,43 @@ SetupDiLoadClassIcon(
     OUT HICON *LargeIcon OPTIONAL,
     OUT PINT MiniIconIndex OPTIONAL)
 {
-    LPWSTR Buffer = NULL;
-    LPCWSTR DllName;
-    INT iconIndex = -18;
-    HKEY hKey = INVALID_HANDLE_VALUE;
-
+    INT iconIndex = 0;
+    LPWSTR DllName = NULL;
     BOOL ret = FALSE;
+    HICON hIcon = NULL;
 
-    if (ClassGuid)
+    if (LargeIcon)
     {
-        hKey = SetupDiOpenClassRegKey(ClassGuid, KEY_QUERY_VALUE);
-        if (hKey != INVALID_HANDLE_VALUE)
-            SETUP_GetIconIndex(hKey, &iconIndex);
-    }
+        if(!SETUP_GetClassIconInfo(ClassGuid, &iconIndex, &DllName))
+            return FALSE;
 
-    if (iconIndex > 0)
-    {
-        /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
-        PWCHAR Comma;
-        LONG rc;
-        DWORD dwRegType, dwLength;
-        rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
-        if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
-        {
-            Buffer = MyMalloc(dwLength + sizeof(WCHAR));
-            if (Buffer == NULL)
-            {
-                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-                goto cleanup;
-            }
-            rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
-            if (rc != ERROR_SUCCESS)
-            {
-                SetLastError(rc);
-                goto cleanup;
-            }
-            /* make sure the returned buffer is NULL-terminated */
-            Buffer[dwLength / sizeof(WCHAR)] = 0;
-        }
-        else if
-            (ERROR_SUCCESS == (rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength))
-            && dwRegType == REG_SZ)
+        if (DllName && ExtractIconExW(DllName, -iconIndex, &hIcon, NULL, 1) == 1 && hIcon != NULL)
         {
-            Buffer = MyMalloc(dwLength + sizeof(WCHAR));
-            if (Buffer == NULL)
-            {
-                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-                goto cleanup;
-            }
-            rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
-            if (rc != ERROR_SUCCESS)
-            {
-                SetLastError(rc);
-                goto cleanup;
-            }
-            /* make sure the returned buffer is NULL-terminated */
-            Buffer[dwLength / sizeof(WCHAR)] = 0;
+            ret = TRUE;
         }
         else
         {
-            /* Unable to find where to load the icon */
-            SetLastError(ERROR_FILE_NOT_FOUND);
-            goto cleanup;
-        }
-        Comma = strchrW(Buffer, ',');
-        if (!Comma)
-        {
-            SetLastError(ERROR_GEN_FAILURE);
-            goto cleanup;
-        }
-        *Comma = '\0';
-        DllName = Buffer;
-    }
-    else
-    {
-        /* Look up icon in setupapi.dll */
-        DllName = SetupapiDll;
-        iconIndex = -iconIndex;
-    }
+            /* load the default unknown device icon if ExtractIcon failed */
+            if(DllName)
+                iconIndex = UNKNOWN_ICON_INDEX;
 
-    TRACE("Icon index %d, dll name %s\n", iconIndex, debugstr_w(DllName));
-    if (LargeIcon)
-    {
-        *LargeIcon = LoadImage(hInstance, MAKEINTRESOURCE(iconIndex), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
-        if (!*LargeIcon)
-        {
-            SetLastError(ERROR_INVALID_INDEX);
-            goto cleanup;
+            hIcon = LoadImage(hInstance, MAKEINTRESOURCE(iconIndex), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
+
+            if(!LargeIcon)
+                goto cleanup;
         }
     }
+
     if (MiniIconIndex)
         *MiniIconIndex = iconIndex;
+
     ret = TRUE;
+    *LargeIcon = hIcon;
 
 cleanup:
-    if (hKey != INVALID_HANDLE_VALUE)
-        RegCloseKey(hKey);
 
-    if (Buffer != NULL)
-        MyFree(Buffer);
+    if(DllName)
+        MyFree(DllName);
 
     TRACE("Returning %d\n", ret);
     return ret;