Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

780 lines
24 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Copyright (c) Microsoft Corporation
  4. //
  5. // File: overlayMN.cpp
  6. //
  7. // This file contains the implementation of CFSIconOverlayManager, a COM object
  8. // that manages the IShellIconOverlayIdentifiers list.
  9. // It aslo managess the Sytem Image List OverlayIndexes, since we have limited slots,
  10. // exactly MAX_OVERLAY_IAMGES of them.
  11. // History:
  12. // 5-2-97 by dli
  13. //------------------------------------------------------------------------
  14. #include "shellprv.h"
  15. #include "ovrlaymn.h"
  16. #include "fstreex.h"
  17. #include "filetbl.h"
  18. extern "C" {
  19. #include "cstrings.h"
  20. #include "ole2dup.h"
  21. }
  22. extern "C" UINT const c_SystemImageListIndexes[];
  23. extern int g_lrFlags;
  24. // NOTE: The value of OVERLAYINDEX_RESERVED is not the same as the overall
  25. // size of the s_ReservedOverlays array, we need to reserved the overlay slot
  26. // #3 for the non-existent Read-Only overaly.
  27. // The Read Only overlay was once there in Win95, but got turned off on IE4
  28. // however, because of the of the original overlay designs,( we used to
  29. // assign overlay 1 to share and 2 to link and 3 to readonly, and the third parties
  30. // just copied our scheme,) we have to keep overlay #3 as a ghost.
  31. #define OVERLAYINDEX_RESERVED 4
  32. typedef struct _ReservedIconOverlay
  33. {
  34. int iShellResvrdImageIndex;
  35. int iImageIndex;
  36. int iOverlayIndex;
  37. int iPriority;
  38. } ReservedIconOverlay;
  39. static ReservedIconOverlay s_ReservedOverlays[] = {
  40. {II_SHARE, II_SHARE, 1, 10},
  41. {II_LINK, II_LINK, 2, 10},
  42. // Slot 3 should be reserved as a ghost slot because of the read-only overlay
  43. {II_SLOWFILE, II_SLOWFILE, 4, 10},
  44. };
  45. // File system Icon overlay Identifiers
  46. typedef struct _FSIconOverlay {
  47. IShellIconOverlayIdentifier * psioi;
  48. CLSID clsid;
  49. int iIconIndex; // Index of the Overlay Icon in szIconFile
  50. int iImageIndex; // System Image List index of the icon overlay image
  51. int iOverlayIndex;
  52. int iPriority;
  53. TCHAR szIconFile[MAX_PATH]; // Path of the icon overlay
  54. } FSIconOverlay;
  55. #define FSIconOverlay_GROW 3
  56. #define DSA_LAST 0x7fffffff
  57. #define MAX_OVERLAY_PRIORITY 100
  58. class CFSIconOverlayManager : public IShellIconOverlayManager
  59. {
  60. public:
  61. CFSIconOverlayManager();
  62. ~CFSIconOverlayManager();
  63. // *** IUnknown Methods
  64. virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  65. virtual STDMETHODIMP_(ULONG) AddRef(void) ;
  66. virtual STDMETHODIMP_(ULONG) Release(void);
  67. // *** IShellIconOverlay Methods
  68. virtual STDMETHODIMP GetFileOverlayInfo(LPCWSTR pwszPath, DWORD dwAttrib, int * pIndex, DWORD dwFlags);
  69. virtual STDMETHODIMP GetReservedOverlayInfo(LPCWSTR pwszPath, DWORD dwAttrib, int * pIndex, DWORD dwFlags, int iReservedID);
  70. virtual STDMETHODIMP RefreshOverlayImages(DWORD dwFlags);
  71. virtual STDMETHODIMP LoadNonloadedOverlayIdentifiers(void);
  72. virtual STDMETHODIMP OverlayIndexFromImageIndex(int iImage, int * piIndex, BOOL fAdd);
  73. // *** Public Methods
  74. // *** Static Methods
  75. static HRESULT CreateInstance(IUnknown* pUnkOuter, REFIID riid, OUT LPVOID * ppvOut);
  76. protected:
  77. // IUnknown
  78. LONG _cRef;
  79. HDSA _hdsaIconOverlays; // Icon Overlay Identifiers array, this list is ordered by the IOIs' priority
  80. HRESULT _InitializeHdsaIconOverlays(); // Initialize the Icon Overlay Identifiers array
  81. HRESULT _DestroyHdsaIconOverlays();
  82. int _GetImageIndex(FSIconOverlay * pfsio);
  83. FSIconOverlay * _FindMatchingID(LPCWSTR pwszPath, DWORD dwAttrib, int iMinPriority, int * pIOverlayIndex);
  84. HRESULT _SetGetOverlayInfo(FSIconOverlay * pfsio, int iOverlayIndex, int * pIndex, DWORD dwFlags);
  85. HRESULT _InitializeReservedOverlays();
  86. HRESULT _LoadIconOverlayIdentifiers(HDSA hdsaOverlays, BOOL bSkipIfLoaded);
  87. BOOL _IsIdentifierLoaded(REFCLSID clsid);
  88. // int _GetAvailableOverlayIndex(int imyhdsa);
  89. // HRESULT _SortIOIList(); // Sort the IOI's in the list according to their priority
  90. };
  91. HRESULT CFSIconOverlayManager::RefreshOverlayImages(DWORD dwFlags)
  92. {
  93. ENTERCRITICAL;
  94. _InitializeReservedOverlays();
  95. if (dwFlags && _hdsaIconOverlays)
  96. {
  97. for (int ihdsa = 0; ihdsa < DSA_GetItemCount(_hdsaIconOverlays); ihdsa++)
  98. {
  99. FSIconOverlay * pfsio = (FSIconOverlay *)DSA_GetItemPtr(_hdsaIconOverlays, ihdsa);
  100. if (dwFlags & SIOM_ICONINDEX)
  101. pfsio->iImageIndex = -1;
  102. if (dwFlags & SIOM_OVERLAYINDEX)
  103. pfsio->iOverlayIndex = -1;
  104. }
  105. }
  106. LEAVECRITICAL;
  107. return S_OK;
  108. }
  109. HRESULT CFSIconOverlayManager::OverlayIndexFromImageIndex(int iImage, int * piIndex, BOOL fAdd)
  110. {
  111. HRESULT hres = E_FAIL;
  112. *piIndex = -1;
  113. int i;
  114. for (i = 0; i < ARRAYSIZE(s_ReservedOverlays); i++)
  115. {
  116. if (s_ReservedOverlays[i].iImageIndex == iImage)
  117. {
  118. *piIndex = s_ReservedOverlays[i].iOverlayIndex;
  119. hres = S_OK;
  120. break;
  121. }
  122. }
  123. if (i == ARRAYSIZE(s_ReservedOverlays))
  124. {
  125. ENTERCRITICAL;
  126. if (_hdsaIconOverlays)
  127. {
  128. int nOverlays = DSA_GetItemCount(_hdsaIconOverlays);
  129. // 1. Try to find this overlay image in the list
  130. int i;
  131. for (i = 0; i < nOverlays; i++)
  132. {
  133. FSIconOverlay * pfsio = (FSIconOverlay *)DSA_GetItemPtr(_hdsaIconOverlays, i);
  134. if (pfsio && pfsio->iImageIndex == iImage)
  135. {
  136. *piIndex = pfsio->iOverlayIndex;
  137. hres = S_OK;
  138. break;
  139. }
  140. }
  141. // 2. Can't find it, let's add it (if requested)
  142. if (fAdd && (i == nOverlays) && (nOverlays < NUM_OVERLAY_IMAGES))
  143. {
  144. FSIconOverlay fsio = {0};
  145. fsio.iImageIndex = iImage;
  146. fsio.iOverlayIndex = nOverlays + OVERLAYINDEX_RESERVED + 1;
  147. if (DSA_InsertItem(_hdsaIconOverlays, DSA_LAST, &fsio) >= 0)
  148. {
  149. hres = S_OK;
  150. for (int j = 0; j < ARRAYSIZE(g_rgshil); j++)
  151. {
  152. if (!ImageList_SetOverlayImage(g_rgshil[j].himl, iImage, fsio.iOverlayIndex))
  153. {
  154. hres = E_FAIL;
  155. break;
  156. }
  157. }
  158. if (SUCCEEDED(hres))
  159. {
  160. *piIndex = fsio.iOverlayIndex;
  161. }
  162. else
  163. {
  164. DSA_DeleteItem(_hdsaIconOverlays, nOverlays);
  165. }
  166. }
  167. }
  168. }
  169. LEAVECRITICAL;
  170. }
  171. return hres;
  172. }
  173. HRESULT CFSIconOverlayManager::_InitializeReservedOverlays()
  174. {
  175. int i;
  176. TCHAR szModule[MAX_PATH];
  177. BOOL fInit = _IsSHILInited();
  178. if (!fInit)
  179. fInit = FileIconInit(FALSE);
  180. if (!fInit)
  181. return E_OUTOFMEMORY;
  182. HKEY hkeyIcons = SHGetShellKey(SHELLKEY_HKLM_EXPLORER, TEXT("Shell Icons"), FALSE);
  183. GetModuleFileName(HINST_THISDLL, szModule, ARRAYSIZE(szModule));
  184. for (i = 0; i < ARRAYSIZE(s_ReservedOverlays); i++)
  185. {
  186. ASSERT(s_ReservedOverlays[i].iShellResvrdImageIndex > 0);
  187. ASSERT(s_ReservedOverlays[i].iOverlayIndex > 0);
  188. ASSERT(s_ReservedOverlays[i].iOverlayIndex <= MAX_OVERLAY_IMAGES);
  189. //
  190. // Warning: This is used by non explorer processes on NT only
  191. // because their image list was initialized with only 4 icons
  192. //
  193. int iIndex = s_ReservedOverlays[i].iShellResvrdImageIndex;
  194. // re-acquire the image index
  195. s_ReservedOverlays[i].iImageIndex = LookupIconIndex(szModule, iIndex, 0);
  196. if (s_ReservedOverlays[i].iImageIndex == -1)
  197. {
  198. HICON rghicon[ARRAYSIZE(g_rgshil)] = {0};
  199. // check to see if icon is overridden in the registry
  200. if (hkeyIcons)
  201. {
  202. TCHAR val[10];
  203. TCHAR ach[MAX_PATH];
  204. DWORD cb = SIZEOF(ach);
  205. wsprintf(val, TEXT("%d"), iIndex);
  206. ach[0] = 0;
  207. SHQueryValueEx(hkeyIcons, val, NULL, NULL, (LPBYTE)ach, &cb);
  208. if (ach[0])
  209. {
  210. int iIcon = PathParseIconLocation(ach);
  211. for (int j = 0; j < ARRAYSIZE(rghicon); j++)
  212. {
  213. ExtractIcons(ach, iIcon, g_rgshil[j].size.cx, g_rgshil[j].size.cy,
  214. &rghicon[j], NULL, 1, g_lrFlags);
  215. }
  216. }
  217. }
  218. // if we got a large icon, run with that for everyone. otherwise fall back to loadimage.
  219. if (rghicon[SHIL_LARGE] == NULL)
  220. {
  221. for (int j = 0; j < ARRAYSIZE(g_rgshil); j++)
  222. {
  223. if (rghicon[j] == NULL)
  224. {
  225. rghicon[j] = (HICON)LoadImage(HINST_THISDLL, MAKEINTRESOURCE(c_SystemImageListIndexes[iIndex]),
  226. IMAGE_ICON, g_rgshil[j].size.cx, g_rgshil[j].size.cy, g_lrFlags);
  227. }
  228. }
  229. }
  230. s_ReservedOverlays[i].iImageIndex = SHAddIconsToCache(rghicon, szModule, iIndex, 0);
  231. _DestroyIcons(rghicon, ARRAYSIZE(rghicon));
  232. }
  233. for (int j = 0; j < ARRAYSIZE(g_rgshil); j++)
  234. {
  235. ImageList_SetOverlayImage(g_rgshil[j].himl, s_ReservedOverlays[i].iImageIndex, s_ReservedOverlays[i].iOverlayIndex);
  236. }
  237. }
  238. if (hkeyIcons)
  239. RegCloseKey(hkeyIcons);
  240. return S_OK;
  241. }
  242. //===========================================================================
  243. // Initialize the IShellIconOverlayIdentifiers
  244. //===========================================================================
  245. HRESULT CFSIconOverlayManager::_InitializeHdsaIconOverlays()
  246. {
  247. HRESULT hres = S_FALSE; // Already initialized.
  248. if (NULL == _hdsaIconOverlays)
  249. {
  250. hres = _InitializeReservedOverlays();
  251. if (SUCCEEDED(hres))
  252. {
  253. _hdsaIconOverlays = DSA_Create(SIZEOF(FSIconOverlay), FSIconOverlay_GROW);
  254. if(NULL != _hdsaIconOverlays)
  255. {
  256. hres = _LoadIconOverlayIdentifiers(_hdsaIconOverlays, FALSE);
  257. }
  258. else
  259. {
  260. hres = E_OUTOFMEMORY;
  261. }
  262. }
  263. }
  264. return hres;
  265. }
  266. HRESULT CFSIconOverlayManager::LoadNonloadedOverlayIdentifiers(void)
  267. {
  268. HRESULT hres;
  269. ENTERCRITICAL;
  270. if (NULL == _hdsaIconOverlays)
  271. {
  272. //
  273. // No overlay HDSA yet. We should never hit this but just in case,
  274. // this will be valid behavior.
  275. //
  276. hres = _InitializeHdsaIconOverlays();
  277. }
  278. else
  279. {
  280. //
  281. // Load unloaded identifiers into existing HDSA.
  282. //
  283. hres = _LoadIconOverlayIdentifiers(_hdsaIconOverlays, TRUE);
  284. }
  285. LEAVECRITICAL;
  286. return hres;
  287. }
  288. HRESULT CFSIconOverlayManager::_LoadIconOverlayIdentifiers(HDSA hdsaOverlays, BOOL bSkipIfLoaded)
  289. {
  290. ASSERT(NULL != hdsaOverlays);
  291. HDCA hdca = DCA_Create();
  292. if (!hdca)
  293. return E_OUTOFMEMORY;
  294. HRESULT hrInit = SHCoInitialize();
  295. // Enumerate all of the Icon Identifiers in
  296. DCA_AddItemsFromKey(hdca, HKEY_LOCAL_MACHINE, REGSTR_ICONOVERLAYID);
  297. if (DCA_GetItemCount(hdca) <= 0)
  298. goto EXIT;
  299. int idca;
  300. for (idca = 0; idca < DCA_GetItemCount(hdca); idca++)
  301. {
  302. const CLSID * pclsid = DCA_GetItem(hdca, idca);
  303. if (bSkipIfLoaded && _IsIdentifierLoaded(*pclsid))
  304. continue;
  305. FSIconOverlay fsio;
  306. ZeroMemory(&fsio, sizeof(fsio));
  307. // These came from HKLM which only administrators can write to,
  308. // so don't need to go through administrator approval
  309. if (FAILED(DCA_CreateInstance(hdca, idca, IID_PPV_ARG(IShellIconOverlayIdentifier, &fsio.psioi))))
  310. continue;
  311. SHPinDllOfCLSID(pclsid);
  312. DWORD dwFlags = 0;
  313. int iIndex;
  314. WCHAR wszIconFile[MAX_PATH];
  315. // Initialize the Overlay Index to -1
  316. fsio.iOverlayIndex = -1;
  317. // Try get the overlay icon information from the Overlay Identifiers
  318. if (S_OK == fsio.psioi->GetOverlayInfo(wszIconFile, ARRAYSIZE(wszIconFile), &iIndex, &dwFlags))
  319. {
  320. if (dwFlags & ISIOI_ICONFILE)
  321. {
  322. SHUnicodeToTChar(wszIconFile, fsio.szIconFile, ARRAYSIZE(fsio.szIconFile));
  323. fsio.iImageIndex = -1;
  324. if (dwFlags & ISIOI_ICONINDEX)
  325. fsio.iIconIndex = iIndex;
  326. else
  327. fsio.iIconIndex = 0;
  328. }
  329. if (FAILED(fsio.psioi->GetPriority(&fsio.iPriority)))
  330. fsio.iPriority = MAX_OVERLAY_PRIORITY;
  331. CopyMemory(&fsio.clsid, pclsid, sizeof(fsio.clsid));
  332. DSA_InsertItem(hdsaOverlays, DSA_LAST, &fsio);
  333. }
  334. // Now try to look in the registry for the Overlay Icons
  335. else
  336. {
  337. fsio.iImageIndex = -1;
  338. const CLSID * pclsid = DCA_GetItem(hdca, idca);
  339. if (pclsid)
  340. {
  341. TCHAR szCLSID[GUIDSTR_MAX];
  342. TCHAR szRegKey[GUIDSTR_MAX + 40];
  343. HKEY hkeyIcon;
  344. SHStringFromGUID(*pclsid, szCLSID, ARRAYSIZE(szCLSID));
  345. wsprintf(szRegKey, REGSTR_ICONOVERLAYCLSID, szCLSID);
  346. if (ERROR_SUCCESS == RegOpenKey(HKEY_CLASSES_ROOT, szRegKey, &hkeyIcon))
  347. {
  348. LONG cb = SIZEOF(fsio.szIconFile);
  349. if (SHRegQueryValue(hkeyIcon, c_szDefaultIcon, fsio.szIconFile, &cb) == ERROR_SUCCESS && fsio.szIconFile[0])
  350. {
  351. fsio.iIconIndex = PathParseIconLocation(fsio.szIconFile);
  352. CopyMemory(&fsio.clsid, pclsid, sizeof(fsio.clsid));
  353. DSA_InsertItem(hdsaOverlays, DSA_LAST, &fsio);
  354. }
  355. // Unfinished !!! Code to retrieve the priority here
  356. fsio.iPriority = MAX_OVERLAY_PRIORITY;
  357. RegCloseKey(hkeyIcon);
  358. }
  359. }
  360. }
  361. // Stop when we have more than we can handle
  362. if (DSA_GetItemCount(hdsaOverlays) >= (MAX_OVERLAY_IMAGES - OVERLAYINDEX_RESERVED))
  363. break;
  364. }
  365. EXIT:
  366. DCA_Destroy(hdca);
  367. SHCoUninitialize(hrInit);
  368. return S_OK;
  369. }
  370. BOOL CFSIconOverlayManager::_IsIdentifierLoaded(REFCLSID clsid)
  371. {
  372. if (NULL != _hdsaIconOverlays)
  373. {
  374. int cEntries = DSA_GetItemCount(_hdsaIconOverlays);
  375. for (int i = 0; i < cEntries; i++)
  376. {
  377. FSIconOverlay *pfsio = (FSIconOverlay *)DSA_GetItemPtr(_hdsaIconOverlays, i);
  378. if (pfsio->clsid == clsid)
  379. return TRUE;
  380. }
  381. }
  382. return FALSE;
  383. }
  384. CFSIconOverlayManager::CFSIconOverlayManager() : _cRef(1) // _hdsaIconOverlays(NULL)
  385. {
  386. }
  387. HRESULT CFSIconOverlayManager::_DestroyHdsaIconOverlays()
  388. {
  389. if (_hdsaIconOverlays)
  390. {
  391. DSA_Destroy(_hdsaIconOverlays);
  392. }
  393. return S_OK;
  394. }
  395. CFSIconOverlayManager::~CFSIconOverlayManager()
  396. {
  397. if (_hdsaIconOverlays)
  398. _DestroyHdsaIconOverlays();
  399. }
  400. //
  401. // CFSFolder_GetAvailableOverlayIndex:
  402. // This function first tries to find an empty slot in all the available overlay indexes
  403. // If none found, it goes through the _hdsaIconOverlays array elements who have lower
  404. // priorities and grab their overlay indexes if they are using one
  405. //
  406. /*int CFSIconOverlayManager::_GetAvailableOverlayIndex(int imyhdsa)
  407. {
  408. int ib;
  409. for (ib = 0; ib < MAX_OVERLAY_IMAGES; ib++)
  410. if (_bOverlayIndexOccupied[ib] == FALSE)
  411. break;
  412. // Add code to grab indexes here.
  413. return ++ib;
  414. }*/
  415. HRESULT CFSIconOverlayManager::QueryInterface(REFIID riid, LPVOID * ppvObj)
  416. {
  417. // ppvObj must not be NULL
  418. ASSERT(ppvObj != NULL);
  419. if (IsEqualIID(riid, IID_IUnknown))
  420. {
  421. *ppvObj = SAFECAST(this, IUnknown *);
  422. DebugMsg(DM_TRACE, TEXT("QI IUnknown succeeded"));
  423. }
  424. else if (IsEqualIID(riid, IID_IShellIconOverlayManager))
  425. {
  426. *ppvObj = SAFECAST(this, IShellIconOverlayManager*);
  427. DebugMsg(DM_TRACE, TEXT("QI IShellIconOverlayManager succeeded"));
  428. }
  429. else
  430. {
  431. *ppvObj = NULL;
  432. return E_NOINTERFACE; // Otherwise, don't delegate to HTMLObj!!
  433. }
  434. AddRef();
  435. return S_OK;
  436. }
  437. ULONG CFSIconOverlayManager::AddRef()
  438. {
  439. return InterlockedIncrement(&_cRef);
  440. }
  441. ULONG CFSIconOverlayManager::Release()
  442. {
  443. if (InterlockedDecrement(&_cRef))
  444. return _cRef;
  445. delete this;
  446. return 0;
  447. }
  448. int CFSIconOverlayManager::_GetImageIndex(FSIconOverlay * pfsio)
  449. {
  450. int iImage = LookupIconIndex(pfsio->szIconFile, pfsio->iIconIndex, GIL_FORSHELL);
  451. if (iImage == -1)
  452. {
  453. // we couldn't find it from the cache
  454. HICON rghicon[ARRAYSIZE(g_rgshil)] = {0};
  455. for (int i = 0; i < ARRAYSIZE(g_rgshil); i++)
  456. {
  457. SHDefExtractIcon(pfsio->szIconFile, pfsio->iIconIndex, GIL_FORSHELL, &rghicon[i],
  458. NULL, g_rgshil[i].size.cx);
  459. }
  460. iImage = SHAddIconsToCache(rghicon, pfsio->szIconFile, pfsio->iIconIndex, GIL_FORSHELL);
  461. _DestroyIcons(rghicon, ARRAYSIZE(rghicon));
  462. }
  463. return iImage;
  464. }
  465. FSIconOverlay * CFSIconOverlayManager::_FindMatchingID(LPCWSTR pwszPath, DWORD dwAttrib, int iMinPriority, int * pIOverlayIndex)
  466. {
  467. // If we got here, we must have the DSA array
  468. ASSERT(_hdsaIconOverlays);
  469. if (_hdsaIconOverlays)
  470. {
  471. int ihdsa;
  472. for (ihdsa = 0; ihdsa < DSA_GetItemCount(_hdsaIconOverlays); ihdsa++)
  473. {
  474. FSIconOverlay * pfsio = (FSIconOverlay *)DSA_GetItemPtr(_hdsaIconOverlays, ihdsa);
  475. ASSERT(pfsio);
  476. if (pfsio->iPriority >= iMinPriority)
  477. continue;
  478. if (pfsio->psioi && pfsio->psioi->IsMemberOf(pwszPath, dwAttrib) == S_OK)
  479. {
  480. // Overlay indexes start from 1, and let's not use the reserved ones
  481. ASSERT(pIOverlayIndex);
  482. *pIOverlayIndex = ihdsa + OVERLAYINDEX_RESERVED + 1;
  483. return pfsio;
  484. }
  485. }
  486. }
  487. return NULL;
  488. }
  489. HRESULT CFSIconOverlayManager::_SetGetOverlayInfo(FSIconOverlay * pfsio, int iOverlayIndex, int * pIndex, DWORD dwFlags)
  490. {
  491. HRESULT hres = E_FAIL;
  492. RIP(pIndex);
  493. *pIndex = -1;
  494. #if 0 // we don't want to return the priority for now
  495. if (dwFlags == SIOM_PRIORITY)
  496. {
  497. // This must have been initialized in the initialization function
  498. *pIndex = pfsio->iPriority;
  499. }
  500. #endif
  501. if (pfsio->iImageIndex == -1)
  502. {
  503. int iImage = _GetImageIndex(pfsio);
  504. // Either we couldn't get it or we couldn't put it in cache
  505. if (iImage == -1)
  506. {
  507. // leave this as a zombie
  508. pfsio->iImageIndex = 0;
  509. pfsio->iOverlayIndex = 0;
  510. }
  511. else
  512. pfsio->iImageIndex = iImage;
  513. }
  514. // Only if we have a reasonable image index will we proceed.
  515. if (pfsio->iImageIndex > 0)
  516. {
  517. if (dwFlags == SIOM_ICONINDEX)
  518. {
  519. *pIndex = pfsio->iImageIndex;
  520. }
  521. else
  522. {
  523. ASSERT(iOverlayIndex > 0);
  524. ASSERT(iOverlayIndex <= MAX_OVERLAY_IMAGES);
  525. if (pfsio->iOverlayIndex == -1)
  526. {
  527. // Now set the overlay
  528. ASSERT(_IsSHILInited());
  529. for (int i = 0; i < ARRAYSIZE(g_rgshil); i++)
  530. {
  531. ImageList_SetOverlayImage(g_rgshil[i].himl, pfsio->iImageIndex, iOverlayIndex);
  532. }
  533. pfsio->iOverlayIndex = iOverlayIndex;
  534. }
  535. // Must be the overlayindex flag
  536. ASSERT(dwFlags == SIOM_OVERLAYINDEX);
  537. *pIndex = pfsio->iOverlayIndex;
  538. }
  539. hres = S_OK;
  540. }
  541. return hres;
  542. }
  543. HRESULT CFSIconOverlayManager::GetFileOverlayInfo(LPCWSTR pwszPath, DWORD dwAttrib, int * pIndex, DWORD dwFlags)
  544. {
  545. ASSERT((dwFlags == SIOM_OVERLAYINDEX) || (dwFlags == SIOM_ICONINDEX)); // || (dwFlags == SIOM_PRIORITY));
  546. HRESULT hres = E_FAIL;
  547. int iOverlayIndex;
  548. *pIndex = 0;
  549. ENTERCRITICAL;
  550. if (_hdsaIconOverlays)
  551. {
  552. FSIconOverlay * pfsio = _FindMatchingID(pwszPath, dwAttrib, MAX_OVERLAY_PRIORITY, &iOverlayIndex);
  553. if (pfsio)
  554. hres = _SetGetOverlayInfo(pfsio, iOverlayIndex, pIndex, dwFlags);
  555. }
  556. LEAVECRITICAL;
  557. return hres;
  558. }
  559. HRESULT CFSIconOverlayManager::GetReservedOverlayInfo(LPCWSTR pwszPath, DWORD dwAttrib, int * pIndex, DWORD dwFlags, int iReservedID)
  560. {
  561. ASSERT(iReservedID < OVERLAYINDEX_RESERVED);
  562. HRESULT hres = S_OK;
  563. ENTERCRITICAL;
  564. if (_hdsaIconOverlays && pwszPath)
  565. {
  566. int iOverlayIndex;
  567. FSIconOverlay * pfsio = _FindMatchingID(pwszPath, dwAttrib, s_ReservedOverlays[iReservedID].iPriority, &iOverlayIndex);
  568. if (pfsio)
  569. {
  570. hres = _SetGetOverlayInfo(pfsio, iOverlayIndex, pIndex, dwFlags);
  571. LEAVECRITICAL;
  572. return hres;
  573. }
  574. }
  575. if (dwFlags == SIOM_ICONINDEX)
  576. *pIndex = s_ReservedOverlays[iReservedID].iImageIndex;
  577. else
  578. {
  579. ASSERT(dwFlags == SIOM_OVERLAYINDEX);
  580. *pIndex = s_ReservedOverlays[iReservedID].iOverlayIndex;
  581. }
  582. LEAVECRITICAL;
  583. return hres;
  584. }
  585. HRESULT CFSIconOverlayManager::CreateInstance(IUnknown* pUnkOuter, REFIID riid, OUT LPVOID * ppvOut)
  586. {
  587. HRESULT hr;
  588. DebugMsg(DM_TRACE, TEXT("CFSIconOverlayManager::CreateInstance()"));
  589. *ppvOut = NULL; // null the out param
  590. CFSIconOverlayManager *pcfsiom = new CFSIconOverlayManager;
  591. if (!pcfsiom)
  592. return E_OUTOFMEMORY;
  593. hr = pcfsiom->_InitializeHdsaIconOverlays();
  594. if (SUCCEEDED(hr))
  595. hr = pcfsiom->QueryInterface(riid, ppvOut);
  596. pcfsiom->Release();
  597. return hr;
  598. }
  599. STDAPI CFSIconOverlayManager_CreateInstance(IUnknown* pUnkOuter, REFIID riid, OUT LPVOID * ppvOut)
  600. {
  601. return CFSIconOverlayManager::CreateInstance(pUnkOuter, riid, ppvOut);
  602. }
  603. STDAPI_(int) SHGetIconOverlayIndexW(LPCWSTR pwszIconPath, int iIconIndex)
  604. {
  605. TCHAR szIconPath[MAX_PATH];
  606. int iRet = -1;
  607. int iImage = -1;
  608. // If NULL path is passed in, see if the index matches one of our special indexes
  609. if (pwszIconPath == NULL)
  610. {
  611. switch (iIconIndex)
  612. {
  613. case IDO_SHGIOI_SHARE:
  614. iImage = s_ReservedOverlays[0].iImageIndex;
  615. break;
  616. case IDO_SHGIOI_LINK:
  617. iImage = s_ReservedOverlays[1].iImageIndex;
  618. break;
  619. case IDO_SHGIOI_SLOWFILE:
  620. iImage = s_ReservedOverlays[2].iImageIndex;
  621. break;
  622. }
  623. }
  624. else if (SHUnicodeToTChar(pwszIconPath, szIconPath, ARRAYSIZE(szIconPath)))
  625. // Try to load the image into the shell icon cache
  626. iImage = Shell_GetCachedImageIndex(szIconPath, iIconIndex, 0);
  627. if (iImage >= 0)
  628. {
  629. IShellIconOverlayManager *psiom;
  630. if (SUCCEEDED(GetIconOverlayManager(&psiom)))
  631. {
  632. int iCandidate = -1;
  633. if (SUCCEEDED(psiom->OverlayIndexFromImageIndex(iImage, &iCandidate, TRUE)))
  634. {
  635. iRet = iCandidate;
  636. }
  637. psiom->Release();
  638. }
  639. }
  640. return iRet;
  641. }
  642. STDAPI_(int) SHGetIconOverlayIndexA(LPCSTR pszIconPath, int iIconIndex)
  643. {
  644. int iRet = -1;
  645. WCHAR wszIconPath[MAX_PATH];
  646. LPCWSTR pwszIconPath = NULL;
  647. if (pszIconPath)
  648. {
  649. wszIconPath[0] = L'\0';
  650. SHAnsiToUnicode(pszIconPath, wszIconPath, ARRAYSIZE(wszIconPath));
  651. pwszIconPath = wszIconPath;
  652. }
  653. return SHGetIconOverlayIndexW(pwszIconPath, iIconIndex);
  654. }