// -------------------------------------------------------------------------- // Enumfmt.cpp // Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved // -------------------------------------------------------------------------- #include "pch.hxx" #include "enumfmt.h" #include ////////////////////////////////////////////////////////////////////////////// // // 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); }