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:
parent
f0af162aa3
commit
d3521da667
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue