[SETUPAPI]

- actually use the icon source we get from registry instead of loading all icons from setupapi itself
CORE-8614

svn path=/trunk/; revision=64845
This commit is contained in:
Kamil Hornicek 2014-10-20 13:08:42 +00:00
parent df8c74d505
commit 6beb0e5668

View file

@ -22,6 +22,7 @@
#include "setupapi_private.h" #include "setupapi_private.h"
#include <wingdi.h> #include <wingdi.h>
#include <shellapi.h>
/* Unicode constants */ /* Unicode constants */
static const WCHAR BackSlash[] = {'\\',0}; static const WCHAR BackSlash[] = {'\\',0};
@ -76,6 +77,7 @@ static const INSTALL_PARAMS_DATA InstallParamsData[] = {
}; };
#undef ADD_PARAM_HANDLER #undef ADD_PARAM_HANDLER
#define UNKNOWN_ICON_INDEX 18
/*********************************************************************** /***********************************************************************
* SetupDiDestroyClassImageList(SETUPAPI.@) * SetupDiDestroyClassImageList(SETUPAPI.@)
@ -330,9 +332,6 @@ cleanup:
return rc; return rc;
} }
/***********************************************************************
* SetupDiGetClassImageIndex (SETUPAPI.@)
*/
static BOOL static BOOL
SETUP_GetIconIndex( SETUP_GetIconIndex(
IN HKEY hClassKey, IN HKEY hClassKey,
@ -378,6 +377,9 @@ cleanup:
return ret; return ret;
} }
/***********************************************************************
* SetupDiGetClassImageIndex (SETUPAPI.@)
*/
BOOL WINAPI BOOL WINAPI
SetupDiGetClassImageIndex( SetupDiGetClassImageIndex(
IN PSP_CLASSIMAGELIST_DATA ClassImageListData, IN PSP_CLASSIMAGELIST_DATA ClassImageListData,
@ -458,6 +460,102 @@ SetupDiGetClassImageListExA(
return ret; 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.@) * SetupDiGetClassImageListExW(SETUPAPI.@)
*/ */
@ -570,25 +668,33 @@ SetupDiGetClassImageListExW(
for (i = 0; i < list->NumberOfGuids; i++) for (i = 0; i < list->NumberOfGuids; i++)
{ {
INT miniIconIndex; INT miniIconIndex;
LPWSTR DllName = NULL;
ret = SetupDiLoadClassIcon( if (SETUP_GetClassIconInfo(&list->Guids[i], &miniIconIndex, &DllName))
&list->Guids[i],
NULL,
&miniIconIndex);
if (ret)
{ {
hIcon = LoadImage(hInstance, MAKEINTRESOURCE(miniIconIndex), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); if (DllName && ExtractIconExW(DllName, -miniIconIndex, NULL, &hIcon, 1) == 1)
if (hIcon)
{ {
list->IconIndexes[i] = ImageList_AddIcon(ClassImageListData->ImageList, hIcon); 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 else
list->IconIndexes[i] = -1; list->IconIndexes[i] = -1;
if(DllName)
MyFree(DllName);
} }
else else
{
list->IconIndexes[i] = -1; /* Special value to indicate that the icon is unavailable */ list->IconIndexes[i] = -1; /* Special value to indicate that the icon is unavailable */
} }
}
/* Finally, add the overlay icons to the image list */ /* Finally, add the overlay icons to the image list */
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
@ -660,105 +766,43 @@ SetupDiLoadClassIcon(
OUT HICON *LargeIcon OPTIONAL, OUT HICON *LargeIcon OPTIONAL,
OUT PINT MiniIconIndex OPTIONAL) OUT PINT MiniIconIndex OPTIONAL)
{ {
LPWSTR Buffer = NULL; INT iconIndex = 0;
LPCWSTR DllName; LPWSTR DllName = NULL;
INT iconIndex = -18;
HKEY hKey = INVALID_HANDLE_VALUE;
BOOL ret = FALSE; BOOL ret = FALSE;
HICON hIcon = NULL;
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';
DllName = Buffer;
}
else
{
/* Look up icon in setupapi.dll */
DllName = SetupapiDll;
iconIndex = -iconIndex;
}
TRACE("Icon index %d, dll name %s\n", iconIndex, debugstr_w(DllName));
if (LargeIcon) if (LargeIcon)
{ {
*LargeIcon = LoadImage(hInstance, MAKEINTRESOURCE(iconIndex), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR); if(!SETUP_GetClassIconInfo(ClassGuid, &iconIndex, &DllName))
if (!*LargeIcon) return FALSE;
if (DllName && ExtractIconExW(DllName, -iconIndex, &hIcon, NULL, 1) == 1 && hIcon != NULL)
{ {
SetLastError(ERROR_INVALID_INDEX); ret = TRUE;
}
else
{
/* load the default unknown device icon if ExtractIcon failed */
if(DllName)
iconIndex = UNKNOWN_ICON_INDEX;
hIcon = LoadImage(hInstance, MAKEINTRESOURCE(iconIndex), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
if(!LargeIcon)
goto cleanup; goto cleanup;
} }
} }
if (MiniIconIndex) if (MiniIconIndex)
*MiniIconIndex = iconIndex; *MiniIconIndex = iconIndex;
ret = TRUE; ret = TRUE;
*LargeIcon = hIcon;
cleanup: cleanup:
if (hKey != INVALID_HANDLE_VALUE)
RegCloseKey(hKey);
if (Buffer != NULL) if(DllName)
MyFree(Buffer); MyFree(DllName);
TRACE("Returning %d\n", ret); TRACE("Returning %d\n", ret);
return ret; return ret;