781 lines
24 KiB
C++
781 lines
24 KiB
C++
|
//---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation
|
||
|
//
|
||
|
// File: overlayMN.cpp
|
||
|
//
|
||
|
// This file contains the implementation of CFSIconOverlayManager, a COM object
|
||
|
// that manages the IShellIconOverlayIdentifiers list.
|
||
|
// It aslo managess the Sytem Image List OverlayIndexes, since we have limited slots,
|
||
|
// exactly MAX_OVERLAY_IAMGES of them.
|
||
|
// History:
|
||
|
// 5-2-97 by dli
|
||
|
//------------------------------------------------------------------------
|
||
|
#include "shellprv.h"
|
||
|
#include "ovrlaymn.h"
|
||
|
#include "fstreex.h"
|
||
|
#include "filetbl.h"
|
||
|
extern "C" {
|
||
|
#include "cstrings.h"
|
||
|
#include "ole2dup.h"
|
||
|
}
|
||
|
|
||
|
|
||
|
extern "C" UINT const c_SystemImageListIndexes[];
|
||
|
extern int g_lrFlags;
|
||
|
|
||
|
// NOTE: The value of OVERLAYINDEX_RESERVED is not the same as the overall
|
||
|
// size of the s_ReservedOverlays array, we need to reserved the overlay slot
|
||
|
// #3 for the non-existent Read-Only overaly.
|
||
|
// The Read Only overlay was once there in Win95, but got turned off on IE4
|
||
|
// however, because of the of the original overlay designs,( we used to
|
||
|
// assign overlay 1 to share and 2 to link and 3 to readonly, and the third parties
|
||
|
// just copied our scheme,) we have to keep overlay #3 as a ghost.
|
||
|
#define OVERLAYINDEX_RESERVED 4
|
||
|
|
||
|
typedef struct _ReservedIconOverlay
|
||
|
{
|
||
|
int iShellResvrdImageIndex;
|
||
|
int iImageIndex;
|
||
|
int iOverlayIndex;
|
||
|
int iPriority;
|
||
|
} ReservedIconOverlay;
|
||
|
|
||
|
static ReservedIconOverlay s_ReservedOverlays[] = {
|
||
|
{II_SHARE, II_SHARE, 1, 10},
|
||
|
{II_LINK, II_LINK, 2, 10},
|
||
|
// Slot 3 should be reserved as a ghost slot because of the read-only overlay
|
||
|
{II_SLOWFILE, II_SLOWFILE, 4, 10},
|
||
|
};
|
||
|
|
||
|
// File system Icon overlay Identifiers
|
||
|
typedef struct _FSIconOverlay {
|
||
|
IShellIconOverlayIdentifier * psioi;
|
||
|
CLSID clsid;
|
||
|
int iIconIndex; // Index of the Overlay Icon in szIconFile
|
||
|
int iImageIndex; // System Image List index of the icon overlay image
|
||
|
int iOverlayIndex;
|
||
|
int iPriority;
|
||
|
TCHAR szIconFile[MAX_PATH]; // Path of the icon overlay
|
||
|
} FSIconOverlay;
|
||
|
|
||
|
#define FSIconOverlay_GROW 3
|
||
|
#define DSA_LAST 0x7fffffff
|
||
|
#define MAX_OVERLAY_PRIORITY 100
|
||
|
class CFSIconOverlayManager : public IShellIconOverlayManager
|
||
|
{
|
||
|
public:
|
||
|
CFSIconOverlayManager();
|
||
|
~CFSIconOverlayManager();
|
||
|
|
||
|
// *** IUnknown Methods
|
||
|
virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
|
||
|
virtual STDMETHODIMP_(ULONG) AddRef(void) ;
|
||
|
virtual STDMETHODIMP_(ULONG) Release(void);
|
||
|
|
||
|
// *** IShellIconOverlay Methods
|
||
|
virtual STDMETHODIMP GetFileOverlayInfo(LPCWSTR pwszPath, DWORD dwAttrib, int * pIndex, DWORD dwFlags);
|
||
|
virtual STDMETHODIMP GetReservedOverlayInfo(LPCWSTR pwszPath, DWORD dwAttrib, int * pIndex, DWORD dwFlags, int iReservedID);
|
||
|
virtual STDMETHODIMP RefreshOverlayImages(DWORD dwFlags);
|
||
|
virtual STDMETHODIMP LoadNonloadedOverlayIdentifiers(void);
|
||
|
virtual STDMETHODIMP OverlayIndexFromImageIndex(int iImage, int * piIndex, BOOL fAdd);
|
||
|
|
||
|
// *** Public Methods
|
||
|
|
||
|
// *** Static Methods
|
||
|
static HRESULT CreateInstance(IUnknown* pUnkOuter, REFIID riid, OUT LPVOID * ppvOut);
|
||
|
|
||
|
protected:
|
||
|
|
||
|
// IUnknown
|
||
|
LONG _cRef;
|
||
|
HDSA _hdsaIconOverlays; // Icon Overlay Identifiers array, this list is ordered by the IOIs' priority
|
||
|
HRESULT _InitializeHdsaIconOverlays(); // Initialize the Icon Overlay Identifiers array
|
||
|
HRESULT _DestroyHdsaIconOverlays();
|
||
|
int _GetImageIndex(FSIconOverlay * pfsio);
|
||
|
FSIconOverlay * _FindMatchingID(LPCWSTR pwszPath, DWORD dwAttrib, int iMinPriority, int * pIOverlayIndex);
|
||
|
HRESULT _SetGetOverlayInfo(FSIconOverlay * pfsio, int iOverlayIndex, int * pIndex, DWORD dwFlags);
|
||
|
HRESULT _InitializeReservedOverlays();
|
||
|
HRESULT _LoadIconOverlayIdentifiers(HDSA hdsaOverlays, BOOL bSkipIfLoaded);
|
||
|
|
||
|
BOOL _IsIdentifierLoaded(REFCLSID clsid);
|
||
|
// int _GetAvailableOverlayIndex(int imyhdsa);
|
||
|
// HRESULT _SortIOIList(); // Sort the IOI's in the list according to their priority
|
||
|
};
|
||
|
|
||
|
|
||
|
HRESULT CFSIconOverlayManager::RefreshOverlayImages(DWORD dwFlags)
|
||
|
{
|
||
|
ENTERCRITICAL;
|
||
|
|
||
|
_InitializeReservedOverlays();
|
||
|
|
||
|
if (dwFlags && _hdsaIconOverlays)
|
||
|
{
|
||
|
for (int ihdsa = 0; ihdsa < DSA_GetItemCount(_hdsaIconOverlays); ihdsa++)
|
||
|
{
|
||
|
FSIconOverlay * pfsio = (FSIconOverlay *)DSA_GetItemPtr(_hdsaIconOverlays, ihdsa);
|
||
|
if (dwFlags & SIOM_ICONINDEX)
|
||
|
pfsio->iImageIndex = -1;
|
||
|
if (dwFlags & SIOM_OVERLAYINDEX)
|
||
|
pfsio->iOverlayIndex = -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LEAVECRITICAL;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CFSIconOverlayManager::OverlayIndexFromImageIndex(int iImage, int * piIndex, BOOL fAdd)
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
*piIndex = -1;
|
||
|
int i;
|
||
|
for (i = 0; i < ARRAYSIZE(s_ReservedOverlays); i++)
|
||
|
{
|
||
|
if (s_ReservedOverlays[i].iImageIndex == iImage)
|
||
|
{
|
||
|
*piIndex = s_ReservedOverlays[i].iOverlayIndex;
|
||
|
hres = S_OK;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (i == ARRAYSIZE(s_ReservedOverlays))
|
||
|
{
|
||
|
ENTERCRITICAL;
|
||
|
|
||
|
if (_hdsaIconOverlays)
|
||
|
{
|
||
|
int nOverlays = DSA_GetItemCount(_hdsaIconOverlays);
|
||
|
|
||
|
// 1. Try to find this overlay image in the list
|
||
|
int i;
|
||
|
for (i = 0; i < nOverlays; i++)
|
||
|
{
|
||
|
FSIconOverlay * pfsio = (FSIconOverlay *)DSA_GetItemPtr(_hdsaIconOverlays, i);
|
||
|
if (pfsio && pfsio->iImageIndex == iImage)
|
||
|
{
|
||
|
*piIndex = pfsio->iOverlayIndex;
|
||
|
hres = S_OK;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 2. Can't find it, let's add it (if requested)
|
||
|
if (fAdd && (i == nOverlays) && (nOverlays < NUM_OVERLAY_IMAGES))
|
||
|
{
|
||
|
FSIconOverlay fsio = {0};
|
||
|
fsio.iImageIndex = iImage;
|
||
|
fsio.iOverlayIndex = nOverlays + OVERLAYINDEX_RESERVED + 1;
|
||
|
if (DSA_InsertItem(_hdsaIconOverlays, DSA_LAST, &fsio) >= 0)
|
||
|
{
|
||
|
hres = S_OK;
|
||
|
for (int j = 0; j < ARRAYSIZE(g_rgshil); j++)
|
||
|
{
|
||
|
if (!ImageList_SetOverlayImage(g_rgshil[j].himl, iImage, fsio.iOverlayIndex))
|
||
|
{
|
||
|
hres = E_FAIL;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
*piIndex = fsio.iOverlayIndex;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DSA_DeleteItem(_hdsaIconOverlays, nOverlays);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
LEAVECRITICAL;
|
||
|
}
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CFSIconOverlayManager::_InitializeReservedOverlays()
|
||
|
{
|
||
|
int i;
|
||
|
TCHAR szModule[MAX_PATH];
|
||
|
|
||
|
BOOL fInit = _IsSHILInited();
|
||
|
if (!fInit)
|
||
|
fInit = FileIconInit(FALSE);
|
||
|
|
||
|
if (!fInit)
|
||
|
return E_OUTOFMEMORY;
|
||
|
|
||
|
HKEY hkeyIcons = SHGetShellKey(SHELLKEY_HKLM_EXPLORER, TEXT("Shell Icons"), FALSE);
|
||
|
|
||
|
GetModuleFileName(HINST_THISDLL, szModule, ARRAYSIZE(szModule));
|
||
|
|
||
|
for (i = 0; i < ARRAYSIZE(s_ReservedOverlays); i++)
|
||
|
{
|
||
|
ASSERT(s_ReservedOverlays[i].iShellResvrdImageIndex > 0);
|
||
|
ASSERT(s_ReservedOverlays[i].iOverlayIndex > 0);
|
||
|
ASSERT(s_ReservedOverlays[i].iOverlayIndex <= MAX_OVERLAY_IMAGES);
|
||
|
|
||
|
//
|
||
|
// Warning: This is used by non explorer processes on NT only
|
||
|
// because their image list was initialized with only 4 icons
|
||
|
//
|
||
|
int iIndex = s_ReservedOverlays[i].iShellResvrdImageIndex;
|
||
|
|
||
|
// re-acquire the image index
|
||
|
s_ReservedOverlays[i].iImageIndex = LookupIconIndex(szModule, iIndex, 0);
|
||
|
|
||
|
if (s_ReservedOverlays[i].iImageIndex == -1)
|
||
|
{
|
||
|
HICON rghicon[ARRAYSIZE(g_rgshil)] = {0};
|
||
|
|
||
|
// check to see if icon is overridden in the registry
|
||
|
if (hkeyIcons)
|
||
|
{
|
||
|
TCHAR val[10];
|
||
|
TCHAR ach[MAX_PATH];
|
||
|
DWORD cb = SIZEOF(ach);
|
||
|
|
||
|
wsprintf(val, TEXT("%d"), iIndex);
|
||
|
|
||
|
ach[0] = 0;
|
||
|
SHQueryValueEx(hkeyIcons, val, NULL, NULL, (LPBYTE)ach, &cb);
|
||
|
|
||
|
if (ach[0])
|
||
|
{
|
||
|
int iIcon = PathParseIconLocation(ach);
|
||
|
|
||
|
for (int j = 0; j < ARRAYSIZE(rghicon); j++)
|
||
|
{
|
||
|
ExtractIcons(ach, iIcon, g_rgshil[j].size.cx, g_rgshil[j].size.cy,
|
||
|
&rghicon[j], NULL, 1, g_lrFlags);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if we got a large icon, run with that for everyone. otherwise fall back to loadimage.
|
||
|
if (rghicon[SHIL_LARGE] == NULL)
|
||
|
{
|
||
|
for (int j = 0; j < ARRAYSIZE(g_rgshil); j++)
|
||
|
{
|
||
|
if (rghicon[j] == NULL)
|
||
|
{
|
||
|
rghicon[j] = (HICON)LoadImage(HINST_THISDLL, MAKEINTRESOURCE(c_SystemImageListIndexes[iIndex]),
|
||
|
IMAGE_ICON, g_rgshil[j].size.cx, g_rgshil[j].size.cy, g_lrFlags);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
s_ReservedOverlays[i].iImageIndex = SHAddIconsToCache(rghicon, szModule, iIndex, 0);
|
||
|
|
||
|
_DestroyIcons(rghicon, ARRAYSIZE(rghicon));
|
||
|
}
|
||
|
for (int j = 0; j < ARRAYSIZE(g_rgshil); j++)
|
||
|
{
|
||
|
ImageList_SetOverlayImage(g_rgshil[j].himl, s_ReservedOverlays[i].iImageIndex, s_ReservedOverlays[i].iOverlayIndex);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (hkeyIcons)
|
||
|
RegCloseKey(hkeyIcons);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//===========================================================================
|
||
|
// Initialize the IShellIconOverlayIdentifiers
|
||
|
//===========================================================================
|
||
|
HRESULT CFSIconOverlayManager::_InitializeHdsaIconOverlays()
|
||
|
{
|
||
|
HRESULT hres = S_FALSE; // Already initialized.
|
||
|
|
||
|
if (NULL == _hdsaIconOverlays)
|
||
|
{
|
||
|
hres = _InitializeReservedOverlays();
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
_hdsaIconOverlays = DSA_Create(SIZEOF(FSIconOverlay), FSIconOverlay_GROW);
|
||
|
|
||
|
if(NULL != _hdsaIconOverlays)
|
||
|
{
|
||
|
hres = _LoadIconOverlayIdentifiers(_hdsaIconOverlays, FALSE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HRESULT CFSIconOverlayManager::LoadNonloadedOverlayIdentifiers(void)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
|
||
|
ENTERCRITICAL;
|
||
|
|
||
|
if (NULL == _hdsaIconOverlays)
|
||
|
{
|
||
|
//
|
||
|
// No overlay HDSA yet. We should never hit this but just in case,
|
||
|
// this will be valid behavior.
|
||
|
//
|
||
|
hres = _InitializeHdsaIconOverlays();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Load unloaded identifiers into existing HDSA.
|
||
|
//
|
||
|
hres = _LoadIconOverlayIdentifiers(_hdsaIconOverlays, TRUE);
|
||
|
}
|
||
|
|
||
|
LEAVECRITICAL;
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CFSIconOverlayManager::_LoadIconOverlayIdentifiers(HDSA hdsaOverlays, BOOL bSkipIfLoaded)
|
||
|
{
|
||
|
ASSERT(NULL != hdsaOverlays);
|
||
|
|
||
|
HDCA hdca = DCA_Create();
|
||
|
if (!hdca)
|
||
|
return E_OUTOFMEMORY;
|
||
|
|
||
|
HRESULT hrInit = SHCoInitialize();
|
||
|
|
||
|
// Enumerate all of the Icon Identifiers in
|
||
|
DCA_AddItemsFromKey(hdca, HKEY_LOCAL_MACHINE, REGSTR_ICONOVERLAYID);
|
||
|
if (DCA_GetItemCount(hdca) <= 0)
|
||
|
goto EXIT;
|
||
|
|
||
|
int idca;
|
||
|
for (idca = 0; idca < DCA_GetItemCount(hdca); idca++)
|
||
|
{
|
||
|
const CLSID * pclsid = DCA_GetItem(hdca, idca);
|
||
|
|
||
|
if (bSkipIfLoaded && _IsIdentifierLoaded(*pclsid))
|
||
|
continue;
|
||
|
|
||
|
FSIconOverlay fsio;
|
||
|
ZeroMemory(&fsio, sizeof(fsio));
|
||
|
// These came from HKLM which only administrators can write to,
|
||
|
// so don't need to go through administrator approval
|
||
|
if (FAILED(DCA_CreateInstance(hdca, idca, IID_PPV_ARG(IShellIconOverlayIdentifier, &fsio.psioi))))
|
||
|
continue;
|
||
|
|
||
|
SHPinDllOfCLSID(pclsid);
|
||
|
|
||
|
DWORD dwFlags = 0;
|
||
|
int iIndex;
|
||
|
WCHAR wszIconFile[MAX_PATH];
|
||
|
// Initialize the Overlay Index to -1
|
||
|
fsio.iOverlayIndex = -1;
|
||
|
|
||
|
// Try get the overlay icon information from the Overlay Identifiers
|
||
|
if (S_OK == fsio.psioi->GetOverlayInfo(wszIconFile, ARRAYSIZE(wszIconFile), &iIndex, &dwFlags))
|
||
|
{
|
||
|
if (dwFlags & ISIOI_ICONFILE)
|
||
|
{
|
||
|
SHUnicodeToTChar(wszIconFile, fsio.szIconFile, ARRAYSIZE(fsio.szIconFile));
|
||
|
fsio.iImageIndex = -1;
|
||
|
if (dwFlags & ISIOI_ICONINDEX)
|
||
|
fsio.iIconIndex = iIndex;
|
||
|
else
|
||
|
fsio.iIconIndex = 0;
|
||
|
}
|
||
|
|
||
|
if (FAILED(fsio.psioi->GetPriority(&fsio.iPriority)))
|
||
|
fsio.iPriority = MAX_OVERLAY_PRIORITY;
|
||
|
|
||
|
CopyMemory(&fsio.clsid, pclsid, sizeof(fsio.clsid));
|
||
|
DSA_InsertItem(hdsaOverlays, DSA_LAST, &fsio);
|
||
|
}
|
||
|
// Now try to look in the registry for the Overlay Icons
|
||
|
else
|
||
|
{
|
||
|
fsio.iImageIndex = -1;
|
||
|
const CLSID * pclsid = DCA_GetItem(hdca, idca);
|
||
|
if (pclsid)
|
||
|
{
|
||
|
TCHAR szCLSID[GUIDSTR_MAX];
|
||
|
TCHAR szRegKey[GUIDSTR_MAX + 40];
|
||
|
HKEY hkeyIcon;
|
||
|
SHStringFromGUID(*pclsid, szCLSID, ARRAYSIZE(szCLSID));
|
||
|
wsprintf(szRegKey, REGSTR_ICONOVERLAYCLSID, szCLSID);
|
||
|
if (ERROR_SUCCESS == RegOpenKey(HKEY_CLASSES_ROOT, szRegKey, &hkeyIcon))
|
||
|
{
|
||
|
LONG cb = SIZEOF(fsio.szIconFile);
|
||
|
if (SHRegQueryValue(hkeyIcon, c_szDefaultIcon, fsio.szIconFile, &cb) == ERROR_SUCCESS && fsio.szIconFile[0])
|
||
|
{
|
||
|
fsio.iIconIndex = PathParseIconLocation(fsio.szIconFile);
|
||
|
CopyMemory(&fsio.clsid, pclsid, sizeof(fsio.clsid));
|
||
|
DSA_InsertItem(hdsaOverlays, DSA_LAST, &fsio);
|
||
|
}
|
||
|
|
||
|
// Unfinished !!! Code to retrieve the priority here
|
||
|
fsio.iPriority = MAX_OVERLAY_PRIORITY;
|
||
|
RegCloseKey(hkeyIcon);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Stop when we have more than we can handle
|
||
|
if (DSA_GetItemCount(hdsaOverlays) >= (MAX_OVERLAY_IMAGES - OVERLAYINDEX_RESERVED))
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
EXIT:
|
||
|
DCA_Destroy(hdca);
|
||
|
SHCoUninitialize(hrInit);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CFSIconOverlayManager::_IsIdentifierLoaded(REFCLSID clsid)
|
||
|
{
|
||
|
if (NULL != _hdsaIconOverlays)
|
||
|
{
|
||
|
int cEntries = DSA_GetItemCount(_hdsaIconOverlays);
|
||
|
for (int i = 0; i < cEntries; i++)
|
||
|
{
|
||
|
FSIconOverlay *pfsio = (FSIconOverlay *)DSA_GetItemPtr(_hdsaIconOverlays, i);
|
||
|
if (pfsio->clsid == clsid)
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
CFSIconOverlayManager::CFSIconOverlayManager() : _cRef(1) // _hdsaIconOverlays(NULL)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
HRESULT CFSIconOverlayManager::_DestroyHdsaIconOverlays()
|
||
|
{
|
||
|
if (_hdsaIconOverlays)
|
||
|
{
|
||
|
DSA_Destroy(_hdsaIconOverlays);
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
CFSIconOverlayManager::~CFSIconOverlayManager()
|
||
|
{
|
||
|
if (_hdsaIconOverlays)
|
||
|
_DestroyHdsaIconOverlays();
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// CFSFolder_GetAvailableOverlayIndex:
|
||
|
// This function first tries to find an empty slot in all the available overlay indexes
|
||
|
// If none found, it goes through the _hdsaIconOverlays array elements who have lower
|
||
|
// priorities and grab their overlay indexes if they are using one
|
||
|
//
|
||
|
/*int CFSIconOverlayManager::_GetAvailableOverlayIndex(int imyhdsa)
|
||
|
{
|
||
|
int ib;
|
||
|
for (ib = 0; ib < MAX_OVERLAY_IMAGES; ib++)
|
||
|
if (_bOverlayIndexOccupied[ib] == FALSE)
|
||
|
break;
|
||
|
|
||
|
// Add code to grab indexes here.
|
||
|
return ++ib;
|
||
|
}*/
|
||
|
|
||
|
HRESULT CFSIconOverlayManager::QueryInterface(REFIID riid, LPVOID * ppvObj)
|
||
|
{
|
||
|
// ppvObj must not be NULL
|
||
|
ASSERT(ppvObj != NULL);
|
||
|
|
||
|
if (IsEqualIID(riid, IID_IUnknown))
|
||
|
{
|
||
|
*ppvObj = SAFECAST(this, IUnknown *);
|
||
|
DebugMsg(DM_TRACE, TEXT("QI IUnknown succeeded"));
|
||
|
}
|
||
|
else if (IsEqualIID(riid, IID_IShellIconOverlayManager))
|
||
|
{
|
||
|
*ppvObj = SAFECAST(this, IShellIconOverlayManager*);
|
||
|
DebugMsg(DM_TRACE, TEXT("QI IShellIconOverlayManager succeeded"));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*ppvObj = NULL;
|
||
|
return E_NOINTERFACE; // Otherwise, don't delegate to HTMLObj!!
|
||
|
}
|
||
|
|
||
|
AddRef();
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
ULONG CFSIconOverlayManager::AddRef()
|
||
|
{
|
||
|
return InterlockedIncrement(&_cRef);
|
||
|
}
|
||
|
|
||
|
ULONG CFSIconOverlayManager::Release()
|
||
|
{
|
||
|
if (InterlockedDecrement(&_cRef))
|
||
|
return _cRef;
|
||
|
|
||
|
delete this;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int CFSIconOverlayManager::_GetImageIndex(FSIconOverlay * pfsio)
|
||
|
{
|
||
|
int iImage = LookupIconIndex(pfsio->szIconFile, pfsio->iIconIndex, GIL_FORSHELL);
|
||
|
|
||
|
if (iImage == -1)
|
||
|
{
|
||
|
// we couldn't find it from the cache
|
||
|
HICON rghicon[ARRAYSIZE(g_rgshil)] = {0};
|
||
|
|
||
|
for (int i = 0; i < ARRAYSIZE(g_rgshil); i++)
|
||
|
{
|
||
|
SHDefExtractIcon(pfsio->szIconFile, pfsio->iIconIndex, GIL_FORSHELL, &rghicon[i],
|
||
|
NULL, g_rgshil[i].size.cx);
|
||
|
}
|
||
|
|
||
|
iImage = SHAddIconsToCache(rghicon, pfsio->szIconFile, pfsio->iIconIndex, GIL_FORSHELL);
|
||
|
|
||
|
_DestroyIcons(rghicon, ARRAYSIZE(rghicon));
|
||
|
}
|
||
|
|
||
|
return iImage;
|
||
|
}
|
||
|
|
||
|
FSIconOverlay * CFSIconOverlayManager::_FindMatchingID(LPCWSTR pwszPath, DWORD dwAttrib, int iMinPriority, int * pIOverlayIndex)
|
||
|
{
|
||
|
// If we got here, we must have the DSA array
|
||
|
ASSERT(_hdsaIconOverlays);
|
||
|
if (_hdsaIconOverlays)
|
||
|
{
|
||
|
int ihdsa;
|
||
|
for (ihdsa = 0; ihdsa < DSA_GetItemCount(_hdsaIconOverlays); ihdsa++)
|
||
|
{
|
||
|
FSIconOverlay * pfsio = (FSIconOverlay *)DSA_GetItemPtr(_hdsaIconOverlays, ihdsa);
|
||
|
ASSERT(pfsio);
|
||
|
if (pfsio->iPriority >= iMinPriority)
|
||
|
continue;
|
||
|
if (pfsio->psioi && pfsio->psioi->IsMemberOf(pwszPath, dwAttrib) == S_OK)
|
||
|
{
|
||
|
// Overlay indexes start from 1, and let's not use the reserved ones
|
||
|
ASSERT(pIOverlayIndex);
|
||
|
*pIOverlayIndex = ihdsa + OVERLAYINDEX_RESERVED + 1;
|
||
|
return pfsio;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
HRESULT CFSIconOverlayManager::_SetGetOverlayInfo(FSIconOverlay * pfsio, int iOverlayIndex, int * pIndex, DWORD dwFlags)
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
RIP(pIndex);
|
||
|
*pIndex = -1;
|
||
|
#if 0 // we don't want to return the priority for now
|
||
|
if (dwFlags == SIOM_PRIORITY)
|
||
|
{
|
||
|
// This must have been initialized in the initialization function
|
||
|
*pIndex = pfsio->iPriority;
|
||
|
}
|
||
|
#endif
|
||
|
if (pfsio->iImageIndex == -1)
|
||
|
{
|
||
|
int iImage = _GetImageIndex(pfsio);
|
||
|
|
||
|
// Either we couldn't get it or we couldn't put it in cache
|
||
|
if (iImage == -1)
|
||
|
{
|
||
|
// leave this as a zombie
|
||
|
pfsio->iImageIndex = 0;
|
||
|
pfsio->iOverlayIndex = 0;
|
||
|
}
|
||
|
else
|
||
|
pfsio->iImageIndex = iImage;
|
||
|
}
|
||
|
|
||
|
// Only if we have a reasonable image index will we proceed.
|
||
|
if (pfsio->iImageIndex > 0)
|
||
|
{
|
||
|
if (dwFlags == SIOM_ICONINDEX)
|
||
|
{
|
||
|
*pIndex = pfsio->iImageIndex;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT(iOverlayIndex > 0);
|
||
|
ASSERT(iOverlayIndex <= MAX_OVERLAY_IMAGES);
|
||
|
if (pfsio->iOverlayIndex == -1)
|
||
|
{
|
||
|
// Now set the overlay
|
||
|
ASSERT(_IsSHILInited());
|
||
|
|
||
|
for (int i = 0; i < ARRAYSIZE(g_rgshil); i++)
|
||
|
{
|
||
|
ImageList_SetOverlayImage(g_rgshil[i].himl, pfsio->iImageIndex, iOverlayIndex);
|
||
|
}
|
||
|
|
||
|
pfsio->iOverlayIndex = iOverlayIndex;
|
||
|
}
|
||
|
|
||
|
// Must be the overlayindex flag
|
||
|
ASSERT(dwFlags == SIOM_OVERLAYINDEX);
|
||
|
*pIndex = pfsio->iOverlayIndex;
|
||
|
}
|
||
|
hres = S_OK;
|
||
|
|
||
|
}
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
HRESULT CFSIconOverlayManager::GetFileOverlayInfo(LPCWSTR pwszPath, DWORD dwAttrib, int * pIndex, DWORD dwFlags)
|
||
|
{
|
||
|
ASSERT((dwFlags == SIOM_OVERLAYINDEX) || (dwFlags == SIOM_ICONINDEX)); // || (dwFlags == SIOM_PRIORITY));
|
||
|
|
||
|
HRESULT hres = E_FAIL;
|
||
|
int iOverlayIndex;
|
||
|
*pIndex = 0;
|
||
|
|
||
|
ENTERCRITICAL;
|
||
|
if (_hdsaIconOverlays)
|
||
|
{
|
||
|
FSIconOverlay * pfsio = _FindMatchingID(pwszPath, dwAttrib, MAX_OVERLAY_PRIORITY, &iOverlayIndex);
|
||
|
if (pfsio)
|
||
|
hres = _SetGetOverlayInfo(pfsio, iOverlayIndex, pIndex, dwFlags);
|
||
|
}
|
||
|
LEAVECRITICAL;
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
HRESULT CFSIconOverlayManager::GetReservedOverlayInfo(LPCWSTR pwszPath, DWORD dwAttrib, int * pIndex, DWORD dwFlags, int iReservedID)
|
||
|
{
|
||
|
ASSERT(iReservedID < OVERLAYINDEX_RESERVED);
|
||
|
HRESULT hres = S_OK;
|
||
|
|
||
|
ENTERCRITICAL;
|
||
|
if (_hdsaIconOverlays && pwszPath)
|
||
|
{
|
||
|
int iOverlayIndex;
|
||
|
FSIconOverlay * pfsio = _FindMatchingID(pwszPath, dwAttrib, s_ReservedOverlays[iReservedID].iPriority, &iOverlayIndex);
|
||
|
if (pfsio)
|
||
|
{
|
||
|
hres = _SetGetOverlayInfo(pfsio, iOverlayIndex, pIndex, dwFlags);
|
||
|
LEAVECRITICAL;
|
||
|
return hres;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dwFlags == SIOM_ICONINDEX)
|
||
|
*pIndex = s_ReservedOverlays[iReservedID].iImageIndex;
|
||
|
else
|
||
|
{
|
||
|
ASSERT(dwFlags == SIOM_OVERLAYINDEX);
|
||
|
*pIndex = s_ReservedOverlays[iReservedID].iOverlayIndex;
|
||
|
}
|
||
|
LEAVECRITICAL;
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CFSIconOverlayManager::CreateInstance(IUnknown* pUnkOuter, REFIID riid, OUT LPVOID * ppvOut)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
DebugMsg(DM_TRACE, TEXT("CFSIconOverlayManager::CreateInstance()"));
|
||
|
|
||
|
*ppvOut = NULL; // null the out param
|
||
|
|
||
|
CFSIconOverlayManager *pcfsiom = new CFSIconOverlayManager;
|
||
|
|
||
|
if (!pcfsiom)
|
||
|
return E_OUTOFMEMORY;
|
||
|
|
||
|
hr = pcfsiom->_InitializeHdsaIconOverlays();
|
||
|
if (SUCCEEDED(hr))
|
||
|
hr = pcfsiom->QueryInterface(riid, ppvOut);
|
||
|
pcfsiom->Release();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
STDAPI CFSIconOverlayManager_CreateInstance(IUnknown* pUnkOuter, REFIID riid, OUT LPVOID * ppvOut)
|
||
|
{
|
||
|
return CFSIconOverlayManager::CreateInstance(pUnkOuter, riid, ppvOut);
|
||
|
}
|
||
|
|
||
|
STDAPI_(int) SHGetIconOverlayIndexW(LPCWSTR pwszIconPath, int iIconIndex)
|
||
|
{
|
||
|
|
||
|
TCHAR szIconPath[MAX_PATH];
|
||
|
int iRet = -1;
|
||
|
int iImage = -1;
|
||
|
|
||
|
// If NULL path is passed in, see if the index matches one of our special indexes
|
||
|
if (pwszIconPath == NULL)
|
||
|
{
|
||
|
switch (iIconIndex)
|
||
|
{
|
||
|
case IDO_SHGIOI_SHARE:
|
||
|
iImage = s_ReservedOverlays[0].iImageIndex;
|
||
|
break;
|
||
|
case IDO_SHGIOI_LINK:
|
||
|
iImage = s_ReservedOverlays[1].iImageIndex;
|
||
|
break;
|
||
|
case IDO_SHGIOI_SLOWFILE:
|
||
|
iImage = s_ReservedOverlays[2].iImageIndex;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else if (SHUnicodeToTChar(pwszIconPath, szIconPath, ARRAYSIZE(szIconPath)))
|
||
|
// Try to load the image into the shell icon cache
|
||
|
iImage = Shell_GetCachedImageIndex(szIconPath, iIconIndex, 0);
|
||
|
|
||
|
if (iImage >= 0)
|
||
|
{
|
||
|
IShellIconOverlayManager *psiom;
|
||
|
if (SUCCEEDED(GetIconOverlayManager(&psiom)))
|
||
|
{
|
||
|
int iCandidate = -1;
|
||
|
if (SUCCEEDED(psiom->OverlayIndexFromImageIndex(iImage, &iCandidate, TRUE)))
|
||
|
{
|
||
|
iRet = iCandidate;
|
||
|
}
|
||
|
psiom->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return iRet;
|
||
|
}
|
||
|
|
||
|
STDAPI_(int) SHGetIconOverlayIndexA(LPCSTR pszIconPath, int iIconIndex)
|
||
|
{
|
||
|
int iRet = -1;
|
||
|
WCHAR wszIconPath[MAX_PATH];
|
||
|
LPCWSTR pwszIconPath = NULL;
|
||
|
if (pszIconPath)
|
||
|
{
|
||
|
wszIconPath[0] = L'\0';
|
||
|
SHAnsiToUnicode(pszIconPath, wszIconPath, ARRAYSIZE(wszIconPath));
|
||
|
pwszIconPath = wszIconPath;
|
||
|
}
|
||
|
|
||
|
return SHGetIconOverlayIndexW(pwszIconPath, iIconIndex);
|
||
|
}
|