256 lines
6.3 KiB
C++
256 lines
6.3 KiB
C++
|
/*****************************************************************************
|
||
|
*
|
||
|
* ftpicon.cpp - IExtractIcon interface
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#include "priv.h"
|
||
|
#include "ftpicon.h"
|
||
|
#include "ftpurl.h"
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
INT GetFtpIcon(UINT uFlags, BOOL fIsRoot)
|
||
|
{
|
||
|
INT nIcon = (uFlags & GIL_OPENICON) ? IDI_FTPOPENFOLDER : IDI_FTPFOLDER;
|
||
|
|
||
|
if (fIsRoot)
|
||
|
nIcon = IDI_FTPSERVER; // This is an FTP Server Icon.
|
||
|
|
||
|
return nIcon;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
#ifndef UNICODE
|
||
|
#define PathFindExtensionA PathFindExtension
|
||
|
#endif
|
||
|
|
||
|
//===========================
|
||
|
// *** IExtractIconA Interface ***
|
||
|
//===========================
|
||
|
|
||
|
/*****************************************************************************\
|
||
|
FUNCTION: GetIconLocation
|
||
|
|
||
|
DESCRIPTION:
|
||
|
Get the icon location from the registry.
|
||
|
|
||
|
_UNDOCUMENTED_: Not mentioned is that if you return GIL_NOTFILENAME,
|
||
|
you should take steps to ensure uniqueness of the non-filename
|
||
|
return value, to avoid colliding with non-filenames from other
|
||
|
shell extensions.
|
||
|
|
||
|
_UNDOCUMENTED_: The inability of SHGetFileInfo to work properly
|
||
|
on "magic internal" cached association icons like "*23" is not
|
||
|
documented. As a result of this "feature", the SHGFI_ICONLOCATION
|
||
|
flag is useless.
|
||
|
|
||
|
|
||
|
Actually, we can still use SHGetFileInfo; we'll use the shell's own
|
||
|
feature against it. We'll do a SHGFI_SYSICONINDEX and return that
|
||
|
as the icon index, with "*" as the GIL_NOTFILENAME.
|
||
|
|
||
|
|
||
|
We don't handle the cases where we ought to use GIL_SIMULATEDOC.
|
||
|
\*****************************************************************************/
|
||
|
HRESULT CFtpIcon::GetIconLocation(UINT uFlags, LPSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags)
|
||
|
{
|
||
|
static CHAR szMSIEFTP[MAX_PATH] = "";
|
||
|
|
||
|
if (0 == szMSIEFTP[0])
|
||
|
GetModuleFileNameA(HINST_THISDLL, szMSIEFTP, ARRAYSIZE(szMSIEFTP));
|
||
|
|
||
|
// NOTE: This is negative because it's a resource index.
|
||
|
*piIndex = (0 - GetFtpIcon(uFlags, m_nRoot));
|
||
|
|
||
|
if (pwFlags)
|
||
|
*pwFlags = GIL_PERCLASS; //(uFlags & GIL_OPENICON);
|
||
|
|
||
|
StrCpyNA(szIconFile, szMSIEFTP, cchMax);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
//===========================
|
||
|
// *** IExtractIconW Interface ***
|
||
|
//===========================
|
||
|
HRESULT CFtpIcon::GetIconLocation(UINT uFlags, LPWSTR wzIconFile, UINT cchMax, int *piIndex, UINT *pwFlags)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
CHAR szIconFile[MAX_PATH];
|
||
|
|
||
|
ASSERT_SINGLE_THREADED;
|
||
|
hres = GetIconLocation(uFlags, szIconFile, ARRAYSIZE(szIconFile), piIndex, pwFlags);
|
||
|
if (EVAL(SUCCEEDED(hres)))
|
||
|
SHAnsiToUnicode(szIconFile, wzIconFile, cchMax);
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
//===========================
|
||
|
// *** IQueryInfo Interface ***
|
||
|
//===========================
|
||
|
HRESULT CFtpIcon::GetInfoTip(DWORD dwFlags, WCHAR **ppwszTip)
|
||
|
{
|
||
|
ASSERT_SINGLE_THREADED;
|
||
|
if (ppwszTip) // The shell doesn't check the return value
|
||
|
*ppwszTip = NULL; // so we always have to NULL the output pointer.
|
||
|
|
||
|
// SHStrDupW(L"", ppwszTip);
|
||
|
|
||
|
return E_NOTIMPL;
|
||
|
|
||
|
/**************
|
||
|
// This InfoTip will appear when the user hovers over an item in defview.
|
||
|
// We don't want to support this now because it isn't needed and looks different
|
||
|
// than the shell.
|
||
|
|
||
|
HRESULT hr = E_FAIL;
|
||
|
LPITEMIDLIST pidl;
|
||
|
|
||
|
if (!ppwszTip)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
*ppwszTip = NULL;
|
||
|
if (m_pflHfpl && (pidl = m_pflHfpl->GetPidl(0)))
|
||
|
{
|
||
|
WCHAR wzToolTip[MAX_URL_STRING];
|
||
|
|
||
|
hr = FtpPidl_GetDisplayName(pidl, wzItemName, ARRAYSIZE(wzItemName));
|
||
|
if (EVAL(SUCCEEDED(hr)))
|
||
|
hr = SHStrDupW(wzToolTip, ppwszTip);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
***********/
|
||
|
}
|
||
|
|
||
|
HRESULT CFtpIcon::GetInfoFlags(DWORD *pdwFlags)
|
||
|
{
|
||
|
*pdwFlags = 0;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* CFtpIcon_Create
|
||
|
*
|
||
|
* We just stash away the pflHfpl; the real work happens on the
|
||
|
* GetIconLocation call.
|
||
|
*
|
||
|
* _HACKHACK_: psf = 0 if we are being called by the property sheet code.
|
||
|
*****************************************************************************/
|
||
|
HRESULT CFtpIcon_Create(CFtpFolder * pff, CFtpPidlList * pflHfpl, REFIID riid, LPVOID * ppvObj)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
CFtpIcon * pfi;
|
||
|
|
||
|
*ppvObj = NULL;
|
||
|
|
||
|
hres = CFtpIcon_Create(pff, pflHfpl, &pfi);
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
hres = pfi->QueryInterface(riid, ppvObj);
|
||
|
pfi->Release();
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* CFtpIcon_Create
|
||
|
*
|
||
|
* We just stash away the m_pflHfpl; the real work happens on the
|
||
|
* GetIconLocation call.
|
||
|
*
|
||
|
* _HACKHACK_: psf = 0 if we are being called by the property sheet code.
|
||
|
*****************************************************************************/
|
||
|
HRESULT CFtpIcon_Create(CFtpFolder * pff, CFtpPidlList * pflHfpl, CFtpIcon ** ppfi)
|
||
|
{
|
||
|
HRESULT hres= E_OUTOFMEMORY;
|
||
|
|
||
|
*ppfi = new CFtpIcon();
|
||
|
if (*ppfi)
|
||
|
{
|
||
|
IUnknown_Set(&(*ppfi)->m_pflHfpl, pflHfpl);
|
||
|
if (pff && pff->IsRoot())
|
||
|
{
|
||
|
(*ppfi)->m_nRoot++;
|
||
|
}
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************\
|
||
|
Constructor
|
||
|
\****************************************************/
|
||
|
CFtpIcon::CFtpIcon() : m_cRef(1)
|
||
|
{
|
||
|
DllAddRef();
|
||
|
|
||
|
// This needs to be allocated in Zero Inited Memory.
|
||
|
// Assert that all Member Variables are inited to Zero.
|
||
|
ASSERT(!m_pflHfpl);
|
||
|
ASSERT(!m_nRoot);
|
||
|
|
||
|
INIT_SINGLE_THREADED_ASSERT;
|
||
|
LEAK_ADDREF(LEAK_CFtpIcon);
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************\
|
||
|
Destructor
|
||
|
\****************************************************/
|
||
|
CFtpIcon::~CFtpIcon()
|
||
|
{
|
||
|
ATOMICRELEASE(m_pflHfpl);
|
||
|
|
||
|
DllRelease();
|
||
|
LEAK_DELREF(LEAK_CFtpIcon);
|
||
|
}
|
||
|
|
||
|
|
||
|
//===========================
|
||
|
// *** IUnknown Interface ***
|
||
|
//===========================
|
||
|
|
||
|
ULONG CFtpIcon::AddRef()
|
||
|
{
|
||
|
m_cRef++;
|
||
|
return m_cRef;
|
||
|
}
|
||
|
|
||
|
ULONG CFtpIcon::Release()
|
||
|
{
|
||
|
ASSERT(m_cRef > 0);
|
||
|
m_cRef--;
|
||
|
|
||
|
if (m_cRef > 0)
|
||
|
return m_cRef;
|
||
|
|
||
|
delete this;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
HRESULT CFtpIcon::QueryInterface(REFIID riid, void **ppvObj)
|
||
|
{
|
||
|
static const QITAB qit[] = {
|
||
|
QITABENT(CFtpIcon, IExtractIconW),
|
||
|
QITABENT(CFtpIcon, IExtractIconA),
|
||
|
QITABENT(CFtpIcon, IQueryInfo),
|
||
|
{ 0 },
|
||
|
};
|
||
|
|
||
|
return QISearch(this, qit, riid, ppvObj);
|
||
|
}
|