SHGetFileInfoW(): handle SHGFI_LINKOVERLAY and SHGFI_OVERLAYINDEX.

SHMapPIDLToSystemImageListIndex(): determine overlay flag for
PidlToSicIndex() and return -1 in error cases.
Read shell overlay icon settings from registry to allow icon
overrides.
This commit is contained in:
Martin Fuchs 2005-11-21 13:35:06 +00:00 committed by Alexandre Julliard
parent f0af162aa3
commit d3521da667
3 changed files with 122 additions and 31 deletions

View File

@ -96,6 +96,9 @@ static INT CALLBACK SIC_CompareEntries( LPVOID p1, LPVOID p2, LPARAM lparam)
return 0; return 0;
} }
/* declare SIC_LoadOverlayIcon() */
static int SIC_LoadOverlayIcon(int idx);
/***************************************************************************** /*****************************************************************************
* SIC_OverlayShortcutImage [internal] * SIC_OverlayShortcutImage [internal]
* *
@ -103,7 +106,7 @@ static INT CALLBACK SIC_CompareEntries( LPVOID p1, LPVOID p2, LPARAM lparam)
* Creates a new icon as a copy of the passed-in icon, overlayed with a * Creates a new icon as a copy of the passed-in icon, overlayed with a
* shortcut image. * shortcut image.
*/ */
static HICON SIC_OverlayShortcutImage(HICON SourceIcon) static HICON SIC_OverlayShortcutImage(HICON SourceIcon, BOOL large)
{ ICONINFO SourceIconInfo, ShortcutIconInfo, TargetIconInfo; { ICONINFO SourceIconInfo, ShortcutIconInfo, TargetIconInfo;
HICON ShortcutIcon, TargetIcon; HICON ShortcutIcon, TargetIcon;
BITMAP SourceBitmapInfo, ShortcutBitmapInfo; BITMAP SourceBitmapInfo, ShortcutBitmapInfo;
@ -115,15 +118,28 @@ static HICON SIC_OverlayShortcutImage(HICON SourceIcon)
OldShortcutBitmap = NULL, OldShortcutBitmap = NULL,
OldTargetBitmap = NULL; OldTargetBitmap = NULL;
static int s_imgListIdx = -1;
/* Get information about the source icon and shortcut overlay */ /* Get information about the source icon and shortcut overlay */
if (! GetIconInfo(SourceIcon, &SourceIconInfo) if (! GetIconInfo(SourceIcon, &SourceIconInfo)
|| 0 == GetObjectW(SourceIconInfo.hbmColor, sizeof(BITMAP), &SourceBitmapInfo)) || 0 == GetObjectW(SourceIconInfo.hbmColor, sizeof(BITMAP), &SourceBitmapInfo))
{ {
return NULL; return NULL;
} }
ShortcutIcon = LoadImageW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_SHORTCUT),
IMAGE_ICON, SourceBitmapInfo.bmWidth, SourceBitmapInfo.bmWidth, /* search for the shortcut icon only once */
LR_SHARED); if (s_imgListIdx == -1)
s_imgListIdx = SIC_LoadOverlayIcon(29); /* icon index for IDI_SHELL_SHORTCUT */
if (s_imgListIdx != -1)
{
if (large)
ShortcutIcon = ImageList_GetIcon(ShellBigIconList, s_imgListIdx, ILD_TRANSPARENT);
else
ShortcutIcon = ImageList_GetIcon(ShellSmallIconList, s_imgListIdx, ILD_TRANSPARENT);
} else
ShortcutIcon = NULL;
if (NULL == ShortcutIcon if (NULL == ShortcutIcon
|| ! GetIconInfo(ShortcutIcon, &ShortcutIconInfo) || ! GetIconInfo(ShortcutIcon, &ShortcutIconInfo)
|| 0 == GetObjectW(ShortcutIconInfo.hbmColor, sizeof(BITMAP), &ShortcutBitmapInfo)) || 0 == GetObjectW(ShortcutIconInfo.hbmColor, sizeof(BITMAP), &ShortcutBitmapInfo))
@ -299,8 +315,8 @@ static INT SIC_LoadIcon (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags)
if (0 != (dwFlags & GIL_FORSHORTCUT)) if (0 != (dwFlags & GIL_FORSHORTCUT))
{ {
hiconLargeShortcut = SIC_OverlayShortcutImage(hiconLarge); hiconLargeShortcut = SIC_OverlayShortcutImage(hiconLarge, TRUE);
hiconSmallShortcut = SIC_OverlayShortcutImage(hiconSmall); hiconSmallShortcut = SIC_OverlayShortcutImage(hiconSmall, FALSE);
if (NULL != hiconLargeShortcut && NULL != hiconSmallShortcut) if (NULL != hiconLargeShortcut && NULL != hiconSmallShortcut)
{ {
hiconLarge = hiconLargeShortcut; hiconLarge = hiconLargeShortcut;
@ -443,6 +459,52 @@ void SIC_Destroy(void)
DeleteCriticalSection(&SHELL32_SicCS); DeleteCriticalSection(&SHELL32_SicCS);
} }
/*****************************************************************************
* SIC_LoadOverlayIcon [internal]
*
* Load a shell overlay icon and return its icon cache index.
*/
static int SIC_LoadOverlayIcon(int idx)
{
WCHAR buffer[1024], wszIdx[8];
HKEY hKeyShellIcons;
LPCWSTR iconPath;
int iconIdx;
static const WCHAR wszShellIcons[] = {
'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'E','x','p','l','o','r','e','r','\\','S','h','e','l','l',' ','I','c','o','n','s',0
};
static const WCHAR wszNumFmt[] = {'%','d',0};
iconPath = swShell32Name; /* default: load icon from shell32.dll */
iconIdx = idx;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszShellIcons, 0, KEY_READ, &hKeyShellIcons) == ERROR_SUCCESS)
{
DWORD count = sizeof(buffer);
sprintfW(wszIdx, wszNumFmt, idx);
/* read icon path and index */
if (RegQueryValueExW(hKeyShellIcons, wszIdx, NULL, NULL, (LPBYTE)buffer, &count) == ERROR_SUCCESS)
{
LPWSTR p = strchrW(buffer, ',');
if (p)
*p++ = 0;
iconPath = buffer;
iconIdx = atoiW(p);
}
RegCloseKey(hKeyShellIcons);
}
return SIC_LoadIcon(iconPath, iconIdx, 0);
}
/************************************************************************* /*************************************************************************
* Shell_GetImageList [SHELL32.71] * Shell_GetImageList [SHELL32.71]
* *
@ -481,29 +543,15 @@ BOOL PidlToSicIndex (
{ {
IExtractIconW *ei; IExtractIconW *ei;
WCHAR szIconFile[MAX_PATH]; /* file containing the icon */ WCHAR szIconFile[MAX_PATH]; /* file containing the icon */
char szTemp[MAX_PATH];
INT iSourceIndex; /* index or resID(negated) in this file */ INT iSourceIndex; /* index or resID(negated) in this file */
BOOL ret = FALSE; BOOL ret = FALSE;
UINT dwFlags = 0; UINT dwFlags = 0;
HKEY keyCls;
int iShortcutDefaultIndex = INVALID_INDEX; int iShortcutDefaultIndex = INVALID_INDEX;
TRACE("sf=%p pidl=%p %s\n", sh, pidl, bBigIcon?"Big":"Small"); TRACE("sf=%p pidl=%p %s\n", sh, pidl, bBigIcon?"Big":"Small");
if (SUCCEEDED (IShellFolder_GetUIObjectOf(sh, 0, 1, &pidl, &IID_IExtractIconW, 0, (void **)&ei))) if (SUCCEEDED (IShellFolder_GetUIObjectOf(sh, 0, 1, &pidl, &IID_IExtractIconW, 0, (void **)&ei)))
{ {
if (_ILGetExtension(pidl, szTemp, MAX_PATH) &&
HCR_MapTypeToValueA(szTemp, szTemp, MAX_PATH, TRUE))
{
if (ERROR_SUCCESS == RegOpenKeyExA(HKEY_CLASSES_ROOT, szTemp, 0, KEY_QUERY_VALUE, &keyCls))
{
if (ERROR_SUCCESS == RegQueryValueExA(keyCls, "IsShortcut", NULL, NULL, NULL, NULL))
{
uFlags |= GIL_FORSHORTCUT;
}
RegCloseKey(keyCls);
}
}
if (SUCCEEDED(IExtractIconW_GetIconLocation(ei, uFlags, szIconFile, MAX_PATH, &iSourceIndex, &dwFlags))) if (SUCCEEDED(IExtractIconW_GetIconLocation(ei, uFlags, szIconFile, MAX_PATH, &iSourceIndex, &dwFlags)))
{ {
*pIndex = SIC_GetIconIndex(szIconFile, iSourceIndex, uFlags); *pIndex = SIC_GetIconIndex(szIconFile, iSourceIndex, uFlags);
@ -547,13 +595,21 @@ int WINAPI SHMapPIDLToSystemImageListIndex(
int *pIndex) int *pIndex)
{ {
int Index; int Index;
UINT uGilFlags = 0;
TRACE("(SF=%p,pidl=%p,%p)\n",sh,pidl,pIndex); TRACE("(SF=%p,pidl=%p,%p)\n",sh,pidl,pIndex);
pdump(pidl); pdump(pidl);
if (SHELL_IsShortcut(pidl))
uGilFlags |= GIL_FORSHORTCUT;
if (pIndex) if (pIndex)
PidlToSicIndex ( sh, pidl, 1, 0, pIndex); if (!PidlToSicIndex ( sh, pidl, 1, uGilFlags, pIndex))
PidlToSicIndex ( sh, pidl, 0, 0, &Index); *pIndex = -1;
if (!PidlToSicIndex ( sh, pidl, 0, uGilFlags, &Index))
return -1;
return Index; return Index;
} }

View File

@ -297,6 +297,32 @@ static DWORD shgfi_get_exe_type(LPCWSTR szFullPath)
return 0; return 0;
} }
/*************************************************************************
* SHELL_IsShortcut [internal]
*
* Decide if an item id list points to a shell shortcut
*/
BOOL SHELL_IsShortcut(LPCITEMIDLIST pidlLast)
{
char szTemp[MAX_PATH];
HKEY keyCls;
BOOL ret = FALSE;
if (_ILGetExtension(pidlLast, szTemp, MAX_PATH) &&
HCR_MapTypeToValueA(szTemp, szTemp, MAX_PATH, TRUE))
{
if (ERROR_SUCCESS == RegOpenKeyExA(HKEY_CLASSES_ROOT, szTemp, 0, KEY_QUERY_VALUE, &keyCls))
{
if (ERROR_SUCCESS == RegQueryValueExA(keyCls, "IsShortcut", NULL, NULL, NULL, NULL))
ret = TRUE;
RegCloseKey(keyCls);
}
}
return ret;
}
#define SHGFI_KNOWN_FLAGS \ #define SHGFI_KNOWN_FLAGS \
(SHGFI_SMALLICON | SHGFI_OPENICON | SHGFI_SHELLICONSIZE | SHGFI_PIDL | \ (SHGFI_SMALLICON | SHGFI_OPENICON | SHGFI_SHELLICONSIZE | SHGFI_PIDL | \
SHGFI_USEFILEATTRIBUTES | SHGFI_ADDOVERLAYS | SHGFI_OVERLAYINDEX | \ SHGFI_USEFILEATTRIBUTES | SHGFI_ADDOVERLAYS | SHGFI_OVERLAYINDEX | \
@ -320,6 +346,7 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
LPITEMIDLIST pidlLast = NULL, pidl = NULL; LPITEMIDLIST pidlLast = NULL, pidl = NULL;
HRESULT hr = S_OK; HRESULT hr = S_OK;
BOOL IconNotYetLoaded=TRUE; BOOL IconNotYetLoaded=TRUE;
UINT uGilFlags = 0;
TRACE("%s fattr=0x%lx sfi=%p(attr=0x%08lx) size=0x%x flags=0x%x\n", TRACE("%s fattr=0x%lx sfi=%p(attr=0x%08lx) size=0x%x flags=0x%x\n",
(flags & SHGFI_PIDL)? "pidl" : debugstr_w(path), dwFileAttributes, (flags & SHGFI_PIDL)? "pidl" : debugstr_w(path), dwFileAttributes,
@ -458,15 +485,21 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
} }
/* ### icons ###*/ /* ### icons ###*/
if (flags & SHGFI_ADDOVERLAYS) if (flags & SHGFI_OPENICON)
FIXME("SHGFI_ADDOVERLAYS unhandled\n"); uGilFlags |= GIL_OPENICON;
if (flags & SHGFI_LINKOVERLAY)
uGilFlags |= GIL_FORSHORTCUT;
else if ((flags&SHGFI_ADDOVERLAYS) ||
(flags&(SHGFI_ICON|SHGFI_SMALLICON))==SHGFI_ICON)
{
if (SHELL_IsShortcut(pidlLast))
uGilFlags |= GIL_FORSHORTCUT;
}
if (flags & SHGFI_OVERLAYINDEX) if (flags & SHGFI_OVERLAYINDEX)
FIXME("SHGFI_OVERLAYINDEX unhandled\n"); FIXME("SHGFI_OVERLAYINDEX unhandled\n");
if (flags & SHGFI_LINKOVERLAY)
FIXME("set icon to link, stub\n");
if (flags & SHGFI_SELECTED) if (flags & SHGFI_SELECTED)
FIXME("set icon to selected, stub\n"); FIXME("set icon to selected, stub\n");
@ -483,12 +516,11 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
&uDummy, (LPVOID*)&pei); &uDummy, (LPVOID*)&pei);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = IExtractIconW_GetIconLocation(pei, hr = IExtractIconW_GetIconLocation(pei, uGilFlags,
(flags & SHGFI_OPENICON)? GIL_OPENICON : 0,
szLocation, MAX_PATH, &iIndex, &uFlags); szLocation, MAX_PATH, &iIndex, &uFlags);
psfi->iIcon = iIndex; psfi->iIcon = iIndex;
if (uFlags != GIL_NOTFILENAME) if (!(uFlags & GIL_NOTFILENAME))
lstrcpyW (psfi->szDisplayName, szLocation); lstrcpyW (psfi->szDisplayName, szLocation);
else else
ret = FALSE; ret = FALSE;
@ -550,7 +582,7 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
else else
{ {
if (!(PidlToSicIndex(psfParent, pidlLast, !(flags & SHGFI_SMALLICON), if (!(PidlToSicIndex(psfParent, pidlLast, !(flags & SHGFI_SMALLICON),
(flags & SHGFI_OPENICON)? GIL_OPENICON : 0, &(psfi->iIcon)))) uGilFlags, &(psfi->iIcon))))
{ {
ret = FALSE; ret = FALSE;
} }

View File

@ -231,4 +231,7 @@ extern const GUID CLSID_UnixDosFolder;
/* Default shell folder value registration */ /* Default shell folder value registration */
HRESULT SHELL_RegisterShellFolders(void); HRESULT SHELL_RegisterShellFolders(void);
/* Detect Shell Links */
BOOL SHELL_IsShortcut(LPCITEMIDLIST);
#endif #endif