shell32: Load icons with the correct size.

Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Huw Davies 2017-05-02 16:12:36 +01:00 committed by Alexandre Julliard
parent b8bf0c2628
commit a7d79fe445
4 changed files with 86 additions and 41 deletions

View File

@ -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);

View File

@ -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 );
}

View File

@ -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;

View File

@ -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
{