971 lines
22 KiB
C++
971 lines
22 KiB
C++
// 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;
|
|
}
|
|
|
|
|
|
|