Leaked source code of windows server 2003
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.

782 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[12];
  203. TCHAR ach[MAX_PATH];
  204. DWORD cb = SIZEOF(ach);
  205. HRESULT hr;
  206. hr = StringCchPrintf(val, ARRAYSIZE(val), TEXT("%d"), iIndex); // ok to truncate
  207. ach[0] = 0;
  208. SHQueryValueEx(hkeyIcons, val, NULL, NULL, (LPBYTE)ach, &cb);
  209. if (ach[0])
  210. {
  211. int iIcon = PathParseIconLocation(ach);
  212. for (int j = 0; j < ARRAYSIZE(rghicon); j++)
  213. {
  214. ExtractIcons(ach, iIcon, g_rgshil[j].size.cx, g_rgshil[j].size.cy,
  215. &rghicon[j], NULL, 1, g_lrFlags);
  216. }
  217. }
  218. }
  219. // if we got a large icon, run with that for everyone. otherwise fall back to loadimage.
  220. if (rghicon[SHIL_LARGE] == NULL)
  221. {
  222. for (int j = 0; j < ARRAYSIZE(g_rgshil); j++)
  223. {
  224. if (rghicon[j] == NULL)
  225. {
  226. rghicon[j] = (HICON)LoadImage(HINST_THISDLL, MAKEINTRESOURCE(c_SystemImageListIndexes[iIndex]),
  227. IMAGE_ICON, g_rgshil[j].size.cx, g_rgshil[j].size.cy, g_lrFlags);
  228. }
  229. }
  230. }
  231. s_ReservedOverlays[i].iImageIndex = SHAddIconsToCache(rghicon, szModule, iIndex, 0);
  232. _DestroyIcons(rghicon, ARRAYSIZE(rghicon));
  233. }
  234. for (int j = 0; j < ARRAYSIZE(g_rgshil); j++)
  235. {
  236. ImageList_SetOverlayImage(g_rgshil[j].himl, s_ReservedOverlays[i].iImageIndex, s_ReservedOverlays[i].iOverlayIndex);
  237. }
  238. }
  239. if (hkeyIcons)
  240. RegCloseKey(hkeyIcons);
  241. return S_OK;
  242. }
  243. //===========================================================================
  244. // Initialize the IShellIconOverlayIdentifiers
  245. //===========================================================================
  246. HRESULT CFSIconOverlayManager::_InitializeHdsaIconOverlays()
  247. {
  248. HRESULT hres = S_FALSE; // Already initialized.
  249. if (NULL == _hdsaIconOverlays)
  250. {
  251. hres = _InitializeReservedOverlays();
  252. if (SUCCEEDED(hres))
  253. {
  254. _hdsaIconOverlays = DSA_Create(SIZEOF(FSIconOverlay), FSIconOverlay_GROW);
  255. if(NULL != _hdsaIconOverlays)
  256. {
  257. hres = _LoadIconOverlayIdentifiers(_hdsaIconOverlays, FALSE);
  258. }
  259. else
  260. {
  261. hres = E_OUTOFMEMORY;
  262. }
  263. }
  264. }
  265. return hres;
  266. }
  267. HRESULT CFSIconOverlayManager::LoadNonloadedOverlayIdentifiers(void)
  268. {
  269. HRESULT hres;
  270. ENTERCRITICAL;
  271. if (NULL == _hdsaIconOverlays)
  272. {
  273. //
  274. // No overlay HDSA yet. We should never hit this but just in case,
  275. // this will be valid behavior.
  276. //
  277. hres = _InitializeHdsaIconOverlays();
  278. }
  279. else
  280. {
  281. //
  282. // Load unloaded identifiers into existing HDSA.
  283. //
  284. hres = _LoadIconOverlayIdentifiers(_hdsaIconOverlays, TRUE);
  285. }
  286. LEAVECRITICAL;
  287. return hres;
  288. }
  289. HRESULT CFSIconOverlayManager::_LoadIconOverlayIdentifiers(HDSA hdsaOverlays, BOOL bSkipIfLoaded)
  290. {
  291. ASSERT(NULL != hdsaOverlays);
  292. HDCA hdca = DCA_Create();
  293. if (!hdca)
  294. return E_OUTOFMEMORY;
  295. HRESULT hrInit = SHCoInitialize();
  296. // Enumerate all of the Icon Identifiers in
  297. DCA_AddItemsFromKey(hdca, HKEY_LOCAL_MACHINE, REGSTR_ICONOVERLAYID);
  298. if (DCA_GetItemCount(hdca) <= 0)
  299. goto EXIT;
  300. int idca;
  301. for (idca = 0; idca < DCA_GetItemCount(hdca); idca++)
  302. {
  303. const CLSID * pclsid = DCA_GetItem(hdca, idca);
  304. if (bSkipIfLoaded && _IsIdentifierLoaded(*pclsid))
  305. continue;
  306. FSIconOverlay fsio;
  307. ZeroMemory(&fsio, sizeof(fsio));
  308. // These came from HKLM which only administrators can write to,
  309. // so don't need to go through administrator approval
  310. if (FAILED(DCA_CreateInstance(hdca, idca, IID_PPV_ARG(IShellIconOverlayIdentifier, &fsio.psioi))))
  311. continue;
  312. SHPinDllOfCLSID(pclsid);
  313. DWORD dwFlags = 0;
  314. int iIndex;
  315. WCHAR wszIconFile[MAX_PATH];
  316. // Initialize the Overlay Index to -1
  317. fsio.iOverlayIndex = -1;
  318. // Try get the overlay icon information from the Overlay Identifiers
  319. if (S_OK == fsio.psioi->GetOverlayInfo(wszIconFile, ARRAYSIZE(wszIconFile), &iIndex, &dwFlags))
  320. {
  321. if (dwFlags & ISIOI_ICONFILE)
  322. {
  323. SHUnicodeToTChar(wszIconFile, fsio.szIconFile, ARRAYSIZE(fsio.szIconFile));
  324. fsio.iImageIndex = -1;
  325. if (dwFlags & ISIOI_ICONINDEX)
  326. fsio.iIconIndex = iIndex;
  327. else
  328. fsio.iIconIndex = 0;
  329. }
  330. if (FAILED(fsio.psioi->GetPriority(&fsio.iPriority)))
  331. fsio.iPriority = MAX_OVERLAY_PRIORITY;
  332. CopyMemory(&fsio.clsid, pclsid, sizeof(fsio.clsid));
  333. DSA_InsertItem(hdsaOverlays, DSA_LAST, &fsio);
  334. }
  335. // Now try to look in the registry for the Overlay Icons
  336. else
  337. {
  338. fsio.iImageIndex = -1;
  339. const CLSID * pclsid = DCA_GetItem(hdca, idca);
  340. if (pclsid)
  341. {
  342. TCHAR szCLSID[GUIDSTR_MAX];
  343. TCHAR szRegKey[GUIDSTR_MAX + 40];
  344. HKEY hkeyIcon;
  345. HRESULT hr;
  346. SHStringFromGUID(*pclsid, szCLSID, ARRAYSIZE(szCLSID));
  347. hr = StringCchPrintf(szRegKey, ARRAYSIZE(szRegKey), REGSTR_ICONOVERLAYCLSID, szCLSID);
  348. if (SUCCEEDED(hr))
  349. {
  350. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szRegKey, 0, KEY_QUERY_VALUE, &hkeyIcon))
  351. {
  352. if (ERROR_SUCCESS == SHRegGetString(hkeyIcon, NULL, c_szDefaultIcon, fsio.szIconFile, ARRAYSIZE(fsio.szIconFile))
  353. && fsio.szIconFile[0])
  354. {
  355. fsio.iIconIndex = PathParseIconLocation(fsio.szIconFile);
  356. CopyMemory(&fsio.clsid, pclsid, sizeof(fsio.clsid));
  357. DSA_InsertItem(hdsaOverlays, DSA_LAST, &fsio);
  358. }
  359. // Unfinished !!! Code to retrieve the priority here
  360. fsio.iPriority = MAX_OVERLAY_PRIORITY;
  361. RegCloseKey(hkeyIcon);
  362. }
  363. }
  364. }
  365. }
  366. // Stop when we have more than we can handle
  367. if (DSA_GetItemCount(hdsaOverlays) >= (MAX_OVERLAY_IMAGES - OVERLAYINDEX_RESERVED))
  368. break;
  369. }
  370. EXIT:
  371. DCA_Destroy(hdca);
  372. SHCoUninitialize(hrInit);
  373. return S_OK;
  374. }
  375. BOOL CFSIconOverlayManager::_IsIdentifierLoaded(REFCLSID clsid)
  376. {
  377. if (NULL != _hdsaIconOverlays)
  378. {
  379. int cEntries = DSA_GetItemCount(_hdsaIconOverlays);
  380. for (int i = 0; i < cEntries; i++)
  381. {
  382. FSIconOverlay *pfsio = (FSIconOverlay *)DSA_GetItemPtr(_hdsaIconOverlays, i);
  383. if (pfsio->clsid == clsid)
  384. return TRUE;
  385. }
  386. }
  387. return FALSE;
  388. }
  389. CFSIconOverlayManager::CFSIconOverlayManager() : _cRef(1) // _hdsaIconOverlays(NULL)
  390. {
  391. }
  392. HRESULT CFSIconOverlayManager::_DestroyHdsaIconOverlays()
  393. {
  394. if (_hdsaIconOverlays)
  395. {
  396. DSA_Destroy(_hdsaIconOverlays);
  397. }
  398. return S_OK;
  399. }
  400. CFSIconOverlayManager::~CFSIconOverlayManager()
  401. {
  402. if (_hdsaIconOverlays)
  403. _DestroyHdsaIconOverlays();
  404. }
  405. //
  406. // CFSFolder_GetAvailableOverlayIndex:
  407. // This function first tries to find an empty slot in all the available overlay indexes
  408. // If none found, it goes through the _hdsaIconOverlays array elements who have lower
  409. // priorities and grab their overlay indexes if they are using one
  410. //
  411. /*int CFSIconOverlayManager::_GetAvailableOverlayIndex(int imyhdsa)
  412. {
  413. int ib;
  414. for (ib = 0; ib < MAX_OVERLAY_IMAGES; ib++)
  415. if (_bOverlayIndexOccupied[ib] == FALSE)
  416. break;
  417. // Add code to grab indexes here.
  418. return ++ib;
  419. }*/
  420. HRESULT CFSIconOverlayManager::QueryInterface(REFIID riid, LPVOID * ppvObj)
  421. {
  422. // ppvObj must not be NULL
  423. ASSERT(ppvObj != NULL);
  424. if (IsEqualIID(riid, IID_IUnknown))
  425. {
  426. *ppvObj = SAFECAST(this, IUnknown *);
  427. DebugMsg(DM_TRACE, TEXT("QI IUnknown succeeded"));
  428. }
  429. else if (IsEqualIID(riid, IID_IShellIconOverlayManager))
  430. {
  431. *ppvObj = SAFECAST(this, IShellIconOverlayManager*);
  432. DebugMsg(DM_TRACE, TEXT("QI IShellIconOverlayManager succeeded"));
  433. }
  434. else
  435. {
  436. *ppvObj = NULL;
  437. return E_NOINTERFACE; // Otherwise, don't delegate to HTMLObj!!
  438. }
  439. AddRef();
  440. return S_OK;
  441. }
  442. ULONG CFSIconOverlayManager::AddRef()
  443. {
  444. return InterlockedIncrement(&_cRef);
  445. }
  446. ULONG CFSIconOverlayManager::Release()
  447. {
  448. ASSERT( 0 != _cRef );
  449. ULONG cRef = InterlockedDecrement(&_cRef);
  450. if ( 0 == cRef )
  451. {
  452. delete this;
  453. }
  454. return cRef;
  455. }
  456. int CFSIconOverlayManager::_GetImageIndex(FSIconOverlay * pfsio)
  457. {
  458. int iImage = LookupIconIndex(pfsio->szIconFile, pfsio->iIconIndex, GIL_FORSHELL);
  459. if (iImage == -1)
  460. {
  461. // we couldn't find it from the cache
  462. HICON rghicon[ARRAYSIZE(g_rgshil)] = {0};
  463. for (int i = 0; i < ARRAYSIZE(g_rgshil); i++)
  464. {
  465. SHDefExtractIcon(pfsio->szIconFile, pfsio->iIconIndex, GIL_FORSHELL, &rghicon[i],
  466. NULL, g_rgshil[i].size.cx);
  467. }
  468. iImage = SHAddIconsToCache(rghicon, pfsio->szIconFile, pfsio->iIconIndex, GIL_FORSHELL);
  469. _DestroyIcons(rghicon, ARRAYSIZE(rghicon));
  470. }
  471. return iImage;
  472. }
  473. FSIconOverlay * CFSIconOverlayManager::_FindMatchingID(LPCWSTR pwszPath, DWORD dwAttrib, int iMinPriority, int * pIOverlayIndex)
  474. {
  475. // If we got here, we must have the DSA array
  476. ASSERT(_hdsaIconOverlays);
  477. if (_hdsaIconOverlays)
  478. {
  479. int ihdsa;
  480. for (ihdsa = 0; ihdsa < DSA_GetItemCount(_hdsaIconOverlays); ihdsa++)
  481. {
  482. FSIconOverlay * pfsio = (FSIconOverlay *)DSA_GetItemPtr(_hdsaIconOverlays, ihdsa);
  483. ASSERT(pfsio);
  484. if (pfsio->iPriority >= iMinPriority)
  485. continue;
  486. if (pfsio->psioi && pfsio->psioi->IsMemberOf(pwszPath, dwAttrib) == S_OK)
  487. {
  488. // Overlay indexes start from 1, and let's not use the reserved ones
  489. ASSERT(pIOverlayIndex);
  490. *pIOverlayIndex = ihdsa + OVERLAYINDEX_RESERVED + 1;
  491. return pfsio;
  492. }
  493. }
  494. }
  495. return NULL;
  496. }
  497. HRESULT CFSIconOverlayManager::_SetGetOverlayInfo(FSIconOverlay * pfsio, int iOverlayIndex, int * pIndex, DWORD dwFlags)
  498. {
  499. HRESULT hres = E_FAIL;
  500. RIP(pIndex);
  501. *pIndex = -1;
  502. if (pfsio->iImageIndex == -1)
  503. {
  504. int iImage = _GetImageIndex(pfsio);
  505. // Either we couldn't get it or we couldn't put it in cache
  506. if (iImage == -1)
  507. {
  508. // leave this as a zombie
  509. pfsio->iImageIndex = 0;
  510. pfsio->iOverlayIndex = 0;
  511. }
  512. else
  513. pfsio->iImageIndex = iImage;
  514. }
  515. // Only if we have a reasonable image index will we proceed.
  516. if (pfsio->iImageIndex > 0)
  517. {
  518. if (dwFlags == SIOM_ICONINDEX)
  519. {
  520. *pIndex = pfsio->iImageIndex;
  521. }
  522. else
  523. {
  524. ASSERT(iOverlayIndex > 0);
  525. ASSERT(iOverlayIndex <= MAX_OVERLAY_IMAGES);
  526. if (pfsio->iOverlayIndex == -1)
  527. {
  528. // Now set the overlay
  529. ASSERT(_IsSHILInited());
  530. for (int i = 0; i < ARRAYSIZE(g_rgshil); i++)
  531. {
  532. ImageList_SetOverlayImage(g_rgshil[i].himl, pfsio->iImageIndex, iOverlayIndex);
  533. }
  534. pfsio->iOverlayIndex = iOverlayIndex;
  535. }
  536. // Must be the overlayindex flag
  537. ASSERT(dwFlags == SIOM_OVERLAYINDEX);
  538. *pIndex = pfsio->iOverlayIndex;
  539. }
  540. hres = S_OK;
  541. }
  542. return hres;
  543. }
  544. HRESULT CFSIconOverlayManager::GetFileOverlayInfo(LPCWSTR pwszPath, DWORD dwAttrib, int * pIndex, DWORD dwFlags)
  545. {
  546. ASSERT((dwFlags == SIOM_OVERLAYINDEX) || (dwFlags == SIOM_ICONINDEX)); // || (dwFlags == SIOM_PRIORITY));
  547. HRESULT hres = E_FAIL;
  548. int iOverlayIndex;
  549. *pIndex = 0;
  550. ENTERCRITICAL;
  551. if (_hdsaIconOverlays)
  552. {
  553. FSIconOverlay * pfsio = _FindMatchingID(pwszPath, dwAttrib, MAX_OVERLAY_PRIORITY, &iOverlayIndex);
  554. if (pfsio)
  555. hres = _SetGetOverlayInfo(pfsio, iOverlayIndex, pIndex, dwFlags);
  556. }
  557. LEAVECRITICAL;
  558. return hres;
  559. }
  560. HRESULT CFSIconOverlayManager::GetReservedOverlayInfo(LPCWSTR pwszPath, DWORD dwAttrib, int * pIndex, DWORD dwFlags, int iReservedID)
  561. {
  562. ASSERT(iReservedID < OVERLAYINDEX_RESERVED);
  563. HRESULT hres = S_OK;
  564. ENTERCRITICAL;
  565. if (_hdsaIconOverlays && pwszPath)
  566. {
  567. int iOverlayIndex;
  568. FSIconOverlay * pfsio = _FindMatchingID(pwszPath, dwAttrib, s_ReservedOverlays[iReservedID].iPriority, &iOverlayIndex);
  569. if (pfsio)
  570. {
  571. hres = _SetGetOverlayInfo(pfsio, iOverlayIndex, pIndex, dwFlags);
  572. LEAVECRITICAL;
  573. return hres;
  574. }
  575. }
  576. if (dwFlags == SIOM_ICONINDEX)
  577. *pIndex = s_ReservedOverlays[iReservedID].iImageIndex;
  578. else
  579. {
  580. ASSERT(dwFlags == SIOM_OVERLAYINDEX);
  581. *pIndex = s_ReservedOverlays[iReservedID].iOverlayIndex;
  582. }
  583. LEAVECRITICAL;
  584. return hres;
  585. }
  586. HRESULT CFSIconOverlayManager::CreateInstance(IUnknown* pUnkOuter, REFIID riid, OUT LPVOID * ppvOut)
  587. {
  588. HRESULT hr;
  589. DebugMsg(DM_TRACE, TEXT("CFSIconOverlayManager::CreateInstance()"));
  590. *ppvOut = NULL; // null the out param
  591. CFSIconOverlayManager *pcfsiom = new CFSIconOverlayManager;
  592. if (!pcfsiom)
  593. return E_OUTOFMEMORY;
  594. hr = pcfsiom->_InitializeHdsaIconOverlays();
  595. if (SUCCEEDED(hr))
  596. hr = pcfsiom->QueryInterface(riid, ppvOut);
  597. pcfsiom->Release();
  598. return hr;
  599. }
  600. STDAPI CFSIconOverlayManager_CreateInstance(IUnknown* pUnkOuter, REFIID riid, OUT LPVOID * ppvOut)
  601. {
  602. return CFSIconOverlayManager::CreateInstance(pUnkOuter, riid, ppvOut);
  603. }
  604. STDAPI_(int) SHGetIconOverlayIndexW(LPCWSTR pwszIconPath, int iIconIndex)
  605. {
  606. TCHAR szIconPath[MAX_PATH];
  607. int iRet = -1;
  608. int iImage = -1;
  609. // If NULL path is passed in, see if the index matches one of our special indexes
  610. if (pwszIconPath == NULL)
  611. {
  612. switch (iIconIndex)
  613. {
  614. case IDO_SHGIOI_SHARE:
  615. iImage = s_ReservedOverlays[0].iImageIndex;
  616. break;
  617. case IDO_SHGIOI_LINK:
  618. iImage = s_ReservedOverlays[1].iImageIndex;
  619. break;
  620. case IDO_SHGIOI_SLOWFILE:
  621. iImage = s_ReservedOverlays[2].iImageIndex;
  622. break;
  623. }
  624. }
  625. else if (SHUnicodeToTChar(pwszIconPath, szIconPath, ARRAYSIZE(szIconPath)))
  626. // Try to load the image into the shell icon cache
  627. iImage = Shell_GetCachedImageIndex(szIconPath, iIconIndex, 0);
  628. if (iImage >= 0)
  629. {
  630. IShellIconOverlayManager *psiom;
  631. if (SUCCEEDED(GetIconOverlayManager(&psiom)))
  632. {
  633. int iCandidate = -1;
  634. if (SUCCEEDED(psiom->OverlayIndexFromImageIndex(iImage, &iCandidate, TRUE)))
  635. {
  636. iRet = iCandidate;
  637. }
  638. psiom->Release();
  639. }
  640. }
  641. return iRet;
  642. }
  643. STDAPI_(int) SHGetIconOverlayIndexA(LPCSTR pszIconPath, int iIconIndex)
  644. {
  645. int iRet = -1;
  646. WCHAR wszIconPath[MAX_PATH];
  647. LPCWSTR pwszIconPath = NULL;
  648. if (pszIconPath)
  649. {
  650. wszIconPath[0] = L'\0';
  651. SHAnsiToUnicode(pszIconPath, wszIconPath, ARRAYSIZE(wszIconPath));
  652. pwszIconPath = wszIconPath;
  653. }
  654. return SHGetIconOverlayIndexW(pwszIconPath, iIconIndex);
  655. }