|
|
// SnapinDataObject.cpp : implementation file
//
#include "stdafx.h"
#include "ScopePaneItem.h"
#include "ResultsPaneItem.h"
#include "SnapinDataObject.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
/////////////////////////////////////////////////////////////////////////////
// CSnapinDataObject
UINT CSnapinDataObject::s_cfInternal = 0; UINT CSnapinDataObject::s_cfExtension = 0;
// *CLEAN ME*
LPCTSTR CF_SNAPIN_INTERNAL = _T("HealthMonitor"); LPCTSTR CF_SNAPIN_EXTENSION = _T("HealthMonitorExtension");
// *CLEAN ME*
// {FBBB8DAE-AB34-11d2-BD62-0000F87A3912}
static const GUID CLSID_SnapIn = { 0xfbbb8dae, 0xab34, 0x11d2, { 0xbd, 0x62, 0x0, 0x0, 0xf8, 0x7a, 0x39, 0x12 } }; //{ 0x69a539f8, 0x9520, 0x11d2, { 0xbd, 0x4a, 0x0, 0x0, 0xf8, 0x7a, 0x39, 0x12 } };
IMPLEMENT_DYNCREATE(CSnapinDataObject, CCmdTarget)
CSnapinDataObject::CSnapinDataObject() { TRACEX(_T("CSnapinDataObject::CSnapinDataObject\n"));
EnableAutomation();
// To keep the application running as long as an OLE automation
// object is active, the constructor calls AfxOleLockApp.
AfxOleLockApp();
if( ! RegisterClipboardFormats() ) { TRACE(_T("FAILED : RegisterClipboardFormats failed.\n")); ASSERT(FALSE); }
m_ulCookie = 0; m_ItemType = CCT_UNINITIALIZED; }
CSnapinDataObject::~CSnapinDataObject() { // To terminate the application when all objects created with
// with OLE automation, the destructor calls AfxOleUnlockApp.
AfxOleUnlockApp(); }
/////////////////////////////////////////////////////////////////////////////
// Clipboard Members
inline bool CSnapinDataObject::RegisterClipboardFormats() { if( ! s_cfInternal ) s_cfInternal = RegisterClipboardFormat(CF_SNAPIN_INTERNAL); if( ! s_cfExtension ) s_cfExtension = RegisterClipboardFormat(CF_SNAPIN_EXTENSION); m_cfDisplayName = RegisterClipboardFormat(CCF_DISPLAY_NAME); m_cfSPIGuid = RegisterClipboardFormat(CCF_NODETYPE); m_cfSnapinCLSID = RegisterClipboardFormat(CCF_SNAPIN_CLASSID);
return s_cfInternal && s_cfExtension && m_cfDisplayName && m_cfSPIGuid && m_cfSnapinCLSID; }
/////////////////////////////////////////////////////////////////////////////
// Item Members
DATA_OBJECT_TYPES CSnapinDataObject::GetItemType() { TRACEX(_T("CSnapinDataObject::GetItemType\n")); TRACEARGn(m_ItemType);
return m_ItemType; }
ULONG CSnapinDataObject::GetCookie() { TRACEX(_T("CSnapinDataObject::GetCookie\n")); TRACEARGn(m_ulCookie);
return m_ulCookie; }
bool CSnapinDataObject::GetItem(CScopePaneItem*& pSPItem) { TRACEX(_T("CSnapinDataObject::GetItem(SPI)\n"));
if( GetItemType() != CCT_SCOPE ) { TRACE(_T("WARNING : Item is not of type CCT_SCOPE.\n")); pSPItem = NULL; return false; }
pSPItem = (CScopePaneItem*)GetCookie();
if( ! CHECKOBJPTR(pSPItem,RUNTIME_CLASS(CScopePaneItem),sizeof(CScopePaneItem)) ) { TRACE(_T("FAILED : The cookie is invalid or corrupt.\n")); pSPItem = NULL; return false; }
return true; }
bool CSnapinDataObject::GetItem(CResultsPaneItem*& pRPItem) { TRACEX(_T("CSnapinDataObject::GetItem(RPI)\n"));
if( GetItemType() != CCT_RESULT ) { TRACE(_T("WARNING : Item is not of type CCT_RESULT.\n")); pRPItem = NULL; return false; }
pRPItem = (CResultsPaneItem*)GetCookie();
if( ! CHECKOBJPTR(pRPItem,RUNTIME_CLASS(CResultsPaneItem),sizeof(CResultsPaneItem)) ) { TRACE(_T("FAILED : The cookie is invalid or corrupt.\n")); pRPItem = NULL; return false; }
return true; }
void CSnapinDataObject::SetItem(CScopePaneItem* pSPItem) { TRACEX(_T("CSnapinDataObject::SetItem(SPI)\n")); TRACEARGn(pSPItem);
if( ! CHECKOBJPTR(pSPItem,RUNTIME_CLASS(CScopePaneItem),sizeof(CScopePaneItem)) ) { TRACE(_T("FAILED : pSPItem is an invalid CScopePaneItem pointer.\n")); m_ulCookie = NULL; m_ItemType = CCT_UNINITIALIZED; return; }
#ifndef IA64
m_ulCookie = (ULONG)pSPItem; #endif // IA64
m_ItemType = CCT_SCOPE; }
void CSnapinDataObject::SetItem(CResultsPaneItem* pRPItem) { TRACEX(_T("CSnapinDataObject::SetItem(RPI)\n")); TRACEARGn(pRPItem);
if( ! CHECKOBJPTR(pRPItem,RUNTIME_CLASS(CResultsPaneItem),sizeof(CResultsPaneItem)) ) { TRACE(_T("FAILED : pRPItem is an invalid CResultsPaneItem pointer.\n")); m_ulCookie = NULL; m_ItemType = CCT_UNINITIALIZED; return; }
#ifndef IA64
m_ulCookie = (ULONG)pRPItem; #endif // IA64
m_ItemType = CCT_RESULT; }
/////////////////////////////////////////////////////////////////////////////
// DataObject Members
CSnapinDataObject* CSnapinDataObject::GetSnapinDataObject(LPDATAOBJECT lpDataObject) { TRACEX(_T("CSnapinDataObject::GetSnapinDataObject\n")); TRACEARGn(lpDataObject);
if( ! CHECKPTR(lpDataObject,sizeof(IDataObject)) ) { TRACE(_T("FAILED : lpDataObject pointer is invalid!\n")); return NULL; }
HGLOBAL hGlobal = NULL; CSnapinDataObject* psdo = NULL;
HRESULT hr = GetDataObject( lpDataObject, CSnapinDataObject::s_cfInternal, sizeof(CSnapinDataObject**), &hGlobal );
if( hr == DV_E_FORMATETC || ! CHECKHRESULT(hr) ) { return NULL; }
psdo = *((CSnapinDataObject**)(hGlobal));
if( ! CHECKOBJPTR(psdo,RUNTIME_CLASS(CSnapinDataObject),sizeof(CSnapinDataObject)) ) { return NULL; }
GlobalFree(hGlobal);
return psdo; }
HRESULT CSnapinDataObject::GetDataObject(LPDATAOBJECT lpDataObject, UINT cfClipFormat, ULONG nByteCount, HGLOBAL* phGlobal) { TRACEX(_T("CSnapinDataObject::GetDataObject\n")); TRACEARGn(lpDataObject); TRACEARGn(cfClipFormat); TRACEARGn(nByteCount); TRACEARGn(phGlobal);
if( ! CHECKPTR(lpDataObject,sizeof(IDataObject)) ) { TRACE(_T("FAILED : lpDataObject is invalid.\n")); return E_FAIL; }
HRESULT hr = S_OK; STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL }; FORMATETC formatetc = { (unsigned short)cfClipFormat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
*phGlobal = NULL;
// Allocate memory for the stream
stgmedium.hGlobal = GlobalAlloc( GMEM_SHARE, nByteCount );
if( ! stgmedium.hGlobal ) { hr = E_OUTOFMEMORY; TRACE(_T("FAILED : Out of Memory.\n")); return hr; }
// Attempt to get data from the object
hr = lpDataObject->GetDataHere( &formatetc, &stgmedium ); if( hr == DV_E_FORMATETC || ! CHECKHRESULT(hr) ) { TRACE(_T("lpDataObject->GetDataFromHere failed.\n")); GlobalFree(stgmedium.hGlobal); stgmedium.hGlobal = NULL; return hr; }
// stgmedium now has the data we need
*phGlobal = stgmedium.hGlobal; stgmedium.hGlobal = NULL;
return hr; }
/////////////////////////////////////////////////////////////////////////////
// Write Members
HRESULT CSnapinDataObject::WriteGuid(LPSTREAM pStream) { TRACEX(_T("CSnapinDataObject::WriteGuid\n")); TRACEARGn(pStream);
if( ! CHECKPTR(pStream,sizeof(IStream)) ) { TRACE(_T("FAILED : Invalid IStream pointer passed.\n")); return E_FAIL; }
LPGUID pGuid = NULL;
if( GetItemType() == CCT_SCOPE ) { CScopePaneItem* pItem = NULL; if( ! GetItem(pItem) ) { return S_OK; }
ASSERT(pItem);
pGuid = pItem->GetItemType(); } else if( GetItemType() == CCT_RESULT ) { CResultsPaneItem* pItem = NULL; if( ! GetItem(pItem) ) { return S_OK; }
ASSERT(pItem);
pGuid = pItem->GetItemType();
if( ! pGuid ) { return S_OK; } }
if( pGuid == NULL ) { TRACE(_T("FAILED : CScopePaneItem::GetItemType returns NULL.\n")); return E_FAIL; }
return pStream->Write( (LPVOID)pGuid, sizeof(GUID), NULL ); }
HRESULT CSnapinDataObject::WriteDisplayName(LPSTREAM pStream) { TRACEX(_T("CSnapinDataObject::WriteDisplayName\n")); TRACEARGn(pStream);
if( ! CHECKPTR(pStream,sizeof(IStream)) ) { TRACE(_T("FAILED : Invalid IStream pointer passed.\n")); return E_FAIL; }
CString sDisplayName;
switch(GetItemType()) { case CCT_SCOPE: { CScopePaneItem* pItem = NULL;
if( ! GetItem(pItem) ) { TRACE(_T("FAILED : GetItem failed.\n")); return E_FAIL; }
ASSERT(pItem);
sDisplayName = pItem->GetDisplayName(); } break;
case CCT_RESULT: { CResultsPaneItem* pItem = NULL;
if( ! GetItem(pItem) ) { TRACE(_T("FAILED : GetItem failed.\n")); return E_FAIL; }
ASSERT(pItem);
sDisplayName = pItem->GetDisplayName(); } break; }
ULONG ulSizeofName = sDisplayName.GetLength() + 1; ulSizeofName *= sizeof(TCHAR);
return pStream->Write(sDisplayName, ulSizeofName, NULL); }
HRESULT CSnapinDataObject::WriteSnapinCLSID(LPSTREAM pStream) { TRACEX(_T("CSnapinDataObject::WriteSnapinCLSID\n")); TRACEARGn(pStream);
if( ! CHECKPTR(pStream,sizeof(IStream)) ) { TRACE(_T("FAILED : Invalid IStream pointer passed.\n")); return E_FAIL; }
return pStream->Write(&CLSID_SnapIn,sizeof(CLSID_SnapIn),NULL); }
HRESULT CSnapinDataObject::WriteDataObject(LPSTREAM pStream) { TRACEX(_T("CSnapinDataObject::WriteDataObject\n")); TRACEARGn(pStream);
if( ! CHECKPTR(pStream,sizeof(IStream)) ) { TRACE(_T("FAILED : Invalid IStream pointer passed.\n")); return E_FAIL; }
CSnapinDataObject* pThis = this; return pStream->Write(&pThis,sizeof(CSnapinDataObject*),NULL); }
HRESULT CSnapinDataObject::WriteExtensionData(LPSTREAM pStream) { TRACEX(_T("CSnapinDataObject::WriteExtensionData\n")); TRACEARGn(pStream);
if( ! CHECKPTR(pStream,sizeof(IStream)) ) { TRACE(_T("FAILED : Invalid IStream pointer passed.\n")); return E_FAIL; }
switch(GetItemType()) { case CCT_SCOPE: { CScopePaneItem* pItem = NULL;
if( ! GetItem(pItem) ) { TRACE(_T("FAILED : GetItem failed.\n")); return E_FAIL; }
ASSERT(pItem);
return pItem->WriteExtensionData(pStream); } break;
case CCT_RESULT: { CResultsPaneItem* pItem = NULL;
if( ! GetItem(pItem) ) { TRACE(_T("FAILED : GetItem failed.\n")); return E_FAIL; }
ASSERT(pItem);
return pItem->WriteExtensionData(pStream); } break; }
return E_FAIL; }
/////////////////////////////////////////////////////////////////////////////
// MFC Implementation Members
void CSnapinDataObject::OnFinalRelease() { // When the last reference for an automation object is released
// OnFinalRelease is called. The base class will automatically
// deletes the object. Add additional cleanup required for your
// object before calling the base class.
CCmdTarget::OnFinalRelease(); }
BEGIN_MESSAGE_MAP(CSnapinDataObject, CCmdTarget) //{{AFX_MSG_MAP(CSnapinDataObject)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BEGIN_DISPATCH_MAP(CSnapinDataObject, CCmdTarget) //{{AFX_DISPATCH_MAP(CSnapinDataObject)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()
// Note: we add support for IID_ISnapinDataObject to support typesafe binding
// from VBA. This IID must match the GUID that is attached to the
// dispinterface in the .ODL file.
// {7D4A685E-9056-11D2-BD45-0000F87A3912}
static const IID IID_ISnapinDataObject = { 0x7d4a685e, 0x9056, 0x11d2, { 0xbd, 0x45, 0x0, 0x0, 0xf8, 0x7a, 0x39, 0x12 } };
BEGIN_INTERFACE_MAP(CSnapinDataObject, CCmdTarget) INTERFACE_PART(CSnapinDataObject, IID_ISnapinDataObject, Dispatch) INTERFACE_PART(CSnapinDataObject, IID_IDataObject, DataObject) END_INTERFACE_MAP()
// {01CB0090-AFCB-11d2-BD6B-0000F87A3912}
IMPLEMENT_OLECREATE_EX(CSnapinDataObject, "SnapIn.SnapinDataObject", 0x1cb0090, 0xafcb, 0x11d2, 0xbd, 0x6b, 0x0, 0x0, 0xf8, 0x7a, 0x39, 0x12);
BOOL CSnapinDataObject::CSnapinDataObjectFactory::UpdateRegistry(BOOL bRegister) { if (bRegister) return AfxOleRegisterServerClass(m_clsid, m_lpszProgID, m_lpszProgID, m_lpszProgID, OAT_DISPATCH_OBJECT); else return AfxOleUnregisterClass(m_clsid, m_lpszProgID); }
/////////////////////////////////////////////////////////////////////////////
// IDataObject Interface Part
ULONG FAR EXPORT CSnapinDataObject::XDataObject::AddRef() { METHOD_PROLOGUE(CSnapinDataObject, DataObject) return pThis->ExternalAddRef(); }
ULONG FAR EXPORT CSnapinDataObject::XDataObject::Release() { METHOD_PROLOGUE(CSnapinDataObject, DataObject) return pThis->ExternalRelease(); }
HRESULT FAR EXPORT CSnapinDataObject::XDataObject::QueryInterface(REFIID iid, void FAR* FAR* ppvObj) { METHOD_PROLOGUE(CSnapinDataObject, DataObject) return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj); }
HRESULT FAR EXPORT CSnapinDataObject::XDataObject::GetData( /* [unique][in] */ FORMATETC __RPC_FAR *pformatetcIn, /* [out] */ STGMEDIUM __RPC_FAR *pmedium) { METHOD_PROLOGUE(CSnapinDataObject, DataObject) TRACEX(_T("CSnapinDataObject::XDataObject::GetData")); TRACEARGn(pformatetcIn); TRACEARGn(pmedium);
HRESULT hr = S_OK;
// Make sure FORMATETC is something we can handle.
if( !(DVASPECT_CONTENT & pformatetcIn->dwAspect) || !(TYMED_HGLOBAL & pformatetcIn->tymed) ) { hr = DATA_E_FORMATETC; } if( S_OK == hr ) { if( s_cfExtension == pformatetcIn->cfFormat ) { IStream *pStream = NULL; // Allocate memory for the stream
pmedium->hGlobal = GlobalAlloc( GMEM_SHARE, 1024 );
if( ! pmedium->hGlobal ) { hr = E_OUTOFMEMORY; TRACE(_T("FAILED : Out of Memory.\n")); return hr; } hr = CreateStreamOnHGlobal( pmedium->hGlobal, FALSE, &pStream ); hr = pThis->WriteExtensionData( pStream ); pStream->Release(); } else { hr = DATA_E_FORMATETC; } }
return hr; }
HRESULT FAR EXPORT CSnapinDataObject::XDataObject::GetDataHere( /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc, /* [out][in] */ STGMEDIUM __RPC_FAR *pmedium) { METHOD_PROLOGUE(CSnapinDataObject, DataObject) TRACEX(_T("CSnapinDataObject::XDataObject::GetDataHere")); TRACEARGn(pformatetc); TRACEARGn(pmedium);
HRESULT hr = DV_E_FORMATETC; // Unknown format
const CLIPFORMAT cf = pformatetc->cfFormat; IStream *pStream = NULL;
pmedium->pUnkForRelease = NULL; // by OLE spec
// Write data to the stream based
// on the clipformat
hr = CreateStreamOnHGlobal( pmedium->hGlobal, FALSE, &pStream ); if( ! CHECKHRESULT(hr) ) { TRACE(_T("FAILED : Failed on call to CreateStreamOnHGlobal.\n")); return hr; // Minimal error checking
}
if( pThis->m_cfDisplayName == cf ) { hr = pThis->WriteDisplayName( pStream ); } else if( pThis->s_cfInternal == cf ) { hr = pThis->WriteDataObject( pStream ); } else if( pThis->s_cfExtension == cf ) { hr = pThis->WriteExtensionData( pStream ); } else if( pThis->m_cfSPIGuid == cf ) { hr = pThis->WriteGuid( pStream ); } else if( pThis->m_cfSnapinCLSID == cf ) { hr = pThis->WriteSnapinCLSID( pStream ); }
pStream->Release();
return hr; }
HRESULT FAR EXPORT CSnapinDataObject::XDataObject::QueryGetData( /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc) { METHOD_PROLOGUE(CSnapinDataObject, DataObject) TRACEX(_T("CSnapinDataObject::XDataObject::QueryGetData")); TRACEARGn(pformatetc);
HRESULT hr = S_OK;
// For this sample, we just do a simple test.
if( s_cfExtension == pformatetc->cfFormat ) hr = S_OK; else hr = S_FALSE; return hr; }
HRESULT FAR EXPORT CSnapinDataObject::XDataObject::GetCanonicalFormatEtc( /* [unique][in] */ FORMATETC __RPC_FAR *pformatectIn, /* [out] */ FORMATETC __RPC_FAR *pformatetcOut) { METHOD_PROLOGUE(CSnapinDataObject, DataObject) TRACEX(_T("CSnapinDataObject::XDataObject::GetCanonicalFormatEtc")); TRACEARGn(pformatectIn); TRACEARGn(pformatetcOut);
return E_NOTIMPL; }
HRESULT FAR EXPORT CSnapinDataObject::XDataObject::SetData( /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc, /* [unique][in] */ STGMEDIUM __RPC_FAR *pmedium, /* [in] */ BOOL fRelease) { METHOD_PROLOGUE(CSnapinDataObject, DataObject) TRACEX(_T("CSnapinDataObject::XDataObject::SetData")); TRACEARGn(pformatetc); TRACEARGn(pmedium); TRACEARGn(fRelease);
return E_NOTIMPL; }
HRESULT FAR EXPORT CSnapinDataObject::XDataObject::EnumFormatEtc( /* [in] */ DWORD dwDirection, /* [out] */ IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenumFormatEtc) { METHOD_PROLOGUE(CSnapinDataObject, DataObject) TRACEX(_T("CSnapinDataObject::XDataObject::EnumFormatEtc")); TRACEARGn(dwDirection); TRACEARGn(ppenumFormatEtc);
HRESULT hr = S_OK; static FORMATETC ForEtcArr[1]; // Use array so we can add more later
ForEtcArr[0].cfFormat = (CLIPFORMAT)s_cfExtension; ForEtcArr[0].dwAspect = DVASPECT_CONTENT; ForEtcArr[0].ptd = NULL; ForEtcArr[0].tymed = TYMED_HGLOBAL; ForEtcArr[0].lindex = -1;
switch( dwDirection ) { case DATADIR_GET: *ppenumFormatEtc = new CEnumFormatEtc(1, ForEtcArr); break;
case DATADIR_SET: default: *ppenumFormatEtc = NULL; break; }
if( NULL == *ppenumFormatEtc ) { hr = E_FAIL; } else { (*ppenumFormatEtc)->AddRef(); hr = S_OK; }
return hr; }
HRESULT FAR EXPORT CSnapinDataObject::XDataObject::DAdvise( /* [in] */ FORMATETC __RPC_FAR *pformatetc, /* [in] */ DWORD advf, /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvSink, /* [out] */ DWORD __RPC_FAR *pdwConnection) { METHOD_PROLOGUE(CSnapinDataObject, DataObject) TRACEX(_T("CSnapinDataObject::XDataObject::DAdvise")); TRACEARGn(pformatetc); TRACEARGn(advf); TRACEARGn(pAdvSink); TRACEARGn(pdwConnection);
return E_NOTIMPL; }
HRESULT FAR EXPORT CSnapinDataObject::XDataObject::DUnadvise( /* [in] */ DWORD dwConnection) { METHOD_PROLOGUE(CSnapinDataObject, DataObject) TRACEX(_T("CSnapinDataObject::XDataObject::DUnadvise")); TRACEARGn(dwConnection);
return E_NOTIMPL; }
HRESULT FAR EXPORT CSnapinDataObject::XDataObject::EnumDAdvise( /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise) { METHOD_PROLOGUE(CSnapinDataObject, DataObject) TRACEX(_T("CSnapinDataObject::XDataObject::EnumDAdvise")); TRACEARGn(ppenumAdvise);
return E_NOTIMPL; }
/////////////////////////////////////////////////////////////////////////////
// CSnapinDataObject message handlers
/////////////////////////////////////////////////////////////////////////////
// CEnumFormatEtc Implementation
/*
* CEnumFormatEtc::CEnumFormatEtc * CEnumFormatEtc::~CEnumFormatEtc * * Parameters (Constructor): * cFE ULONG number of FORMATETCs in pFE * prgFE LPFORMATETC to the array to enumerate. */
CEnumFormatEtc::CEnumFormatEtc(ULONG cFE, LPFORMATETC prgFE) { UINT i;
m_cRef=0; 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]=prgFE[i]; }
return; }
CEnumFormatEtc::~CEnumFormatEtc(void) { if (NULL!=m_prgfe) delete [] m_prgfe; }
/*
* CEnumFormatEtc::QueryInterface * CEnumFormatEtc::AddRef * CEnumFormatEtc::Release * * Purpose: * IUnknown members for CEnumFormatEtc object. For QueryInterface * we only return out own interfaces and not those of the data * object. However, since enumerating formats only makes sense * when the data object is around, we insure that it stays as * long as we stay by calling an outer IUnknown for AddRef * and Release. But since we are not controlled by the lifetime * of the outer object, we still keep our own reference count in * order to free ourselves. */
STDMETHODIMP CEnumFormatEtc::QueryInterface(REFIID riid, VOID ** ppv) { *ppv=NULL;
/*
* Enumerators are separate objects, not the data object, so * we only need to support out IUnknown and IEnumFORMATETC * interfaces here with no concern for aggregation. */ if (IID_IUnknown==riid || IID_IEnumFORMATETC==riid) *ppv=this;
//AddRef any interface we'll return.
if (NULL!=*ppv) { ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; }
return ResultFromScode(E_NOINTERFACE); }
STDMETHODIMP_(ULONG) CEnumFormatEtc::AddRef(void) { ++m_cRef; return m_cRef; }
STDMETHODIMP_(ULONG) CEnumFormatEtc::Release(void) { if (0!=--m_cRef) return m_cRef;
delete this; return 0; }
/*
* CEnumFormatEtc::Next * * Purpose: * Returns the next element in the enumeration. * * Parameters: * cFE ULONG number of FORMATETCs to return. * pFE LPFORMATETC in which to store the returned * structures. * pulFE ULONG * in which to return how many we * enumerated. * * Return Value: * HRESULT NOERROR if successful, S_FALSE otherwise, */
STDMETHODIMP CEnumFormatEtc::Next(ULONG cFE, LPFORMATETC pFE, ULONG *pulFE) { ULONG cReturn=0L;
if (NULL==m_prgfe) return ResultFromScode(S_FALSE);
if (NULL==pulFE) { if (1L!=cFE) return ResultFromScode(E_POINTER); } else *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; }
/*
* CEnumFormatEtc::Skip * * Purpose: * Skips the next n elements in the enumeration. * * Parameters: * cSkip ULONG number of elements to skip. * * Return Value: * HRESULT NOERROR if successful, S_FALSE if we could not * skip the requested number. */
STDMETHODIMP CEnumFormatEtc::Skip(ULONG cSkip) { if (((m_iCur+cSkip) >= m_cfe) || NULL==m_prgfe) return ResultFromScode(S_FALSE);
m_iCur+=cSkip; return NOERROR; }
/*
* CEnumFormatEtc::Reset * * Purpose: * Resets the current element index in the enumeration to zero. * * Parameters: * None * * Return Value: * HRESULT NOERROR */
STDMETHODIMP CEnumFormatEtc::Reset(void) { m_iCur=0; return NOERROR; }
/*
* CEnumFormatEtc::Clone * * Purpose: * Returns another IEnumFORMATETC with the same state as ourselves. * * Parameters: * ppEnum LPENUMFORMATETC * in which to return the * new object. * * Return Value: * HRESULT NOERROR or a general error value. */
STDMETHODIMP CEnumFormatEtc::Clone(LPENUMFORMATETC *ppEnum) { PCEnumFormatEtc pNew;
*ppEnum=NULL;
//Create the clone
pNew=new CEnumFormatEtc(m_cfe, m_prgfe);
if (NULL==pNew) return ResultFromScode(E_OUTOFMEMORY);
pNew->AddRef(); pNew->m_iCur=m_iCur;
*ppEnum=pNew; return NOERROR; }
|