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.
1951 lines
51 KiB
1951 lines
51 KiB
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// iconhand.cpp
|
|
//
|
|
// The registered icon handler for cdf files. This handler returns icons for
|
|
// .cdf files.
|
|
//
|
|
// History:
|
|
//
|
|
// 3/21/97 edwardp Created.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Includes
|
|
//
|
|
|
|
#include "stdinc.h"
|
|
#include "resource.h"
|
|
#include "cdfidl.h"
|
|
#include "xmlutil.h"
|
|
#include "persist.h"
|
|
#include "iconhand.h"
|
|
#include "exticon.h"
|
|
#include "cdfview.h"
|
|
#include "tooltip.h"
|
|
#include "dll.h"
|
|
#include "chanapi.h"
|
|
|
|
#include <mluisupp.h>
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** MakeXMLErrorURL() ***
|
|
//
|
|
// Set the error based on the IXMLDocument * passed in
|
|
// Upon return CParseError will in an error state no matter what
|
|
// although it may not be in the CParseError::ERR_XML state
|
|
//
|
|
// This function returns the approriate URL to navigate to
|
|
// given the current error. Always changes *ppsz, but *ppsz maybe NULL
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#define CDFERROR_MAX_FOUND 100 // max char length for xml error found string
|
|
#define CDFERROR_MAX_EXPECTED 100 // max char length for xml error expected string
|
|
|
|
// format string for wsprintf of res:// ... URL
|
|
const LPTSTR CDFERROR_URL_FORMAT_TRAILER = TEXT("#%u#%ls#%ls");
|
|
|
|
// this is the number or extra chars (incl null) that CDFERROR_URL_FORMAT_TRAILER
|
|
// may have in comparison to the output buffer of wsprinf
|
|
const unsigned int CDFERROR_URL_FORMAT_EXTRA = 6;
|
|
|
|
// upper char # bound on result of building res URL
|
|
const unsigned CDFERROR_MAX_URL_LENGTH =
|
|
6 + // "res://"
|
|
MAX_PATH + // path to resource DLL
|
|
1 + // "/"
|
|
ARRAYSIZE(SZH_XMLERRORPAGE) + // "xmlerror.htm"
|
|
ARRAYSIZE(CDFERROR_URL_FORMAT_TRAILER) +
|
|
_INTEGRAL_MAX_BITS +
|
|
CDFERROR_MAX_EXPECTED +
|
|
CDFERROR_MAX_FOUND;
|
|
|
|
// upper char # bound on result of InternetCanonicalizeUrl
|
|
// with result from wsprintf with CDFERROR_URL_FORMAT
|
|
// for each funky char in the found and expected substrs, might be encoded as "%xx"
|
|
const unsigned CDFERROR_MAX_URL_LENGTH_ENCODED =
|
|
CDFERROR_MAX_URL_LENGTH + 2*(CDFERROR_MAX_EXPECTED + CDFERROR_MAX_FOUND);
|
|
|
|
|
|
HRESULT MakeXMLErrorURL( LPTSTR pszRet, DWORD dwRetLen, IXMLDocument *pXMLDoc )
|
|
{
|
|
IXMLError *pXMLError = NULL;
|
|
XML_ERROR xmle = { 0 };
|
|
HRESULT hr;
|
|
|
|
ASSERT(pXMLDoc);
|
|
|
|
hr =
|
|
( pXMLDoc ? pXMLDoc->QueryInterface(IID_IXMLError, (void **)&pXMLError) :
|
|
E_INVALIDARG );
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
ASSERT(pXMLError);
|
|
hr = pXMLError->GetErrorInfo(&xmle);
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
TCHAR szTemp[CDFERROR_MAX_URL_LENGTH];
|
|
WCHAR szExpected[CDFERROR_MAX_EXPECTED];
|
|
WCHAR szFound[CDFERROR_MAX_FOUND];
|
|
|
|
StrCpyNW( szExpected, xmle._pszExpected, ARRAYSIZE(szExpected) );
|
|
StrCpyNW( szFound, xmle._pszFound, ARRAYSIZE(szFound) );
|
|
|
|
// fill in the "res://<path>\cdfvwlc.dll" part of the res URL
|
|
hr = MLBuildResURLWrap(TEXT("cdfvwlc.dll"),
|
|
g_hinst,
|
|
ML_CROSSCODEPAGE,
|
|
SZH_XMLERRORPAGE,
|
|
szTemp,
|
|
ARRAYSIZE(szTemp),
|
|
TEXT("cdfview.dll"));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
int nCharsWritten;
|
|
int count;
|
|
|
|
nCharsWritten = lstrlen(szTemp);
|
|
|
|
count = wnsprintf(szTemp+nCharsWritten, ARRAYSIZE(szTemp)-nCharsWritten,
|
|
CDFERROR_URL_FORMAT_TRAILER, xmle._nLine, szExpected, szFound );
|
|
if ( count + CDFERROR_URL_FORMAT_EXTRA < ARRAYSIZE(CDFERROR_URL_FORMAT_TRAILER) )
|
|
{
|
|
// not all the chars were successfully written
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
if ( !InternetCanonicalizeUrl( szTemp, pszRet, &dwRetLen, 0 ) )
|
|
hr = E_FAIL;
|
|
|
|
TraceMsg(TF_CDFPARSE, "Parse error string created: %s", pszRet );
|
|
}
|
|
|
|
SysFreeString(xmle._pszFound);
|
|
SysFreeString(xmle._pszExpected);
|
|
SysFreeString(xmle._pchBuf);
|
|
}
|
|
|
|
else
|
|
{
|
|
TraceMsg(TF_CDFPARSE, "Could not get IXMLError error info" );
|
|
}
|
|
|
|
pXMLError->Release();
|
|
}
|
|
else
|
|
{
|
|
TraceMsg(TF_CDFPARSE, "Could not get IXMLError" );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Constructor and destructor.
|
|
//
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::CIconHandler ***
|
|
//
|
|
// Constructor.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
CIconHandler::CIconHandler (
|
|
void
|
|
)
|
|
: m_cRef(1)
|
|
{
|
|
ASSERT(NULL == m_pIExtractIcon);
|
|
ASSERT(NULL == m_bstrImageURL);
|
|
ASSERT(NULL == m_bstrImageWideURL);
|
|
ASSERT(NULL == m_pszErrURL);
|
|
|
|
TraceMsg(TF_OBJECTS, "+ handler object");
|
|
|
|
DllAddRef();
|
|
|
|
return;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::~CIconHandler ***
|
|
//
|
|
// Destructor.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
CIconHandler::~CIconHandler (
|
|
void
|
|
)
|
|
{
|
|
ASSERT(0 == m_cRef);
|
|
|
|
if (m_pIExtractIcon)
|
|
m_pIExtractIcon->Release();
|
|
|
|
if (m_bstrImageURL)
|
|
SysFreeString(m_bstrImageURL);
|
|
|
|
if (m_bstrImageWideURL)
|
|
SysFreeString(m_bstrImageWideURL);
|
|
|
|
if (m_pcdfidl)
|
|
CDFIDL_Free(m_pcdfidl);
|
|
|
|
if (m_pszErrURL)
|
|
delete[] m_pszErrURL;
|
|
|
|
//
|
|
// Matching Release for the constructor Addref.
|
|
//
|
|
|
|
TraceMsg(TF_OBJECTS, "- handler object");
|
|
|
|
DllRelease();
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// IUnknown methods.
|
|
//
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::QueryInterface ***
|
|
//
|
|
// CIconHandler QI.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CIconHandler::QueryInterface (
|
|
REFIID riid,
|
|
void **ppv
|
|
)
|
|
{
|
|
ASSERT(ppv);
|
|
|
|
HRESULT hr;
|
|
|
|
*ppv = NULL;
|
|
|
|
if (IID_IUnknown == riid || IID_IExtractIcon == riid)
|
|
{
|
|
*ppv = (IExtractIcon*)this;
|
|
}
|
|
#ifdef UNICODE
|
|
else if (IID_IExtractIconA == riid)
|
|
{
|
|
*ppv = (IExtractIconA*)this;
|
|
}
|
|
#endif
|
|
else if (IID_IPersistFile == riid || IID_IPersist == riid)
|
|
{
|
|
*ppv = (IPersistFile*)this;
|
|
}
|
|
else if (IID_IPersistFolder == riid)
|
|
{
|
|
*ppv = (IPersistFolder*)this;
|
|
}
|
|
else if (IID_IExtractImage == riid || IID_IExtractLogo == riid)
|
|
{
|
|
*ppv = (IExtractImage*)this;
|
|
}
|
|
else if (IID_IRunnableTask == riid)
|
|
{
|
|
*ppv = (IRunnableTask*)this;
|
|
}
|
|
|
|
if (*ppv)
|
|
{
|
|
((IUnknown*)*ppv)->AddRef();
|
|
hr = S_OK;
|
|
}
|
|
|
|
//
|
|
// REVIEW: QI on the following two objects doesn't come here.
|
|
//
|
|
|
|
else if (IID_IShellLink == riid
|
|
#ifdef UNICODE
|
|
|| IID_IShellLinkA == riid
|
|
#endif
|
|
)
|
|
|
|
{
|
|
if (!m_bCdfParsed)
|
|
ParseCdfShellLink();
|
|
|
|
if (m_pcdfidl)
|
|
{
|
|
hr = QueryInternetShortcut(m_pcdfidl, riid, ppv);
|
|
}
|
|
else
|
|
{
|
|
if ( m_pszErrURL && *m_pszErrURL)
|
|
{
|
|
hr = QueryInternetShortcut(m_pszErrURL, riid, ppv);
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
}
|
|
else if (IID_IQueryInfo == riid)
|
|
{
|
|
hr = ParseCdfInfoTip(ppv);
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
ASSERT((SUCCEEDED(hr) && *ppv) || (FAILED(hr) && NULL == *ppv));
|
|
|
|
return hr;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::AddRef ***
|
|
//
|
|
// CExtractIcon AddRef.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_(ULONG)
|
|
CIconHandler::AddRef (
|
|
void
|
|
)
|
|
{
|
|
ASSERT(m_cRef != 0);
|
|
ASSERT(m_cRef < (ULONG)-1);
|
|
|
|
return ++m_cRef;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::Release ***
|
|
//
|
|
// CIconHandler Release.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_(ULONG)
|
|
CIconHandler::Release (
|
|
void
|
|
)
|
|
{
|
|
ASSERT (m_cRef != 0);
|
|
|
|
ULONG cRef = --m_cRef;
|
|
|
|
if (0 == cRef)
|
|
delete this;
|
|
|
|
return cRef;
|
|
}
|
|
|
|
|
|
//
|
|
// IExtractIcon methods.
|
|
//
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::GetIconLocation ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Returns a name index pair for the icon associated with this cdf item.
|
|
//
|
|
// Parameters:
|
|
// [In] uFlags - GIL_FORSHELL, GIL_OPENICON.
|
|
// [Out] szIconFile - The address of the buffer that receives the associated
|
|
// icon name. It can be a filename, but doesn't have to
|
|
// be.
|
|
// [In] cchMax - Size of the buffer that receives the icon location.
|
|
// [Out] piIndex - A pointer that receives the icon's index.
|
|
// [Out] pwFlags - A pointer the receives flags about the icon.
|
|
//
|
|
// Return:
|
|
// S_OK if an was found.
|
|
// S_FALSE if the shell should supply a default icon.
|
|
//
|
|
// Comments:
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CIconHandler::GetIconLocation(
|
|
UINT uFlags,
|
|
LPTSTR szIconFile,
|
|
UINT cchMax,
|
|
int *piIndex,
|
|
UINT *pwFlags
|
|
)
|
|
{
|
|
ASSERT(szIconFile);
|
|
ASSERT(piIndex);
|
|
ASSERT(pwFlags);
|
|
|
|
HRESULT hr;
|
|
|
|
TraceMsg(TF_CDFICON, "<IN > CIconHandler::GetIconLocation (Icon) tid:0x%x",
|
|
GetCurrentThreadId());
|
|
|
|
if (uFlags & GIL_ASYNC)
|
|
{
|
|
hr = E_PENDING;
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
|
|
if ( IsDefaultChannel())
|
|
{
|
|
m_bstrImageURL = CPersist::ReadFromIni( TSTR_INI_ICON );
|
|
if ( m_bstrImageURL )
|
|
{
|
|
ASSERT( !m_pIExtractIcon );
|
|
m_pIExtractIcon = (IExtractIcon*)new CExtractIcon( m_bstrImageURL );
|
|
}
|
|
}
|
|
if (!m_pIExtractIcon && !m_bCdfParsed)
|
|
ParseCdfIcon();
|
|
|
|
if (m_pIExtractIcon)
|
|
{
|
|
hr = m_pIExtractIcon->GetIconLocation(uFlags, szIconFile, cchMax,
|
|
piIndex, pwFlags);
|
|
}
|
|
|
|
if (FAILED(hr) ||
|
|
(StrEql(szIconFile, g_szModuleName) &&
|
|
-IDI_CHANNEL == *piIndex) )
|
|
{
|
|
//
|
|
// Try and get the icon out of the desktop.ini file.
|
|
//
|
|
|
|
m_bstrImageURL = CPersist::ReadFromIni(TSTR_INI_ICON);
|
|
|
|
if (m_bstrImageURL)
|
|
{
|
|
BOOL bRemovePrefix =
|
|
(0 == StrCmpNIW(L"file://", m_bstrImageURL, 7));
|
|
|
|
if (SHUnicodeToTChar(
|
|
bRemovePrefix ? m_bstrImageURL + 7 : m_bstrImageURL,
|
|
szIconFile, cchMax))
|
|
{
|
|
LPTSTR pszExt = PathFindExtension(szIconFile);
|
|
|
|
if (*pszExt != TEXT('.') ||
|
|
0 != StrCmpI(pszExt, TSTR_ICO_EXT))
|
|
{
|
|
*piIndex = INDEX_IMAGE;
|
|
MungePath(szIconFile);
|
|
}
|
|
else
|
|
{
|
|
*piIndex = 0;
|
|
*pwFlags = 0;
|
|
}
|
|
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
//
|
|
// Try to return the default channel icon.
|
|
//
|
|
|
|
*pwFlags = 0;
|
|
|
|
StrCpyN(szIconFile, g_szModuleName, cchMax);
|
|
|
|
if (*szIconFile)
|
|
{
|
|
*piIndex = -IDI_CHANNEL;
|
|
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
*piIndex = 0;
|
|
|
|
hr = S_FALSE; // The shell will use a default icon.
|
|
}
|
|
}
|
|
|
|
//
|
|
// If this a generated icon and it should contain a gleam prepend
|
|
// the string with a 'G'.
|
|
//
|
|
|
|
if (S_OK == hr && m_fDrawGleam)
|
|
{
|
|
TCHAR* pszBuffer = new TCHAR[cchMax];
|
|
|
|
if (m_pIExtractIcon)
|
|
{
|
|
CExtractIcon *pExtract = (CExtractIcon *)m_pIExtractIcon;
|
|
pExtract->SetGleam(m_fDrawGleam);
|
|
}
|
|
|
|
if (pszBuffer)
|
|
{
|
|
StrCpyN(pszBuffer, szIconFile, cchMax);
|
|
|
|
*szIconFile = TEXT('G');
|
|
cchMax--;
|
|
|
|
StrCpyN(szIconFile+1, pszBuffer, cchMax);
|
|
|
|
delete [] pszBuffer;
|
|
}
|
|
}
|
|
|
|
*pwFlags = (m_fDrawGleam || INDEX_IMAGE == *piIndex) ? GIL_NOTFILENAME :
|
|
0;
|
|
|
|
if (m_fDrawGleam)
|
|
*piIndex += GLEAM_OFFSET;
|
|
|
|
TraceMsg(TF_GLEAM, "%c Icon Location %s,%d", m_fDrawGleam ? '+' : '-',
|
|
SUCCEEDED(hr) ? szIconFile : TEXT("FAILED"), *piIndex);
|
|
|
|
ASSERT((S_OK == hr && *szIconFile) ||
|
|
(S_FALSE == hr && 0 == *szIconFile));
|
|
}
|
|
|
|
TraceMsg(TF_CDFICON, "<OUT> CIconHandler::GetIconLocation (Icon) %s",
|
|
szIconFile);
|
|
return hr;
|
|
}
|
|
#ifdef UNICODE
|
|
STDMETHODIMP
|
|
CIconHandler::GetIconLocation(
|
|
UINT uFlags,
|
|
LPSTR szIconFile,
|
|
UINT cchMax,
|
|
int *piIndex,
|
|
UINT *pwFlags
|
|
)
|
|
{
|
|
ASSERT(szIconFile);
|
|
ASSERT(piIndex);
|
|
ASSERT(pwFlags);
|
|
|
|
HRESULT hr;
|
|
|
|
TraceMsg(TF_CDFICON, "<IN > CIconHandler::GetIconLocationA (Icon) tid:0x%x",
|
|
GetCurrentThreadId());
|
|
|
|
WCHAR* pszIconFileW = new WCHAR[cchMax];
|
|
if (pszIconFileW == NULL)
|
|
return ERROR_OUTOFMEMORY;
|
|
hr = GetIconLocation(uFlags, pszIconFileW, cchMax, piIndex, pwFlags);
|
|
if (SUCCEEDED(hr))
|
|
SHUnicodeToAnsi(pszIconFileW, szIconFile, cchMax);
|
|
|
|
delete [] pszIconFileW;
|
|
return hr;
|
|
}
|
|
#endif
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::Extract ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Return an icon given the name index pair returned from GetIconLocation.
|
|
//
|
|
// Parameters:
|
|
// [In] pszFile - A pointer to the name associated with the requested
|
|
// icon.
|
|
// [In] nIconIndex - An index associated with the requested icon.
|
|
// [Out] phiconLarge - Pointer to the variable that receives the handle of
|
|
// the large icon.
|
|
// [Out] phiconSmall - Pointer to the variable that receives the handle of
|
|
// the small icon.
|
|
// [Out] nIconSize - Value specifying the size, in pixels, of the icon
|
|
// required. The LOWORD and HIWORD specify the size of
|
|
// the large and small icons, respectively.
|
|
//
|
|
// Return:
|
|
// S_OK if the icon was extracted.
|
|
// S_FALSE if the shell should extract the icon assuming the name is a
|
|
// filename and the index is the icon index.
|
|
//
|
|
// Comments:
|
|
// The shell may cache the icon returned from this function.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CIconHandler::Extract(
|
|
LPCTSTR pszFile,
|
|
UINT nIconIndex,
|
|
HICON *phiconLarge,
|
|
HICON *phiconSmall,
|
|
UINT nIconSize
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
TraceMsg(TF_CDFICON, "<IN > CIconHandler::Extract (Icon) tid:0x%x",
|
|
GetCurrentThreadId());
|
|
|
|
DWORD dwType;
|
|
DWORD dwVal; // Bits per pixel
|
|
DWORD cbVal = sizeof(DWORD);
|
|
|
|
if ((SHGetValue(HKEY_CURRENT_USER, c_szHICKey, c_szHICVal, &dwType, &dwVal,
|
|
&cbVal) != ERROR_SUCCESS)
|
|
||
|
|
(REG_DWORD != dwType))
|
|
|
|
{
|
|
dwVal = 0;
|
|
}
|
|
|
|
// Convert bits per pixel to # colors
|
|
m_dwClrDepth = (dwVal == 16) ? 256 : 16;
|
|
|
|
if (m_fDrawGleam)
|
|
nIconIndex -= GLEAM_OFFSET;
|
|
|
|
if (m_pIExtractIcon)
|
|
{
|
|
hr = m_pIExtractIcon->Extract(pszFile, nIconIndex, phiconLarge,
|
|
phiconSmall, nIconSize);
|
|
|
|
//
|
|
// If an icon couldn't be extracted, try and display the default icon.
|
|
//
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
hr = Priv_SHDefExtractIcon(g_szModuleName, -IDI_CHANNEL, 0,
|
|
phiconLarge, phiconSmall, nIconSize);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
TraceMsg(TF_GLEAM, "%c Icon Extract %s %s", m_fDrawGleam ? '+' : '-',
|
|
pszFile, (S_OK == hr) ? TEXT("SUCCEEDED") : TEXT("FAILED"));
|
|
|
|
TraceMsg(TF_CDFICON, "<OUT> CIconHandler::Extract (Icon) tid:0x%x",
|
|
GetCurrentThreadId());
|
|
|
|
return hr;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
STDMETHODIMP
|
|
CIconHandler::Extract(
|
|
LPCSTR pszFile,
|
|
UINT nIconIndex,
|
|
HICON *phiconLarge,
|
|
HICON *phiconSmall,
|
|
UINT nIconSize
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
TraceMsg(TF_CDFICON, "<IN > CIconHandler::ExtractA (Icon) tid:0x%x",
|
|
GetCurrentThreadId());
|
|
|
|
int cch = lstrlenA(pszFile) + 1;
|
|
WCHAR* pszFileW = new WCHAR[cch];
|
|
if (pszFileW == NULL)
|
|
return ERROR_OUTOFMEMORY;
|
|
SHAnsiToUnicode(pszFile, pszFileW, cch);
|
|
|
|
hr = Extract(pszFileW, nIconIndex, phiconLarge, phiconSmall, nIconSize);
|
|
|
|
delete [] pszFileW;
|
|
return hr;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// IExtractImage methods.
|
|
//
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::GetLocation ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Returns a string to associate with this files image.
|
|
//
|
|
// Parameters:
|
|
// [Out] pszPathBuffer - A buffer that receives this items string.
|
|
// [In] cch - The size of the buffer.
|
|
// [Out] pdwPriority - The priority of this item's image.
|
|
// [In/Out] pdwFlags - Flags associated with this call.
|
|
//
|
|
// Return:
|
|
// S_OK if a string is returned.
|
|
// E_FAIL otherwise.
|
|
//
|
|
// Comments:
|
|
// IExtractImage uses the returned value to share images accross multiple
|
|
// items. If three items in the same directory return "Default" all three
|
|
// would use the same image.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CIconHandler::GetLocation(
|
|
LPWSTR pszPathBuffer,
|
|
DWORD cch,
|
|
DWORD* pdwPriority,
|
|
const SIZE * prgSize,
|
|
DWORD dwRecClrDepth,
|
|
DWORD* pdwFlags
|
|
)
|
|
{
|
|
LPWSTR pstrURL = NULL;
|
|
|
|
ASSERT(pszPathBuffer || 0 == cch);
|
|
ASSERT(pdwFlags);
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
TraceMsg(TF_CDFLOGO, "<IN > CIconHandler::GetIconLocation (Logo) tid:0x%x",
|
|
GetCurrentThreadId());
|
|
|
|
if ( !prgSize )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
m_rgSize = *prgSize;
|
|
m_dwClrDepth = dwRecClrDepth;
|
|
|
|
if ( IsDefaultChannel() && !UseWideLogo(prgSize->cx))
|
|
{
|
|
// avoid having to partse the CDF if possible by
|
|
// pulling the entry from the desktop.ini file...
|
|
pstrURL = m_bstrImageURL = CPersist::ReadFromIni(TSTR_INI_LOGO);
|
|
}
|
|
|
|
if (pstrURL == NULL && !m_bCdfParsed)
|
|
ParseCdfImage(&m_bstrImageURL, &m_bstrImageWideURL);
|
|
|
|
pstrURL = (UseWideLogo(prgSize->cx) && m_bstrImageWideURL) ?
|
|
m_bstrImageWideURL :
|
|
m_bstrImageURL;
|
|
|
|
if (pstrURL)
|
|
{
|
|
ASSERT(0 != *m_bstrImageURL);
|
|
|
|
if (m_fDrawGleam && cch > 0)
|
|
{
|
|
*pszPathBuffer++ = L'G';
|
|
cch--;
|
|
}
|
|
|
|
if (StrCpyNW(pszPathBuffer, pstrURL, cch))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
if (m_bstrImageURL)
|
|
{
|
|
SysFreeString(m_bstrImageURL);
|
|
m_bstrImageURL = NULL;
|
|
}
|
|
|
|
if (m_bstrImageWideURL)
|
|
{
|
|
SysFreeString(m_bstrImageWideURL);
|
|
m_bstrImageWideURL = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
m_bstrImageURL = CPersist::ReadFromIni(TSTR_INI_LOGO);
|
|
m_bstrImageWideURL = CPersist::ReadFromIni(TSTR_INI_WIDELOGO);
|
|
|
|
pstrURL = (UseWideLogo(prgSize->cx) && m_bstrImageWideURL) ?
|
|
m_bstrImageWideURL :
|
|
m_bstrImageURL;
|
|
|
|
if (pstrURL)
|
|
{
|
|
if (m_fDrawGleam && cch > 0)
|
|
{
|
|
*pszPathBuffer++ = L'G';
|
|
cch--;
|
|
}
|
|
|
|
if (StrCpyNW(pszPathBuffer, pstrURL, cch))
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
BOOL bAsync = *pdwFlags & IEIFLAG_ASYNC;
|
|
|
|
//
|
|
// REVIEW: Long URLs truncated in pszPathBuffer.
|
|
//
|
|
|
|
//TSTRToWideChar(m_szPath, pszPathBuffer, cch);
|
|
|
|
if (pdwPriority)
|
|
*pdwPriority = ITSAT_DEFAULT_PRIORITY; //0x10000; // Low priority since this could hit the net.
|
|
|
|
*pdwFlags = m_fDrawGleam ? IEIFLAG_GLEAM : 0;
|
|
|
|
TraceMsg(TF_GLEAM, "%c Logo Location %S", m_fDrawGleam ? '+' : '-',
|
|
SUCCEEDED(hr) ? pszPathBuffer : L"FAILED");
|
|
|
|
//
|
|
// REVIEW: Proper IEIFLAG_ASYNC handling.
|
|
//
|
|
|
|
TraceMsg(TF_CDFLOGO, "<OUT> CIconHandler::GetIconLocation (Logo) tid:0x%x",
|
|
GetCurrentThreadId());
|
|
|
|
return (SUCCEEDED(hr) && bAsync) ? E_PENDING : hr;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::Extract ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Returns a hbitmap for use as a logo for this cdf file.
|
|
//
|
|
// Parameters:
|
|
// [Out] phBmp - The returned bitmap.
|
|
//
|
|
// Return:
|
|
// S_OK if an image was extracted.
|
|
// E_FAIL if an image couldn't be extracted.
|
|
//
|
|
// Comments:
|
|
// The returned bitmap is stretched to pSize.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CIconHandler::Extract(
|
|
HBITMAP * phBmp
|
|
)
|
|
{
|
|
ASSERT(phBmp);
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
TraceMsg(TF_CDFLOGO, "<IN > CIconHandler::Extract (Logo) tid:0x%x",
|
|
GetCurrentThreadId());
|
|
|
|
if (m_bstrImageURL)
|
|
{
|
|
hr = ExtractCustomImage(&m_rgSize, phBmp);
|
|
}
|
|
|
|
// Let the extractor build a default logo.
|
|
//if (FAILED(hr))
|
|
// hr = ExtractDefaultImage(pSize, phBmp);
|
|
|
|
TraceMsg(TF_CDFLOGO, "<OUT> CIconHandler::Extract (Logo) tid:0x%x",
|
|
GetCurrentThreadId());
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// Helper functions.
|
|
//
|
|
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::IsDefaultChannel***
|
|
//
|
|
//
|
|
// Description:
|
|
// Checks to see if the channel we are dealing with is a default one.
|
|
//
|
|
// Parameters:
|
|
// None.
|
|
//
|
|
// Return:
|
|
// TRUE if it is a default channel.
|
|
// FALSE otherwise.
|
|
//
|
|
// Comments:
|
|
// This is used in an attempt to avoid parsing the CDF if the only
|
|
// information we need is already in the desktop.ini file.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL CIconHandler::IsDefaultChannel()
|
|
{
|
|
BOOL fDefault = FALSE;
|
|
|
|
// get the desktop.ini path and see if it points to the systemdir\web
|
|
BSTR pstrURL = CPersist::ReadFromIni( TSTR_INI_URL );
|
|
if ( pstrURL )
|
|
{
|
|
fDefault = Channel_CheckURLMapping( pstrURL );
|
|
SysFreeString( pstrURL );
|
|
}
|
|
return fDefault;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::ParseCdfIcon ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Parses the cdf file associated with this folder.
|
|
//
|
|
// Parameters:
|
|
// None.
|
|
//
|
|
// Return:
|
|
// S_OK if the cdf file was found and successfully parsed.
|
|
// E_FAIL otherwise.
|
|
//
|
|
// Comments:
|
|
// This parse function gets the root channel item and uses it to create
|
|
// a CExtractIcon object. The CExtractIcon object is later called to get
|
|
// the icon location and extract the icon.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CIconHandler::ParseCdfIcon(
|
|
void
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Parse the file and get back the root channel element.
|
|
//
|
|
|
|
IXMLDocument* pIXMLDocument = NULL;
|
|
|
|
TraceMsg(TF_CDFICON, "Extracting icon URL for %s",
|
|
PathFindFileName(m_szPath));
|
|
TraceMsg(TF_CDFPARSE, "Extracting icon URL for %s",
|
|
PathFindFileName(m_szPath));
|
|
|
|
hr = CPersist::ParseCdf(NULL, &pIXMLDocument, PARSE_LOCAL);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ASSERT(pIXMLDocument);
|
|
|
|
m_fDrawGleam = CPersist::IsUnreadCdf();
|
|
|
|
IXMLElement* pIXMLElement;
|
|
LONG nIndex;
|
|
|
|
hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLElement, &nIndex);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ASSERT(pIXMLElement);
|
|
|
|
PCDFITEMIDLIST pcdfidl = CDFIDL_CreateFromXMLElement(pIXMLElement,
|
|
nIndex);
|
|
|
|
if (pcdfidl)
|
|
{
|
|
//
|
|
// Create a CExtractIcon object for the root channel.
|
|
//
|
|
|
|
m_pIExtractIcon = (IExtractIcon*)new CExtractIcon(pcdfidl,
|
|
pIXMLElement);
|
|
|
|
hr = m_pIExtractIcon ? S_OK : E_OUTOFMEMORY;
|
|
|
|
CDFIDL_Free(pcdfidl);
|
|
}
|
|
|
|
pIXMLElement->Release();
|
|
}
|
|
}
|
|
|
|
if (pIXMLDocument)
|
|
pIXMLDocument->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::ParseCdfImage ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Parses the cdf file associated with this folder.
|
|
//
|
|
// Parameters:
|
|
// [In] pbstrURL - A pointer that receives the URL for the image associated
|
|
// with the root channel.
|
|
//
|
|
// Return:
|
|
// S_OK if the URL was found.
|
|
// E_FAIL if the URL wasn't found.
|
|
//
|
|
// Comments:
|
|
// This function parses the cdf file and returns an URL to the image
|
|
// associated with this cdf file.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CIconHandler::ParseCdfImage(
|
|
BSTR* pbstrURL,
|
|
BSTR* pbstrWURL
|
|
)
|
|
{
|
|
ASSERT(pbstrURL);
|
|
|
|
HRESULT hr;
|
|
|
|
*pbstrURL = NULL;
|
|
|
|
IXMLDocument* pIXMLDocument = NULL;
|
|
|
|
//
|
|
// Parse the file.
|
|
//
|
|
|
|
TraceMsg(TF_CDFPARSE, "Extracting logo URL for %s",
|
|
PathFindFileName(m_szPath));
|
|
TraceMsg(TF_CDFLOGO, "Extracting logo URL for %s",
|
|
PathFindFileName(m_szPath));
|
|
|
|
hr = CPersist::ParseCdf(NULL, &pIXMLDocument, PARSE_LOCAL);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ASSERT(pIXMLDocument);
|
|
|
|
m_fDrawGleam = CPersist::IsUnreadCdf();
|
|
|
|
//
|
|
// Get the first channel element.
|
|
//
|
|
|
|
IXMLElement* pIXMLElement;
|
|
LONG nIndex;
|
|
|
|
hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLElement, &nIndex);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ASSERT(pIXMLElement);
|
|
|
|
//
|
|
// Get the logo URL of the first channel element.
|
|
//
|
|
|
|
*pbstrURL = XML_GetAttribute(pIXMLElement, XML_LOGO);
|
|
|
|
hr = *pbstrURL ? S_OK : E_FAIL;
|
|
|
|
*pbstrWURL = XML_GetAttribute(pIXMLElement, XML_LOGO_WIDE);
|
|
|
|
pIXMLElement->Release();
|
|
}
|
|
}
|
|
|
|
if (pIXMLDocument)
|
|
pIXMLDocument->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** Name ***
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
//
|
|
// Parameters:
|
|
//
|
|
//
|
|
// Return:
|
|
//
|
|
//
|
|
// Comments:
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CIconHandler::ParseCdfShellLink(
|
|
void
|
|
)
|
|
{
|
|
//
|
|
// Parse the file and get back the root channel element.
|
|
//
|
|
|
|
IXMLDocument* pIXMLDocument = NULL;
|
|
|
|
TraceMsg(TF_CDFPARSE, "Extracting IShellLink for %s",
|
|
PathFindFileName(m_szPath));
|
|
|
|
HRESULT hr = CPersist::ParseCdf(NULL, &pIXMLDocument,
|
|
PARSE_LOCAL | PARSE_REMOVEGLEAM);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ASSERT(pIXMLDocument);
|
|
|
|
IXMLElement* pIXMLElement;
|
|
LONG nIndex;
|
|
|
|
hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLElement, &nIndex);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ASSERT(pIXMLElement);
|
|
|
|
m_pcdfidl = CDFIDL_CreateFromXMLElement(pIXMLElement,
|
|
nIndex);
|
|
|
|
pIXMLElement->Release();
|
|
}
|
|
}
|
|
else if (OLE_E_NOCACHE == hr)
|
|
{
|
|
//
|
|
// If it wasn't in the cache pass the url of the cdf so it gets reloaded.
|
|
//
|
|
|
|
BSTR bstrURL = CPersist::ReadFromIni(TSTR_INI_URL);
|
|
|
|
if (bstrURL)
|
|
{
|
|
if (InternetGetConnectedState(NULL, 0))
|
|
{
|
|
int cch = StrLenW(bstrURL) + 1;
|
|
m_pszErrURL = new TCHAR[cch];
|
|
|
|
if (m_pszErrURL)
|
|
{
|
|
if (!SHUnicodeToTChar(bstrURL, m_pszErrURL, cch))
|
|
{
|
|
delete []m_pszErrURL;
|
|
m_pszErrURL = NULL;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TCHAR szResURL[INTERNET_MAX_URL_LENGTH];
|
|
|
|
ASSERT(NULL == m_pszErrURL);
|
|
|
|
if (SUCCEEDED(MLBuildResURLWrap(TEXT("cdfvwlc.dll"),
|
|
g_hinst,
|
|
ML_CROSSCODEPAGE,
|
|
TEXT("cacheerr.htm#"),
|
|
szResURL,
|
|
ARRAYSIZE(szResURL),
|
|
TEXT("cdfview.dll"))))
|
|
{
|
|
int cchPrefix = StrLen(szResURL);
|
|
|
|
int cch = StrLenW(bstrURL) + cchPrefix + 1;
|
|
|
|
m_pszErrURL = new TCHAR[cch];
|
|
|
|
if (m_pszErrURL &&
|
|
(!StrCpyN(m_pszErrURL, szResURL, cch) ||
|
|
!SHUnicodeToTChar(bstrURL, m_pszErrURL + cchPrefix, cch - cchPrefix)))
|
|
{
|
|
delete []m_pszErrURL;
|
|
m_pszErrURL = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
SysFreeString(bstrURL);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
DWORD dwSize = sizeof(TCHAR[CDFERROR_MAX_URL_LENGTH_ENCODED]); // count in bytes
|
|
if (NULL==m_pszErrURL)
|
|
m_pszErrURL = new TCHAR[CDFERROR_MAX_URL_LENGTH_ENCODED];
|
|
if (m_pszErrURL)
|
|
{
|
|
if (pIXMLDocument)
|
|
{
|
|
if ( FAILED(MakeXMLErrorURL(m_pszErrURL, dwSize / sizeof(TCHAR), pIXMLDocument)) )
|
|
{
|
|
delete[] m_pszErrURL;
|
|
m_pszErrURL = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pIXMLDocument)
|
|
pIXMLDocument->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** Name ***
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
//
|
|
// Parameters:
|
|
//
|
|
//
|
|
// Return:
|
|
//
|
|
//
|
|
// Comments:
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CIconHandler::ParseCdfInfoTip(
|
|
void** ppv
|
|
)
|
|
{
|
|
ASSERT(ppv);
|
|
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Parse the file and get back the root channel element.
|
|
//
|
|
|
|
IXMLDocument* pIXMLDocument = NULL;
|
|
|
|
TraceMsg(TF_CDFPARSE, "Extracting IQueryInfo for %s",
|
|
PathFindFileName(m_szPath));
|
|
|
|
hr = CPersist::ParseCdf(NULL, &pIXMLDocument, PARSE_LOCAL);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ASSERT(pIXMLDocument);
|
|
|
|
IXMLElement* pIXMLElement;
|
|
LONG nIndex;
|
|
|
|
hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLElement, &nIndex);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ASSERT(pIXMLElement);
|
|
|
|
*ppv = (IQueryInfo*)new CQueryInfo(pIXMLElement, XML_IsFolder(pIXMLElement));
|
|
|
|
hr = *ppv ? S_OK : E_FAIL;
|
|
|
|
pIXMLElement->Release();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Even if the cdf isn't in the cache, return a IQueryInfo interface.
|
|
// The caller can stil call GetInfoFlags.
|
|
//
|
|
|
|
*ppv = (IQueryInfo*)new CQueryInfo(NULL, FALSE);
|
|
|
|
hr = *ppv ? S_OK : E_FAIL;
|
|
}
|
|
|
|
if (pIXMLDocument)
|
|
pIXMLDocument->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::ExtractCustomImage ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Extract an image from an URL.
|
|
//
|
|
// Parameters:
|
|
// [In] pSize - The requested size of the image.
|
|
// [Out] phBmp - The returned bitmap.
|
|
//
|
|
// Return:
|
|
// S_OK if the bitmap was successfully extracted.
|
|
// E_FAIL otherwise.
|
|
//
|
|
// Comments:
|
|
// The URL of the image is in m_bstrImageURL and was set when the cdf
|
|
// file was parsed.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CIconHandler::ExtractCustomImage(
|
|
const SIZE* pSize,
|
|
HBITMAP* phBmp
|
|
)
|
|
{
|
|
ASSERT(pSize);
|
|
ASSERT(phBmp);
|
|
|
|
HRESULT hr;
|
|
|
|
IImgCtx* pIImgCtx;
|
|
|
|
hr = CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IImgCtx, (void**)&pIImgCtx);
|
|
|
|
BOOL bCoInit = FALSE;
|
|
|
|
if ((CO_E_NOTINITIALIZED == hr || REGDB_E_IIDNOTREG == hr) &&
|
|
SUCCEEDED(CoInitialize(NULL)))
|
|
{
|
|
bCoInit = TRUE;
|
|
hr = CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IImgCtx, (void**)&pIImgCtx);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ASSERT(pIImgCtx);
|
|
|
|
hr = SynchronousDownload(pIImgCtx,
|
|
(UseWideLogo(pSize->cx) && m_bstrImageWideURL) ?
|
|
m_bstrImageWideURL :
|
|
m_bstrImageURL);
|
|
|
|
//
|
|
// If the load of the wide logo failed try and use the regular logo.
|
|
//
|
|
|
|
if (FAILED(hr) && UseWideLogo(pSize->cx) && m_bstrImageWideURL &&
|
|
m_bstrImageURL)
|
|
{
|
|
hr = SynchronousDownload(pIImgCtx, m_bstrImageURL);
|
|
|
|
SysFreeString(m_bstrImageWideURL);
|
|
m_bstrImageWideURL = NULL;
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = GetBitmap(pIImgCtx, pSize, phBmp);
|
|
|
|
if (FAILED(hr))
|
|
*phBmp = NULL;
|
|
}
|
|
|
|
pIImgCtx->Release();
|
|
}
|
|
|
|
if (bCoInit)
|
|
CoUninitialize();
|
|
|
|
ASSERT((SUCCEEDED(hr) && *phBmp) || (FAILED(hr) && NULL == *phBmp));
|
|
|
|
return hr;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::ExtractDefaultImage ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Returns the default channel bitmap.
|
|
//
|
|
// [In] pSize - The requested size of the image.
|
|
// [Out] phBmp - The returned bitmap.
|
|
//
|
|
// Return:
|
|
// S_OK if the bitmap was successfully extracted.
|
|
// E_FAIL otherwise.
|
|
//
|
|
// Comments:
|
|
// If a cdf doesn't specify a logo image or the logo image couldn't be
|
|
// downloaded a default image is used.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/*HRESULT
|
|
CIconHandler::ExtractDefaultImage(
|
|
const SIZE* pSize,
|
|
HBITMAP* phBmp
|
|
)
|
|
{
|
|
ASSERT(pSize);
|
|
ASSERT(phBmp);
|
|
|
|
HRESULT hr;
|
|
|
|
hr = GetBitmap(NULL, pSize, phBmp);
|
|
|
|
if (FAILED(hr))
|
|
*phBmp = NULL;
|
|
|
|
ASSERT((SUCCEEDED(hr) && *phBmp) || (FAILED(hr) && NULL == *phBmp));
|
|
|
|
return hr;
|
|
}*/
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::GetBitmap ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Gets the requested bitmap
|
|
//
|
|
// Parameters:
|
|
// [In] pIImgCtx - The ImgCtx of the image. NULL if the default image is
|
|
// to be returned.
|
|
// [In] pSize - The requested size of the image.
|
|
// [Out] phBmp - A pointer that receives the returned image.
|
|
//
|
|
// Return:
|
|
// S_OK if the image was extracted.
|
|
// E_FAIL otherwise.
|
|
//
|
|
// Comments:
|
|
// This function conatins code that is shared by the custom image extractor
|
|
// and the default image extractor. The pIImhCtx parameter is used as a
|
|
// flag indicating which image - default or custom - is to be extracted.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CIconHandler::GetBitmap(
|
|
IImgCtx* pIImgCtx,
|
|
const SIZE* pSize,
|
|
HBITMAP* phBmp
|
|
)
|
|
{
|
|
ASSERT(pSize);
|
|
ASSERT(phBmp);
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
//
|
|
// REVIEW: Pallete use for 8bpp DCs?
|
|
//
|
|
|
|
HDC hdcScreen = GetDC(NULL);
|
|
|
|
if (hdcScreen)
|
|
{
|
|
HDC hdcDst = CreateCompatibleDC(NULL);
|
|
|
|
if (hdcDst)
|
|
{
|
|
LPVOID lpBits;
|
|
struct {
|
|
BITMAPINFOHEADER bi;
|
|
DWORD ct[256];
|
|
} dib;
|
|
|
|
dib.bi.biSize = sizeof(BITMAPINFOHEADER);
|
|
dib.bi.biWidth = pSize->cx;
|
|
dib.bi.biHeight = pSize->cy;
|
|
dib.bi.biPlanes = 1;
|
|
dib.bi.biBitCount = (WORD) m_dwClrDepth;
|
|
dib.bi.biCompression = BI_RGB;
|
|
dib.bi.biSizeImage = 0;
|
|
dib.bi.biXPelsPerMeter = 0;
|
|
dib.bi.biYPelsPerMeter = 0;
|
|
dib.bi.biClrUsed = ( m_dwClrDepth <= 8 ) ? (1 << m_dwClrDepth) : 0;
|
|
dib.bi.biClrImportant = 0;
|
|
|
|
if ( m_dwClrDepth <= 8 )
|
|
{
|
|
HPALETTE hpal = NULL;
|
|
// need to get the right palette....
|
|
hr = pIImgCtx->GetPalette( & hpal );
|
|
if ( SUCCEEDED( hr ) && hpal )
|
|
{
|
|
GetPaletteEntries(hpal, 0, 256, (LPPALETTEENTRY)&dib.ct[0]);
|
|
for (int i = 0; i < (int)dib.bi.biClrUsed; i ++)
|
|
dib.ct[i] = RGB(GetBValue(dib.ct[i]),GetGValue(dib.ct[i]),GetRValue(dib.ct[i]));
|
|
}
|
|
}
|
|
|
|
*phBmp = CreateDIBSection(hdcDst, (LPBITMAPINFO)&dib, DIB_RGB_COLORS, &lpBits, NULL, 0);
|
|
|
|
HBITMAP hOld = (HBITMAP) SelectObject( hdcDst, *phBmp );
|
|
if (*phBmp && hOld)
|
|
{
|
|
RECT rc;
|
|
rc.top = rc.left = 0;
|
|
rc.bottom = pSize->cy;
|
|
rc.right = pSize->cx;
|
|
|
|
// black background...
|
|
HBRUSH hbr = (HBRUSH) GetStockObject( BLACK_BRUSH );
|
|
|
|
FillRect( hdcDst, &rc, hbr );
|
|
DeleteObject( hbr );
|
|
|
|
if (pIImgCtx)
|
|
{
|
|
hr = StretchBltCustomImage(pIImgCtx, pSize, hdcDst);
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL; //StretchBltDefaultImage(pSize, hdcDst);
|
|
}
|
|
SelectObject( hdcDst, hOld );
|
|
}
|
|
|
|
DeleteDC(hdcDst);
|
|
}
|
|
|
|
ReleaseDC(NULL, hdcScreen);
|
|
}
|
|
|
|
ASSERT((SUCCEEDED(hr) && *phBmp) || FAILED(hr));
|
|
|
|
return hr;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::StretchBltCustomImage ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Stretches the image associated with IImgCtx to the given size and places
|
|
// the result in the given DC.
|
|
//
|
|
// Parameters:
|
|
// [In] pIImgCtx - The image context for the image.
|
|
// [In] pSize - The size of the resultant image.
|
|
// [In/Out] hdcDst - The destination DC of the stretch blt.
|
|
//
|
|
// Return:
|
|
// S_OK if the image was successfully resized into the destination DC.
|
|
// E_FAIL otherwise.
|
|
//
|
|
// Comments:
|
|
// The destination DC already a bitmap of pSize selected into it.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CIconHandler::StretchBltCustomImage(
|
|
IImgCtx* pIImgCtx,
|
|
const SIZE* pSize,
|
|
HDC hdcDst
|
|
)
|
|
{
|
|
ASSERT(pIImgCtx);
|
|
ASSERT(hdcDst);
|
|
|
|
HRESULT hr;
|
|
|
|
SIZE sz;
|
|
ULONG fState;
|
|
|
|
hr = pIImgCtx->GetStateInfo(&fState, &sz, FALSE);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
HPALETTE hpal = NULL;
|
|
HPALETTE hpalOld;
|
|
|
|
hr = pIImgCtx->GetPalette( &hpal );
|
|
if (hpal)
|
|
{
|
|
hpalOld = SelectPalette( hdcDst, hpal, TRUE );
|
|
RealizePalette( hdcDst );
|
|
}
|
|
|
|
if (UseWideLogo(pSize->cx) && NULL == m_bstrImageWideURL)
|
|
{
|
|
hr = pIImgCtx->StretchBlt(hdcDst, 0, 0, LOGO_WIDTH, pSize->cy, 0, 0,
|
|
sz.cx, sz.cy, SRCCOPY);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Color fill the logo.
|
|
//
|
|
|
|
COLORREF clr = GetPixel(hdcDst, 0, 0);
|
|
|
|
if (m_dwClrDepth <= 8)
|
|
clr = PALETTEINDEX(GetNearestPaletteIndex(hpal, clr));
|
|
|
|
HBRUSH hbr = CreateSolidBrush(clr);
|
|
|
|
if (hbr)
|
|
{
|
|
RECT rc;
|
|
|
|
rc.top = 0;
|
|
rc.bottom = pSize->cy;
|
|
rc.left = LOGO_WIDTH;
|
|
rc.right = pSize->cx;
|
|
|
|
FillRect(hdcDst, &rc, hbr);
|
|
|
|
DeleteObject(hbr);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = pIImgCtx->StretchBlt(hdcDst, 0, 0, pSize->cx, pSize->cy, 0, 0,
|
|
sz.cx, sz.cy, SRCCOPY);
|
|
}
|
|
|
|
if (SUCCEEDED(hr) && m_fDrawGleam)
|
|
DrawGleam(hdcDst);
|
|
|
|
if ( hpal )
|
|
{
|
|
SelectPalette( hdcDst, hpalOld, TRUE );
|
|
RealizePalette( hdcDst );
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::StretchBltDefaultImage ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Stretches the deafult channel image to fit the requested size.
|
|
//
|
|
// Parameters:
|
|
// [In] pSize - The requested size of the image.
|
|
// [In/Out] hdcDest - The destination DC for the resized image.
|
|
//
|
|
// Return:
|
|
// S_OK if the image is successfully resized into the destination DC.
|
|
// E_FAIL otherwise.
|
|
//
|
|
// Comments:
|
|
// This function creates a source DC, copies the deafult bitmap into the
|
|
// the source DC, then strch blts the source DC into the destination DC.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/*HRESULT
|
|
CIconHandler::StretchBltDefaultImage(
|
|
const SIZE* pSize,
|
|
HDC hdcDst
|
|
)
|
|
{
|
|
ASSERT(hdcDst);
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
HBITMAP hBmp = LoadBitmap(g_hinst, MAKEINTRESOURCE(IDB_DEFAULT));
|
|
|
|
if (hBmp)
|
|
{
|
|
HDC hdcSrc = CreateCompatibleDC(NULL);
|
|
|
|
if (hdcSrc && SelectObject(hdcSrc, hBmp))
|
|
{
|
|
BITMAP bmp;
|
|
|
|
if (GetObject(hBmp, sizeof(BITMAP), (void*)&bmp))
|
|
{
|
|
if (StretchBlt(hdcDst, 0, 0, pSize->cx, pSize->cy,
|
|
hdcSrc, 0, 0, bmp.bmWidth, bmp.bmHeight,
|
|
SRCCOPY))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
DeleteDC(hdcSrc);
|
|
}
|
|
|
|
DeleteObject(hBmp);
|
|
}
|
|
|
|
return hr;
|
|
}*/
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::DrawGleam ***
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return:
|
|
//
|
|
// Comments:
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CIconHandler::DrawGleam(
|
|
HDC hdcDst
|
|
)
|
|
{
|
|
ASSERT(hdcDst)
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
HICON hGleam = (HICON)LoadImage(g_hinst, TEXT("LOGOGLEAM"),
|
|
IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
|
|
|
|
if (hGleam)
|
|
{
|
|
if (DrawIcon(hdcDst, 1, 1, hGleam))
|
|
hr = S_OK;
|
|
|
|
DestroyIcon(hGleam);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::SynchronousDownload ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Synchronously downloads the image associated with the image context.
|
|
//
|
|
// Parameters:
|
|
// [In] pIImgCtx - A pointer to the image context.
|
|
//
|
|
// Return:
|
|
// S_OK if the image was successfully downloaded.
|
|
// E_FAIL if the image wasn't downloaded.
|
|
//
|
|
// Comments:
|
|
// The image context object doesn't directly support synchronous download.
|
|
// Here a message loop is used to make sure ulrmon keeps geeting messages
|
|
// and the download progresses.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CIconHandler::SynchronousDownload(
|
|
IImgCtx* pIImgCtx,
|
|
LPCWSTR pwszURL
|
|
)
|
|
{
|
|
ASSERT(pIImgCtx);
|
|
|
|
HRESULT hr;
|
|
|
|
TCHAR szLocalFile[MAX_PATH];
|
|
TCHAR szURL[INTERNET_MAX_URL_LENGTH];
|
|
|
|
SHUnicodeToTChar(pwszURL, szURL, ARRAYSIZE(szURL));
|
|
|
|
hr = URLGetLocalFileName(szURL, szLocalFile, ARRAYSIZE(szLocalFile), NULL);
|
|
|
|
TraceMsg(TF_GLEAM, "%c Logo Extract %s", m_fDrawGleam ? '+' : '-',
|
|
szLocalFile);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
TraceMsg(TF_CDFLOGO, "[URLGetLocalFileName %s]", szLocalFile);
|
|
|
|
#ifdef UNIX
|
|
unixEnsureFileScheme(szLocalFile);
|
|
#endif /* UNIX */
|
|
|
|
WCHAR szLocalFileW[MAX_PATH];
|
|
|
|
SHTCharToUnicode(szLocalFile, szLocalFileW, ARRAYSIZE(szLocalFileW));
|
|
|
|
hr = pIImgCtx->Load(szLocalFileW, 0);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ULONG fState;
|
|
SIZE sz;
|
|
|
|
pIImgCtx->GetStateInfo(&fState, &sz, TRUE);
|
|
|
|
if (!(fState & (IMGLOAD_COMPLETE | IMGLOAD_ERROR)))
|
|
{
|
|
m_fDone = FALSE;
|
|
|
|
hr = pIImgCtx->SetCallback(ImgCtx_Callback, &m_fDone);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pIImgCtx->SelectChanges(IMGCHG_COMPLETE, 0, TRUE);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
MSG msg;
|
|
BOOL fMsg;
|
|
|
|
// HACK: restrict the message pump to those messages we know that URLMON and
|
|
// HACK: the imageCtx stuff needs, otherwise we will be pumping messages for
|
|
// HACK: windows we shouldn't be pumping right now...
|
|
while(!m_fDone )
|
|
{
|
|
fMsg = PeekMessage(&msg, NULL, WM_USER + 1, WM_USER + 4, PM_REMOVE );
|
|
|
|
if (!fMsg)
|
|
{
|
|
fMsg = PeekMessage( &msg, NULL, WM_APP + 2, WM_APP + 2, PM_REMOVE );
|
|
}
|
|
|
|
if (!fMsg)
|
|
{
|
|
// go to sleep until we get a new message....
|
|
WaitMessage();
|
|
continue;
|
|
}
|
|
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
pIImgCtx->Disconnect();
|
|
}
|
|
|
|
hr = pIImgCtx->GetStateInfo(&fState, &sz, TRUE);
|
|
|
|
if (SUCCEEDED(hr))
|
|
hr = (fState & IMGLOAD_COMPLETE) ? S_OK : E_FAIL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TraceMsg(TF_CDFLOGO, "[URLGetLocalFileName %s FAILED]",szURL);
|
|
}
|
|
|
|
TraceMsg(TF_CDFPARSE, "[IImgCtx downloading logo %s %s]", szLocalFile,
|
|
SUCCEEDED(hr) ? TEXT("SUCCEEDED") : TEXT("FAILED"));
|
|
TraceMsg(TF_CDFLOGO, "[IImgCtx downloading logo %s %s]", szLocalFile,
|
|
SUCCEEDED(hr) ? TEXT("SUCCEEDED") : TEXT("FAILED"));
|
|
|
|
return hr;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::Run ***
|
|
//
|
|
// IRunnableTask method.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CIconHandler::Run(
|
|
void
|
|
)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::Kill ***
|
|
//
|
|
// IRunnableTask method.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CIconHandler::Kill(
|
|
BOOL fWait
|
|
)
|
|
{
|
|
m_fDone = TRUE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::Suspend ***
|
|
//
|
|
// IRunnableTask method.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CIconHandler::Suspend(
|
|
void
|
|
)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::Resume ***
|
|
//
|
|
// IRunnableTask method.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CIconHandler::Resume(
|
|
void
|
|
)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CIconHandler::IsRunning ***
|
|
//
|
|
// IRunnableTask method.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_(ULONG)
|
|
CIconHandler::IsRunning(
|
|
void
|
|
)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|