[PATCH v2 3/6] shell32: Load icons with the correct size.

Huw Davies huw at codeweavers.com
Tue May 2 09:13:15 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