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.

1081 lines
29 KiB

  1. /*
  2. * isexicon.cpp - IExtractIcon implementation for URL class.
  3. */
  4. #include "priv.h"
  5. #include "htregmng.h"
  6. #include "ishcut.h"
  7. #include "resource.h"
  8. // We still have to use url.dll as the source of the internet shortcut
  9. // icons because the icons need to still be valid on uninstall.
  10. #ifndef UNIX
  11. #define c_szIntshcutDefaultIcon TEXT("url.dll")
  12. #else
  13. // IEUNIX(perf) : use unixstyle dll name
  14. #ifdef ux10
  15. #define c_szIntshcutDefaultIcon TEXT("liburl.sl")
  16. #else
  17. #define c_szIntshcutDefaultIcon TEXT("liburl.so")
  18. #endif
  19. #endif
  20. #define IDEFICON_NORMAL 0
  21. #define II_OVERLAY_UPDATED 1
  22. typedef struct
  23. {
  24. HIMAGELIST himl;
  25. HIMAGELIST himlSm;
  26. } URLIMAGES;
  27. HRESULT
  28. URLGetLocalFileName(
  29. LPCTSTR pszURL,
  30. LPTSTR szLocalFile,
  31. int cch,
  32. FILETIME* pftLastMod);
  33. /*----------------------------------------------------------
  34. Purpose: Initializes the images lists used by the URL icon
  35. handler.
  36. There are just two icons placed in each imagelist:
  37. the given hicon and an overlay for the updated
  38. asterisk.
  39. Returns:
  40. Cond: --
  41. */
  42. STDMETHODIMP
  43. InitURLImageLists(
  44. IN URLIMAGES * pui,
  45. IN HICON hicon,
  46. IN HICON hiconSm)
  47. {
  48. HRESULT hres = E_OUTOFMEMORY;
  49. LoadCommonIcons();
  50. _InitSysImageLists();
  51. pui->himl = ImageList_Create(g_cxIcon, g_cyIcon, ILC_MASK, 2, 2);
  52. if (pui->himl)
  53. {
  54. pui->himlSm = ImageList_Create(g_cxSmIcon, g_cySmIcon, ILC_MASK, 2, 2);
  55. if ( !pui->himlSm )
  56. ImageList_Destroy(pui->himl);
  57. else
  58. {
  59. ImageList_SetBkColor(pui->himl, GetSysColor(COLOR_WINDOW));
  60. ImageList_SetBkColor(pui->himlSm, GetSysColor(COLOR_WINDOW));
  61. // Add the given icons
  62. ImageList_ReplaceIcon(pui->himl, -1, hicon);
  63. ImageList_ReplaceIcon(pui->himlSm, -1, hiconSm);
  64. // Add the overlay icon to the list
  65. ASSERT(IS_VALID_HANDLE(g_hiconSplat, ICON));
  66. ASSERT(IS_VALID_HANDLE(g_hiconSplatSm, ICON));
  67. if (g_hiconSplat)
  68. {
  69. int iOverlay = ImageList_ReplaceIcon(pui->himl, -1, g_hiconSplat);
  70. ImageList_ReplaceIcon(pui->himlSm, -1, g_hiconSplatSm);
  71. ImageList_SetOverlayImage(pui->himl, iOverlay, II_OVERLAY_UPDATED);
  72. ImageList_SetOverlayImage(pui->himlSm, iOverlay, II_OVERLAY_UPDATED);
  73. }
  74. hres = S_OK;
  75. }
  76. }
  77. return hres;
  78. }
  79. /*----------------------------------------------------------
  80. Purpose: Destroys the url image lists
  81. Returns:
  82. Cond: --
  83. */
  84. STDMETHODIMP
  85. DestroyURLImageLists(
  86. IN URLIMAGES * pui)
  87. {
  88. if (pui->himl)
  89. {
  90. ImageList_Destroy(pui->himl);
  91. pui->himl = NULL;
  92. }
  93. if (pui->himlSm)
  94. {
  95. ImageList_Destroy(pui->himlSm);
  96. pui->himlSm = NULL;
  97. }
  98. return S_OK;
  99. }
  100. /*----------------------------------------------------------
  101. Purpose: Gets the icon location (filename and index) from the registry
  102. of the given key.
  103. Returns:
  104. Cond: --
  105. */
  106. HRESULT
  107. GetURLIcon(
  108. IN HKEY hkey,
  109. IN LPCTSTR pcszKey,
  110. IN LPTSTR pszIconFile,
  111. IN UINT cchIconFile,
  112. OUT PINT pniIcon)
  113. {
  114. HRESULT hres = S_FALSE;
  115. DWORD dwSize = CbFromCch(cchIconFile);
  116. ASSERT(IS_VALID_HANDLE(hkey, KEY));
  117. ASSERT(IS_VALID_STRING_PTR(pcszKey, -1));
  118. ASSERT(IS_VALID_WRITE_BUFFER(pszIconFile, TCHAR, cchIconFile));
  119. ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT));
  120. if (NO_ERROR == SHGetValue(hkey, pcszKey, NULL, NULL, pszIconFile, &dwSize))
  121. {
  122. *pniIcon = PathParseIconLocation(pszIconFile);
  123. hres = S_OK;
  124. }
  125. ASSERT(IsValidIconIndex(hres, pszIconFile, cchIconFile, *pniIcon));
  126. return hres;
  127. }
  128. /*
  129. ** GetFallBackGenericURLIcon()
  130. **
  131. **
  132. **
  133. ** Arguments:
  134. **
  135. ** Returns: S_OK if fallback generic icon information retrieved
  136. ** successfully.
  137. ** E_FAIL if not.
  138. **
  139. ** Side Effects: none
  140. */
  141. HRESULT
  142. GetFallBackGenericURLIcon(
  143. LPTSTR pszIconFile,
  144. UINT cchIconFile,
  145. PINT pniIcon)
  146. {
  147. HRESULT hr;
  148. ASSERT(IS_VALID_WRITE_BUFFER(pszIconFile, TCHAR, cchIconFile));
  149. ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT));
  150. // Fall back to first icon in this module.
  151. StrCpyN(pszIconFile, c_szIntshcutDefaultIcon, cchIconFile);
  152. *pniIcon = IDEFICON_NORMAL;
  153. hr = S_OK;
  154. TraceMsg(TF_INTSHCUT, "GetFallBackGenericURLIcon(): Using generic URL icon file %s, index %d.",
  155. pszIconFile, *pniIcon);
  156. ASSERT(IsValidIconIndex(hr, pszIconFile, cchIconFile, *pniIcon));
  157. return(hr);
  158. }
  159. /*
  160. ** GetGenericURLIcon()
  161. **
  162. **
  163. **
  164. ** Arguments:
  165. **
  166. ** Returns: S_OK if generic icon information retrieved successfully.
  167. ** Otherwise error.
  168. **
  169. ** Side Effects: none
  170. */
  171. HRESULT
  172. GetGenericURLIcon(
  173. LPTSTR pszIconFile,
  174. UINT cchIconFile,
  175. PINT pniIcon)
  176. {
  177. HRESULT hr;
  178. ASSERT(IS_VALID_WRITE_BUFFER(pszIconFile, TCHAR, cchIconFile));
  179. ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT));
  180. hr = GetURLIcon(HKEY_CLASSES_ROOT, TEXT("InternetShortcut\\DefaultIcon"), pszIconFile,
  181. cchIconFile, pniIcon);
  182. if (hr == S_FALSE)
  183. hr = GetFallBackGenericURLIcon(pszIconFile, cchIconFile, pniIcon);
  184. ASSERT(IsValidIconIndex(hr, pszIconFile, cchIconFile, *pniIcon));
  185. return(hr);
  186. }
  187. /****************************** Public Functions *****************************/
  188. /*----------------------------------------------------------
  189. Purpose: Given a full URL path, this function returns the
  190. registry path to the associated protocol (plus the
  191. subkey path).
  192. pszBuf must be MAX_PATH.
  193. Returns:
  194. Cond: --
  195. */
  196. HRESULT
  197. GetURLKey(
  198. LPCTSTR pcszURL,
  199. LPCTSTR pszSubKey,
  200. LPTSTR pszBuf,
  201. int cchBuf)
  202. {
  203. HRESULT hres;
  204. PTSTR pszProtocol;
  205. ASSERT(IS_VALID_STRING_PTR(pcszURL, -1));
  206. ASSERT(IS_VALID_STRING_PTR(pszSubKey, -1));
  207. ASSERT(IS_VALID_WRITE_BUFFER(pszBuf, TCHAR, MAX_PATH));
  208. *pszBuf = '\0';
  209. hres = CopyURLProtocol(pcszURL, &pszProtocol, NULL);
  210. if (hres == S_OK)
  211. {
  212. StrCpyN(pszBuf, pszProtocol, cchBuf);
  213. PathAppend(pszBuf, pszSubKey);
  214. LocalFree(pszProtocol);
  215. pszProtocol = NULL;
  216. }
  217. return hres;
  218. }
  219. /********************************** Methods **********************************/
  220. /*----------------------------------------------------------
  221. Purpose : To help determine if the file to which this shortcut
  222. is persisted is in the favorites hierarchy
  223. Returns : Returns TRUE if this shortcut is in the favorites
  224. folder
  225. */
  226. BOOL Intshcut::_IsInFavoritesFolder()
  227. {
  228. BOOL fRet = FALSE;
  229. if(m_pszFile)
  230. {
  231. TCHAR szPath[MAX_PATH];
  232. if(SHGetSpecialFolderPath(NULL, szPath, CSIDL_FAVORITES, TRUE))
  233. {
  234. // Is szPath (i.e. the favorites dir) a prefix of the file associated with this
  235. // shortcut ?
  236. fRet = PathIsPrefix(szPath, m_pszFile);
  237. }
  238. }
  239. return fRet;
  240. }
  241. /*----------------------------------------------------------
  242. Purpose: Get the icon location of the given url.
  243. Returns: S_FALSE if the location is default for the type
  244. S_OK if the location is custom
  245. The way this extracticon stuff works is very strange and not
  246. well-documented. In particular, there are multiple levels of
  247. name munging going on, and it's not clear how information is
  248. passed between IExtractIcon::GetIconLocation and
  249. IExtractIcon::Extract. (In particular, it seems that we maintain
  250. state in our object in order to do secret communication between
  251. the two methods, which is out of spec. The shell is allowed to
  252. instantiate you, call GetIconLocation, then destroy you. Then
  253. the next day, it can instantiate you and call Extract with the
  254. result from yesterday's GetIconLocation.)
  255. I'm not going to try to fix it; I'm just
  256. pointing it out in case somebody has to go debugging into this
  257. code and wonders what is going on.
  258. Cond: --
  259. */
  260. STDMETHODIMP
  261. Intshcut::GetURLIconLocation(
  262. IN UINT uInFlags,
  263. IN LPTSTR pszBuf,
  264. IN UINT cchBuf,
  265. OUT int * pniIcon,
  266. BOOL fRecentlyChanged,
  267. OUT PUINT puOutFlags)
  268. {
  269. // Call the IShellLink::GetIconLocation method
  270. HRESULT hres = _GetIconLocationWithURLHelper(pszBuf, cchBuf, pniIcon, NULL, 0, fRecentlyChanged);
  271. BOOL fNeedQualify = TRUE;
  272. hres = S_FALSE;
  273. if (*pszBuf)
  274. {
  275. if(puOutFlags && (FALSE == PathFileExists(pszBuf)))
  276. SetFlag(*puOutFlags, GIL_NOTFILENAME);
  277. }
  278. else
  279. {
  280. if(FALSE == _IsInFavoritesFolder() || (IsIEDefaultBrowserQuick()))
  281. {
  282. // This shortcut is not in the favorites folder as far as we know
  283. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  284. *szURL = 0;
  285. hres = InitProp();
  286. if (SUCCEEDED(hres))
  287. m_pprop->GetProp(PID_IS_URL, szURL, SIZECHARS(szURL));
  288. if (*szURL)
  289. {
  290. TCHAR szT[MAX_PATH];
  291. hres = E_FAIL;
  292. // If it's a file:// URL, then default to the icon from
  293. // the file target. Must use IExtractIconA in case we're
  294. // on Win95.
  295. IExtractIconA *pxi;
  296. if (_TryLink(IID_IExtractIconA, (void **)&pxi))
  297. {
  298. uInFlags |= GIL_FORSHORTCUT; // to help break recursion
  299. // S_FALSE means "I don't know what icon to use",
  300. // so treat only S_OK as successful icon extraction.
  301. if (IExtractIcon_GetIconLocation(pxi, uInFlags, pszBuf, cchBuf, pniIcon, puOutFlags) == S_OK)
  302. {
  303. hres = S_OK;
  304. fNeedQualify = FALSE;
  305. }
  306. pxi->Release();
  307. }
  308. // If couldn't get target icon or not a file:// URL, then
  309. // go get some default icon based on the URL scheme.
  310. if (FAILED(hres))
  311. {
  312. // Look up URL icon based on protocol handler.
  313. hres = GetURLKey(szURL, TEXT("DefaultIcon"), szT, ARRAYSIZE(szT));
  314. if (hres == S_OK)
  315. {
  316. hres = GetURLIcon(HKEY_CLASSES_ROOT, szT, pszBuf,
  317. cchBuf, pniIcon);
  318. }
  319. }
  320. }
  321. }
  322. if (hres == S_FALSE)
  323. {
  324. // Use generic URL icon.
  325. hres = GetFallBackGenericURLIcon(pszBuf, cchBuf, pniIcon); // Make sure we have the E icon and
  326. // Not any of netscape's icons
  327. if (hres == S_OK)
  328. TraceMsg(TF_INTSHCUT, "Intshcut::GetIconLocation(): Using generic URL icon.");
  329. }
  330. if (hres == S_OK && fNeedQualify)
  331. {
  332. TCHAR szFullPath[MAX_PATH];
  333. if (PathSearchAndQualify(pszBuf, szFullPath, SIZECHARS(szFullPath)))
  334. {
  335. hres = S_OK;
  336. if ((UINT)lstrlen(szFullPath) < cchBuf)
  337. StrCpyN(pszBuf, szFullPath, cchBuf);
  338. else
  339. hres = E_FAIL;
  340. }
  341. else
  342. hres = E_FILE_NOT_FOUND;
  343. }
  344. }
  345. return hres;
  346. }
  347. /*----------------------------------------------------------
  348. Purpose: Helper function that determines the icon location based
  349. on the flags property of the internet site property set.
  350. Returns:
  351. Cond: --
  352. */
  353. STDMETHODIMP
  354. Intshcut::GetIconLocationFromFlags(
  355. IN UINT uInFlags,
  356. OUT LPTSTR pszIconFile,
  357. IN UINT cchIconFile,
  358. OUT PINT pniIcon,
  359. OUT PUINT puOutFlags,
  360. IN DWORD dwPropFlags)
  361. {
  362. HRESULT hres = S_FALSE;
  363. *puOutFlags = 0;
  364. ClearFlag(m_dwFlags, ISF_SPECIALICON);
  365. // Normally, the icon is the standard icon that is retrieved.
  366. // If the url has been updated, though, we want to add the
  367. // overlay, in which case we return GIL_NOTFILENAME so the
  368. // Extract method will be called.
  369. hres = GetURLIconLocation(uInFlags, pszIconFile, cchIconFile, pniIcon,
  370. IsFlagSet(dwPropFlags, PIDISF_RECENTLYCHANGED), puOutFlags);
  371. if (SUCCEEDED(hres))
  372. {
  373. // (scotth): we don't support red splats on browser
  374. // only because it requires new SHELL32 APIs.
  375. // Has this item been updated since last viewed?
  376. if (IsFlagSet(dwPropFlags, PIDISF_RECENTLYCHANGED) &&
  377. (FALSE == (*puOutFlags & GIL_NOTFILENAME)))
  378. {
  379. // Yes; cache the item as a non-file so we get the
  380. // dynamically created icon
  381. SetFlag(*puOutFlags, GIL_NOTFILENAME);
  382. // Add the icon index at the end of the filename, so
  383. // it will be hashed differently from the filename
  384. // instance.
  385. wnsprintf(&pszIconFile[lstrlen(pszIconFile)], cchIconFile - lstrlen(pszIconFile),
  386. TEXT(",%d"), *pniIcon);
  387. // cdturner
  388. // this is done for browser only mode to stop the shell hacking the path
  389. // down to the dll and not calling us
  390. // remove the dot from the string
  391. LPTSTR pszDot = StrRChr( pszIconFile, NULL, TCHAR('.'));
  392. if ( pszDot )
  393. {
  394. *pszDot = TCHAR('*'); // should be DBCS safe as it is in the lower 7 bits ASCII
  395. }
  396. SetFlag(m_dwFlags, ISF_SPECIALICON);
  397. }
  398. }
  399. else
  400. {
  401. // Init to default values
  402. *pniIcon = IDEFICON_NORMAL;
  403. if (cchIconFile > 0)
  404. StrCpyN(pszIconFile, c_szIntshcutDefaultIcon, cchIconFile);
  405. }
  406. return S_OK;
  407. }
  408. /*----------------------------------------------------------
  409. Purpose: IExtractIcon::GetIconLocation handler for Intshcut
  410. Returns:
  411. Cond: --
  412. */
  413. // This is the real one for the platform...
  414. HRESULT
  415. Intshcut::_GetIconLocation(
  416. IN UINT uInFlags,
  417. OUT LPWSTR pszIconFile,
  418. IN UINT cchIconFile,
  419. OUT PINT pniIcon,
  420. OUT PUINT puOutFlags)
  421. {
  422. HRESULT hres;
  423. if (uInFlags & (GIL_ASYNC | GIL_FORSHORTCUT))
  424. {
  425. hres = GetGenericURLIcon(pszIconFile, cchIconFile, pniIcon);
  426. if (uInFlags & GIL_ASYNC)
  427. return ((SUCCEEDED(hres)) ? E_PENDING : hres);
  428. else
  429. return hres;
  430. }
  431. hres = LoadFromAsyncFileNow();
  432. if(FAILED(hres))
  433. return hres;
  434. hres = S_FALSE;
  435. // We also use this method to perform the mirroring
  436. // of the values between the internet shortcut file and
  437. // the central database. IExtractIcon is a good interface
  438. // to do this because it is virtually guaranteed to be
  439. // called for a URL.
  440. MirrorProperties();
  441. // Init to default values
  442. *puOutFlags = 0;
  443. *pniIcon = 0;
  444. if (cchIconFile > 0)
  445. *pszIconFile = TEXT('\0');
  446. DWORD dwVal = 0;
  447. if (m_psiteprop)
  448. m_psiteprop->GetProp(PID_INTSITE_FLAGS, &dwVal);
  449. hres = GetIconLocationFromFlags(uInFlags, pszIconFile, cchIconFile, pniIcon,
  450. puOutFlags, dwVal);
  451. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  452. return hres;
  453. }
  454. HRESULT Intshcut::_CreateShellLink(LPCTSTR pszPath, IUnknown **ppunk)
  455. {
  456. IUnknown *punk;
  457. HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&punk);
  458. if (SUCCEEDED(hr))
  459. {
  460. if (g_fRunningOnNT)
  461. {
  462. IShellLink *psl;
  463. hr = punk->QueryInterface(IID_IShellLink, (void **)&psl);
  464. if (SUCCEEDED(hr))
  465. {
  466. hr = psl->SetPath(pszPath);
  467. psl->Release();
  468. }
  469. }
  470. else
  471. {
  472. IShellLinkA *psl;
  473. hr = punk->QueryInterface(IID_IShellLinkA, (void **)&psl);
  474. if (SUCCEEDED(hr))
  475. {
  476. CHAR sz[MAX_PATH];
  477. SHTCharToAnsi(pszPath, sz, SIZECHARS(sz));
  478. hr = psl->SetPath(sz);
  479. psl->Release();
  480. }
  481. }
  482. if (SUCCEEDED(hr))
  483. {
  484. *ppunk = punk;
  485. }
  486. else
  487. punk->Release();
  488. }
  489. return hr;
  490. }
  491. HRESULT
  492. Intshcut::GetIconLocation(
  493. IN UINT uInFlags,
  494. OUT LPTSTR pszIconFile,
  495. IN UINT cchIconFile,
  496. OUT PINT pniIcon,
  497. OUT PUINT puOutFlags)
  498. {
  499. HRESULT hr = E_FAIL;
  500. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  501. ASSERT(IS_VALID_WRITE_BUFFER(pszIconFile, TCHAR, cchIconFile));
  502. ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT));
  503. ASSERT(IS_VALID_WRITE_PTR(puOutFlags, UINT));
  504. if (FAILED(hr))
  505. {
  506. hr = _GetIconLocation(uInFlags, pszIconFile, cchIconFile, pniIcon, puOutFlags);
  507. }
  508. return hr;
  509. }
  510. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\
  511. //
  512. // *** URLGetLocalFileName ***
  513. //
  514. //
  515. // Description:
  516. //
  517. //
  518. // Parameters:
  519. //
  520. //
  521. // Return:
  522. //
  523. //
  524. // Comments:
  525. //
  526. //
  527. ///////////////////////////////////////////////////////////////////////////////
  528. HRESULT
  529. URLGetLocalFileName(
  530. LPCTSTR pszURL,
  531. LPTSTR szLocalFile,
  532. int cch,
  533. FILETIME* pftLastMod
  534. )
  535. {
  536. ASSERT(pszURL);
  537. ASSERT(szLocalFile || 0 == cch);
  538. HRESULT hr = E_FAIL;
  539. if (pftLastMod)
  540. {
  541. pftLastMod->dwLowDateTime = 0;
  542. pftLastMod->dwHighDateTime = 0;
  543. }
  544. // by using the internal shlwapi function, we avoid loading WININET
  545. // unless we really really need it...
  546. DWORD scheme = GetUrlScheme(pszURL);
  547. if (scheme != URL_SCHEME_INVALID)
  548. {
  549. switch(scheme)
  550. {
  551. case URL_SCHEME_HTTP:
  552. case URL_SCHEME_FTP:
  553. case URL_SCHEME_GOPHER:
  554. {
  555. ULONG cbSize = MAX_CACHE_ENTRY_INFO_SIZE;
  556. INTERNET_CACHE_ENTRY_INFO* piceiAlloced =
  557. (INTERNET_CACHE_ENTRY_INFO*) new BYTE[cbSize];
  558. if (piceiAlloced)
  559. {
  560. piceiAlloced->dwStructSize =
  561. sizeof(INTERNET_CACHE_ENTRY_INFO);
  562. if (GetUrlCacheEntryInfoEx(pszURL, piceiAlloced,
  563. &cbSize, NULL, NULL,
  564. NULL, 0))
  565. {
  566. if (StrCpyN(szLocalFile,
  567. piceiAlloced->lpszLocalFileName, cch))
  568. {
  569. if (pftLastMod)
  570. {
  571. *pftLastMod = piceiAlloced->LastModifiedTime;
  572. }
  573. hr = S_OK;
  574. }
  575. }
  576. delete [] piceiAlloced;
  577. }
  578. }
  579. break;
  580. case URL_SCHEME_FILE:
  581. hr = PathCreateFromUrl(pszURL, szLocalFile, (LPDWORD)&cch, 0);
  582. break;
  583. }
  584. }
  585. else
  586. {
  587. if (StrCpyN(szLocalFile, pszURL, cch))
  588. hr = S_OK;
  589. }
  590. return hr;
  591. }
  592. BOOL
  593. PretendFileIsICONFileAndLoad(
  594. IN LPTSTR lpszTempBuf,
  595. OUT HICON * phiconLarge,
  596. OUT HICON * phiconSmall,
  597. IN UINT ucIconSize)
  598. {
  599. WORD wSizeSmall = HIWORD(ucIconSize);
  600. WORD wSizeLarge = LOWORD(ucIconSize);
  601. BOOL fRet = FALSE;
  602. // Pretend that the file is a .ico file and load it
  603. ASSERT(phiconLarge);
  604. ASSERT(phiconSmall);
  605. *phiconSmall = (HICON)LoadImage(NULL, lpszTempBuf, IMAGE_ICON, wSizeSmall, wSizeSmall, LR_LOADFROMFILE);
  606. if(*phiconSmall)
  607. {
  608. fRet = TRUE;
  609. *phiconLarge = (HICON)LoadImage(NULL, lpszTempBuf, IMAGE_ICON, wSizeLarge, wSizeLarge, LR_LOADFROMFILE);
  610. }
  611. return fRet;
  612. }
  613. BOOL
  614. Intshcut::ExtractIconFromWininetCache(
  615. IN LPCTSTR pszIconString,
  616. IN UINT iIcon,
  617. OUT HICON * phiconLarge,
  618. OUT HICON * phiconSmall,
  619. IN UINT ucIconSize,
  620. BOOL *pfFoundUrl,
  621. DWORD dwPropFlags)
  622. {
  623. IPropertyStorage *ppropstg = NULL;
  624. BOOL fRet = FALSE;
  625. INT iTempIconIndex;
  626. HRESULT hr;
  627. BOOL fFoundURL = FALSE;
  628. ASSERT(pfFoundUrl && (FALSE == *pfFoundUrl));
  629. ASSERT((lstrlen(pszIconString) + 1)<= MAX_PATH);
  630. TCHAR szTempBuf[MAX_URL_STRING + 1];
  631. *szTempBuf = TEXT('\0');
  632. TCHAR szTempIconBuf[MAX_PATH + 1];
  633. *szTempIconBuf = TEXT('\0');
  634. hr = _GetIconLocationWithURLHelper(
  635. szTempIconBuf, ARRAYSIZE(szTempIconBuf), &iTempIconIndex,
  636. szTempBuf, ARRAYSIZE(szTempBuf), IsFlagSet(dwPropFlags, PIDISF_RECENTLYCHANGED));
  637. if((S_OK == hr) && (*szTempIconBuf))
  638. {
  639. if((UINT)iTempIconIndex == iIcon)
  640. {
  641. if(0 == StrCmp(szTempIconBuf, pszIconString))
  642. {
  643. if(*szTempBuf)
  644. {
  645. BOOL fUsesCache=FALSE;
  646. DWORD dwBufSize=0;
  647. CoInternetQueryInfo(szTempBuf, QUERY_USES_CACHE, 0,
  648. &fUsesCache, sizeof(fUsesCache), &dwBufSize, 0);
  649. if(fUsesCache)
  650. {
  651. fFoundURL = TRUE;
  652. }
  653. }
  654. }
  655. }
  656. }
  657. if(fFoundURL)
  658. {
  659. // Now szTempBuf has the URL of the ICON
  660. // now look and see if the shortcut file itself has the icon and if so
  661. // simply use it --- TBD
  662. // we need to grovel in the cache and see if we can get
  663. // it there and then convert it to an icon
  664. TCHAR szIconFile[MAX_PATH + 1];
  665. hr = URLGetLocalFileName(szTempBuf, szIconFile, ARRAYSIZE(szIconFile), NULL);
  666. if(S_OK == hr)
  667. {
  668. if(PretendFileIsICONFileAndLoad(szIconFile, phiconLarge, phiconSmall, ucIconSize))
  669. {
  670. fRet = TRUE;
  671. }
  672. // It's a bitmap, gif or a jpeg
  673. }
  674. }
  675. if(pfFoundUrl)
  676. *pfFoundUrl = fFoundURL;
  677. return fRet;
  678. }
  679. /*----------------------------------------------------------
  680. Purpose: IExtractIcon::Extract method for Intshcut
  681. Extract the icon. This function really returns an icon
  682. that is dynamically created, based upon the properties
  683. of the URL (recently changed, etc).
  684. Expect that for normal cases, when the icon does not
  685. need to be munged (an overlay added), the GetIconLocation
  686. method should suffice. Otherwise, this method will get
  687. called.
  688. Returns:
  689. Cond: --
  690. */
  691. // This is the real one for the platform...
  692. HRESULT
  693. Intshcut::_Extract(
  694. IN LPCTSTR pszIconFile,
  695. IN UINT iIcon,
  696. OUT HICON * phiconLarge,
  697. OUT HICON * phiconSmall,
  698. IN UINT ucIconSize)
  699. {
  700. HRESULT hres;
  701. HICON hiconLarge = NULL;
  702. HICON hiconSmall = NULL;
  703. TCHAR szPath[MAX_PATH];
  704. int nIndex;
  705. BOOL fSpecialUrl = FALSE;
  706. *phiconLarge = NULL;
  707. *phiconSmall = NULL;
  708. DWORD dwPropFlags = 0;
  709. hres = LoadFromAsyncFileNow();
  710. if(FAILED(hres))
  711. return hres;
  712. hres = S_FALSE;
  713. InitSiteProp();
  714. // Get the property Flags
  715. if (m_psiteprop)
  716. m_psiteprop->GetProp(PID_INTSITE_FLAGS, &dwPropFlags);
  717. // First check to see if this is a special icon
  718. // This function returns a usable value for fSpecialUrl even if it returns FALSE
  719. if(ExtractIconFromWininetCache(pszIconFile, iIcon, &hiconLarge, &hiconSmall, ucIconSize, &fSpecialUrl, dwPropFlags))
  720. {
  721. hres = S_OK;
  722. }
  723. else
  724. {
  725. if(TRUE == fSpecialUrl)
  726. {
  727. // The extract failed even though this was a special URL
  728. // we need to revert back to using the default IE icon
  729. hres = GetGenericURLIcon(szPath, MAX_PATH, (int *)(&iIcon));
  730. if (hres == S_OK)
  731. {
  732. fSpecialUrl = FALSE; // It's no longer a special URL
  733. hres = InitProp();
  734. if (SUCCEEDED(hres))
  735. {
  736. hres = m_pprop->SetProp(PID_IS_ICONFILE, szPath);
  737. if (SUCCEEDED(hres))
  738. {
  739. hres = m_pprop->SetProp(PID_IS_ICONINDEX, (INT)iIcon);
  740. }
  741. }
  742. }
  743. if(S_OK != hres)
  744. {
  745. ASSERT(0);
  746. goto DefIcons;
  747. }
  748. }
  749. else
  750. {
  751. StrCpyN(szPath, pszIconFile, ARRAYSIZE(szPath));
  752. // The path may be munged. Get the icon index as appropriate.
  753. if (IsFlagSet(m_dwFlags, ISF_SPECIALICON) && (!fSpecialUrl) )
  754. {
  755. // Get the icon location from the munged path
  756. iIcon = PathParseIconLocation(szPath);
  757. // cdturner
  758. // now replace the '*' with the dot
  759. // this is done for browser only mode to stop the shell hacking the path
  760. // down to the dll and not calling us
  761. LPTSTR pszPlus = StrRChr( szPath, NULL, TCHAR('*'));
  762. if ( pszPlus )
  763. {
  764. *pszPlus = TCHAR('.');
  765. }
  766. }
  767. }
  768. nIndex = iIcon;
  769. if(!fSpecialUrl)
  770. {
  771. if ( WhichPlatform() == PLATFORM_INTEGRATED )
  772. {
  773. // Extract the icons
  774. CHAR szTempPath[MAX_PATH + 1];
  775. SHTCharToAnsi(szPath, szTempPath, ARRAYSIZE(szTempPath));
  776. hres = SHDefExtractIconA(szTempPath, nIndex, 0, &hiconLarge, &hiconSmall,
  777. ucIconSize);
  778. }
  779. else
  780. {
  781. // cdturner
  782. // use a more hacky solution to support browser only mode..
  783. _InitSysImageLists();
  784. int iIndex = Shell_GetCachedImageIndex( szPath, nIndex, 0 );
  785. if ( iIndex > 0 )
  786. {
  787. hiconLarge = ImageList_GetIcon( g_himlSysLarge, iIndex, 0 );
  788. hiconSmall = ImageList_GetIcon( g_himlSysSmall, iIndex, 0 );
  789. hres = NOERROR;
  790. }
  791. else
  792. {
  793. hiconLarge = hiconSmall = NULL;
  794. // it will get the windows icon if it should be gleamed, and
  795. // it will the normal icon otherwsie
  796. hres = IsFlagSet(dwPropFlags, PIDISF_RECENTLYCHANGED) ? E_FAIL : S_FALSE;
  797. goto DefIcons;
  798. }
  799. }
  800. }
  801. }
  802. if (SUCCEEDED(hres))
  803. {
  804. // Has this URL changed recently?
  805. if (IsFlagSet(dwPropFlags, PIDISF_RECENTLYCHANGED))
  806. {
  807. // Yes
  808. URLIMAGES ui;
  809. if (SUCCEEDED(InitURLImageLists(&ui, hiconLarge, hiconSmall)))
  810. {
  811. *phiconLarge = ImageList_GetIcon(ui.himl, 0, INDEXTOOVERLAYMASK(II_OVERLAY_UPDATED));
  812. *phiconSmall = ImageList_GetIcon(ui.himlSm, 0, INDEXTOOVERLAYMASK(II_OVERLAY_UPDATED));
  813. DestroyURLImageLists(&ui);
  814. // these were created, they are not global handles, so they must be cleanedup.
  815. DestroyIcon( hiconLarge );
  816. DestroyIcon( hiconSmall );
  817. }
  818. else
  819. goto DefIcons;
  820. }
  821. else
  822. {
  823. // No
  824. DefIcons:
  825. *phiconLarge = hiconLarge;
  826. *phiconSmall = hiconSmall;
  827. }
  828. }
  829. return hres;
  830. }
  831. STDMETHODIMP
  832. Intshcut::Extract(
  833. IN LPCTSTR pszIconFile,
  834. IN UINT iIcon,
  835. OUT HICON * phiconLarge,
  836. OUT HICON * phiconSmall,
  837. IN UINT ucIconSize)
  838. {
  839. if (URL_SCHEME_FILE == GetScheme() && _punkLink)
  840. return IExtractIcon_Extract(_punkLink, pszIconFile, iIcon, phiconLarge, phiconSmall, ucIconSize);
  841. else
  842. return _Extract(pszIconFile, iIcon, phiconLarge, phiconSmall, ucIconSize);
  843. }
  844. // Now handle the
  845. // Unicode or Ansi one for the "Other" platform...
  846. STDMETHODIMP
  847. Intshcut::GetIconLocation(UINT uInFlags, LPSTR pszIconFile, UINT cchIconFile,
  848. PINT pniIcon, PUINT puOutFlags)
  849. {
  850. HRESULT hres;
  851. WCHAR wszIconFile[MAX_PATH];
  852. // IconFile is output so...
  853. // Note, we will only handle up to MAXPATH
  854. if (cchIconFile > ARRAYSIZE(wszIconFile))
  855. cchIconFile = ARRAYSIZE(wszIconFile);
  856. ASSERT(IS_VALID_WRITE_BUFFER(pszIconFile, TCHAR, cchIconFile));
  857. hres = GetIconLocation(uInFlags, wszIconFile, cchIconFile, pniIcon, puOutFlags);
  858. if (cchIconFile > 0 && SUCCEEDED(hres))
  859. {
  860. WideCharToMultiByte(CP_ACP, 0, wszIconFile, -1, pszIconFile, cchIconFile, NULL, NULL);
  861. }
  862. return hres;
  863. }
  864. STDMETHODIMP Intshcut::Extract(IN LPCSTR pszIconFile, IN UINT iIcon,
  865. OUT HICON * phiconLarge, OUT HICON * phiconSmall, IN UINT ucIconSize)
  866. {
  867. WCHAR wszIconFile[MAX_PATH];
  868. // First convert the string...
  869. MultiByteToWideChar(CP_ACP, 0, pszIconFile, -1, wszIconFile, ARRAYSIZE(wszIconFile));
  870. return Extract(wszIconFile, iIcon, phiconLarge, phiconSmall, ucIconSize);
  871. }