/***************************************************************************** * * 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); }