DATAOBJ.CPP

/************************************************************************** 
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Copyright 1997 Microsoft Corporation. All Rights Reserved.
**************************************************************************/

/**************************************************************************

File: DataObj.cpp

Description: CDataObject and CEnumForamtEtc implementation.

**************************************************************************/

/**************************************************************************
#include statements
**************************************************************************/

#include "DataObj.h"

/**************************************************************************

CDataObject::CDataObject()

**************************************************************************/

CDataObject::CDataObject(COleDocument *pOleDoc)
{
OutputDebugString(TEXT("CDataObject's constructor\n"));

m_pOleDoc = pOleDoc;

m_pDataAdviseHolder = NULL;

m_cfEmbedSource = RegisterClipboardFormat(CF_EMBEDSOURCE);
}

/**************************************************************************

CDataObject::~CDataObject()

**************************************************************************/

CDataObject::~CDataObject(void)
{
if(m_pDataAdviseHolder)
m_pDataAdviseHolder->Release();

OutputDebugString(TEXT("CDataObject's destructor\n"));
}

/**************************************************************************

CDataObject::QueryInterface()

**************************************************************************/

STDMETHODIMP CDataObject::QueryInterface(REFIID riid, LPVOID *ppReturn)
{
OutputDebugString(TEXT("CDataObject::QueryInterface\n"));

return m_pOleDoc->QueryInterface(riid, ppReturn);
}

/**************************************************************************

CDataObject::AddRef()

**************************************************************************/

STDMETHODIMP_(ULONG) CDataObject::AddRef()
{
OutputDebugString(TEXT("CDataObject::AddRef\n"));

return m_pOleDoc->AddRef();
}

/**************************************************************************

CDataObject::Release()

**************************************************************************/

STDMETHODIMP_(ULONG) CDataObject::Release()
{
OutputDebugString(TEXT("CDataObject::Release\n"));

return m_pOleDoc->Release();
}

/**************************************************************************

CDataObject::QueryGetData()

**************************************************************************/

STDMETHODIMP CDataObject::QueryGetData(LPFORMATETC pformatetc)
{
OutputDebugString(TEXT("CDataObject::QueryGetData\n"));

HRESULT hr = DATA_E_FORMATETC;

// check the validity of the formatetc.
if( (pformatetc->cfFormat == m_cfEmbedSource) &&
(pformatetc->dwAspect == DVASPECT_CONTENT) &&
(pformatetc->tymed == TYMED_ISTORAGE))
{
hr = S_OK;
}

return hr;
}

/**************************************************************************

CDataObject::DAdvise()

**************************************************************************/

STDMETHODIMP CDataObject::DAdvise( LPFORMATETC pFormatetc,
DWORD advf,
LPADVISESINK pAdvSink,
LPDWORD pdwConnection)
{
OutputDebugString(TEXT("CDataObject::DAdvise\n"));

// if no DataAdviseHolder has been created, then create one.
if(!m_pDataAdviseHolder)
CreateDataAdviseHolder(&m_pDataAdviseHolder);

if(m_pDataAdviseHolder)
{
// pass on to the DataAdviseHolder
return m_pDataAdviseHolder->Advise(this, pFormatetc, advf, pAdvSink, pdwConnection);
}

return E_FAIL;
}

/**************************************************************************

CDataObject::DUnadvise()

**************************************************************************/

STDMETHODIMP CDataObject::DUnadvise(DWORD dwConnection)
{
OutputDebugString(TEXT("CDataObject::DUnadvise\n"));

if(m_pDataAdviseHolder)
{
// pass on to the DataAdviseHolder
return m_pDataAdviseHolder->Unadvise(dwConnection);
}

return E_FAIL;
}

/**************************************************************************

CDataObject::GetData()

**************************************************************************/

