782 lines
20 KiB
C++
782 lines
20 KiB
C++
|
//+---------------------------------------------------------------------
|
|||
|
//
|
|||
|
// 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
|
|||
|
|