[PATCH v3 3/6] shell32: Load icons with the correct size.
Huw Davies
huw at codeweavers.com
Tue May 2 10:12:36 CDT 2017
Signed-off-by: Huw Davies <huw at codeweavers.com>
---
dlls/shell32/iconcache.c | 44 +++++++++++++++++++++++++
dlls/shell32/shell32_main.c | 75 ++++++++++++++++++++++--------------------
dlls/shell32/shell32_main.h | 1 +
dlls/shell32/tests/shlfileop.c | 7 ++--
4 files changed, 86 insertions(+), 41 deletions(-)
diff --git a/dlls/shell32/iconcache.c b/dlls/shell32/iconcache.c
index 59fd8fb104..0ea2eb9e0e 100644
--- a/dlls/shell32/iconcache.c
+++ b/dlls/shell32/iconcache.c
@@ -78,6 +78,8 @@ static const WCHAR WindowMetrics[] = {'C','o','n','t','r','o','l',' ','P','a','n
'W','i','n','d','o','w','M','e','t','r','i','c','s',0};
static const WCHAR ShellIconSize[] = {'S','h','e','l','l',' ','I','c','o','n',' ','S','i','z','e',0};
+#define SIC_COMPARE_LISTINDEX 1
+
/*****************************************************************************
* SIC_CompareEntries
*
@@ -94,6 +96,10 @@ static INT CALLBACK SIC_CompareEntries( LPVOID p1, LPVOID p2, LPARAM lparam)
* loaded from, their resource index and the fact if they have a shortcut
* icon overlay or not.
*/
+
+ if (lparam & SIC_COMPARE_LISTINDEX)
+ return e1->dwListIndex != e2->dwListIndex;
+
if (e1->dwSourceIndex != e2->dwSourceIndex || /* first the faster one */
(e1->dwFlags & GIL_FORSHORTCUT) != (e2->dwFlags & GIL_FORSHORTCUT))
return 1;
@@ -104,6 +110,44 @@ static INT CALLBACK SIC_CompareEntries( LPVOID p1, LPVOID p2, LPARAM lparam)
return 0;
}
+/**************************************************************************************
+ * SIC_get_location
+ *
+ * Returns the source file and resource index of an icon with the given imagelist index
+ */
+HRESULT SIC_get_location( int list_idx, WCHAR *file, DWORD *size, int *res_idx )
+{
+ SIC_ENTRY seek, *found;
+ DWORD needed;
+ HRESULT hr = E_INVALIDARG;
+ int dpa_idx;
+
+ seek.dwListIndex = list_idx;
+
+ EnterCriticalSection( &SHELL32_SicCS );
+
+ dpa_idx = DPA_Search( sic_hdpa, &seek, 0, SIC_CompareEntries, SIC_COMPARE_LISTINDEX, 0 );
+ if (dpa_idx != -1)
+ {
+ found = (SIC_ENTRY *)DPA_GetPtr( sic_hdpa, dpa_idx );
+ needed = (strlenW( found->sSourceFile ) + 1) * sizeof(WCHAR);
+ if (needed <= *size)
+ {
+ memcpy( file, found->sSourceFile, needed );
+ *res_idx = found->dwSourceIndex;
+ hr = S_OK;
+ }
+ else
+ {
+ *size = needed;
+ hr = E_NOT_SUFFICIENT_BUFFER;
+ }
+ }
+ LeaveCriticalSection( &SHELL32_SicCS );
+
+ return hr;
+}
+
/* declare SIC_LoadOverlayIcon() */
static int SIC_LoadOverlayIcon(int icon_idx);
diff --git a/dlls/shell32/shell32_main.c b/dlls/shell32/shell32_main.c
index 71225916bb..04924c0563 100644
--- a/dlls/shell32/shell32_main.c
+++ b/dlls/shell32/shell32_main.c
@@ -427,7 +427,6 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
IExtractIconW * pei = NULL;
LPITEMIDLIST pidlLast = NULL, pidl = NULL;
HRESULT hr = S_OK;
- BOOL IconNotYetLoaded=TRUE;
UINT uGilFlags = 0;
TRACE("%s fattr=0x%x sfi=%p(attr=0x%08x) size=0x%x flags=0x%x\n",
@@ -598,9 +597,6 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
if (flags & SHGFI_SELECTED)
FIXME("set icon to selected, stub\n");
- if (flags & SHGFI_SHELLICONSIZE)
- FIXME("set icon to shell size, stub\n");
-
/* get the iconlocation */
if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION ))
{
@@ -667,17 +663,16 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL))
{
- WCHAR sTemp [MAX_PATH];
- WCHAR * szExt;
- int icon_idx=0;
-
- lstrcpynW(sTemp, szFullPath, MAX_PATH);
-
if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
psfi->iIcon = SIC_GetIconIndex(swShell32Name, -IDI_SHELL_FOLDER, 0);
else
{
static const WCHAR p1W[] = {'%','1',0};
+ WCHAR sTemp[MAX_PATH];
+ WCHAR *szExt;
+ int icon_idx = 0;
+
+ lstrcpynW(sTemp, szFullPath, MAX_PATH);
psfi->iIcon = 0;
szExt = PathFindExtensionW(sTemp);
@@ -688,31 +683,9 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
if (!lstrcmpW(p1W,sTemp)) /* icon is in the file */
strcpyW(sTemp, szFullPath);
- if (flags & SHGFI_SYSICONINDEX)
- {
- psfi->iIcon = SIC_GetIconIndex(sTemp,icon_idx,0);
- if (psfi->iIcon == -1)
- psfi->iIcon = 0;
- }
- else
- {
- UINT ret;
- if (flags & SHGFI_SMALLICON)
- ret = PrivateExtractIconsW( sTemp,icon_idx,
- GetSystemMetrics( SM_CXSMICON ),
- GetSystemMetrics( SM_CYSMICON ),
- &psfi->hIcon, 0, 1, 0);
- else
- ret = PrivateExtractIconsW( sTemp, icon_idx,
- GetSystemMetrics( SM_CXICON),
- GetSystemMetrics( SM_CYICON),
- &psfi->hIcon, 0, 1, 0);
- if (ret != 0 && ret != (UINT)-1)
- {
- IconNotYetLoaded=FALSE;
- psfi->iIcon = icon_idx;
- }
- }
+ psfi->iIcon = SIC_GetIconIndex(sTemp, icon_idx, 0);
+ if (psfi->iIcon == -1)
+ psfi->iIcon = 0;
}
}
}
@@ -731,7 +704,37 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
}
if (ret && (flags & SHGFI_ICON))
{
- hr = IImageList_GetIcon( icon_list, psfi->iIcon, ILD_NORMAL, &psfi->hIcon );
+ if (flags & SHGFI_SHELLICONSIZE)
+ hr = IImageList_GetIcon( icon_list, psfi->iIcon, ILD_NORMAL, &psfi->hIcon );
+ else
+ {
+ int width = GetSystemMetrics( (flags & SHGFI_SMALLICON) ? SM_CXSMICON : SM_CXICON );
+ int height = GetSystemMetrics( (flags & SHGFI_SMALLICON) ? SM_CYSMICON : SM_CYICON );
+ int list_width, list_height;
+
+ IImageList_GetIconSize( icon_list, &list_width, &list_height );
+ if (list_width == width && list_height == height)
+ hr = IImageList_GetIcon( icon_list, psfi->iIcon, ILD_NORMAL, &psfi->hIcon );
+ else /* Use SHIL_SYSSMALL for SHFI_SMALLICONS when we implement it */
+ {
+ WCHAR buf[MAX_PATH], *file = buf;
+ DWORD size = sizeof(buf);
+ int icon_idx;
+
+ while ((hr = SIC_get_location( psfi->iIcon, file, &size, &icon_idx ) == E_NOT_SUFFICIENT_BUFFER))
+ {
+ if (file == buf) file = HeapAlloc( GetProcessHeap(), 0, size );
+ else file = HeapReAlloc( GetProcessHeap(), 0, file, size );
+ if (!file) break;
+ }
+ if (SUCCEEDED(hr))
+ {
+ ret = PrivateExtractIconsW( file, icon_idx, width, height, &psfi->hIcon, 0, 1, 0);
+ if (ret == 0 || ret == (UINT)-1) hr = E_FAIL;
+ }
+ if (file != buf) HeapFree( GetProcessHeap(), 0, file );
+ }
+ }
}
IImageList_Release( icon_list );
}
diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h
index bdebcba0e3..941ca74f32 100644
--- a/dlls/shell32/shell32_main.h
+++ b/dlls/shell32/shell32_main.h
@@ -51,6 +51,7 @@ extern CLSID CLSID_ShellImageDataFactory;
void SIC_Destroy(void) DECLSPEC_HIDDEN;
BOOL PidlToSicIndex (IShellFolder * sh, LPCITEMIDLIST pidl, BOOL bBigIcon, UINT uFlags, int * pIndex) DECLSPEC_HIDDEN;
INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags ) DECLSPEC_HIDDEN;
+HRESULT SIC_get_location( int list_idx, WCHAR *file, DWORD *size, int *res_idx ) DECLSPEC_HIDDEN;
/* Classes Root */
BOOL HCR_MapTypeToValueW(LPCWSTR szExtension, LPWSTR szFileType, LONG len, BOOL bPrependDot) DECLSPEC_HIDDEN;
diff --git a/dlls/shell32/tests/shlfileop.c b/dlls/shell32/tests/shlfileop.c
index 8f637f62e7..dd933f6d1f 100644
--- a/dlls/shell32/tests/shlfileop.c
+++ b/dlls/shell32/tests/shlfileop.c
@@ -338,11 +338,8 @@ static void check_icon_size( HICON icon, DWORD flags )
if (flags & SHGFI_SHELLICONSIZE)
{
- todo_wine_if(list_size.cx != metrics_size.cx)
- {
- ok( bm.bmWidth == list_size.cx, "got %d expected %d\n", bm.bmWidth, list_size.cx );
- ok( bm.bmHeight == list_size.cy, "got %d expected %d\n", bm.bmHeight, list_size.cy );
- }
+ ok( bm.bmWidth == list_size.cx, "got %d expected %d\n", bm.bmWidth, list_size.cx );
+ ok( bm.bmHeight == list_size.cy, "got %d expected %d\n", bm.bmHeight, list_size.cy );
}
else
{
--
2.12.0
More information about the wine-patches
mailing list