windows-nt/Source/XPSP1/NT/shell/ext/ftp/ftpicon.cpp

256 lines
6.3 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*****************************************************************************
*
* 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);
}