windows-nt/Source/XPSP1/NT/shell/ext/ftp/ftpefe.cpp
2020-09-26 16:20:57 +08:00

372 lines
9.7 KiB
C++

/*****************************************************************************
*
* ftpefe.cpp - IEnumFORMATETC interface
*
*****************************************************************************/
#include "priv.h"
#include "ftpefe.h"
#include "ftpobj.h"
/*****************************************************************************
* CFtpEfe::_NextOne
*****************************************************************************/
HRESULT CFtpEfe::_NextOne(FORMATETC * pfetc)
{
HRESULT hr = S_FALSE;
while (ShouldSkipDropFormat(m_dwIndex))
m_dwIndex++;
ASSERT(m_hdsaFormatEtc);
if (m_dwIndex < (DWORD) DSA_GetItemCount(m_hdsaFormatEtc))
{
DSA_GetItem(m_hdsaFormatEtc, m_dwIndex, (LPVOID) pfetc);
m_dwIndex++; // We are off to the next one
hr = S_OK;
}
if ((S_OK != hr) && m_pfo)
{
// We finished looking thru the types supported by the IDataObject.
// Now look for other items inserted by IDataObject::SetData()
if (m_dwExtraIndex < (DWORD) DSA_GetItemCount(m_pfo->m_hdsaSetData))
{
FORMATETC_STGMEDIUM fs;
DSA_GetItem(m_pfo->m_hdsaSetData, m_dwExtraIndex, (LPVOID) &fs);
*pfetc = fs.formatEtc;
m_dwExtraIndex++; // We are off to the next one
hr = S_OK;
}
}
return hr;
}
//===========================
// *** IEnumFORMATETC Interface ***
//===========================
/*****************************************************************************
*
* IEnumFORMATETC::Next
*
* Creates a brand new enumerator based on an existing one.
*
*
* OLE random documentation of the day: IEnumXXX::Next.
*
* rgelt - Receives an array of size celt (or larger).
*
* "Receives an array"? No, it doesn't receive an array.
* It *is* an array. The array receives *elements*.
*
* "Or larger"? Does this mean I can return more than the caller
* asked for? No, of course not, because the caller didn't allocate
* enough memory to hold that many return values.
*
* No semantics are assigned to the possibility of celt = 0.
* Since I am a mathematician, I treat it as vacuous success.
*
* pcelt is documented as an INOUT parameter, but no semantics
* are assigned to its input value.
*
* The dox don't say that you are allowed to return *pcelt < celt
* for reasons other than "no more elements", but the shell does
* it everywhere, so maybe it's legal...
*
*****************************************************************************/
HRESULT CFtpEfe::Next(ULONG celt, FORMATETC * rgelt, ULONG *pceltFetched)
{
HRESULT hres = S_FALSE;
DWORD dwIndex;
// Do they want more and do we have more to give?
for (dwIndex = 0; dwIndex < celt; dwIndex++)
{
if (S_FALSE == _NextOne(&rgelt[dwIndex])) // Yes, so give away...
break;
ASSERT(NULL == rgelt[dwIndex].ptd); // We don't do this correctly.
#ifdef DEBUG
char szName[MAX_PATH];
GetCfBufA(rgelt[dwIndex].cfFormat, szName, ARRAYSIZE(szName));
//TraceMsg(TF_FTP_IDENUM, "CFtpEfe::Next() - Returning %hs", szName);
#endif // DEBUG
}
if (pceltFetched)
*pceltFetched = dwIndex;
// Were we able to give any?
if ((0 != dwIndex) || (0 == celt))
hres = S_OK;
return hres;
}
/*****************************************************************************
* IEnumFORMATETC::Skip
*****************************************************************************/
HRESULT CFtpEfe::Skip(ULONG celt)
{
m_dwIndex += celt;
return S_OK;
}
/*****************************************************************************
* IEnumFORMATETC::Reset
*****************************************************************************/
HRESULT CFtpEfe::Reset(void)
{
m_dwIndex = 0;
return S_OK;
}
/*****************************************************************************
*
* IEnumFORMATETC::Clone
*
* Creates a brand new enumerator based on an existing one.
*
*****************************************************************************/
HRESULT CFtpEfe::Clone(IEnumFORMATETC **ppenum)
{
return CFtpEfe_Create((DWORD) DSA_GetItemCount(m_hdsaFormatEtc), m_hdsaFormatEtc, m_dwIndex, m_pfo, ppenum);
}
/*****************************************************************************
*
* CFtpEfe_Create
*
* Creates a brand new enumerator based on a list of possibilities.
*
* Note that we are EVIL and know about CFSTR_FILECONTENTS here:
* A FORMATETC of FileContents is always valid. This is important,
* because CFtpObj doesn't actually have a STGMEDIUM for file contents.
* (Due to lindex weirdness.)
*
*****************************************************************************/
HRESULT CFtpEfe_Create(DWORD dwSize, FORMATETC rgfe[], STGMEDIUM rgstg[], CFtpObj * pfo, CFtpEfe ** ppfefe)
{
CFtpEfe * pfefe;
HRESULT hres = E_OUTOFMEMORY;
pfefe = *ppfefe = new CFtpEfe(dwSize, rgfe, rgstg, pfo);
if (pfefe)
{
if (!pfefe->m_hdsaFormatEtc)
pfefe->Release();
else
hres = S_OK;
}
if (FAILED(hres) && pfefe)
IUnknown_Set(ppfefe, NULL);
return hres;
}
/*****************************************************************************
*
* CFtpEfe_Create
*
* Creates a brand new enumerator based on a list of possibilities.
*
* Note that we are EVIL and know about CFSTR_FILECONTENTS here:
* A FORMATETC of FileContents is always valid. This is important,
* because CFtpObj doesn't actually have a STGMEDIUM for file contents.
* (Due to lindex weirdness.)
*
*****************************************************************************/
HRESULT CFtpEfe_Create(DWORD dwSize, FORMATETC rgfe[], STGMEDIUM rgstg[], CFtpObj * pfo, IEnumFORMATETC ** ppenum)
{
CFtpEfe * pfefe;
HRESULT hres = CFtpEfe_Create(dwSize, rgfe, rgstg, pfo, &pfefe);
if (pfefe)
{
hres = pfefe->QueryInterface(IID_IEnumFORMATETC, (LPVOID *) ppenum);
pfefe->Release();
}
return hres;
}
/*****************************************************************************
*
* CFtpEfe_Create
*****************************************************************************/
HRESULT CFtpEfe_Create(DWORD dwSize, HDSA m_hdsaFormatEtc, DWORD dwIndex, CFtpObj * pfo, IEnumFORMATETC ** ppenum)
{
CFtpEfe * pfefe;
HRESULT hres = E_OUTOFMEMORY;
pfefe = new CFtpEfe(dwSize, m_hdsaFormatEtc, pfo, dwIndex);
if (pfefe)
{
hres = pfefe->QueryInterface(IID_IEnumFORMATETC, (LPVOID *) ppenum);
pfefe->Release();
}
return hres;
}
/****************************************************\
Constructor
\****************************************************/
CFtpEfe::CFtpEfe(DWORD dwSize, FORMATETC rgfe[], STGMEDIUM rgstg[], CFtpObj * pfo) : m_cRef(1)
{
DllAddRef();
// This needs to be allocated in Zero Inited Memory.
// Assert that all Member Variables are inited to Zero.
ASSERT(!m_dwIndex);
ASSERT(!m_hdsaFormatEtc);
ASSERT(!m_pfo);
m_hdsaFormatEtc = DSA_Create(sizeof(rgfe[0]), 10);
if (m_hdsaFormatEtc)
{
DWORD dwIndex;
for (dwIndex = 0; dwIndex < dwSize; dwIndex++)
{
#ifdef DEBUG
char szNameDebug[MAX_PATH];
GetCfBufA(rgfe[dwIndex].cfFormat, szNameDebug, ARRAYSIZE(szNameDebug));
#endif // DEBUG
if (rgfe[dwIndex].tymed == TYMED_ISTREAM ||
(rgstg && rgfe[dwIndex].tymed == rgstg[dwIndex].tymed))
{
#ifdef DEBUG
//TraceMsg(TF_FTP_IDENUM, "CFtpEfe() Keeping %hs", szNameDebug);
#endif // DEBUG
DSA_SetItem(m_hdsaFormatEtc, dwIndex, &rgfe[dwIndex]);
}
else
{
#ifdef DEBUG
//TraceMsg(TF_FTP_IDENUM, "CFtpEfe() Ignoring %hs", szNameDebug);
#endif // DEBUG
}
}
}
if (pfo)
{
m_pfo = pfo;
m_pfo->AddRef();
}
LEAK_ADDREF(LEAK_CFtpEfe);
}
/****************************************************\
Constructor
\****************************************************/
CFtpEfe::CFtpEfe(DWORD dwSize, HDSA hdsaFormatEtc, CFtpObj * pfo, DWORD dwIndex) : m_cRef(1)
{
DllAddRef();
// This needs to be allocated in Zero Inited Memory.
// Assert that all Member Variables are inited to Zero.
ASSERT(!m_dwIndex);
ASSERT(!m_hdsaFormatEtc);
ASSERT(!m_pfo);
ASSERT(hdsaFormatEtc);
m_hdsaFormatEtc = DSA_Create(sizeof(FORMATETC), 10);
if (m_hdsaFormatEtc)
{
for (dwIndex = 0; dwIndex < (DWORD) DSA_GetItemCount(hdsaFormatEtc); dwIndex++)
{
DSA_SetItem(m_hdsaFormatEtc, dwIndex, DSA_GetItemPtr(hdsaFormatEtc, dwIndex));
}
}
if (pfo)
{
m_pfo = pfo;
m_pfo->AddRef();
}
LEAK_ADDREF(LEAK_CFtpEfe);
}
/****************************************************\
Destructor
\****************************************************/
CFtpEfe::~CFtpEfe()
{
DSA_Destroy(m_hdsaFormatEtc);
if (m_pfo)
m_pfo->Release();
DllRelease();
LEAK_DELREF(LEAK_CFtpEfe);
}
//===========================
// *** IUnknown Interface ***
//===========================
ULONG CFtpEfe::AddRef()
{
m_cRef++;
return m_cRef;
}
ULONG CFtpEfe::Release()
{
ASSERT(m_cRef > 0);
m_cRef--;
if (m_cRef > 0)
return m_cRef;
delete this;
return 0;
}
HRESULT CFtpEfe::QueryInterface(REFIID riid, void **ppvObj)
{
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IEnumFORMATETC))
{
*ppvObj = SAFECAST(this, IEnumFORMATETC*);
}
else
{
TraceMsg(TF_FTPQI, "CFtpEfe::QueryInterface() failed.");
*ppvObj = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}