|
|
//+---------------------------------------------------------------------
//
// File: stdenum.cxx
//
// Contents: Standard implementations of common enumerators
//
//----------------------------------------------------------------------
#include "headers.hxx"
#pragma hdrstop
#include <limits.h> // for UINT_MAX below
//
// forward declarations
//
class StdEnumOLEVERB; typedef StdEnumOLEVERB FAR* LPSTDENUMOLEVERB;
class StdEnumFORMATETC; typedef StdEnumFORMATETC FAR* LPSTDENUMFORMATETC;
#if 1
class StdStaticEnum; typedef StdStaticEnum FAR* LPSTDSTATICENUM; #endif // 0
//+---------------------------------------------------------------
//
// Class: StdEnumOLEVERB
//
// Purpose: Standard enumerator of OLEVERB tables
//
//---------------------------------------------------------------
class StdEnumOLEVERB: public IEnumOLEVERB { friend HRESULT CreateOLEVERBEnum(LPOLEVERB, ULONG, LPENUMOLEVERB FAR*);
public: DECLARE_STANDARD_IUNKNOWN(StdEnumOLEVERB);
// *** IEnumOLEVERB methods ***
STDMETHOD(Next) (ULONG celt, LPOLEVERB rgelt, ULONG FAR* pceltFetched); STDMETHOD(Skip) (ULONG celt); STDMETHOD(Reset) (void); STDMETHOD(Clone) (IEnumOLEVERB FAR* FAR* ppenm);
private: StdEnumOLEVERB(LPOLEVERB pStart, ULONG cCount); ~StdEnumOLEVERB(void);
LPOLEVERB _pStart; ULONG _cCount; ULONG _cCurrent; };
//+---------------------------------------------------------------
//
// Member: StdEnumOLEVERB::StdEnumOLEVERB, private
//
// Synopsis: Constructor for StdEnumOLEVERB objects
//
// Arguments: [pStart] -- pointer to the beginning of the OLEVERB array
// [cCount] -- the number of elements in the array
//
// Notes: OLEVERB enumerators should be constructed using the
// CreateOLEVERBEnum function.
//
//----------------------------------------------------------------
StdEnumOLEVERB::StdEnumOLEVERB(LPOLEVERB pStart, ULONG cCount) { _ulRefs = 1; _pStart = pStart; _cCount = cCount; _cCurrent = 0; DOUT(TEXT("StdEnumOLEVERB constructed.\r\n")); }
//+---------------------------------------------------------------
//
// Member: StdEnumOLEVERB::~StdEnumOLEVERB, private
//
// Synopsis: Destructor for StdEnumOLEVERB objects
//
// Notes: Static enumerators should never be `deleted' but
// instead IUnknown::Release'd.
//
//----------------------------------------------------------------
StdEnumOLEVERB::~StdEnumOLEVERB(void) { DOUT(TEXT("StdEnumOLEVERB destructed.\r\n")); }
IMPLEMENT_STANDARD_IUNKNOWN(StdEnumOLEVERB)
//+---------------------------------------------------------------
//
// Member: StdEnumOLEVERB::QueryInterface, public
//
// Synopsis: Method of IUnknown interface
//
//----------------------------------------------------------------
STDMETHODIMP StdEnumOLEVERB::QueryInterface(REFIID riid, LPVOID FAR* ppvObj) { if (IsEqualIID(riid,IID_IUnknown) || IsEqualIID(riid,IID_IEnumOLEVERB)) { *ppvObj = this; AddRef(); return NOERROR; } DOUT(TEXT("StdEnumOLEVERB::QueryInterface E_NOINTERFACE\r\n")); *ppvObj = NULL; return E_NOINTERFACE; }
//+---------------------------------------------------------------
//
// Member: StdEnumOLEVERB::Next
//
// Synopsis: Member of IEnumXXX interface
//
//----------------------------------------------------------------
STDMETHODIMP StdEnumOLEVERB::Next(ULONG celt, LPOLEVERB pArrayObjs, ULONG FAR* pceltFetched) { /* skip ahead to primary verb */ for (;_cCurrent <= _cCount; _cCurrent++) { LPOLEVERB pVerb = &_pStart[_cCurrent]; if (pVerb->lVerb >= OLEIVERB_PRIMARY) break; }
ULONG celtFetched = min(celt, _cCount-_cCurrent); for (ULONG i = 0; i < celtFetched; i++, _cCurrent++) { LPOLEVERB pVerb = &_pStart[_cCurrent];
pArrayObjs[i] = *pVerb; if (pVerb->lpszVerbName!=NULL) { HRESULT r; r = TaskAllocString(pVerb->lpszVerbName, &pArrayObjs[i].lpszVerbName); if (!OK(r)) return r; } }
if (pceltFetched != NULL) { *pceltFetched = celtFetched; }
return ((celtFetched == celt) ? NOERROR : S_FALSE); }
//+---------------------------------------------------------------
//
// Member: StdEnumOLEVERB::Skip
//
// Synopsis: Member of IEnumXXX interface
//
//----------------------------------------------------------------
STDMETHODIMP StdEnumOLEVERB::Skip(ULONG celt) { _cCurrent += celt; if (_cCurrent >= _cCount) { _cCurrent = _cCount; return S_FALSE; } return NOERROR; }
//+---------------------------------------------------------------
//
// Member: StdEnumOLEVERB::Reset
//
// Synopsis: Member of IEnumXXX interface
//
//----------------------------------------------------------------
STDMETHODIMP StdEnumOLEVERB::Reset(void) { _cCurrent = 0; return NOERROR; }
//+---------------------------------------------------------------
//
// Member: StdEnumOLEVERB::Clone
//
// Synopsis: Member of IEnumXXX interface
//
//----------------------------------------------------------------
STDMETHODIMP StdEnumOLEVERB::Clone(LPENUMOLEVERB FAR* ppenm) { HRESULT r = E_OUTOFMEMORY; //LPSTDENUMOLEVERB penum = new (NullOnFail) StdEnumOLEVERB(_pStart, _cCount);
LPSTDENUMOLEVERB penum = new StdEnumOLEVERB(_pStart, _cCount); if (penum != NULL) { r = NOERROR; penum->_cCurrent = _cCurrent; *ppenm = penum; } else { DOUT(TEXT("o2base/StdEnumOLEVERB::Clone failed\r\n")); } return r; }
//+---------------------------------------------------------------
//
// Function: CreateOLEVERBEnum, public
//
// Synopsis: Creates a standard enumerator over OLEVERB arrays
//
// Arguments: [pVerbs] -- pointer to the beginning of the OLEVERB array
// [cVerbs] -- the number of elements in the array
// [ppenum] -- where the enumerator is returned
//
// Returns: Success if the enumerator could be successfully created
//
// Notes: This function is typically used in the IOleObject::EnumVerbs
// method implementation.
//
//----------------------------------------------------------------
HRESULT CreateOLEVERBEnum(LPOLEVERB pVerbs, ULONG cVerbs, LPENUMOLEVERB FAR* ppenum) { HRESULT r = E_OUTOFMEMORY; //LPSTDENUMOLEVERB penum = new (NullOnFail) StdEnumOLEVERB(pVerbs, cVerbs);
LPSTDENUMOLEVERB penum = new StdEnumOLEVERB(pVerbs, cVerbs); if (penum != NULL) { r = NOERROR; *ppenum = penum; } else { DOUT(TEXT("o2base/stdenum/CreateOLEVERBEnum failed\r\n")); } return r; }
//+---------------------------------------------------------------
//
// Class: StdEnumFORMATETC
//
// Purpose: Standard enumerator of FORMATETC tables
//
//---------------------------------------------------------------
class StdEnumFORMATETC: public IEnumFORMATETC { friend HRESULT CreateFORMATETCEnum(LPFORMATETC, ULONG, LPENUMFORMATETC FAR*); public: DECLARE_STANDARD_IUNKNOWN(StdEnumFORMATETC);
// *** IEnumFORMATETC methods ***
STDMETHOD(Next) (ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetched); STDMETHOD(Skip) (ULONG celt); STDMETHOD(Reset) (void); STDMETHOD(Clone) (IEnumFORMATETC FAR* FAR* ppenm);
private: StdEnumFORMATETC(LPFORMATETC pStart, ULONG cCount); ~StdEnumFORMATETC(void);
LPFORMATETC _pStart; ULONG _cCount; ULONG _cCurrent; };
//+---------------------------------------------------------------
//
// Member: StdEnumFORMATETC::StdEnumFORMATETC, private
//
// Synopsis: Constructor for StdEnumFORMATETC objects
//
// Arguments: [pStart] -- pointer to the beginning of the FORMATETC array
// [cCount] -- the number of elements in the array
//
// Notes: Static enumerators should be constructed using the
// CreateFORMATETCEnum function.
//
//----------------------------------------------------------------
StdEnumFORMATETC::StdEnumFORMATETC(LPFORMATETC pStart, ULONG cCount) { _ulRefs = 1; _pStart = pStart; _cCount = cCount; _cCurrent = 0; DOUT(TEXT("StdEnumFORMATETC constructed.\r\n")); }
//+---------------------------------------------------------------
//
// Member: StdStaticEnum::~StdStaticEnum, private
//
// Synopsis: Destructor for StdStaticEnum objects
//
// Notes: Static enumerators should never be `deleted' but
// instead IUnknown::Release'd.
//
//----------------------------------------------------------------
StdEnumFORMATETC::~StdEnumFORMATETC(void) { DOUT(TEXT("StdEnumFORMATETC destructed.\r\n")); }
IMPLEMENT_STANDARD_IUNKNOWN(StdEnumFORMATETC)
//+---------------------------------------------------------------
//
// Member: StdEnumFORMATETC::QueryInterface, public
//
// Synopsis: Method of IUnknown interface
//
//----------------------------------------------------------------
STDMETHODIMP StdEnumFORMATETC::QueryInterface(REFIID riid, LPVOID FAR* ppvObj) { #ifdef VERBOSE_DBG
TCHAR achBuffer[256]; wsprintf(achBuffer, TEXT("StdEnumFORMATETC::QueryInterface (%lx)\r\n"), riid.Data1); DOUT(achBuffer); #endif //VERBOSE_DBG
if (IsEqualIID(riid,IID_IUnknown) || IsEqualIID(riid,IID_IEnumFORMATETC)) { *ppvObj = this; AddRef(); return NOERROR; }
#if VERBOSE_DBG
wsprintf(achBuffer, TEXT("StdEnumFORMATETC::QueryInterface returning E_NOINTERFACE for %lx\r\n"), riid.Data1); DOUT(achBuffer); #endif //VERBOSE_DBG
*ppvObj = NULL; return E_NOINTERFACE; }
//+---------------------------------------------------------------
//
// Member: StdEnumFORMATETC::Next
//
// Synopsis: Member of IEnumXXX interface
//
//----------------------------------------------------------------
STDMETHODIMP StdEnumFORMATETC::Next(ULONG celt, LPFORMATETC pArrayObjs, ULONG FAR* pceltFetched) { ULONG celtFetched = 0;
if (_pStart == NULL) return S_FALSE;
if (pceltFetched != NULL) *pceltFetched = 0L;
if (pArrayObjs == NULL || _cCurrent >= _cCount) return S_FALSE; while ( _cCurrent < _cCount && celt > 0 ) { LPFORMATETC pFormat = &_pStart[_cCurrent];
// deep copy the FORMATETC structure
*pArrayObjs = *pFormat; if (pFormat->ptd == DVTARGETIGNORE ) pArrayObjs->ptd = NULL; if (pArrayObjs->ptd != NULL) { HRESULT r = TaskAllocMem(sizeof(DVTARGETDEVICE), (LPVOID FAR*)&pArrayObjs->ptd); if (OK(r)) { *(pArrayObjs->ptd) = *(pFormat->ptd); } } pArrayObjs++; _cCurrent++; celtFetched++; celt--; }
if (pceltFetched != NULL) { *pceltFetched = celtFetched - celt; } return NOERROR; }
//+---------------------------------------------------------------
//
// Member: StdEnumFORMATETC::Skip
//
// Synopsis: Member of IEnumXXX interface
//
//----------------------------------------------------------------
STDMETHODIMP StdEnumFORMATETC::Skip(ULONG celt) { _cCurrent += celt; if (_cCurrent >= _cCount) { _cCurrent = _cCount; return S_FALSE; } return NOERROR; }
//+---------------------------------------------------------------
//
// Member: StdEnumFORMATETC::Reset
//
// Synopsis: Member of IEnumXXX interface
//
//----------------------------------------------------------------
STDMETHODIMP StdEnumFORMATETC::Reset(void) { _cCurrent = 0; return NOERROR; }
//+---------------------------------------------------------------
//
// Member: StdEnumFORMATETC::Clone
//
// Synopsis: Member of IEnumXXX interface
//
//----------------------------------------------------------------
STDMETHODIMP StdEnumFORMATETC::Clone(LPENUMFORMATETC FAR* ppenm) { HRESULT r = E_OUTOFMEMORY;; LPSTDENUMFORMATETC penum = new StdEnumFORMATETC(_pStart, _cCount); if (penum != NULL) { r = NOERROR; penum->_cCurrent = _cCurrent; *ppenm = penum; } else { DOUT(TEXT("o2base/StdEnumFORMATETC::Clone failed\r\n")); } return r; }
//+---------------------------------------------------------------
//
// Function: CreateFORMATETCEnum, public
//
// Synopsis: Creates a standard enumerator over FORMATETC arrays
//
// Arguments: [pFormats] -- pointer to the beginning of the FORMATETC array
// [cFormats] -- the number of elements in the array
// [ppenum] -- where the enumerator is returned
//
// Returns: Success if the enumerator could be successfully created
//
// Notes: This function is typically used in the IDataObject::EnumFormatetc
// method implementation.
//
//----------------------------------------------------------------
HRESULT CreateFORMATETCEnum(LPFORMATETC pFormats, ULONG cFormats, LPENUMFORMATETC FAR* ppenum) { HRESULT r; LPSTDENUMFORMATETC penum = new StdEnumFORMATETC(pFormats, cFormats); if (penum == NULL) { DOUT(TEXT("o2base/stdenum/CreateFORMATETCEnum E_OUTOFMEMORY\r\n")); r = E_OUTOFMEMORY; } else { *ppenum = penum; r = NOERROR; } return r; }
#if 1 // this maybe useful later but is not currently used.
//+---------------------------------------------------------------
//
// Class: StdStaticEnum
//
// Purpose: Enumerates over a static array
//
// Notes: This may not be used to enumerate over structures
// that are "deep". For instance, it cannot be used
// to enumerate over an array of FORMATETCs because such
// an enumerator needs to deep copy the ptd field
// and the enumerator client frees these allocated ptd.
// Similarly for the OLEVERB structure where the verb
// name string must be deep copied.
//
//---------------------------------------------------------------
class StdStaticEnum: public IUnknown { friend HRESULT CreateStaticEnum(REFIID, LPVOID, ULONG, ULONG, LPVOID FAR*);
public: DECLARE_STANDARD_IUNKNOWN(StdStaticEnum);
//*** IEnumerator methods ***
STDMETHOD(Next) (ULONG celt, LPVOID pArrayObjs, ULONG FAR* pceltFetched); STDMETHOD(Skip) (ULONG celt); STDMETHOD(Reset) (void); STDMETHOD(Clone) (LPSTDSTATICENUM FAR* ppenm);
private: // constructor/destructor
StdStaticEnum(REFIID riid, LPVOID pStart, ULONG cSize, ULONG cCount); ~StdStaticEnum(void);
IID _iid; LPVOID _pStart; ULONG _cSize; ULONG _cCount; ULONG _cCurrent; };
//+---------------------------------------------------------------
//
// Member: StdStaticEnum::StdStaticEnum, private
//
// Synopsis: Constructor for StdStaticEnum objects
//
// Arguments: [riid] -- the enumerator interface that this class is
// "pretending" to be.
// [pStart] -- pointer to the beginning of the static array
// [cSize] -- the size of the elements of the array
// [cCount] -- the number of elements in the array
//
// Notes: Static enumerators should be constructed using the
// CreateStaticEnum function.
//
//----------------------------------------------------------------
StdStaticEnum::StdStaticEnum(REFIID riid, LPVOID pStart, ULONG cSize, ULONG cCount) { _ulRefs = 1; _iid = riid; _pStart = pStart; _cSize = cSize; _cCount = cCount; _cCurrent = 0; DOUT(TEXT("StdStaticEnum constructed.\r\n")); }
//+---------------------------------------------------------------
//
// Member: StdStaticEnum::~StdStaticEnum, private
//
// Synopsis: Destructor for StdStaticEnum objects
//
// Notes: Static enumerators should never be `deleted' but
// instead IUnknown::Release'd.
//
//----------------------------------------------------------------
StdStaticEnum::~StdStaticEnum(void) { DOUT(TEXT("StdStaticEnum destructed.\r\n")); }
IMPLEMENT_STANDARD_IUNKNOWN(StdStaticEnum);
//+---------------------------------------------------------------
//
// Member: StdStaticEnum::QueryInterface, public
//
// Synopsis: Method of IUnknown interface
//
//----------------------------------------------------------------
STDMETHODIMP StdStaticEnum::QueryInterface(REFIID riid, LPVOID FAR* ppvObj) { if (IsEqualIID(riid,IID_IUnknown) || IsEqualIID(riid,_iid)) { *ppvObj = this; AddRef(); return NOERROR; } DOUT(TEXT("StdStaticEnum::QueryInterface E_NOINTERFACE\r\n")); *ppvObj = NULL; return E_NOINTERFACE; }
//+---------------------------------------------------------------
//
// Member: StdStaticEnum::Next
//
// Synopsis: Member of IEnumXXX interface
//
//----------------------------------------------------------------
STDMETHODIMP StdStaticEnum::Next(ULONG celt, LPVOID pArrayObjs, ULONG FAR* pceltFetched) { ULONG celtFetched = min(celt, _cCount-_cCurrent);
// calculate the number of bytes to copy
if (celtFetched != 0 && _cSize > (UINT_MAX/celtFetched)) { DOUT(TEXT("StdStaticEnum::Next E_FAIL\r\n")); return E_FAIL; // overflow!
}
UINT count = (UINT) (celtFetched*_cSize); _fmemcpy(pArrayObjs, (LPBYTE)_pStart+_cCurrent*_cSize, count); _cCurrent += celtFetched; if (pceltFetched != NULL) { *pceltFetched = celtFetched; } return ((celtFetched == celt) ? NOERROR : S_FALSE); }
//+---------------------------------------------------------------
//
// Member: StdStaticEnum::Skip
//
// Synopsis: Member of IEnumXXX interface
//
//----------------------------------------------------------------
STDMETHODIMP StdStaticEnum::Skip(ULONG celt) { _cCurrent += celt; if (_cCurrent >= _cCount) { _cCurrent = _cCount; return S_FALSE; } return NOERROR; }
//+---------------------------------------------------------------
//
// Member: StdStaticEnum::Reset
//
// Synopsis: Member of IEnumXXX interface
//
//----------------------------------------------------------------
STDMETHODIMP StdStaticEnum::Reset(void) { _cCurrent = 0; return NOERROR; }
//+---------------------------------------------------------------
//
// Member: StdStaticEnum::Clone
//
// Synopsis: Member of IEnumXXX interface
//
//----------------------------------------------------------------
STDMETHODIMP StdStaticEnum::Clone(LPSTDSTATICENUM FAR* ppenm) { HRESULT r; //LPSTDSTATICENUM penum = new (NullOnFail) StdStaticEnum(
LPSTDSTATICENUM penum = new StdStaticEnum( _iid, _pStart, _cSize, _cCount); if (penum == NULL) { DOUT(TEXT("o2base/StdStaticEnum::Clone failed\r\n")); r = E_OUTOFMEMORY; } else { penum->_cCurrent = _cCurrent; *ppenm = penum; r = NOERROR; } return r; }
//+---------------------------------------------------------------
//
// Function: CreateStaticEnum, public
//
// Synopsis: Creates a standard enumerator over static arrays
//
// Arguments: [riid] -- the enumerator interface that this class is
// "pretending" to be.
// [pStart] -- pointer to the beginning of the static array
// [cSize] -- the size of the elements of the array
// [cCount] -- the number of elements in the array
// [ppenum] -- where the enumerator is returned
//
// Returns: Success if the enumerator could be successfully created
//
//----------------------------------------------------------------
HRESULT CreateStaticEnum(REFIID riid, LPVOID pStart, ULONG cSize, ULONG cCount, LPVOID FAR* ppenum) { HRESULT r; //LPSTDSTATICENUM penum = new (NullOnFail) StdStaticEnum(
LPSTDSTATICENUM penum = new StdStaticEnum( riid, pStart, cSize, cCount); if (penum == NULL) { DOUT(TEXT("o2base/stdenum/CreateStaticEnum failed\r\n")); r = E_OUTOFMEMORY; } else { *ppenum = penum; r = NOERROR; } return r; }
#endif // 0
|