228 lines
5.0 KiB
C++
228 lines
5.0 KiB
C++
|
// --------------------------------------------------------------------------
|
||
|
// Enumfmt.cpp
|
||
|
// Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
|
||
|
// --------------------------------------------------------------------------
|
||
|
#include "pch.hxx"
|
||
|
#include "enumfmt.h"
|
||
|
#include <BadStrFunctions.h>
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// CEnumFormatEtc Implementation
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// COMMENTS:
|
||
|
// This class was designed and implemented by Kraig Brockschmidt in
|
||
|
// is book "Inside OLE2". See Chapter 6 "Uniform Data Transfer Using
|
||
|
// Data Objects" for more information.
|
||
|
//
|
||
|
|
||
|
// =================================================================================
|
||
|
// CreateStreamOnHFile
|
||
|
// =================================================================================
|
||
|
OESTDAPI_(HRESULT) CreateEnumFormatEtc(LPUNKNOWN pUnkRef, ULONG celt, PDATAOBJINFO rgInfo, LPFORMATETC rgfe,
|
||
|
IEnumFORMATETC ** lppstmHFile)
|
||
|
{
|
||
|
CEnumFormatEtc * pEnumFmt = NULL;
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
// Check the incoming params
|
||
|
if ((0 == pUnkRef) || (0 == lppstmHFile) || (0 == celt) || ((0 != rgInfo) && (0 != rgfe)))
|
||
|
{
|
||
|
hr = E_INVALIDARG;
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
// Initialize outgoing params
|
||
|
*lppstmHFile = NULL;
|
||
|
|
||
|
// Create the rules manager object
|
||
|
if (NULL != rgInfo)
|
||
|
{
|
||
|
pEnumFmt = new CEnumFormatEtc(pUnkRef, rgInfo, celt);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pEnumFmt = new CEnumFormatEtc(pUnkRef, celt, rgfe);
|
||
|
}
|
||
|
|
||
|
if (NULL == pEnumFmt)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
// Get the rules manager interface
|
||
|
hr = pEnumFmt->QueryInterface(IID_IEnumFORMATETC, (void **) lppstmHFile);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
pEnumFmt = NULL;
|
||
|
|
||
|
// Set the proper return value
|
||
|
hr = S_OK;
|
||
|
|
||
|
exit:
|
||
|
if (NULL != pEnumFmt)
|
||
|
{
|
||
|
delete pEnumFmt;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
CEnumFormatEtc::CEnumFormatEtc(LPUNKNOWN pUnkRef, PDATAOBJINFO rgInfo, ULONG celt)
|
||
|
{
|
||
|
UINT i;
|
||
|
|
||
|
m_cRef = 0;
|
||
|
m_pUnkRef = pUnkRef;
|
||
|
|
||
|
m_iCur = 0;
|
||
|
m_cfe = celt;
|
||
|
m_prgfe = new FORMATETC[(UINT) celt];
|
||
|
|
||
|
if (NULL != m_prgfe)
|
||
|
{
|
||
|
for (i = 0; i < celt; i++)
|
||
|
m_prgfe[i] = rgInfo[i].fe;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CEnumFormatEtc::CEnumFormatEtc(LPUNKNOWN pUnkRef, ULONG cFE, LPFORMATETC rgfe)
|
||
|
{
|
||
|
UINT i;
|
||
|
|
||
|
m_cRef = 0;
|
||
|
m_pUnkRef = pUnkRef;
|
||
|
|
||
|
m_iCur = 0;
|
||
|
m_cfe = cFE;
|
||
|
m_prgfe = new FORMATETC[(UINT) cFE];
|
||
|
|
||
|
if (NULL != m_prgfe)
|
||
|
{
|
||
|
for (i = 0; i < cFE; i++)
|
||
|
m_prgfe[i] = rgfe[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CEnumFormatEtc::~CEnumFormatEtc(void)
|
||
|
{
|
||
|
if (NULL != m_prgfe)
|
||
|
delete [] m_prgfe;
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CEnumFormatEtc::QueryInterface(REFIID riid, LPVOID* ppv)
|
||
|
{
|
||
|
*ppv = NULL;
|
||
|
|
||
|
//
|
||
|
// Enumerators are separate objects, not the data object, so we
|
||
|
// only need to support our IUnknown and IEnumFORMATETC intefaces
|
||
|
// here with no concern for aggregation.
|
||
|
//
|
||
|
|
||
|
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IEnumFORMATETC))
|
||
|
*ppv = (LPVOID) this;
|
||
|
|
||
|
if (NULL != *ppv)
|
||
|
{
|
||
|
((LPUNKNOWN) *ppv)->AddRef();
|
||
|
return (NOERROR);
|
||
|
}
|
||
|
|
||
|
return (ResultFromScode(E_NOINTERFACE));
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CEnumFormatEtc::AddRef(void)
|
||
|
{
|
||
|
++m_cRef;
|
||
|
m_pUnkRef->AddRef();
|
||
|
return (m_cRef);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CEnumFormatEtc::Release(void)
|
||
|
{
|
||
|
ULONG cRefT;
|
||
|
|
||
|
cRefT = --m_cRef;
|
||
|
|
||
|
m_pUnkRef->Release();
|
||
|
|
||
|
if (0 == m_cRef)
|
||
|
delete this;
|
||
|
|
||
|
return (cRefT);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CEnumFormatEtc::Next(ULONG cFE, LPFORMATETC pFE, ULONG* pulFE)
|
||
|
{
|
||
|
ULONG cReturn = 0L;
|
||
|
|
||
|
if (NULL == m_prgfe)
|
||
|
return (ResultFromScode(S_FALSE));
|
||
|
|
||
|
if (NULL != pulFE)
|
||
|
*pulFE = 0L;
|
||
|
|
||
|
if (NULL == pFE || m_iCur >= m_cfe)
|
||
|
return ResultFromScode(S_FALSE);
|
||
|
|
||
|
while (m_iCur < m_cfe && cFE > 0)
|
||
|
{
|
||
|
*pFE++ = m_prgfe[m_iCur++];
|
||
|
cReturn++;
|
||
|
cFE--;
|
||
|
}
|
||
|
|
||
|
if (NULL != pulFE)
|
||
|
*pulFE = cReturn;
|
||
|
|
||
|
return (NOERROR);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CEnumFormatEtc::Skip(ULONG cSkip)
|
||
|
{
|
||
|
if (((m_iCur + cSkip) >= m_cfe) || NULL == m_prgfe)
|
||
|
return (ResultFromScode(S_FALSE));
|
||
|
|
||
|
m_iCur += cSkip;
|
||
|
return (NOERROR);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CEnumFormatEtc::Reset(void)
|
||
|
{
|
||
|
m_iCur = 0;
|
||
|
return (NOERROR);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CEnumFormatEtc::Clone(LPENUMFORMATETC* ppEnum)
|
||
|
{
|
||
|
CEnumFormatEtc* pNew;
|
||
|
|
||
|
*ppEnum = NULL;
|
||
|
|
||
|
// Create the clone.
|
||
|
pNew = new CEnumFormatEtc(m_pUnkRef, m_cfe, m_prgfe);
|
||
|
if (NULL == pNew)
|
||
|
return (ResultFromScode(E_OUTOFMEMORY));
|
||
|
|
||
|
pNew->AddRef();
|
||
|
pNew->m_iCur = m_iCur;
|
||
|
|
||
|
*ppEnum = pNew;
|
||
|
return (NOERROR);
|
||
|
}
|