STDMETHODIMP CDataObject::GetData(LPFORMATETC pFE, LPSTGMEDIUM pStgMedium)
{
OutputDebugString(TEXT("CDataObject::GetData\n"));

HRESULT hr = E_NOTIMPL;

return hr;
}

/**************************************************************************

CDataObject::GetDataHere()

**************************************************************************/

STDMETHODIMP CDataObject::GetDataHere(LPFORMATETC pFormatEtc, LPSTGMEDIUM pStgMedium)
{
OutputDebugString(TEXT("CDataObject::GetDataHere\n"));

HRESULT hr = DATA_E_FORMATETC;

if(pFormatEtc->cfFormat == m_cfEmbedSource)
{
hr = GetOleObjectDataHere( m_pOleDoc->m_pPersistStorage,
pFormatEtc,
pStgMedium);
}

return hr;
}

/**************************************************************************

CDataObject::GetCanonicalFormatEtc()

**************************************************************************/

STDMETHODIMP CDataObject::GetCanonicalFormatEtc(LPFORMATETC pformatetc, LPFORMATETC pformatetcOut)
{
OutputDebugString(TEXT("CDataObject::GetCanonicalFormatEtc\n"));

HRESULT hr;

if(!pformatetcOut)
return E_INVALIDARG;

//set all out parameters to NULL.
pformatetcOut->ptd = NULL;

if(!pformatetc)
return E_INVALIDARG;

// OLE2NOTE: we must validate that the format requested is supported
if(NOERROR != (hr = QueryGetData(pformatetc)))
return hr;

/* OLE2NOTE: an app that is insensitive to target device (as
** SimpSvr is) should fill in the lpformatOut parameter
** but NULL out the "ptd" field; it should return NOERROR if the
** input formatetc->ptd what non-NULL. this tells the caller
** that it is NOT necessary to maintain a separate screen
** rendering and printer rendering. if should return
** DATA_S_SAMEFORMATETC if the input and output formatetc's are
** identical.
*/

*pformatetcOut = *pformatetc;

if(NULL == pformatetc->ptd)
return DATA_S_SAMEFORMATETC;

pformatetcOut->ptd = NULL;

return NOERROR;
}

/**************************************************************************

CDataObject::SetData()

**************************************************************************/

STDMETHODIMP CDataObject::SetData( LPFORMATETC pformatetc,
LPSTGMEDIUM pmedium,
BOOL fRelease)
{
OutputDebugString(TEXT("CDataObject::SetData\n"));

return DATA_E_FORMATETC;
}

/**************************************************************************

CDataObject::EnumFormatEtc()

**************************************************************************/

STDMETHODIMP CDataObject::EnumFormatEtc( DWORD dwDirection,
LPENUMFORMATETC *ppenumFormatEtc)
{
OutputDebugString(TEXT("CDataObject::EnumFormatEtc\n"));

// need to NULL the out parameter
*ppenumFormatEtc = NULL;

if(DATADIR_SET == dwDirection)
return E_NOTIMPL;

*ppenumFormatEtc = new CEnumFormatEtc();

if(*ppenumFormatEtc)
{
(*ppenumFormatEtc)->AddRef();
return S_OK;
}

return E_OUTOFMEMORY;
}

/**************************************************************************

CDataObject::EnumDAdvise()

**************************************************************************/

STDMETHODIMP CDataObject::EnumDAdvise(LPENUMSTATDATA *ppenumAdvise)
{
OutputDebugString(TEXT("CDataObject::EnumDAdvise\n"));

// need to NULL the out parameter
*ppenumAdvise = NULL;

return m_pDataAdviseHolder->EnumAdvise(ppenumAdvise);
}

//////////////////////////////////////////////////////////////////////////////
//
// CEnumFormatEtc Implementation
//

/**************************************************************************

CEnumFormatEtc::CEnumFormatEtc()

**************************************************************************/

