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