/* * isexicon.cpp - IExtractIcon implementation for URL class. */ #include "priv.h" #include "htregmng.h" #include "ishcut.h" #include "resource.h" // We still have to use url.dll as the source of the internet shortcut // icons because the icons need to still be valid on uninstall. #ifndef UNIX #define c_szIntshcutDefaultIcon TEXT("url.dll") #else // IEUNIX(perf) : use unixstyle dll name #ifdef ux10 #define c_szIntshcutDefaultIcon TEXT("liburl.sl") #else #define c_szIntshcutDefaultIcon TEXT("liburl.so") #endif #endif #define IDEFICON_NORMAL 0 #define II_OVERLAY_UPDATED 1 typedef struct { HIMAGELIST himl; HIMAGELIST himlSm; } URLIMAGES; HRESULT URLGetLocalFileName( LPCTSTR pszURL, LPTSTR szLocalFile, int cch, FILETIME* pftLastMod); /*---------------------------------------------------------- Purpose: Initializes the images lists used by the URL icon handler. There are just two icons placed in each imagelist: the given hicon and an overlay for the updated asterisk. Returns: Cond: -- */ STDMETHODIMP InitURLImageLists( IN URLIMAGES * pui, IN HICON hicon, IN HICON hiconSm) { HRESULT hres = E_OUTOFMEMORY; LoadCommonIcons(); _InitSysImageLists(); pui->himl = ImageList_Create(g_cxIcon, g_cyIcon, ILC_MASK, 2, 2); if (pui->himl) { pui->himlSm = ImageList_Create(g_cxSmIcon, g_cySmIcon, ILC_MASK, 2, 2); if ( !pui->himlSm ) ImageList_Destroy(pui->himl); else { ImageList_SetBkColor(pui->himl, GetSysColor(COLOR_WINDOW)); ImageList_SetBkColor(pui->himlSm, GetSysColor(COLOR_WINDOW)); // Add the given icons ImageList_ReplaceIcon(pui->himl, -1, hicon); ImageList_ReplaceIcon(pui->himlSm, -1, hiconSm); // Add the overlay icon to the list ASSERT(IS_VALID_HANDLE(g_hiconSplat, ICON)); ASSERT(IS_VALID_HANDLE(g_hiconSplatSm, ICON)); if (g_hiconSplat) { int iOverlay = ImageList_ReplaceIcon(pui->himl, -1, g_hiconSplat); ImageList_ReplaceIcon(pui->himlSm, -1, g_hiconSplatSm); ImageList_SetOverlayImage(pui->himl, iOverlay, II_OVERLAY_UPDATED); ImageList_SetOverlayImage(pui->himlSm, iOverlay, II_OVERLAY_UPDATED); } hres = S_OK; } } return hres; } /*---------------------------------------------------------- Purpose: Destroys the url image lists Returns: Cond: -- */ STDMETHODIMP DestroyURLImageLists( IN URLIMAGES * pui) { if (pui->himl) { ImageList_Destroy(pui->himl); pui->himl = NULL; } if (pui->himlSm) { ImageList_Destroy(pui->himlSm); pui->himlSm = NULL; } return S_OK; } /*---------------------------------------------------------- Purpose: Gets the icon location (filename and index) from the registry of the given key. Returns: Cond: -- */ HRESULT GetURLIcon( IN HKEY hkey, IN LPCTSTR pcszKey, IN LPTSTR pszIconFile, IN UINT cchIconFile, OUT PINT pniIcon) { HRESULT hres = S_FALSE; DWORD dwSize = CbFromCch(cchIconFile); ASSERT(IS_VALID_HANDLE(hkey, KEY)); ASSERT(IS_VALID_STRING_PTR(pcszKey, -1)); ASSERT(IS_VALID_WRITE_BUFFER(pszIconFile, TCHAR, cchIconFile)); ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT)); if (NO_ERROR == SHGetValue(hkey, pcszKey, NULL, NULL, pszIconFile, &dwSize)) { *pniIcon = PathParseIconLocation(pszIconFile); hres = S_OK; } ASSERT(IsValidIconIndex(hres, pszIconFile, cchIconFile, *pniIcon)); return hres; } /* ** GetFallBackGenericURLIcon() ** ** ** ** Arguments: ** ** Returns: S_OK if fallback generic icon information retrieved ** successfully. ** E_FAIL if not. ** ** Side Effects: none */ HRESULT GetFallBackGenericURLIcon( LPTSTR pszIconFile, UINT cchIconFile, PINT pniIcon) { HRESULT hr; ASSERT(IS_VALID_WRITE_BUFFER(pszIconFile, TCHAR, cchIconFile)); ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT)); // Fall back to first icon in this module. StrCpyN(pszIconFile, c_szIntshcutDefaultIcon, cchIconFile); *pniIcon = IDEFICON_NORMAL; hr = S_OK; TraceMsg(TF_INTSHCUT, "GetFallBackGenericURLIcon(): Using generic URL icon file %s, index %d.", pszIconFile, *pniIcon); ASSERT(IsValidIconIndex(hr, pszIconFile, cchIconFile, *pniIcon)); return(hr); } /* ** GetGenericURLIcon() ** ** ** ** Arguments: ** ** Returns: S_OK if generic icon information retrieved successfully. ** Otherwise error. ** ** Side Effects: none */ HRESULT GetGenericURLIcon( LPTSTR pszIconFile, UINT cchIconFile, PINT pniIcon) { HRESULT hr; ASSERT(IS_VALID_WRITE_BUFFER(pszIconFile, TCHAR, cchIconFile)); ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT)); hr = GetURLIcon(HKEY_CLASSES_ROOT, TEXT("InternetShortcut\\DefaultIcon"), pszIconFile, cchIconFile, pniIcon); if (hr == S_FALSE) hr = GetFallBackGenericURLIcon(pszIconFile, cchIconFile, pniIcon); ASSERT(IsValidIconIndex(hr, pszIconFile, cchIconFile, *pniIcon)); return(hr); } /****************************** Public Functions *****************************/ /*---------------------------------------------------------- Purpose: Given a full URL path, this function returns the registry path to the associated protocol (plus the subkey path). pszBuf must be MAX_PATH. Returns: Cond: -- */ HRESULT GetURLKey( LPCTSTR pcszURL, LPCTSTR pszSubKey, LPTSTR pszBuf, int cchBuf) { HRESULT hres; PTSTR pszProtocol; ASSERT(IS_VALID_STRING_PTR(pcszURL, -1)); ASSERT(IS_VALID_STRING_PTR(pszSubKey, -1)); ASSERT(IS_VALID_WRITE_BUFFER(pszBuf, TCHAR, MAX_PATH)); *pszBuf = '\0'; hres = CopyURLProtocol(pcszURL, &pszProtocol, NULL); if (hres == S_OK) { StrCpyN(pszBuf, pszProtocol, cchBuf); PathAppend(pszBuf, pszSubKey); LocalFree(pszProtocol); pszProtocol = NULL; } return hres; } /********************************** Methods **********************************/ /*---------------------------------------------------------- Purpose : To help determine if the file to which this shortcut is persisted is in the favorites hierarchy Returns : Returns TRUE if this shortcut is in the favorites folder */ BOOL Intshcut::_IsInFavoritesFolder() { BOOL fRet = FALSE; if(m_pszFile) { TCHAR szPath[MAX_PATH]; if(SHGetSpecialFolderPath(NULL, szPath, CSIDL_FAVORITES, TRUE)) { // Is szPath (i.e. the favorites dir) a prefix of the file associated with this // shortcut ? fRet = PathIsPrefix(szPath, m_pszFile); } } return fRet; } /*---------------------------------------------------------- Purpose: Get the icon location of the given url. Returns: S_FALSE if the location is default for the type S_OK if the location is custom The way this extracticon stuff works is very strange and not well-documented. In particular, there are multiple levels of name munging going on, and it's not clear how information is passed between IExtractIcon::GetIconLocation and IExtractIcon::Extract. (In particular, it seems that we maintain state in our object in order to do secret communication between the two methods, which is out of spec. The shell is allowed to instantiate you, call GetIconLocation, then destroy you. Then the next day, it can instantiate you and call Extract with the result from yesterday's GetIconLocation.) I'm not going to try to fix it; I'm just pointing it out in case somebody has to go debugging into this code and wonders what is going on. Cond: -- */ STDMETHODIMP Intshcut::GetURLIconLocation( IN UINT uInFlags, IN LPTSTR pszBuf, IN UINT cchBuf, OUT int * pniIcon, BOOL fRecentlyChanged, OUT PUINT puOutFlags) { // Call the IShellLink::GetIconLocation method HRESULT hres = _GetIconLocationWithURLHelper(pszBuf, cchBuf, pniIcon, NULL, 0, fRecentlyChanged); BOOL fNeedQualify = TRUE; hres = S_FALSE; if (*pszBuf) { if(puOutFlags && (FALSE == PathFileExists(pszBuf))) SetFlag(*puOutFlags, GIL_NOTFILENAME); } else { if(FALSE == _IsInFavoritesFolder() || (IsIEDefaultBrowserQuick())) { // This shortcut is not in the favorites folder as far as we know TCHAR szURL[INTERNET_MAX_URL_LENGTH]; *szURL = 0; hres = InitProp(); if (SUCCEEDED(hres)) m_pprop->GetProp(PID_IS_URL, szURL, SIZECHARS(szURL)); if (*szURL) { TCHAR szT[MAX_PATH]; hres = E_FAIL; // If it's a file:// URL, then default to the icon from // the file target. Must use IExtractIconA in case we're // on Win95. IExtractIconA *pxi; if (_TryLink(IID_IExtractIconA, (void **)&pxi)) { uInFlags |= GIL_FORSHORTCUT; // to help break recursion // S_FALSE means "I don't know what icon to use", // so treat only S_OK as successful icon extraction. if (IExtractIcon_GetIconLocation(pxi, uInFlags, pszBuf, cchBuf, pniIcon, puOutFlags) == S_OK) { hres = S_OK; fNeedQualify = FALSE; } pxi->Release(); } // If couldn't get target icon or not a file:// URL, then // go get some default icon based on the URL scheme. if (FAILED(hres)) { // Look up URL icon based on protocol handler. hres = GetURLKey(szURL, TEXT("DefaultIcon"), szT, ARRAYSIZE(szT)); if (hres == S_OK) { hres = GetURLIcon(HKEY_CLASSES_ROOT, szT, pszBuf, cchBuf, pniIcon); } } } } if (hres == S_FALSE) { // Use generic URL icon. hres = GetFallBackGenericURLIcon(pszBuf, cchBuf, pniIcon); // Make sure we have the E icon and // Not any of netscape's icons if (hres == S_OK) TraceMsg(TF_INTSHCUT, "Intshcut::GetIconLocation(): Using generic URL icon."); } if (hres == S_OK && fNeedQualify) { TCHAR szFullPath[MAX_PATH]; if (PathSearchAndQualify(pszBuf, szFullPath, SIZECHARS(szFullPath))) { hres = S_OK; if ((UINT)lstrlen(szFullPath) < cchBuf) StrCpyN(pszBuf, szFullPath, cchBuf); else hres = E_FAIL; } else hres = E_FILE_NOT_FOUND; } } return hres; } /*---------------------------------------------------------- Purpose: Helper function that determines the icon location based on the flags property of the internet site property set. Returns: Cond: -- */ STDMETHODIMP Intshcut::GetIconLocationFromFlags( IN UINT uInFlags, OUT LPTSTR pszIconFile, IN UINT cchIconFile, OUT PINT pniIcon, OUT PUINT puOutFlags, IN DWORD dwPropFlags) { HRESULT hres = S_FALSE; *puOutFlags = 0; ClearFlag(m_dwFlags, ISF_SPECIALICON); // Normally, the icon is the standard icon that is retrieved. // If the url has been updated, though, we want to add the // overlay, in which case we return GIL_NOTFILENAME so the // Extract method will be called. hres = GetURLIconLocation(uInFlags, pszIconFile, cchIconFile, pniIcon, IsFlagSet(dwPropFlags, PIDISF_RECENTLYCHANGED), puOutFlags); if (SUCCEEDED(hres)) { // (scotth): we don't support red splats on browser // only because it requires new SHELL32 APIs. // Has this item been updated since last viewed? if (IsFlagSet(dwPropFlags, PIDISF_RECENTLYCHANGED) && (FALSE == (*puOutFlags & GIL_NOTFILENAME))) { // Yes; cache the item as a non-file so we get the // dynamically created icon SetFlag(*puOutFlags, GIL_NOTFILENAME); // Add the icon index at the end of the filename, so // it will be hashed differently from the filename // instance. wnsprintf(&pszIconFile[lstrlen(pszIconFile)], cchIconFile - lstrlen(pszIconFile), TEXT(",%d"), *pniIcon); // cdturner // this is done for browser only mode to stop the shell hacking the path // down to the dll and not calling us // remove the dot from the string LPTSTR pszDot = StrRChr( pszIconFile, NULL, TCHAR('.')); if ( pszDot ) { *pszDot = TCHAR('*'); // should be DBCS safe as it is in the lower 7 bits ASCII } SetFlag(m_dwFlags, ISF_SPECIALICON); } } else { // Init to default values *pniIcon = IDEFICON_NORMAL; if (cchIconFile > 0) StrCpyN(pszIconFile, c_szIntshcutDefaultIcon, cchIconFile); } return S_OK; } /*---------------------------------------------------------- Purpose: IExtractIcon::GetIconLocation handler for Intshcut Returns: Cond: -- */ // This is the real one for the platform... HRESULT Intshcut::_GetIconLocation( IN UINT uInFlags, OUT LPWSTR pszIconFile, IN UINT cchIconFile, OUT PINT pniIcon, OUT PUINT puOutFlags) { HRESULT hres; if (uInFlags & (GIL_ASYNC | GIL_FORSHORTCUT)) { hres = GetGenericURLIcon(pszIconFile, cchIconFile, pniIcon); if (uInFlags & GIL_ASYNC) return ((SUCCEEDED(hres)) ? E_PENDING : hres); else return hres; } hres = LoadFromAsyncFileNow(); if(FAILED(hres)) return hres; hres = S_FALSE; // We also use this method to perform the mirroring // of the values between the internet shortcut file and // the central database. IExtractIcon is a good interface // to do this because it is virtually guaranteed to be // called for a URL. MirrorProperties(); // Init to default values *puOutFlags = 0; *pniIcon = 0; if (cchIconFile > 0) *pszIconFile = TEXT('\0'); DWORD dwVal = 0; if (m_psiteprop) m_psiteprop->GetProp(PID_INTSITE_FLAGS, &dwVal); hres = GetIconLocationFromFlags(uInFlags, pszIconFile, cchIconFile, pniIcon, puOutFlags, dwVal); ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut)); return hres; } HRESULT Intshcut::_CreateShellLink(LPCTSTR pszPath, IUnknown **ppunk) { IUnknown *punk; HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&punk); if (SUCCEEDED(hr)) { if (g_fRunningOnNT) { IShellLink *psl; hr = punk->QueryInterface(IID_IShellLink, (void **)&psl); if (SUCCEEDED(hr)) { hr = psl->SetPath(pszPath); psl->Release(); } } else { IShellLinkA *psl; hr = punk->QueryInterface(IID_IShellLinkA, (void **)&psl); if (SUCCEEDED(hr)) { CHAR sz[MAX_PATH]; SHTCharToAnsi(pszPath, sz, SIZECHARS(sz)); hr = psl->SetPath(sz); psl->Release(); } } if (SUCCEEDED(hr)) { *ppunk = punk; } else punk->Release(); } return hr; } HRESULT Intshcut::GetIconLocation( IN UINT uInFlags, OUT LPTSTR pszIconFile, IN UINT cchIconFile, OUT PINT pniIcon, OUT PUINT puOutFlags) { HRESULT hr = E_FAIL; ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut)); ASSERT(IS_VALID_WRITE_BUFFER(pszIconFile, TCHAR, cchIconFile)); ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT)); ASSERT(IS_VALID_WRITE_PTR(puOutFlags, UINT)); if (FAILED(hr)) { hr = _GetIconLocation(uInFlags, pszIconFile, cchIconFile, pniIcon, puOutFlags); } return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\ // // *** URLGetLocalFileName *** // // // Description: // // // Parameters: // // // Return: // // // Comments: // // /////////////////////////////////////////////////////////////////////////////// HRESULT URLGetLocalFileName( LPCTSTR pszURL, LPTSTR szLocalFile, int cch, FILETIME* pftLastMod ) { ASSERT(pszURL); ASSERT(szLocalFile || 0 == cch); HRESULT hr = E_FAIL; if (pftLastMod) { pftLastMod->dwLowDateTime = 0; pftLastMod->dwHighDateTime = 0; } // by using the internal shlwapi function, we avoid loading WININET // unless we really really need it... DWORD scheme = GetUrlScheme(pszURL); if (scheme != URL_SCHEME_INVALID) { switch(scheme) { case URL_SCHEME_HTTP: case URL_SCHEME_FTP: case URL_SCHEME_GOPHER: { ULONG cbSize = MAX_CACHE_ENTRY_INFO_SIZE; INTERNET_CACHE_ENTRY_INFO* piceiAlloced = (INTERNET_CACHE_ENTRY_INFO*) new BYTE[cbSize]; if (piceiAlloced) { piceiAlloced->dwStructSize = sizeof(INTERNET_CACHE_ENTRY_INFO); if (GetUrlCacheEntryInfoEx(pszURL, piceiAlloced, &cbSize, NULL, NULL, NULL, 0)) { if (StrCpyN(szLocalFile, piceiAlloced->lpszLocalFileName, cch)) { if (pftLastMod) { *pftLastMod = piceiAlloced->LastModifiedTime; } hr = S_OK; } } delete [] piceiAlloced; } } break; case URL_SCHEME_FILE: hr = PathCreateFromUrl(pszURL, szLocalFile, (LPDWORD)&cch, 0); break; } } else { if (StrCpyN(szLocalFile, pszURL, cch)) hr = S_OK; } return hr; } BOOL PretendFileIsICONFileAndLoad( IN LPTSTR lpszTempBuf, OUT HICON * phiconLarge, OUT HICON * phiconSmall, IN UINT ucIconSize) { WORD wSizeSmall = HIWORD(ucIconSize); WORD wSizeLarge = LOWORD(ucIconSize); BOOL fRet = FALSE; // Pretend that the file is a .ico file and load it ASSERT(phiconLarge); ASSERT(phiconSmall); *phiconSmall = (HICON)LoadImage(NULL, lpszTempBuf, IMAGE_ICON, wSizeSmall, wSizeSmall, LR_LOADFROMFILE); if(*phiconSmall) { fRet = TRUE; *phiconLarge = (HICON)LoadImage(NULL, lpszTempBuf, IMAGE_ICON, wSizeLarge, wSizeLarge, LR_LOADFROMFILE); } return fRet; } BOOL Intshcut::ExtractIconFromWininetCache( IN LPCTSTR pszIconString, IN UINT iIcon, OUT HICON * phiconLarge, OUT HICON * phiconSmall, IN UINT ucIconSize, BOOL *pfFoundUrl, DWORD dwPropFlags) { IPropertyStorage *ppropstg = NULL; BOOL fRet = FALSE; INT iTempIconIndex; HRESULT hr; BOOL fFoundURL = FALSE; ASSERT(pfFoundUrl && (FALSE == *pfFoundUrl)); ASSERT((lstrlen(pszIconString) + 1)<= MAX_PATH); TCHAR szTempBuf[MAX_URL_STRING + 1]; *szTempBuf = TEXT('\0'); TCHAR szTempIconBuf[MAX_PATH + 1]; *szTempIconBuf = TEXT('\0'); hr = _GetIconLocationWithURLHelper( szTempIconBuf, ARRAYSIZE(szTempIconBuf), &iTempIconIndex, szTempBuf, ARRAYSIZE(szTempBuf), IsFlagSet(dwPropFlags, PIDISF_RECENTLYCHANGED)); if((S_OK == hr) && (*szTempIconBuf)) { if((UINT)iTempIconIndex == iIcon) { if(0 == StrCmp(szTempIconBuf, pszIconString)) { if(*szTempBuf) { BOOL fUsesCache=FALSE; DWORD dwBufSize=0; CoInternetQueryInfo(szTempBuf, QUERY_USES_CACHE, 0, &fUsesCache, sizeof(fUsesCache), &dwBufSize, 0); if(fUsesCache) { fFoundURL = TRUE; } } } } } if(fFoundURL) { // Now szTempBuf has the URL of the ICON // now look and see if the shortcut file itself has the icon and if so // simply use it --- TBD // we need to grovel in the cache and see if we can get // it there and then convert it to an icon TCHAR szIconFile[MAX_PATH + 1]; hr = URLGetLocalFileName(szTempBuf, szIconFile, ARRAYSIZE(szIconFile), NULL); if(S_OK == hr) { if(PretendFileIsICONFileAndLoad(szIconFile, phiconLarge, phiconSmall, ucIconSize)) { fRet = TRUE; } // It's a bitmap, gif or a jpeg } } if(pfFoundUrl) *pfFoundUrl = fFoundURL; return fRet; } /*---------------------------------------------------------- Purpose: IExtractIcon::Extract method for Intshcut Extract the icon. This function really returns an icon that is dynamically created, based upon the properties of the URL (recently changed, etc). Expect that for normal cases, when the icon does not need to be munged (an overlay added), the GetIconLocation method should suffice. Otherwise, this method will get called. Returns: Cond: -- */ // This is the real one for the platform... HRESULT Intshcut::_Extract( IN LPCTSTR pszIconFile, IN UINT iIcon, OUT HICON * phiconLarge, OUT HICON * phiconSmall, IN UINT ucIconSize) { HRESULT hres; HICON hiconLarge = NULL; HICON hiconSmall = NULL; TCHAR szPath[MAX_PATH]; int nIndex; BOOL fSpecialUrl = FALSE; *phiconLarge = NULL; *phiconSmall = NULL; DWORD dwPropFlags = 0; hres = LoadFromAsyncFileNow(); if(FAILED(hres)) return hres; hres = S_FALSE; InitSiteProp(); // Get the property Flags if (m_psiteprop) m_psiteprop->GetProp(PID_INTSITE_FLAGS, &dwPropFlags); // First check to see if this is a special icon // This function returns a usable value for fSpecialUrl even if it returns FALSE if(ExtractIconFromWininetCache(pszIconFile, iIcon, &hiconLarge, &hiconSmall, ucIconSize, &fSpecialUrl, dwPropFlags)) { hres = S_OK; } else { if(TRUE == fSpecialUrl) { // The extract failed even though this was a special URL // we need to revert back to using the default IE icon hres = GetGenericURLIcon(szPath, MAX_PATH, (int *)(&iIcon)); if (hres == S_OK) { fSpecialUrl = FALSE; // It's no longer a special URL hres = InitProp(); if (SUCCEEDED(hres)) { hres = m_pprop->SetProp(PID_IS_ICONFILE, szPath); if (SUCCEEDED(hres)) { hres = m_pprop->SetProp(PID_IS_ICONINDEX, (INT)iIcon); } } } if(S_OK != hres) { ASSERT(0); goto DefIcons; } } else { StrCpyN(szPath, pszIconFile, ARRAYSIZE(szPath)); // The path may be munged. Get the icon index as appropriate. if (IsFlagSet(m_dwFlags, ISF_SPECIALICON) && (!fSpecialUrl) ) { // Get the icon location from the munged path iIcon = PathParseIconLocation(szPath); // cdturner // now replace the '*' with the dot // this is done for browser only mode to stop the shell hacking the path // down to the dll and not calling us LPTSTR pszPlus = StrRChr( szPath, NULL, TCHAR('*')); if ( pszPlus ) { *pszPlus = TCHAR('.'); } } } nIndex = iIcon; if(!fSpecialUrl) { if ( WhichPlatform() == PLATFORM_INTEGRATED ) { // Extract the icons CHAR szTempPath[MAX_PATH + 1]; SHTCharToAnsi(szPath, szTempPath, ARRAYSIZE(szTempPath)); hres = SHDefExtractIconA(szTempPath, nIndex, 0, &hiconLarge, &hiconSmall, ucIconSize); } else { // cdturner // use a more hacky solution to support browser only mode.. _InitSysImageLists(); int iIndex = Shell_GetCachedImageIndex( szPath, nIndex, 0 ); if ( iIndex > 0 ) { hiconLarge = ImageList_GetIcon( g_himlSysLarge, iIndex, 0 ); hiconSmall = ImageList_GetIcon( g_himlSysSmall, iIndex, 0 ); hres = NOERROR; } else { hiconLarge = hiconSmall = NULL; // it will get the windows icon if it should be gleamed, and // it will the normal icon otherwsie hres = IsFlagSet(dwPropFlags, PIDISF_RECENTLYCHANGED) ? E_FAIL : S_FALSE; goto DefIcons; } } } } if (SUCCEEDED(hres)) { // Has this URL changed recently? if (IsFlagSet(dwPropFlags, PIDISF_RECENTLYCHANGED)) { // Yes URLIMAGES ui; if (SUCCEEDED(InitURLImageLists(&ui, hiconLarge, hiconSmall))) { *phiconLarge = ImageList_GetIcon(ui.himl, 0, INDEXTOOVERLAYMASK(II_OVERLAY_UPDATED)); *phiconSmall = ImageList_GetIcon(ui.himlSm, 0, INDEXTOOVERLAYMASK(II_OVERLAY_UPDATED)); DestroyURLImageLists(&ui); // these were created, they are not global handles, so they must be cleanedup. DestroyIcon( hiconLarge ); DestroyIcon( hiconSmall ); } else goto DefIcons; } else { // No DefIcons: *phiconLarge = hiconLarge; *phiconSmall = hiconSmall; } } return hres; } STDMETHODIMP Intshcut::Extract( IN LPCTSTR pszIconFile, IN UINT iIcon, OUT HICON * phiconLarge, OUT HICON * phiconSmall, IN UINT ucIconSize) { if (URL_SCHEME_FILE == GetScheme() && _punkLink) return IExtractIcon_Extract(_punkLink, pszIconFile, iIcon, phiconLarge, phiconSmall, ucIconSize); else return _Extract(pszIconFile, iIcon, phiconLarge, phiconSmall, ucIconSize); } // Now handle the // Unicode or Ansi one for the "Other" platform... STDMETHODIMP Intshcut::GetIconLocation(UINT uInFlags, LPSTR pszIconFile, UINT cchIconFile, PINT pniIcon, PUINT puOutFlags) { HRESULT hres; WCHAR wszIconFile[MAX_PATH]; // IconFile is output so... // Note, we will only handle up to MAXPATH if (cchIconFile > ARRAYSIZE(wszIconFile)) cchIconFile = ARRAYSIZE(wszIconFile); ASSERT(IS_VALID_WRITE_BUFFER(pszIconFile, TCHAR, cchIconFile)); hres = GetIconLocation(uInFlags, wszIconFile, cchIconFile, pniIcon, puOutFlags); if (cchIconFile > 0 && SUCCEEDED(hres)) { WideCharToMultiByte(CP_ACP, 0, wszIconFile, -1, pszIconFile, cchIconFile, NULL, NULL); } return hres; } STDMETHODIMP Intshcut::Extract(IN LPCSTR pszIconFile, IN UINT iIcon, OUT HICON * phiconLarge, OUT HICON * phiconSmall, IN UINT ucIconSize) { WCHAR wszIconFile[MAX_PATH]; // First convert the string... MultiByteToWideChar(CP_ACP, 0, pszIconFile, -1, wszIconFile, ARRAYSIZE(wszIconFile)); return Extract(wszIconFile, iIcon, phiconLarge, phiconSmall, ucIconSize); }