CEnumFormatEtc::CEnumFormatEtc()
{
OutputDebugString(TEXT("CEnumFormatEtc's constructor\n"));

m_ObjRefCount = 0;

m_iCur = 0;

m_cfEmbedSource = RegisterClipboardFormat(CF_EMBEDSOURCE);
}

/**************************************************************************

CEnumFormatEtc::~CEnumFormatEtc()

**************************************************************************/

CEnumFormatEtc::~CEnumFormatEtc(void)
{
OutputDebugString(TEXT("CEnumFormatEtc's destructor\n"));
}

/**************************************************************************

CEnumFormatEtc::QueryInterface()

**************************************************************************/

STDMETHODIMP CEnumFormatEtc::QueryInterface(REFIID riid, LPVOID *ppReturn)
{
OutputDebugString(TEXT("CEnumFormatEtc::QueryInterface\n"));

*ppReturn = NULL;

if(IsEqualIID(riid, IID_IUnknown))
{
*ppReturn = (LPVOID)this;
}
else if(IsEqualIID(riid, IID_IEnumFORMATETC))
{
*ppReturn = (LPVOID)this;
}

if(NULL != *ppReturn)
{
((LPUNKNOWN)*ppReturn)->AddRef();
return NOERROR;
}

return E_NOINTERFACE;
}

/**************************************************************************

CEnumFormatEtc::AddRef()

**************************************************************************/

STDMETHODIMP_(ULONG) CEnumFormatEtc::AddRef(void)
{
OutputDebugString(TEXT("CEnumFormatEtc::AddRef\n"));

return ++m_ObjRefCount;
}

/**************************************************************************

CEnumFormatEtc::Release()

**************************************************************************/

STDMETHODIMP_(ULONG) CEnumFormatEtc::Release(void)
{
TCHAR szText[MAX_PATH];
wsprintf(szText, TEXT("CEnumFormatEtc::Release - ref count will be %d\n"), m_ObjRefCount - 1);
OutputDebugString(szText);

if(0 == --m_ObjRefCount)
{
delete this;
return 0;
}

return m_ObjRefCount;
}

/**************************************************************************

CEnumFormatEtc::Next()

**************************************************************************/

STDMETHODIMP CEnumFormatEtc::Next(ULONG cRequested, LPFORMATETC pFE, ULONG* puFetched)
{
OutputDebugString(TEXT("CEnumFormatEtc::Next\n"));

if(m_iCur > 0)
{
*puFetched = 0;
return S_FALSE;
}

pFE->cfFormat = m_cfEmbedSource;
pFE->dwAspect = DVASPECT_CONTENT;
pFE->tymed == TYMED_ISTORAGE;

*puFetched = 1;

m_iCur++;

return S_OK;
}

/**************************************************************************

CEnumFormatEtc::Skip()

**************************************************************************/

STDMETHODIMP CEnumFormatEtc::Skip(ULONG cSkip)
{
OutputDebugString(TEXT("CEnumFormatEtc::Skip\n"));

if((m_iCur + cSkip) > 1)
return S_FALSE;

m_iCur += cSkip;

return S_OK;
}

/**************************************************************************

CEnumFormatEtc::Reset()

**************************************************************************/

STDMETHODIMP CEnumFormatEtc::Reset(void)
{
OutputDebugString(TEXT("CEnumFormatEtc::Reset\n"));

m_iCur = 0;

return S_OK;
}

/**************************************************************************

CEnumFormatEtc::Clone()

**************************************************************************/

STDMETHODIMP CEnumFormatEtc::Clone(LPENUMFORMATETC* ppEnum)
{
OutputDebugString(TEXT("CEnumFormatEtc::Clone\n"));

CEnumFormatEtc* pNew;

*ppEnum = NULL;

// Create the clone.
pNew = new CEnumFormatEtc();
if (NULL == pNew)
return (ResultFromScode(E_OUTOFMEMORY));

pNew->AddRef();
pNew->m_iCur = m_iCur;

*ppEnum = pNew;

return S_OK;
}