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.

1083 lines
30 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. StringCchCopy(pszIconFile, cchIconFile, c_szIntshcutDefaultIcon);
  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. if (SUCCEEDED(StringCchCopy(pszBuf, cchBuf, pszProtocol)) &&
  213. cchBuf >= MAX_PATH)
  214. {
  215. PathAppend(pszBuf, pszSubKey);
  216. }
  217. else
  218. {
  219. pszBuf[0]=0;
  220. }
  221. LocalFree(pszProtocol);
  222. pszProtocol = NULL;
  223. }
  224. return hres;
  225. }
  226. /********************************** Methods **********************************/
  227. /*----------------------------------------------------------
  228. Purpose : To help determine if the file to which this shortcut
  229. is persisted is in the favorites hierarchy
  230. Returns : Returns TRUE if this shortcut is in the favorites
  231. folder
  232. */
  233. BOOL Intshcut::_IsInFavoritesFolder()
  234. {
  235. BOOL fRet = FALSE;
  236. if(m_pszFile)
  237. {
  238. TCHAR szPath[MAX_PATH];
  239. if(SHGetSpecialFolderPath(NULL, szPath, CSIDL_FAVORITES, TRUE))
  240. {
  241. // Is szPath (i.e. the favorites dir) a prefix of the file associated with this
  242. // shortcut ?
  243. fRet = PathIsPrefix(szPath, m_pszFile);
  244. }
  245. }
  246. return fRet;
  247. }
  248. /*----------------------------------------------------------
  249. Purpose: Get the icon location of the given url.
  250. Returns: S_FALSE if the location is default for the type
  251. S_OK if the location is custom
  252. The way this extracticon stuff works is very strange and not
  253. well-documented. In particular, there are multiple levels of
  254. name munging going on, and it's not clear how information is
  255. passed between IExtractIcon::GetIconLocation and
  256. IExtractIcon::Extract. (In particular, it seems that we maintain
  257. state in our object in order to do secret communication between
  258. the two methods, which is out of spec. The shell is allowed to
  259. instantiate you, call GetIconLocation, then destroy you. Then
  260. the next day, it can instantiate you and call Extract with the
  261. result from yesterday's GetIconLocation.)
  262. I'm not going to try to fix it; I'm just
  263. pointing it out in case somebody has to go debugging into this
  264. code and wonders what is going on.
  265. Cond: --
  266. */
  267. STDMETHODIMP
  268. Intshcut::GetURLIconLocation(
  269. IN UINT uInFlags,
  270. IN LPTSTR pszBuf,
  271. IN UINT cchBuf,
  272. OUT int * pniIcon,
  273. BOOL fRecentlyChanged,
  274. OUT PUINT puOutFlags)
  275. {
  276. // Call the IShellLink::GetIconLocation method
  277. HRESULT hres = _GetIconLocationWithURLHelper(pszBuf, cchBuf, pniIcon, NULL, 0, fRecentlyChanged);
  278. BOOL fNeedQualify = TRUE;
  279. hres = S_FALSE;
  280. if (*pszBuf)
  281. {
  282. if(puOutFlags && (FALSE == PathFileExists(pszBuf)))
  283. SetFlag(*puOutFlags, GIL_NOTFILENAME);
  284. }
  285. else
  286. {
  287. if(FALSE == _IsInFavoritesFolder() || (IsIEDefaultBrowserQuick()))
  288. {
  289. // This shortcut is not in the favorites folder as far as we know
  290. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  291. *szURL = 0;
  292. hres = InitProp();
  293. if (SUCCEEDED(hres))
  294. m_pprop->GetProp(PID_IS_URL, szURL, SIZECHARS(szURL));
  295. if (*szURL)
  296. {
  297. TCHAR szT[MAX_PATH];
  298. hres = E_FAIL;
  299. // If it's a file:// URL, then default to the icon from
  300. // the file target. Must use IExtractIconA in case we're
  301. // on Win95.
  302. IExtractIconA *pxi;
  303. if (_TryLink(IID_IExtractIconA, (void **)&pxi))
  304. {
  305. uInFlags |= GIL_FORSHORTCUT; // to help break recursion
  306. // S_FALSE means "I don't know what icon to use",
  307. // so treat only S_OK as successful icon extraction.
  308. if (IExtractIcon_GetIconLocation(pxi, uInFlags, pszBuf, cchBuf, pniIcon, puOutFlags) == S_OK)
  309. {
  310. hres = S_OK;
  311. fNeedQualify = FALSE;
  312. }
  313. pxi->Release();
  314. }
  315. // If couldn't get target icon or not a file:// URL, then
  316. // go get some default icon based on the URL scheme.
  317. if (FAILED(hres))
  318. {
  319. // Look up URL icon based on protocol handler.
  320. hres = GetURLKey(szURL, TEXT("DefaultIcon"), szT, ARRAYSIZE(szT));
  321. if (hres == S_OK)
  322. {
  323. hres = GetURLIcon(HKEY_CLASSES_ROOT, szT, pszBuf,
  324. cchBuf, pniIcon);
  325. }
  326. }
  327. }
  328. }
  329. if (hres == S_FALSE)
  330. {
  331. // Use generic URL icon.
  332. hres = GetFallBackGenericURLIcon(pszBuf, cchBuf, pniIcon); // Make sure we have the E icon and
  333. // Not any of netscape's icons
  334. if (hres == S_OK)
  335. TraceMsg(TF_INTSHCUT, "Intshcut::GetIconLocation(): Using generic URL icon.");
  336. }
  337. if (hres == S_OK && fNeedQualify)
  338. {
  339. TCHAR szFullPath[MAX_PATH];
  340. if (PathSearchAndQualify(pszBuf, szFullPath, SIZECHARS(szFullPath)))
  341. {
  342. hres = StringCchCopy(pszBuf, cchBuf, szFullPath);
  343. }
  344. else
  345. hres = E_FILE_NOT_FOUND;
  346. }
  347. }
  348. return hres;
  349. }
  350. /*----------------------------------------------------------
  351. Purpose: Helper function that determines the icon location based
  352. on the flags property of the internet site property set.
  353. Returns:
  354. Cond: --
  355. */
  356. STDMETHODIMP
  357. Intshcut::GetIconLocationFromFlags(
  358. IN UINT uInFlags,
  359. OUT LPTSTR pszIconFile,
  360. IN UINT cchIconFile,
  361. OUT PINT pniIcon,
  362. OUT PUINT puOutFlags,
  363. IN DWORD dwPropFlags)
  364. {
  365. HRESULT hres = S_FALSE;
  366. *puOutFlags = 0;
  367. ClearFlag(m_dwFlags, ISF_SPECIALICON);
  368. // Normally, the icon is the standard icon that is retrieved.
  369. // If the url has been updated, though, we want to add the
  370. // overlay, in which case we return GIL_NOTFILENAME so the
  371. // Extract method will be called.
  372. hres = GetURLIconLocation(uInFlags, pszIconFile, cchIconFile, pniIcon,
  373. IsFlagSet(dwPropFlags, PIDISF_RECENTLYCHANGED), puOutFlags);
  374. if (SUCCEEDED(hres))
  375. {
  376. // (scotth): we don't support red splats on browser
  377. // only because it requires new SHELL32 APIs.
  378. // Has this item been updated since last viewed?
  379. if (IsFlagSet(dwPropFlags, PIDISF_RECENTLYCHANGED) &&
  380. (FALSE == (*puOutFlags & GIL_NOTFILENAME)))
  381. {
  382. // Yes; cache the item as a non-file so we get the
  383. // dynamically created icon
  384. SetFlag(*puOutFlags, GIL_NOTFILENAME);
  385. // Add the icon index at the end of the filename, so
  386. // it will be hashed differently from the filename
  387. // instance.
  388. int iIconFileLen = lstrlen(pszIconFile);
  389. StringCchPrintf(&pszIconFile[iIconFileLen], cchIconFile - iIconFileLen,
  390. TEXT(",%d"), *pniIcon);
  391. // cdturner
  392. // this is done for browser only mode to stop the shell hacking the path
  393. // down to the dll and not calling us
  394. // remove the dot from the string
  395. LPTSTR pszDot = StrRChr( pszIconFile, NULL, TCHAR('.'));
  396. if ( pszDot )
  397. {
  398. *pszDot = TCHAR('*'); // should be DBCS safe as it is in the lower 7 bits ASCII
  399. }
  400. SetFlag(m_dwFlags, ISF_SPECIALICON);
  401. }
  402. }
  403. else
  404. {
  405. // Init to default values
  406. *pniIcon = IDEFICON_NORMAL;
  407. if (cchIconFile > 0)
  408. StringCchCopy(pszIconFile, cchIconFile, c_szIntshcutDefaultIcon);
  409. }
  410. return S_OK;
  411. }
  412. /*----------------------------------------------------------
  413. Purpose: IExtractIcon::GetIconLocation handler for Intshcut
  414. Returns:
  415. Cond: --
  416. */
  417. // This is the real one for the platform...
  418. HRESULT
  419. Intshcut::_GetIconLocation(
  420. IN UINT uInFlags,
  421. OUT LPWSTR pszIconFile,
  422. IN UINT cchIconFile,
  423. OUT PINT pniIcon,
  424. OUT PUINT puOutFlags)
  425. {
  426. HRESULT hres;
  427. if (uInFlags & (GIL_ASYNC | GIL_FORSHORTCUT))
  428. {
  429. hres = GetGenericURLIcon(pszIconFile, cchIconFile, pniIcon);
  430. if (uInFlags & GIL_ASYNC)
  431. return ((SUCCEEDED(hres)) ? E_PENDING : hres);
  432. else
  433. return hres;
  434. }
  435. hres = LoadFromAsyncFileNow();
  436. if(FAILED(hres))
  437. return hres;
  438. hres = S_FALSE;
  439. // We also use this method to perform the mirroring
  440. // of the values between the internet shortcut file and
  441. // the central database. IExtractIcon is a good interface
  442. // to do this because it is virtually guaranteed to be
  443. // called for a URL.
  444. MirrorProperties();
  445. // Init to default values
  446. *puOutFlags = 0;
  447. *pniIcon = 0;
  448. if (cchIconFile > 0)
  449. *pszIconFile = TEXT('\0');
  450. DWORD dwVal = 0;
  451. if (m_psiteprop)
  452. m_psiteprop->GetProp(PID_INTSITE_FLAGS, &dwVal);
  453. hres = GetIconLocationFromFlags(uInFlags, pszIconFile, cchIconFile, pniIcon,
  454. puOutFlags, dwVal);
  455. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  456. return hres;
  457. }
  458. HRESULT Intshcut::_CreateShellLink(LPCTSTR pszPath, IUnknown **ppunk)
  459. {
  460. IUnknown *punk;
  461. HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&punk);
  462. if (SUCCEEDED(hr))
  463. {
  464. if (g_fRunningOnNT)
  465. {
  466. IShellLink *psl;
  467. hr = punk->QueryInterface(IID_IShellLink, (void **)&psl);
  468. if (SUCCEEDED(hr))
  469. {
  470. hr = psl->SetPath(pszPath);
  471. psl->Release();
  472. }
  473. }
  474. else
  475. {
  476. IShellLinkA *psl;
  477. hr = punk->QueryInterface(IID_IShellLinkA, (void **)&psl);
  478. if (SUCCEEDED(hr))
  479. {
  480. CHAR sz[MAX_PATH];
  481. SHTCharToAnsi(pszPath, sz, SIZECHARS(sz));
  482. hr = psl->SetPath(sz);
  483. psl->Release();
  484. }
  485. }
  486. if (SUCCEEDED(hr))
  487. {
  488. *ppunk = punk;
  489. }
  490. else
  491. punk->Release();
  492. }
  493. return hr;
  494. }
  495. HRESULT
  496. Intshcut::GetIconLocation(
  497. IN UINT uInFlags,
  498. OUT LPTSTR pszIconFile,
  499. IN UINT cchIconFile,
  500. OUT PINT pniIcon,
  501. OUT PUINT puOutFlags)
  502. {
  503. HRESULT hr = E_FAIL;
  504. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  505. ASSERT(IS_VALID_WRITE_BUFFER(pszIconFile, TCHAR, cchIconFile));
  506. ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT));
  507. ASSERT(IS_VALID_WRITE_PTR(puOutFlags, UINT));
  508. if (FAILED(hr))
  509. {
  510. hr = _GetIconLocation(uInFlags, pszIconFile, cchIconFile, pniIcon, puOutFlags);
  511. }
  512. return hr;
  513. }
  514. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\
  515. //
  516. // *** URLGetLocalFileName ***
  517. //
  518. //
  519. // Description:
  520. //
  521. //
  522. // Parameters:
  523. //
  524. //
  525. // Return:
  526. //
  527. //
  528. // Comments:
  529. //
  530. //
  531. ///////////////////////////////////////////////////////////////////////////////
  532. HRESULT
  533. URLGetLocalFileName(
  534. LPCTSTR pszURL,
  535. LPTSTR szLocalFile,
  536. int cch,
  537. FILETIME* pftLastMod
  538. )
  539. {
  540. ASSERT(pszURL);
  541. ASSERT(szLocalFile || 0 == cch);
  542. HRESULT hr = E_FAIL;
  543. if (pftLastMod)
  544. {
  545. pftLastMod->dwLowDateTime = 0;
  546. pftLastMod->dwHighDateTime = 0;
  547. }
  548. // by using the internal shlwapi function, we avoid loading WININET
  549. // unless we really really need it...
  550. DWORD scheme = GetUrlScheme(pszURL);
  551. if (scheme != URL_SCHEME_INVALID)
  552. {
  553. switch(scheme)
  554. {
  555. case URL_SCHEME_HTTP:
  556. case URL_SCHEME_FTP:
  557. case URL_SCHEME_GOPHER:
  558. {
  559. ULONG cbSize = MAX_CACHE_ENTRY_INFO_SIZE;
  560. INTERNET_CACHE_ENTRY_INFO* piceiAlloced =
  561. (INTERNET_CACHE_ENTRY_INFO*) new BYTE[cbSize];
  562. if (piceiAlloced)
  563. {
  564. piceiAlloced->dwStructSize =
  565. sizeof(INTERNET_CACHE_ENTRY_INFO);
  566. if (GetUrlCacheEntryInfoEx(pszURL, piceiAlloced,
  567. &cbSize, NULL, NULL,
  568. NULL, 0))
  569. {
  570. if (SUCCEEDED(StringCchCopy(szLocalFile, cch,
  571. piceiAlloced->lpszLocalFileName)))
  572. {
  573. if (pftLastMod)
  574. {
  575. *pftLastMod = piceiAlloced->LastModifiedTime;
  576. }
  577. hr = S_OK;
  578. }
  579. }
  580. delete [] piceiAlloced;
  581. }
  582. }
  583. break;
  584. case URL_SCHEME_FILE:
  585. hr = PathCreateFromUrl(pszURL, szLocalFile, (LPDWORD)&cch, 0);
  586. break;
  587. }
  588. }
  589. else
  590. {
  591. hr = StringCchCopy(szLocalFile, cch, pszURL);
  592. }
  593. return hr;
  594. }
  595. BOOL
  596. PretendFileIsICONFileAndLoad(
  597. IN LPTSTR lpszTempBuf,
  598. OUT HICON * phiconLarge,
  599. OUT HICON * phiconSmall,
  600. IN UINT ucIconSize)
  601. {
  602. WORD wSizeSmall = HIWORD(ucIconSize);
  603. WORD wSizeLarge = LOWORD(ucIconSize);
  604. BOOL fRet = FALSE;
  605. // Pretend that the file is a .ico file and load it
  606. ASSERT(phiconLarge);
  607. ASSERT(phiconSmall);
  608. *phiconSmall = (HICON)LoadImage(NULL, lpszTempBuf, IMAGE_ICON, wSizeSmall, wSizeSmall, LR_LOADFROMFILE);
  609. if(*phiconSmall)
  610. {
  611. fRet = TRUE;
  612. *phiconLarge = (HICON)LoadImage(NULL, lpszTempBuf, IMAGE_ICON, wSizeLarge, wSizeLarge, LR_LOADFROMFILE);
  613. }
  614. return fRet;
  615. }
  616. BOOL
  617. Intshcut::ExtractIconFromWininetCache(
  618. IN LPCTSTR pszIconString,
  619. IN UINT iIcon,
  620. OUT HICON * phiconLarge,
  621. OUT HICON * phiconSmall,
  622. IN UINT ucIconSize,
  623. BOOL *pfFoundUrl,
  624. DWORD dwPropFlags)
  625. {
  626. IPropertyStorage *ppropstg = NULL;
  627. BOOL fRet = FALSE;
  628. INT iTempIconIndex;
  629. HRESULT hr;
  630. BOOL fFoundURL = FALSE;
  631. ASSERT(pfFoundUrl && (FALSE == *pfFoundUrl));
  632. ASSERT((lstrlen(pszIconString) + 1)<= MAX_PATH);
  633. TCHAR szTempBuf[MAX_URL_STRING + 1];
  634. *szTempBuf = TEXT('\0');
  635. TCHAR szTempIconBuf[MAX_PATH + 1];
  636. *szTempIconBuf = TEXT('\0');
  637. hr = _GetIconLocationWithURLHelper(
  638. szTempIconBuf, ARRAYSIZE(szTempIconBuf), &iTempIconIndex,
  639. szTempBuf, ARRAYSIZE(szTempBuf), IsFlagSet(dwPropFlags, PIDISF_RECENTLYCHANGED));
  640. if((S_OK == hr) && (*szTempIconBuf))
  641. {
  642. if((UINT)iTempIconIndex == iIcon)
  643. {
  644. if(0 == StrCmp(szTempIconBuf, pszIconString))
  645. {
  646. if(*szTempBuf)
  647. {
  648. BOOL fUsesCache=FALSE;
  649. DWORD dwBufSize=0;
  650. CoInternetQueryInfo(szTempBuf, QUERY_USES_CACHE, 0,
  651. &fUsesCache, sizeof(fUsesCache), &dwBufSize, 0);
  652. if(fUsesCache)
  653. {
  654. fFoundURL = TRUE;
  655. }
  656. }
  657. }
  658. }
  659. }
  660. if(fFoundURL)
  661. {
  662. // Now szTempBuf has the URL of the ICON
  663. // now look and see if the shortcut file itself has the icon and if so
  664. // simply use it --- TBD
  665. // we need to grovel in the cache and see if we can get
  666. // it there and then convert it to an icon
  667. TCHAR szIconFile[MAX_PATH + 1];
  668. hr = URLGetLocalFileName(szTempBuf, szIconFile, ARRAYSIZE(szIconFile), NULL);
  669. if(S_OK == hr)
  670. {
  671. if(PretendFileIsICONFileAndLoad(szIconFile, phiconLarge, phiconSmall, ucIconSize))
  672. {
  673. fRet = TRUE;
  674. }
  675. // It's a bitmap, gif or a jpeg
  676. }
  677. }
  678. if(pfFoundUrl)
  679. *pfFoundUrl = fFoundURL;
  680. return fRet;
  681. }
  682. /*----------------------------------------------------------
  683. Purpose: IExtractIcon::Extract method for Intshcut
  684. Extract the icon. This function really returns an icon
  685. that is dynamically created, based upon the properties
  686. of the URL (recently changed, etc).
  687. Expect that for normal cases, when the icon does not
  688. need to be munged (an overlay added), the GetIconLocation
  689. method should suffice. Otherwise, this method will get
  690. called.
  691. Returns:
  692. Cond: --
  693. */
  694. // This is the real one for the platform...
  695. HRESULT
  696. Intshcut::_Extract(
  697. IN LPCTSTR pszIconFile,
  698. IN UINT iIcon,
  699. OUT HICON * phiconLarge,
  700. OUT HICON * phiconSmall,
  701. IN UINT ucIconSize)
  702. {
  703. HRESULT hres;
  704. HICON hiconLarge = NULL;
  705. HICON hiconSmall = NULL;
  706. TCHAR szPath[MAX_PATH];
  707. int nIndex;
  708. BOOL fSpecialUrl = FALSE;
  709. *phiconLarge = NULL;
  710. *phiconSmall = NULL;
  711. DWORD dwPropFlags = 0;
  712. hres = LoadFromAsyncFileNow();
  713. if(FAILED(hres))
  714. return hres;
  715. hres = S_FALSE;
  716. InitSiteProp();
  717. // Get the property Flags
  718. if (m_psiteprop)
  719. m_psiteprop->GetProp(PID_INTSITE_FLAGS, &dwPropFlags);
  720. // First check to see if this is a special icon
  721. // This function returns a usable value for fSpecialUrl even if it returns FALSE
  722. if(ExtractIconFromWininetCache(pszIconFile, iIcon, &hiconLarge, &hiconSmall, ucIconSize, &fSpecialUrl, dwPropFlags))
  723. {
  724. hres = S_OK;
  725. }
  726. else
  727. {
  728. if(TRUE == fSpecialUrl)
  729. {
  730. // The extract failed even though this was a special URL
  731. // we need to revert back to using the default IE icon
  732. hres = GetGenericURLIcon(szPath, MAX_PATH, (int *)(&iIcon));
  733. if (hres == S_OK)
  734. {
  735. fSpecialUrl = FALSE; // It's no longer a special URL
  736. hres = InitProp();
  737. if (SUCCEEDED(hres))
  738. {
  739. hres = m_pprop->SetProp(PID_IS_ICONFILE, szPath);
  740. if (SUCCEEDED(hres))
  741. {
  742. hres = m_pprop->SetProp(PID_IS_ICONINDEX, (INT)iIcon);
  743. }
  744. }
  745. }
  746. if(S_OK != hres)
  747. {
  748. ASSERT(0);
  749. goto DefIcons;
  750. }
  751. }
  752. else
  753. {
  754. StringCchCopy(szPath, ARRAYSIZE(szPath), pszIconFile);
  755. // The path may be munged. Get the icon index as appropriate.
  756. if (IsFlagSet(m_dwFlags, ISF_SPECIALICON) && (!fSpecialUrl) )
  757. {
  758. // Get the icon location from the munged path
  759. iIcon = PathParseIconLocation(szPath);
  760. // cdturner
  761. // now replace the '*' with the dot
  762. // this is done for browser only mode to stop the shell hacking the path
  763. // down to the dll and not calling us
  764. LPTSTR pszPlus = StrRChr( szPath, NULL, TCHAR('*'));
  765. if ( pszPlus )
  766. {
  767. *pszPlus = TCHAR('.');
  768. }
  769. }
  770. }
  771. nIndex = iIcon;
  772. if(!fSpecialUrl)
  773. {
  774. if ( WhichPlatform() == PLATFORM_INTEGRATED )
  775. {
  776. // Extract the icons
  777. CHAR szTempPath[MAX_PATH + 1];
  778. SHTCharToAnsi(szPath, szTempPath, ARRAYSIZE(szTempPath));
  779. hres = SHDefExtractIconA(szTempPath, nIndex, 0, &hiconLarge, &hiconSmall,
  780. ucIconSize);
  781. }
  782. else
  783. {
  784. // cdturner
  785. // use a more hacky solution to support browser only mode..
  786. _InitSysImageLists();
  787. int iIndex = Shell_GetCachedImageIndex( szPath, nIndex, 0 );
  788. if ( iIndex > 0 )
  789. {
  790. hiconLarge = ImageList_GetIcon( g_himlSysLarge, iIndex, 0 );
  791. hiconSmall = ImageList_GetIcon( g_himlSysSmall, iIndex, 0 );
  792. hres = NOERROR;
  793. }
  794. else
  795. {
  796. hiconLarge = hiconSmall = NULL;
  797. // it will get the windows icon if it should be gleamed, and
  798. // it will the normal icon otherwsie
  799. hres = IsFlagSet(dwPropFlags, PIDISF_RECENTLYCHANGED) ? E_FAIL : S_FALSE;
  800. goto DefIcons;
  801. }
  802. }
  803. }
  804. }
  805. if (SUCCEEDED(hres))
  806. {
  807. // Has this URL changed recently?
  808. if (IsFlagSet(dwPropFlags, PIDISF_RECENTLYCHANGED))
  809. {
  810. // Yes
  811. URLIMAGES ui;
  812. if (SUCCEEDED(InitURLImageLists(&ui, hiconLarge, hiconSmall)))
  813. {
  814. *phiconLarge = ImageList_GetIcon(ui.himl, 0, INDEXTOOVERLAYMASK(II_OVERLAY_UPDATED));
  815. *phiconSmall = ImageList_GetIcon(ui.himlSm, 0, INDEXTOOVERLAYMASK(II_OVERLAY_UPDATED));
  816. DestroyURLImageLists(&ui);
  817. // these were created, they are not global handles, so they must be cleanedup.
  818. DestroyIcon( hiconLarge );
  819. DestroyIcon( hiconSmall );
  820. }
  821. else
  822. goto DefIcons;
  823. }
  824. else
  825. {
  826. // No
  827. DefIcons:
  828. *phiconLarge = hiconLarge;
  829. *phiconSmall = hiconSmall;
  830. }
  831. }
  832. return hres;
  833. }
  834. STDMETHODIMP
  835. Intshcut::Extract(
  836. IN LPCTSTR pszIconFile,
  837. IN UINT iIcon,
  838. OUT HICON * phiconLarge,
  839. OUT HICON * phiconSmall,
  840. IN UINT ucIconSize)
  841. {
  842. if (URL_SCHEME_FILE == GetScheme() && _punkLink)
  843. return IExtractIcon_Extract(_punkLink, pszIconFile, iIcon, phiconLarge, phiconSmall, ucIconSize);
  844. else
  845. return _Extract(pszIconFile, iIcon, phiconLarge, phiconSmall, ucIconSize);
  846. }
  847. // Now handle the
  848. // Unicode or Ansi one for the "Other" platform...
  849. STDMETHODIMP
  850. Intshcut::GetIconLocation(UINT uInFlags, LPSTR pszIconFile, UINT cchIconFile,
  851. PINT pniIcon, PUINT puOutFlags)
  852. {
  853. HRESULT hres;
  854. WCHAR wszIconFile[MAX_PATH];
  855. // IconFile is output so...
  856. // Note, we will only handle up to MAXPATH
  857. if (cchIconFile > ARRAYSIZE(wszIconFile))
  858. cchIconFile = ARRAYSIZE(wszIconFile);
  859. ASSERT(IS_VALID_WRITE_BUFFER(pszIconFile, TCHAR, cchIconFile));
  860. hres = GetIconLocation(uInFlags, wszIconFile, cchIconFile, pniIcon, puOutFlags);
  861. if (cchIconFile > 0 && SUCCEEDED(hres))
  862. {
  863. WideCharToMultiByte(CP_ACP, 0, wszIconFile, -1, pszIconFile, cchIconFile, NULL, NULL);
  864. }
  865. return hres;
  866. }
  867. STDMETHODIMP Intshcut::Extract(IN LPCSTR pszIconFile, IN UINT iIcon,
  868. OUT HICON * phiconLarge, OUT HICON * phiconSmall, IN UINT ucIconSize)
  869. {
  870. WCHAR wszIconFile[MAX_PATH];
  871. // First convert the string...
  872. MultiByteToWideChar(CP_ACP, 0, pszIconFile, -1, wszIconFile, ARRAYSIZE(wszIconFile));
  873. return Extract(wszIconFile, iIcon, phiconLarge, phiconSmall, ucIconSize);
  874. }