|
|
/*
* extricon.cpp - IExtractIcon implementation for URL class. */
/* Headers
**********/
#include "project.hpp"
#pragma hdrstop
#include "assoc.h"
/* Global Constants
*******************/
#pragma data_seg(DATA_SEG_READ_ONLY)
extern const char g_cszURLDefaultIconKey[] = "InternetShortcut\\DefaultIcon";
extern const HKEY g_hkeyURLSettings = HKEY_LOCAL_MACHINE;
#pragma data_seg()
/* Module Constants
*******************/
#pragma data_seg(DATA_SEG_READ_ONLY)
PRIVATE_DATA const char s_cszDefaultIconSubKey[] = "DefaultIcon";
PRIVATE_DATA const char s_cszGenericURLIconFile[] = "url.dll"; PRIVATE_DATA const int s_ciGenericURLIcon = 0;
// IExtractIcon::GetIconLocation() flag combinations
PRIVATE_DATA const int ALL_GIL_IN_FLAGS = (GIL_OPENICON | GIL_FORSHELL);
PRIVATE_DATA const int ALL_GIL_OUT_FLAGS = (GIL_SIMULATEDOC | GIL_PERINSTANCE | GIL_PERCLASS | GIL_NOTFILENAME | GIL_DONTCACHE);
#pragma data_seg()
/***************************** Private Functions *****************************/
/*
** ParseIconEntry() ** ** ** ** Arguments: ** ** Returns: S_OK if icon entry parsed successfully. ** E_FAIL if not. ** ** Side Effects: The contents of pszIconEntry are destroyed. ** ** pszIconEntry and pszIconFile may be the same. */ PRIVATE_CODE HRESULT ParseIconEntry(PSTR pszIconEntry, PSTR pszIconFile, UINT ucbIconFileBufLen, PINT pniIcon) { HRESULT hr; PSTR pszComma;
ASSERT(IS_VALID_STRING_PTR(pszIconEntry, STR)); ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszIconFile, STR, ucbIconFileBufLen)); ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT));
pszComma = StrChr(pszIconEntry, ',');
if (pszComma) { *pszComma++ = '\0'; TrimWhiteSpace(pszComma); *pniIcon = StringToInt(pszComma); } else { *pniIcon = 0;
WARNING_OUT(("ParseIconEntry(): No icon index in entry %s. Using icon index 0.", pszIconEntry)); }
TrimWhiteSpace(pszIconEntry);
if ((UINT)lstrlen(pszIconEntry) < ucbIconFileBufLen) { lstrcpy(pszIconFile, pszIconEntry); hr = S_OK;
TRACE_OUT(("ParseIconEntry(): Parsed icon file %s, index %d.", pszIconFile, *pniIcon)); } else { hr = S_FALSE;
// (+ 1) for null terminator.
WARNING_OUT(("ParseIconEntry(): Icon file buffer too small for icon file %s (%u bytes supplied, %lu bytes required).", pszIconEntry, ucbIconFileBufLen, lstrlen(pszIconEntry) + 1)); }
ASSERT(IsValidIconIndex(hr, pszIconFile, ucbIconFileBufLen, *pniIcon));
return(hr); }
/*
** GetURLIcon() ** ** ** ** Arguments: ** ** Returns: S_OK if icon information retrieved successfully. ** S_FALSE if no icon entry for this URL. ** Otherwise error. ** ** Side Effects: none */ PRIVATE_CODE HRESULT GetURLIcon(HKEY hkey, PCSTR pcszKey, PSTR pszIconFile, UINT ucbIconFileBufLen, PINT pniIcon) { HRESULT hr; DWORD dwcbLen = ucbIconFileBufLen;
ASSERT(IS_VALID_HANDLE(hkey, KEY)); ASSERT(IS_VALID_STRING_PTR(pcszKey, CSTR)); ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszIconFile, STR, ucbIconFileBufLen)); ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT));
if (GetDefaultRegKeyValue(hkey, pcszKey, pszIconFile, &dwcbLen) == ERROR_SUCCESS) hr = ParseIconEntry(pszIconFile, pszIconFile, ucbIconFileBufLen, pniIcon); else { // No protocol handler.
hr = S_FALSE;
TRACE_OUT(("GetURLIcon(): Couldn't get default value for key %s.", pcszKey)); }
ASSERT(IsValidIconIndex(hr, pszIconFile, ucbIconFileBufLen, *pniIcon));
return(hr); }
/*
** GetFallBackGenericURLIcon() ** ** ** ** Arguments: ** ** Returns: S_OK if fallback generic icon information retrieved ** successfully. ** E_FAIL if not. ** ** Side Effects: none */ PRIVATE_CODE HRESULT GetFallBackGenericURLIcon(PSTR pszIconFile, UINT ucbIconFileBufLen, PINT pniIcon) { HRESULT hr;
ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszIconFile, STR, ucbIconFileBufLen)); ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT));
// Fall back to first icon in this module.
if (ucbIconFileBufLen >= sizeof(s_cszGenericURLIconFile)) { lstrcpy(pszIconFile, s_cszGenericURLIconFile); *pniIcon = s_ciGenericURLIcon;
hr = S_OK;
TRACE_OUT(("GetFallBackGenericURLIcon(): Using generic URL icon file %s, index %d.", s_cszGenericURLIconFile, s_ciGenericURLIcon)); } else { hr = E_FAIL;
WARNING_OUT(("GetFallBackGenericURLIcon(): Icon file buffer too small for generic icon file %s (%u bytes supplied, %lu bytes required).", s_cszGenericURLIconFile, ucbIconFileBufLen, sizeof(s_cszGenericURLIconFile))); }
ASSERT(IsValidIconIndex(hr, pszIconFile, ucbIconFileBufLen, *pniIcon));
return(hr); }
/*
** GetGenericURLIcon() ** ** ** ** Arguments: ** ** Returns: S_OK if generic icon information retrieved successfully. ** Otherwise error. ** ** Side Effects: none */ PRIVATE_CODE HRESULT GetGenericURLIcon(PSTR pszIconFile, UINT ucbIconFileBufLen, PINT pniIcon) { HRESULT hr;
ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszIconFile, STR, ucbIconFileBufLen)); ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT));
hr = GetURLIcon(g_hkeyURLProtocols, g_cszURLDefaultIconKey, pszIconFile, ucbIconFileBufLen, pniIcon);
if (hr == S_FALSE) hr = GetFallBackGenericURLIcon(pszIconFile, ucbIconFileBufLen, pniIcon);
ASSERT(IsValidIconIndex(hr, pszIconFile, ucbIconFileBufLen, *pniIcon));
return(hr); }
/****************************** Public Functions *****************************/
/*
** StringToInt() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none ** ** Stops at first non-digit character encountered. */ PUBLIC_CODE int StringToInt(PCSTR pcsz) { int nResult = 0; BOOL bNegative; #ifdef DEBUG
PCSTR pcszStart = pcsz; #endif
ASSERT(IS_VALID_STRING_PTR(pcsz, CSTR));
if (*pcsz == '-') { bNegative = TRUE; pcsz++; } else bNegative = FALSE;
while (IsDigit(*pcsz)) { ASSERT(nResult <= INT_MAX / 10); nResult *= 10; ASSERT(nResult <= INT_MAX - (*pcsz - '0')); nResult += *pcsz++ - '0'; }
if (*pcsz) { WARNING_OUT(("StringToInt(): Stopped at non-digit character %c in string %s.", *pcsz, pcszStart)); }
// nResult may be any value.
return(bNegative ? - nResult : nResult); }
PUBLIC_CODE BOOL IsWhiteSpace(char ch) { return((ch && StrChr(g_cszWhiteSpace, ch)) ? TRUE : FALSE); }
PUBLIC_CODE BOOL AnyMeat(PCSTR pcsz) { ASSERT(! pcsz || IS_VALID_STRING_PTR(pcsz, CSTR));
return(pcsz ? StrSpn(pcsz, g_cszWhiteSpace) < lstrlen(pcsz) : FALSE); }
PUBLIC_CODE HRESULT CopyURLProtocol(PCSTR pcszURL, PSTR *ppszProtocol) { HRESULT hr; PARSEDURL pu;
ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR)); ASSERT(IS_VALID_WRITE_PTR(ppszProtocol, PSTR));
*ppszProtocol = NULL;
pu.cbSize = sizeof(pu); hr = ParseURL(pcszURL, &pu);
if (hr == S_OK) { // (+ 1) for null terminator.
*ppszProtocol = new(char[pu.cchProtocol + 1]);
if (*ppszProtocol) { // (+ 1) for null terminator.
lstrcpyn(*ppszProtocol, pu.pszProtocol, pu.cchProtocol + 1); ASSERT((UINT)lstrlen(*ppszProtocol) == pu.cchProtocol); } else hr = E_OUTOFMEMORY; }
ASSERT(FAILED(hr) || (hr == S_OK && IS_VALID_STRING_PTR(*ppszProtocol, STR)));
return(hr); }
PUBLIC_CODE HRESULT CopyURLSuffix(PCSTR pcszURL, PSTR *ppszSuffix) { HRESULT hr; PARSEDURL pu;
ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR)); ASSERT(IS_VALID_WRITE_PTR(ppszSuffix, PSTR));
*ppszSuffix = NULL;
hr = ParseURL(pcszURL, &pu);
if (hr == S_OK) { // (+ 1) for null terminator.
*ppszSuffix = new(char[pu.cchSuffix + 1]);
if (*ppszSuffix) { // (+ 1) for null terminator.
lstrcpyn(*ppszSuffix, pu.pszSuffix, pu.cchSuffix + 1); ASSERT((UINT)lstrlen(*ppszSuffix) == pu.cchSuffix);
hr = S_OK; } else hr = E_OUTOFMEMORY; }
ASSERT(FAILED(hr) || IS_VALID_STRING_PTR(*ppszSuffix, STR));
return(hr); }
PUBLIC_CODE HRESULT GetProtocolKey(PCSTR pcszProtocol, PCSTR pcszSubKey, PSTR *ppszKey) { HRESULT hr; ULONG ulcbKeyLen;
ASSERT(IS_VALID_STRING_PTR(pcszProtocol, STR)); ASSERT(IS_VALID_STRING_PTR(pcszSubKey, CSTR)); ASSERT(IS_VALID_WRITE_PTR(ppszKey, PSTR));
// (+ 1) for possible separator.
// (+ 1) for null terminator.
ulcbKeyLen = lstrlen(pcszProtocol) + 1 + lstrlen(pcszSubKey) + 1;
*ppszKey = new(char[ulcbKeyLen]);
if (*ppszKey) { lstrcpy(*ppszKey, pcszProtocol); PathAppend(*ppszKey, pcszSubKey);
ASSERT((UINT)lstrlen(*ppszKey) < ulcbKeyLen);
hr = S_OK; } else hr = E_OUTOFMEMORY;
ASSERT((hr == S_OK && IS_VALID_STRING_PTR(*ppszKey, STR)) || hr == E_OUTOFMEMORY);
return(hr); }
PUBLIC_CODE HRESULT GetURLKey(PCSTR pcszURL, PCSTR pcszSubKey, PSTR *pszKey) { HRESULT hr; PSTR pszProtocol;
ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR)); ASSERT(IS_VALID_STRING_PTR(pcszSubKey, CSTR)); ASSERT(IS_VALID_WRITE_PTR(pszKey, PSTR));
*pszKey = NULL;
hr = CopyURLProtocol(pcszURL, &pszProtocol);
if (hr == S_OK) { hr = GetProtocolKey(pszProtocol, pcszSubKey, pszKey);
delete pszProtocol; pszProtocol = NULL; }
ASSERT((hr == S_OK && IS_VALID_STRING_PTR(*pszKey, STR)) || FAILED(hr));
return(hr); }
/********************************** Methods **********************************/
HRESULT STDMETHODCALLTYPE InternetShortcut::GetIconLocation( UINT uInFlags, PSTR pszIconFile, UINT ucbIconFileBufLen, PINT pniIcon, PUINT puOutFlags) { HRESULT hr;
DebugEntry(InternetShortcut::GetIconLocation);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(FLAGS_ARE_VALID(uInFlags, ALL_GIL_IN_FLAGS)); ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszIconFile, STR, ucbIconFileBufLen)); ASSERT(IS_VALID_WRITE_PTR(pniIcon, INT)); ASSERT(IS_VALID_WRITE_PTR(puOutFlags, UINT));
if (IS_FLAG_CLEAR(uInFlags, GIL_OPENICON)) { hr = GetIconLocation(pszIconFile, ucbIconFileBufLen, pniIcon);
if (hr != S_OK) { if (m_pszURL) { PSTR pszDefaultIconKey;
// Look up URL icon based on protocol handler.
hr = GetURLKey(m_pszURL, s_cszDefaultIconSubKey, &pszDefaultIconKey);
if (hr == S_OK) { hr = GetURLIcon(g_hkeyURLProtocols, pszDefaultIconKey, pszIconFile, ucbIconFileBufLen, pniIcon);
delete pszDefaultIconKey; pszDefaultIconKey = NULL; } } else hr = S_FALSE;
if (hr == S_FALSE) { // Use generic URL icon.
hr = GetGenericURLIcon(pszIconFile, ucbIconFileBufLen, pniIcon);
if (hr == S_OK) { TRACE_OUT(("InternetShortcut::GetIconLocation(): Using generic URL icon.")); } }
if (hr == S_OK) { char rgchFullPath[MAX_PATH_LEN];
hr = FullyQualifyPath(pszIconFile, rgchFullPath, sizeof(rgchFullPath));
if (hr == S_OK) { if ((UINT)lstrlen(rgchFullPath) < ucbIconFileBufLen) lstrcpy(pszIconFile, rgchFullPath); else hr = E_FAIL; } } } } else // No "open look" icon.
hr = S_FALSE;
if (hr != S_OK) { if (ucbIconFileBufLen > 0) *pszIconFile = '\0';
*pniIcon = 0; }
*puOutFlags = 0;
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IsValidIconIndex(hr, pszIconFile, ucbIconFileBufLen, *pniIcon) && FLAGS_ARE_VALID(*puOutFlags, ALL_GIL_OUT_FLAGS));
DebugExitHRESULT(InternetShortcut::GetIconLocation, hr);
return(hr); }
#pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
HRESULT STDMETHODCALLTYPE InternetShortcut::Extract(PCSTR pcszIconFile, UINT uiIcon, PHICON phiconLarge, PHICON phiconSmall, UINT ucIconSize) { HRESULT hr;
DebugEntry(InternetShortcut::Extract);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT(IS_VALID_STRING_PTR(pcszIconFile, CSTR)); ASSERT(IsValidIconIndex(S_OK, pcszIconFile, MAX_PATH_LEN, uiIcon)); ASSERT(IS_VALID_WRITE_PTR(phiconLarge, HICON)); ASSERT(IS_VALID_WRITE_PTR(phiconSmall, HICON)); // FEATURE: Validate ucIconSize here.
*phiconLarge = NULL; *phiconSmall = NULL;
// Use caller's default implementation of ExtractIcon().
hr = S_FALSE;
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut)); ASSERT((hr == S_OK && IS_VALID_HANDLE(*phiconLarge, ICON) && IS_VALID_HANDLE(*phiconSmall, ICON)) || (hr != S_OK && ! *phiconLarge && ! *phiconSmall));
DebugExitHRESULT(InternetShortcut::Extract, hr);
return(hr); }
#pragma warning(default:4100) /* "unreferenced formal parameter" warning */
|