Module: wine Branch: master Commit: a7d79fe4458039fc4cbed97860234ac70755020c URL: http://source.winehq.org/git/wine.git/?a=commit;h=a7d79fe4458039fc4cbed97860...
Author: Huw Davies huw@codeweavers.com Date: Tue May 2 16:12:36 2017 +0100
shell32: Load icons with the correct size.
Signed-off-by: Huw Davies huw@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
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 59fd8fb..0ea2eb9 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 7122591..04924c0 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 bdebcba..941ca74 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 8f637f6..dd933f6 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 {