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