1931 lines
37 KiB
C++
1931 lines
37 KiB
C++
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Microsoft Windows
|
|||
|
// Copyright (C) Microsoft Corporation, 1992 - 1993.
|
|||
|
//
|
|||
|
// File: gendata.cpp
|
|||
|
//
|
|||
|
// Contents: implementation of CGenDataObject
|
|||
|
//
|
|||
|
// Classes:
|
|||
|
//
|
|||
|
// Functions:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 06-Jun-94 alexgo added support for OLE1 tests
|
|||
|
// 24-Mar-94 alexgo author
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
#include "oletest.h"
|
|||
|
#include "gendata.h"
|
|||
|
|
|||
|
static const CLSID CLSID_TestCLSID = {0xaabbccee, 0x1122, 0x3344, { 0x55, 0x66,
|
|||
|
0x77, 0x88, 0x99, 0x00, 0xaa, 0xbb }};
|
|||
|
|
|||
|
static const char szTestString[] = "A carefully chosen test string";
|
|||
|
static const OLECHAR wszTestStream[] = OLESTR("TestStream");
|
|||
|
static const char szNativeData[] = "Ole1Test NATIVE data";
|
|||
|
static const char szOwnerLinkData[] = "PBrush\0foo.bmp\00 0 200 160\0\0";
|
|||
|
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::CGenDataObject
|
|||
|
//
|
|||
|
// Synopsis: constructor
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation:
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 06-Jun-94 alexgo added OLE1 support
|
|||
|
// 24-Mar-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
CGenDataObject::CGenDataObject( )
|
|||
|
{
|
|||
|
m_refs = 0;
|
|||
|
m_fQICalled = FALSE;
|
|||
|
|
|||
|
// now set up the formats that we support
|
|||
|
|
|||
|
m_cfTestStorage = RegisterClipboardFormat("OleTest Storage Format");
|
|||
|
m_cfEmbeddedObject = RegisterClipboardFormat("Embedded Object");
|
|||
|
m_cfEmbedSource = RegisterClipboardFormat("Embed Source");
|
|||
|
m_cfLinkSource = RegisterClipboardFormat("Link Source");
|
|||
|
m_cfObjectDescriptor = RegisterClipboardFormat("Object Descriptor");
|
|||
|
m_cfLinkSrcDescriptor = RegisterClipboardFormat("Link Source "
|
|||
|
"Descriptor");
|
|||
|
m_cfOwnerLink = RegisterClipboardFormat("OwnerLink");
|
|||
|
m_cfNative = RegisterClipboardFormat("Native");
|
|||
|
m_cfObjectLink = RegisterClipboardFormat("ObjectLink");
|
|||
|
|
|||
|
// now set up the array of formatetc's. SetupOle1Mode must be
|
|||
|
// called if you want OLE1 formats
|
|||
|
|
|||
|
m_rgFormats = new FORMATETC[2];
|
|||
|
|
|||
|
assert(m_rgFormats);
|
|||
|
|
|||
|
m_rgFormats[0].cfFormat = m_cfTestStorage;
|
|||
|
m_rgFormats[0].ptd = NULL;
|
|||
|
m_rgFormats[0].dwAspect = DVASPECT_CONTENT;
|
|||
|
m_rgFormats[0].lindex = -1;
|
|||
|
m_rgFormats[0].tymed = TYMED_ISTORAGE;
|
|||
|
|
|||
|
m_rgFormats[1].cfFormat = m_cfEmbeddedObject;
|
|||
|
m_rgFormats[1].ptd = NULL;
|
|||
|
m_rgFormats[1].dwAspect = DVASPECT_CONTENT;
|
|||
|
m_rgFormats[1].lindex = -1;
|
|||
|
m_rgFormats[1].tymed = TYMED_ISTORAGE;
|
|||
|
|
|||
|
m_cFormats = 2;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::QueryInterface
|
|||
|
//
|
|||
|
// Synopsis: returns requested interfaces
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [riid] -- the requested interface
|
|||
|
// [ppvObj] -- where to put the interface pointer
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: HRESULT
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IDataObject
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 24-Mar-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP CGenDataObject::QueryInterface( REFIID riid, LPVOID *ppvObj )
|
|||
|
{
|
|||
|
HRESULT hresult = NOERROR;
|
|||
|
|
|||
|
m_fQICalled = TRUE;
|
|||
|
|
|||
|
if( IsEqualIID(riid, IID_IUnknown) ||
|
|||
|
IsEqualIID(riid, IID_IDataObject) )
|
|||
|
{
|
|||
|
*ppvObj = this;
|
|||
|
AddRef();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
*ppvObj = NULL;
|
|||
|
hresult = ResultFromScode(E_NOINTERFACE);
|
|||
|
}
|
|||
|
|
|||
|
return hresult;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::AddRef
|
|||
|
//
|
|||
|
// Synopsis: increments the reference count
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: void
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: ULONG-- the new reference count
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IDataObject
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 24-Mar-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP_(ULONG) CGenDataObject::AddRef( )
|
|||
|
{
|
|||
|
return ++m_refs;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::Release
|
|||
|
//
|
|||
|
// Synopsis: decrements the reference count on the object
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: void
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: ULONG -- the new reference count
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IDataObject
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 24-Mar-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP_(ULONG) CGenDataObject::Release( )
|
|||
|
{
|
|||
|
ULONG cRefs;
|
|||
|
|
|||
|
if( (cRefs = --m_refs ) == 0 )
|
|||
|
{
|
|||
|
delete this;
|
|||
|
}
|
|||
|
return cRefs;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::GetData
|
|||
|
//
|
|||
|
// Synopsis: retrieves data of the specified format
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [pformatetc] -- the requested format
|
|||
|
// [pmedium] -- where to put the data
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: HRESULT
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IDataObject
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 06-Jun-94 alexgo added OLE1 support
|
|||
|
// 24-Mar-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP CGenDataObject::GetData( LPFORMATETC pformatetc, LPSTGMEDIUM
|
|||
|
pmedium)
|
|||
|
{
|
|||
|
HRESULT hresult = NOERROR;
|
|||
|
|
|||
|
if( (pformatetc->cfFormat == m_cfTestStorage ||
|
|||
|
pformatetc->cfFormat == m_cfEmbeddedObject ) &&
|
|||
|
(pformatetc->tymed & TYMED_ISTORAGE) )
|
|||
|
{
|
|||
|
pmedium->tymed = TYMED_ISTORAGE;
|
|||
|
pmedium->pstg = GetTestStorage();
|
|||
|
assert(pmedium->pstg);
|
|||
|
}
|
|||
|
|
|||
|
// test for OLE1 formats
|
|||
|
|
|||
|
else if( pformatetc->cfFormat == m_cfOwnerLink &&
|
|||
|
(m_fOle1 & OLE1_OFFER_OWNERLINK ) &&
|
|||
|
(pformatetc->tymed & TYMED_HGLOBAL) )
|
|||
|
{
|
|||
|
pmedium->tymed = TYMED_HGLOBAL;
|
|||
|
pmedium->hGlobal = GetOwnerOrObjectLink();
|
|||
|
assert(pmedium->hGlobal);
|
|||
|
}
|
|||
|
else if( pformatetc->cfFormat == m_cfObjectLink &&
|
|||
|
(m_fOle1 & OLE1_OFFER_OBJECTLINK ) &&
|
|||
|
(pformatetc->tymed & TYMED_HGLOBAL) )
|
|||
|
{
|
|||
|
pmedium->tymed = TYMED_HGLOBAL;
|
|||
|
pmedium->hGlobal = GetOwnerOrObjectLink();
|
|||
|
assert(pmedium->hGlobal);
|
|||
|
}
|
|||
|
else if( pformatetc->cfFormat == m_cfNative &&
|
|||
|
(m_fOle1 & OLE1_OFFER_NATIVE ) &&
|
|||
|
(pformatetc->tymed &TYMED_HGLOBAL ) )
|
|||
|
{
|
|||
|
pmedium->tymed = TYMED_HGLOBAL;
|
|||
|
pmedium->hGlobal = GetNativeData();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
hresult = ResultFromScode(E_FAIL);
|
|||
|
}
|
|||
|
|
|||
|
return hresult;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::GetDataHere
|
|||
|
//
|
|||
|
// Synopsis: retrieves data of the specified format
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [pformatetc] -- the requested format
|
|||
|
// [pmedium] -- where to put the data
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: HRESULT
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IDataObject
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 24-Mar-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP CGenDataObject::GetDataHere( LPFORMATETC pformatetc, LPSTGMEDIUM
|
|||
|
pmedium)
|
|||
|
{
|
|||
|
(void)pformatetc;
|
|||
|
(void)pmedium;
|
|||
|
|
|||
|
return ResultFromScode(E_NOTIMPL);
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::QueryGetData
|
|||
|
//
|
|||
|
// Synopsis: queries whether a GetData call would succeed
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [pformatetc] -- the requested format
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: HRESULT
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IDataObject
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 24-Mar-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP CGenDataObject::QueryGetData( LPFORMATETC pformatetc )
|
|||
|
{
|
|||
|
(void)pformatetc;
|
|||
|
|
|||
|
return ResultFromScode(E_NOTIMPL);
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::GetCanonicalFormatEtc
|
|||
|
//
|
|||
|
// Synopsis: retrieve the canonical format
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [pformatetc] -- the requested format
|
|||
|
// [pformatetcOut] -- the canonical format
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: HRESULT
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IDataObject
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 24-Mar-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP CGenDataObject::GetCanonicalFormatEtc( LPFORMATETC pformatetc,
|
|||
|
LPFORMATETC pformatetcOut)
|
|||
|
{
|
|||
|
(void)pformatetc;
|
|||
|
(void)pformatetcOut;
|
|||
|
|
|||
|
return ResultFromScode(E_NOTIMPL);
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::SetData
|
|||
|
//
|
|||
|
// Synopsis: sets data of the specified format
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [pformatetc] -- the format of the data
|
|||
|
// [pmedium] -- the data
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: HRESULT
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IDataObject
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 24-Mar-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP CGenDataObject::SetData( LPFORMATETC pformatetc, LPSTGMEDIUM
|
|||
|
pmedium, BOOL fRelease)
|
|||
|
{
|
|||
|
(void)pformatetc;
|
|||
|
(void)pmedium;
|
|||
|
(void)fRelease;
|
|||
|
|
|||
|
return ResultFromScode(E_NOTIMPL);
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::EnumFormatEtc
|
|||
|
//
|
|||
|
// Synopsis: return an enumerator for the available data formats
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [dwDirection] -- the direction (GET or SET)
|
|||
|
// [ppenum] -- where to put the enumerator
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: HRESULT
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IDataObject
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 24-Mar-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP CGenDataObject::EnumFormatEtc( DWORD dwDirection,
|
|||
|
LPENUMFORMATETC * ppenum )
|
|||
|
{
|
|||
|
HRESULT hresult;
|
|||
|
|
|||
|
if( dwDirection == DATADIR_GET )
|
|||
|
{
|
|||
|
hresult = CGenEnumFormatEtc::Create( ppenum, m_rgFormats,
|
|||
|
m_cFormats);
|
|||
|
assert(hresult == NOERROR);
|
|||
|
|
|||
|
return hresult;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return ResultFromScode(E_NOTIMPL);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::DAdvise
|
|||
|
//
|
|||
|
// Synopsis: register a data advise
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [pformatetc] -- the requested format
|
|||
|
// [dwAdvf] -- advise flags
|
|||
|
// [pAdvSink] -- the advise sink
|
|||
|
// [pdwConnection] -- where to put the connection ID
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: HRESULT
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IDataObject
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 24-Mar-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP CGenDataObject::DAdvise( LPFORMATETC pformatetc, DWORD dwAdvf,
|
|||
|
IAdviseSink * pAdvSink, DWORD *pdwConnection )
|
|||
|
{
|
|||
|
(void)pformatetc;
|
|||
|
(void)dwAdvf;
|
|||
|
(void)pAdvSink;
|
|||
|
(void)pdwConnection;
|
|||
|
|
|||
|
return ResultFromScode(E_NOTIMPL);
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::DUnadvise
|
|||
|
//
|
|||
|
// Synopsis: unadvises an advise connection
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [dwConnection] -- the connection to remove
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: HRESULT
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IDataObject
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 24-Mar-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP CGenDataObject::DUnadvise(DWORD dwConnection)
|
|||
|
{
|
|||
|
(void)dwConnection;
|
|||
|
|
|||
|
return ResultFromScode(E_NOTIMPL);
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::EnumDAdvise
|
|||
|
//
|
|||
|
// Synopsis: enumerates data advises
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [ppenum] -- where to put the enumerator
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: HRESULT
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IDataObject
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 24-Mar-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP CGenDataObject::EnumDAdvise( LPENUMSTATDATA *ppenum)
|
|||
|
{
|
|||
|
(void)ppenum;
|
|||
|
|
|||
|
return ResultFromScode(E_NOTIMPL);
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::VerifyMedium
|
|||
|
//
|
|||
|
// Synopsis: verifies the contents of the given medium
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [pmedium] -- the medium to verify
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: BOOL
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation:
|
|||
|
//
|
|||
|
// Algorithm: For OLE1 formats, the following must be true:
|
|||
|
// cfEmbeddedObject:
|
|||
|
// must have OWNERLINK and !NATIVE
|
|||
|
// or OWNERLINK precedes NATIVE
|
|||
|
// cfEmbedSource:
|
|||
|
// must have NATIVE && OWNERLINK and
|
|||
|
// OWNERLINK must not precede NATIVE
|
|||
|
// cfObjectDescriptor:
|
|||
|
// same as EmbedSource
|
|||
|
// cfLinkSource:
|
|||
|
// must have either OBJECTLINK or
|
|||
|
// OWNERLINK must precede NATIVE
|
|||
|
// cfLinkSrcDescriptor:
|
|||
|
// same as LinkSource
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 06-Jun-94 alexgo added OLE1 support
|
|||
|
// 15-Apr-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL CGenDataObject::VerifyFormatAndMedium( FORMATETC *pformatetc,
|
|||
|
STGMEDIUM *pmedium )
|
|||
|
{
|
|||
|
// if any of these flags are set, then we were offering OLE1
|
|||
|
// data. Do relevant tests.
|
|||
|
|
|||
|
if( (m_fOle1 & (OLE1_OFFER_OWNERLINK | OLE1_OFFER_OBJECTLINK |
|
|||
|
OLE1_OFFER_NATIVE) ) )
|
|||
|
{
|
|||
|
// now do individual tests for formats
|
|||
|
if( pformatetc->cfFormat == m_cfEmbedSource ||
|
|||
|
pformatetc->cfFormat == m_cfObjectDescriptor)
|
|||
|
{
|
|||
|
if( (m_fOle1 & OLE1_OFFER_NATIVE) &&
|
|||
|
(m_fOle1 & OLE1_OFFER_OWNERLINK) &&
|
|||
|
!(m_fOle1 & OLE1_OWNERLINK_PRECEDES_NATIVE) )
|
|||
|
{
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
else if( pformatetc->cfFormat == m_cfLinkSource ||
|
|||
|
pformatetc->cfFormat == m_cfLinkSrcDescriptor)
|
|||
|
{
|
|||
|
if( (m_fOle1 & OLE1_OFFER_OBJECTLINK) ||
|
|||
|
((m_fOle1 & OLE1_OFFER_OWNERLINK) &&
|
|||
|
(m_fOle1 & OLE1_OFFER_NATIVE) &&
|
|||
|
(m_fOle1 & OLE1_OWNERLINK_PRECEDES_NATIVE)))
|
|||
|
{
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// no 'else' so we check for cfObjectDescriptor again
|
|||
|
if( pformatetc->cfFormat == m_cfEmbeddedObject ||
|
|||
|
pformatetc->cfFormat == m_cfObjectDescriptor )
|
|||
|
{
|
|||
|
if( ((m_fOle1 & OLE1_OFFER_NATIVE) &&
|
|||
|
(m_fOle1 & OLE1_OFFER_OWNERLINK) &&
|
|||
|
(m_fOle1 & OLE1_OWNERLINK_PRECEDES_NATIVE)) ||
|
|||
|
((m_fOle1 & OLE1_OFFER_OWNERLINK) &&
|
|||
|
!(m_fOle1 & OLE1_OFFER_NATIVE)) )
|
|||
|
{
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
// fall through and do rest of testing, in case we didn't
|
|||
|
// hit one of the synthesized formats.
|
|||
|
}
|
|||
|
|
|||
|
if( pformatetc->cfFormat == m_cfTestStorage ||
|
|||
|
pformatetc->cfFormat == m_cfEmbeddedObject )
|
|||
|
{
|
|||
|
return VerifyTestStorage( pformatetc, pmedium );
|
|||
|
}
|
|||
|
else if( pformatetc->cfFormat == m_cfOwnerLink ||
|
|||
|
pformatetc->cfFormat == m_cfObjectLink )
|
|||
|
{
|
|||
|
return VerifyOwnerOrObjectLink(pformatetc, pmedium);
|
|||
|
}
|
|||
|
else if( pformatetc->cfFormat == m_cfNative )
|
|||
|
{
|
|||
|
return VerifyNativeData(pformatetc, pmedium);
|
|||
|
}
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::VerifyTestStorage
|
|||
|
//
|
|||
|
// Synopsis: verifies the test storage format
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: BOOL
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation:
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 15-Apr-94 alexgo author; tax day :-(
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL CGenDataObject::VerifyTestStorage( FORMATETC *pformatetc,
|
|||
|
STGMEDIUM *pmedium)
|
|||
|
{
|
|||
|
IStream * pstm;
|
|||
|
STATSTG statstg;
|
|||
|
char szBuf[sizeof(szTestString)];
|
|||
|
HRESULT hresult;
|
|||
|
|
|||
|
if( pmedium->tymed != TYMED_ISTORAGE )
|
|||
|
{
|
|||
|
//REVIEW: we may want to convert and test different
|
|||
|
//mediums at a later date
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// check the class ID
|
|||
|
|
|||
|
pmedium->pstg->Stat(&statstg, STATFLAG_NONAME);
|
|||
|
|
|||
|
if( !IsEqualCLSID(statstg.clsid, CLSID_TestCLSID) )
|
|||
|
{
|
|||
|
OutputString("Failed CLSID check on storage in "
|
|||
|
"VerifyTestStorage!!\r\n");
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// now open the test stream
|
|||
|
|
|||
|
hresult = pmedium->pstg->OpenStream(wszTestStream, NULL, (STGM_READ |
|
|||
|
STGM_SHARE_EXCLUSIVE), 0, &pstm);
|
|||
|
|
|||
|
if( hresult != NOERROR )
|
|||
|
{
|
|||
|
OutputString("OpenStream in VerifyTestStorage failed! (%lx)"
|
|||
|
"\r\n", hresult);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
hresult = pstm->Read((void *)szBuf, sizeof(szTestString), NULL);
|
|||
|
|
|||
|
if( hresult != NOERROR )
|
|||
|
{
|
|||
|
OutputString("Stream->Read failed in VerifyTestStorage (%lx)"
|
|||
|
"\r\n", hresult);
|
|||
|
pstm->Release();
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if( strcmp(szBuf, szTestString) != 0 )
|
|||
|
{
|
|||
|
OutputString("'%s' != '%s'\r\n", szBuf, szTestString);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
pstm->Release();
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::GetTestStorage (private)
|
|||
|
//
|
|||
|
// Synopsis:
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: a new storage
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation:
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 15-Apr-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
IStorage * CGenDataObject::GetTestStorage( void )
|
|||
|
{
|
|||
|
IStorage * pstg;
|
|||
|
IStream * pstm;
|
|||
|
HRESULT hresult;
|
|||
|
|
|||
|
|
|||
|
// create the docfile
|
|||
|
|
|||
|
hresult = StgCreateDocfile(NULL, (STGM_READWRITE | STGM_DIRECT |
|
|||
|
STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE), NULL,
|
|||
|
&pstg);
|
|||
|
|
|||
|
if( hresult != NOERROR )
|
|||
|
{
|
|||
|
OutputString("GetTestStorage: CreateDocfile failed!! (%lx)"
|
|||
|
"\r\n", hresult);
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
// set the class ID
|
|||
|
|
|||
|
hresult = pstg->SetClass(CLSID_TestCLSID);
|
|||
|
|
|||
|
// now create the stream
|
|||
|
|
|||
|
hresult = pstg->CreateStream(wszTestStream, (STGM_READWRITE |
|
|||
|
STGM_SHARE_EXCLUSIVE ), 0, 0, &pstm);
|
|||
|
|
|||
|
if( hresult != NOERROR )
|
|||
|
{
|
|||
|
OutputString("GetTestStorage: CreateStream failed! (%lx)\r\n",
|
|||
|
hresult);
|
|||
|
pstg->Release();
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
hresult = pstm->Write((void *)szTestString, sizeof(szTestString),
|
|||
|
NULL);
|
|||
|
|
|||
|
if( hresult != NOERROR )
|
|||
|
{
|
|||
|
OutputString("GetTestStorage: Stream->Write failed! (%lx)\r\n",
|
|||
|
hresult);
|
|||
|
pstm->Release();
|
|||
|
pstg->Release();
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
pstm->Release();
|
|||
|
|
|||
|
return pstg;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::GetOwnerOrObjectLink (private)
|
|||
|
//
|
|||
|
// Synopsis: Creates either cfOwnerLink or cfObjectLink for a dummy
|
|||
|
// Paintbrush (ole1) object
|
|||
|
//
|
|||
|
// Effects: allocates an HGLOBAL
|
|||
|
//
|
|||
|
// Arguments: void
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: HGLOBAL
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation:
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 06-Jun-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
HGLOBAL CGenDataObject::GetOwnerOrObjectLink( void )
|
|||
|
{
|
|||
|
HGLOBAL hglobal;
|
|||
|
char *pdata;
|
|||
|
|
|||
|
hglobal = GlobalAlloc(GMEM_MOVEABLE, sizeof(szOwnerLinkData));
|
|||
|
|
|||
|
assert(hglobal);
|
|||
|
|
|||
|
pdata = (char *)GlobalLock(hglobal);
|
|||
|
|
|||
|
assert(pdata);
|
|||
|
|
|||
|
memcpy(pdata, szOwnerLinkData, sizeof(szOwnerLinkData));
|
|||
|
|
|||
|
GlobalUnlock(hglobal);
|
|||
|
|
|||
|
return hglobal;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::GetNativeData (private)
|
|||
|
//
|
|||
|
// Synopsis: Creates OLE1 Native data
|
|||
|
//
|
|||
|
// Effects: allocates an hglobal
|
|||
|
//
|
|||
|
// Arguments: void
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: HGLOBAL
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation:
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 06-Jun-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
HGLOBAL CGenDataObject::GetNativeData( void )
|
|||
|
{
|
|||
|
HGLOBAL hglobal;
|
|||
|
char *pdata;
|
|||
|
|
|||
|
hglobal = GlobalAlloc(GMEM_MOVEABLE, sizeof(szNativeData) + 1);
|
|||
|
|
|||
|
assert(hglobal);
|
|||
|
|
|||
|
pdata = (char *)GlobalLock(hglobal);
|
|||
|
|
|||
|
assert(pdata);
|
|||
|
|
|||
|
memcpy(pdata, szNativeData, sizeof(szNativeData)+1);
|
|||
|
|
|||
|
GlobalUnlock(hglobal);
|
|||
|
|
|||
|
return hglobal;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::VerifyOwnerOrObjectLink
|
|||
|
//
|
|||
|
// Synopsis: verifies that the owner or object link data is correct
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [pformatetc] -- the formatetc describing the data
|
|||
|
// [pmedium] -- the data
|
|||
|
//
|
|||
|
// Requires: pformatetc must be for OwnerLink or ObjectLink
|
|||
|
//
|
|||
|
// Returns: BOOL
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation:
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 06-Jun-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
// NB!!: must be expanded to cover container-side cases
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL CGenDataObject::VerifyOwnerOrObjectLink( FORMATETC *pformatetc,
|
|||
|
STGMEDIUM *pmedium )
|
|||
|
{
|
|||
|
char * pdata;
|
|||
|
BOOL fRet = FALSE;
|
|||
|
|
|||
|
|
|||
|
assert(pformatetc->cfFormat == m_cfOwnerLink ||
|
|||
|
pformatetc->cfFormat == m_cfObjectLink );
|
|||
|
|
|||
|
// check standard stuff
|
|||
|
if( !(pformatetc->tymed & TYMED_HGLOBAL ) ||
|
|||
|
pformatetc->dwAspect != DVASPECT_CONTENT ||
|
|||
|
pformatetc->ptd != NULL ||
|
|||
|
pformatetc->lindex != -1 ||
|
|||
|
pmedium->tymed != TYMED_HGLOBAL )
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// if we offered the data natively from OLE1, then
|
|||
|
// check the contents.
|
|||
|
|
|||
|
// this conditional tests to see if the format in question
|
|||
|
// was originally offered by us
|
|||
|
|
|||
|
if( ((m_fOle1 & OLE1_OFFER_OWNERLINK) &&
|
|||
|
pformatetc->cfFormat == m_cfOwnerLink) ||
|
|||
|
((m_fOle1 & OLE1_OFFER_OBJECTLINK) &&
|
|||
|
pformatetc->cfFormat == m_cfObjectLink) )
|
|||
|
{
|
|||
|
|
|||
|
pdata = (char *)GlobalLock(pmedium->hGlobal);
|
|||
|
|
|||
|
if( memcmp(pdata, szOwnerLinkData,
|
|||
|
sizeof(szOwnerLinkData)) == 0 )
|
|||
|
{
|
|||
|
fRet = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
GlobalUnlock(pmedium->hGlobal);
|
|||
|
}
|
|||
|
// else CHECK SYNTHESIZED OLE1 FORMATS WHEN IMPLEMENTED
|
|||
|
|
|||
|
|
|||
|
return fRet;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::VerifyNativeData (private)
|
|||
|
//
|
|||
|
// Synopsis: verifies OLE1 Native data
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [pformatetc] -- formatetc for the data
|
|||
|
// [pmedium] -- location of the native data
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation:
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 06-Jun-95 alexgo author
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL CGenDataObject::VerifyNativeData( FORMATETC *pformatetc,
|
|||
|
STGMEDIUM *pmedium )
|
|||
|
{
|
|||
|
char * pdata;
|
|||
|
BOOL fRet = FALSE;
|
|||
|
|
|||
|
|
|||
|
assert(pformatetc->cfFormat == m_cfNative );
|
|||
|
|
|||
|
// check standard stuff
|
|||
|
if( !(pformatetc->tymed & TYMED_HGLOBAL) ||
|
|||
|
pformatetc->dwAspect != DVASPECT_CONTENT ||
|
|||
|
pformatetc->ptd != NULL ||
|
|||
|
pformatetc->lindex != -1 ||
|
|||
|
pmedium->tymed != TYMED_HGLOBAL )
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// if we offered the data natively from OLE1, then
|
|||
|
// check the contents.
|
|||
|
|
|||
|
// this conditional tests to see if the format in question
|
|||
|
// was originally offered by us
|
|||
|
|
|||
|
if( (m_fOle1 & OLE1_OFFER_NATIVE) )
|
|||
|
{
|
|||
|
|
|||
|
pdata = (char *)GlobalLock(pmedium->hGlobal);
|
|||
|
|
|||
|
if( memcmp(pdata, szNativeData,
|
|||
|
sizeof(szNativeData)) == 0 )
|
|||
|
{
|
|||
|
fRet = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
GlobalUnlock(pmedium->hGlobal);
|
|||
|
}
|
|||
|
// else CHECK SYNTHESIZED OLE1 FORMATS WHEN IMPLEMENTED
|
|||
|
|
|||
|
|
|||
|
return fRet;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::SetupOle1Mode (public)
|
|||
|
//
|
|||
|
// Synopsis: Sets the data object up for OLE1 compatibility mode
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [fFlags] -- specifies various OLE1 options
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: void
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation:
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 06-Jun-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
// The default test information in the data object will be
|
|||
|
// lost by this call. Simply create a new data object if
|
|||
|
// it is needed again.
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
void CGenDataObject::SetupOle1Mode( Ole1TestFlags fFlags )
|
|||
|
{
|
|||
|
DWORD count = 0, i = 0;
|
|||
|
UINT cfFormats[3]; // OLE1 formats offered
|
|||
|
|
|||
|
if( fFlags == 0 )
|
|||
|
{
|
|||
|
// don't need to do anything
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// the formats we had previously
|
|||
|
|
|||
|
delete m_rgFormats;
|
|||
|
|
|||
|
|
|||
|
// first figure out how many formats we need
|
|||
|
|
|||
|
if( (fFlags & OLE1_OFFER_NATIVE) )
|
|||
|
{
|
|||
|
if( !((fFlags & OLE1_OWNERLINK_PRECEDES_NATIVE) &&
|
|||
|
(fFlags & OLE1_OFFER_OWNERLINK)) )
|
|||
|
{
|
|||
|
cfFormats[i] = m_cfNative;
|
|||
|
i++;
|
|||
|
}
|
|||
|
count++;
|
|||
|
}
|
|||
|
|
|||
|
if( (fFlags & OLE1_OFFER_OWNERLINK) )
|
|||
|
{
|
|||
|
cfFormats[i] = m_cfOwnerLink;
|
|||
|
i++;
|
|||
|
|
|||
|
if( (fFlags & OLE1_OWNERLINK_PRECEDES_NATIVE) &&
|
|||
|
(fFlags & OLE1_OFFER_NATIVE) )
|
|||
|
{
|
|||
|
cfFormats[i] = m_cfNative;
|
|||
|
i++;
|
|||
|
}
|
|||
|
|
|||
|
count++;
|
|||
|
}
|
|||
|
|
|||
|
if( (fFlags & OLE1_OFFER_OBJECTLINK) )
|
|||
|
{
|
|||
|
|
|||
|
cfFormats[i] = m_cfObjectLink;
|
|||
|
|
|||
|
count++;
|
|||
|
}
|
|||
|
|
|||
|
m_rgFormats = new FORMATETC[count];
|
|||
|
|
|||
|
assert(m_rgFormats);
|
|||
|
|
|||
|
for(i = 0; i < count; i++ )
|
|||
|
{
|
|||
|
m_rgFormats[i].cfFormat = cfFormats[i];
|
|||
|
m_rgFormats[i].ptd = NULL;
|
|||
|
m_rgFormats[i].dwAspect = DVASPECT_CONTENT;
|
|||
|
m_rgFormats[i].lindex = -1;
|
|||
|
m_rgFormats[i].tymed = TYMED_HGLOBAL;
|
|||
|
}
|
|||
|
|
|||
|
m_cFormats = count;
|
|||
|
|
|||
|
m_fOle1 = fFlags;
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::SetOle1ToClipboard
|
|||
|
//
|
|||
|
// Synopsis: stuffs available OLE1 formats to the clipboard
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: void
|
|||
|
//
|
|||
|
// Requires: SetOle1Mode *must* have been called
|
|||
|
//
|
|||
|
// Returns: HRESULT
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation:
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 06-Jun-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
HRESULT CGenDataObject::SetOle1ToClipboard( void )
|
|||
|
{
|
|||
|
HRESULT hresult = NOERROR;
|
|||
|
DWORD i;
|
|||
|
HGLOBAL hglobal;
|
|||
|
|
|||
|
assert((m_fOle1 & (OLE1_OFFER_OWNERLINK | OLE1_OFFER_OBJECTLINK |
|
|||
|
OLE1_OFFER_NATIVE)));
|
|||
|
|
|||
|
if( !OpenClipboard(vApp.m_hwndMain) )
|
|||
|
{
|
|||
|
return ResultFromScode(CLIPBRD_E_CANT_OPEN);
|
|||
|
}
|
|||
|
|
|||
|
if( !EmptyClipboard() )
|
|||
|
{
|
|||
|
CloseClipboard();
|
|||
|
return ResultFromScode(CLIPBRD_E_CANT_EMPTY);
|
|||
|
}
|
|||
|
|
|||
|
for( i = 0 ; i < m_cFormats; i++ )
|
|||
|
{
|
|||
|
if( m_rgFormats[i].cfFormat == m_cfNative )
|
|||
|
{
|
|||
|
hglobal = GetNativeData();
|
|||
|
SetClipboardData(m_cfNative, hglobal);
|
|||
|
}
|
|||
|
else if( m_rgFormats[i].cfFormat == m_cfOwnerLink )
|
|||
|
{
|
|||
|
hglobal = GetOwnerOrObjectLink();
|
|||
|
SetClipboardData(m_cfOwnerLink, hglobal);
|
|||
|
}
|
|||
|
else if( m_rgFormats[i].cfFormat == m_cfObjectLink )
|
|||
|
{
|
|||
|
hglobal = GetOwnerOrObjectLink();
|
|||
|
SetClipboardData(m_cfObjectLink, hglobal);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
hresult = ResultFromScode(E_UNEXPECTED);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
CloseClipboard();
|
|||
|
|
|||
|
return hresult;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::HasQIBeenCalled (public)
|
|||
|
//
|
|||
|
// Synopsis: returns wether or not QueryInterface has been called on
|
|||
|
// this data object. Used in testing OleQueryCreateFromData
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: none
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: TRUE/FALSE
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation:
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 23-Aug-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL CGenDataObject::HasQIBeenCalled()
|
|||
|
{
|
|||
|
return m_fQICalled;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenDataObject::SetDatFormats
|
|||
|
//
|
|||
|
// Synopsis: sets the formats that the data object will offer
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [fFlags] -- formats to offer
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: void
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation:
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 23-Aug-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
void CGenDataObject::SetDataFormats( DataFlags fFlags )
|
|||
|
{
|
|||
|
DWORD cFormats = 0;
|
|||
|
DWORD flags = (DWORD)fFlags;
|
|||
|
DWORD i =0;
|
|||
|
|
|||
|
if( m_rgFormats )
|
|||
|
{
|
|||
|
delete m_rgFormats;
|
|||
|
m_rgFormats = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if( flags == 0 )
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// count the number of formats to offer
|
|||
|
|
|||
|
cFormats++;
|
|||
|
|
|||
|
while( flags &= (flags -1) )
|
|||
|
{
|
|||
|
cFormats++;
|
|||
|
}
|
|||
|
|
|||
|
m_rgFormats = new FORMATETC[cFormats];
|
|||
|
|
|||
|
assert(m_rgFormats);
|
|||
|
|
|||
|
memset(m_rgFormats, 0, sizeof(FORMATETC)*cFormats);
|
|||
|
|
|||
|
if( fFlags & OFFER_TESTSTORAGE )
|
|||
|
{
|
|||
|
m_rgFormats[i].cfFormat = m_cfTestStorage;
|
|||
|
m_rgFormats[i].ptd = NULL;
|
|||
|
m_rgFormats[i].dwAspect = DVASPECT_CONTENT;
|
|||
|
m_rgFormats[i].lindex = -1;
|
|||
|
m_rgFormats[i].tymed = TYMED_ISTORAGE;
|
|||
|
|
|||
|
i++;
|
|||
|
}
|
|||
|
|
|||
|
if( fFlags & OFFER_EMBEDDEDOBJECT )
|
|||
|
{
|
|||
|
m_rgFormats[i].cfFormat = m_cfEmbeddedObject;
|
|||
|
m_rgFormats[i].ptd = NULL;
|
|||
|
m_rgFormats[i].dwAspect = DVASPECT_CONTENT;
|
|||
|
m_rgFormats[i].lindex = -1;
|
|||
|
m_rgFormats[i].tymed = TYMED_ISTORAGE;
|
|||
|
i++;
|
|||
|
}
|
|||
|
|
|||
|
m_cFormats = i;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Generic Data Object formatetc enumerator
|
|||
|
//
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenEnumFormatEtc::QueryInterface
|
|||
|
//
|
|||
|
// Synopsis: returns requested interfaces
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [riid] -- the requested interface
|
|||
|
// [ppvObj] -- where to put the interface pointer
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: HRESULT
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IEnumFORMATETC
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 15-Apr-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP CGenEnumFormatEtc::QueryInterface( REFIID riid, LPVOID *ppvObj )
|
|||
|
{
|
|||
|
HRESULT hresult = NOERROR;
|
|||
|
|
|||
|
if( IsEqualIID(riid, IID_IUnknown) ||
|
|||
|
IsEqualIID(riid, IID_IEnumFORMATETC) )
|
|||
|
{
|
|||
|
*ppvObj = this;
|
|||
|
AddRef();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
*ppvObj = NULL;
|
|||
|
hresult = ResultFromScode(E_NOINTERFACE);
|
|||
|
}
|
|||
|
|
|||
|
return hresult;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenEnumFormatEtc::AddRef
|
|||
|
//
|
|||
|
// Synopsis: increments the reference count
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: void
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: ULONG-- the new reference count
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IEnumFORMATETC
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 15-Apr-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP_(ULONG) CGenEnumFormatEtc::AddRef( )
|
|||
|
{
|
|||
|
return ++m_refs;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenEnumFormatEtc::Release
|
|||
|
//
|
|||
|
// Synopsis: decrements the reference count on the object
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: void
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: ULONG -- the new reference count
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IEnumFORMATETC
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 15-Apr-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP_(ULONG) CGenEnumFormatEtc::Release( )
|
|||
|
{
|
|||
|
ULONG cRefs;
|
|||
|
|
|||
|
if( (cRefs = --m_refs ) == 0 )
|
|||
|
{
|
|||
|
delete this;
|
|||
|
}
|
|||
|
return cRefs;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenEnumFormatEtc::Next
|
|||
|
//
|
|||
|
// Synopsis: gets the next [celt] formats
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [celt] -- the number of elements to fetch
|
|||
|
// [rgelt] -- where to put them
|
|||
|
// [pceltFetched] -- the number of formats actually fetched
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: NOERROR
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IEnumFORMATETC
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 15-Apr-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP CGenEnumFormatEtc::Next( ULONG celt, FORMATETC *rgelt,
|
|||
|
ULONG *pceltFetched)
|
|||
|
{
|
|||
|
HRESULT hresult = NOERROR;
|
|||
|
ULONG cFetched;
|
|||
|
|
|||
|
if( celt > m_cTotal - m_iCurrent )
|
|||
|
{
|
|||
|
cFetched = m_cTotal - m_iCurrent;
|
|||
|
hresult = ResultFromScode(S_FALSE);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
cFetched = celt;
|
|||
|
}
|
|||
|
|
|||
|
memcpy( rgelt, m_rgFormats + m_iCurrent,
|
|||
|
cFetched * sizeof(FORMATETC) );
|
|||
|
|
|||
|
m_iCurrent += cFetched;
|
|||
|
|
|||
|
if( pceltFetched )
|
|||
|
{
|
|||
|
*pceltFetched = cFetched;
|
|||
|
}
|
|||
|
|
|||
|
return hresult;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenEnumFormatEtc::Skip
|
|||
|
//
|
|||
|
// Synopsis: skips the next [celt] formats
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [celt] -- the number of elements to skip
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: NOERROR
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IEnumFORMATETC
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 15-Apr-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP CGenEnumFormatEtc::Skip( ULONG celt )
|
|||
|
{
|
|||
|
HRESULT hresult = NOERROR;
|
|||
|
|
|||
|
m_iCurrent += celt;
|
|||
|
|
|||
|
if( m_iCurrent > m_cTotal )
|
|||
|
{
|
|||
|
// whoops, skipped to far ahead. Set us to the max limit.
|
|||
|
m_iCurrent = m_cTotal;
|
|||
|
hresult = ResultFromScode(S_FALSE);
|
|||
|
}
|
|||
|
|
|||
|
return hresult;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenEnumFormatEtc::Reset
|
|||
|
//
|
|||
|
// Synopsis: resets the seek pointer to zero
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: void
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: NOERROR
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IEnumFORMATETC
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 15-Apr-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP CGenEnumFormatEtc::Reset( void )
|
|||
|
{
|
|||
|
m_iCurrent = 0;
|
|||
|
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenEnumFormatEtc::Clone
|
|||
|
//
|
|||
|
// Synopsis: clones the enumerator
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [ppIEnum] -- where to put the cloned enumerator
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns: HRESULT
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation: IEnumFORMATETC
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 15-Apr-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
STDMETHODIMP CGenEnumFormatEtc::Clone( IEnumFORMATETC **ppIEnum )
|
|||
|
{
|
|||
|
HRESULT hresult = ResultFromScode(E_OUTOFMEMORY);
|
|||
|
CGenEnumFormatEtc * pClipEnum;
|
|||
|
|
|||
|
*ppIEnum = NULL;
|
|||
|
|
|||
|
pClipEnum = new CGenEnumFormatEtc();
|
|||
|
|
|||
|
// ref count will be 1 and m_iCurrent will be zero.
|
|||
|
|
|||
|
if( pClipEnum )
|
|||
|
{
|
|||
|
pClipEnum->m_cTotal = m_cTotal;
|
|||
|
pClipEnum->m_rgFormats = new FORMATETC[m_cTotal];
|
|||
|
pClipEnum->m_iCurrent = m_iCurrent;
|
|||
|
|
|||
|
assert(pClipEnum->m_rgFormats);
|
|||
|
|
|||
|
if( pClipEnum->m_rgFormats )
|
|||
|
{
|
|||
|
// copy our formatetc's into the cloned enumerator's
|
|||
|
// array
|
|||
|
memcpy(pClipEnum->m_rgFormats, m_rgFormats,
|
|||
|
m_cTotal * sizeof(FORMATETC) );
|
|||
|
|
|||
|
*ppIEnum = pClipEnum;
|
|||
|
|
|||
|
hresult = NOERROR;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
|
|||
|
delete pClipEnum;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return hresult;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenEnumFormatEtc::CGenEnumFormatEtc, private
|
|||
|
//
|
|||
|
// Synopsis: constructor
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: void
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation:
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 15-Apr-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
CGenEnumFormatEtc::CGenEnumFormatEtc( void )
|
|||
|
{
|
|||
|
m_refs = 1; // give the intial reference
|
|||
|
m_rgFormats = NULL;
|
|||
|
m_iCurrent = 0;
|
|||
|
m_cTotal = 0;
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenEnumFormatEtc::~CGenEnumFormatEtc, private
|
|||
|
//
|
|||
|
// Synopsis: destructor
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: void
|
|||
|
//
|
|||
|
// Requires:
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation:
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 15-Apr-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
CGenEnumFormatEtc::~CGenEnumFormatEtc( void )
|
|||
|
{
|
|||
|
if( m_rgFormats )
|
|||
|
{
|
|||
|
delete m_rgFormats;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CGenEnumFormatEtc::Create, static, public
|
|||
|
//
|
|||
|
// Synopsis: Creates a clipboard formatetc enumerator
|
|||
|
//
|
|||
|
// Effects:
|
|||
|
//
|
|||
|
// Arguments: [ppIEnum] -- where to put the enumerator
|
|||
|
//
|
|||
|
// Requires: the clipboard must be open
|
|||
|
//
|
|||
|
// Returns: HRESULT
|
|||
|
//
|
|||
|
// Signals:
|
|||
|
//
|
|||
|
// Modifies:
|
|||
|
//
|
|||
|
// Derivation:
|
|||
|
//
|
|||
|
// Algorithm:
|
|||
|
//
|
|||
|
// History: dd-mmm-yy Author Comment
|
|||
|
// 15-Apr-94 alexgo author
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
HRESULT CGenEnumFormatEtc::Create( IEnumFORMATETC **ppIEnum,
|
|||
|
FORMATETC *prgFormats, DWORD cFormats )
|
|||
|
{
|
|||
|
HRESULT hresult = ResultFromScode(E_OUTOFMEMORY);
|
|||
|
CGenEnumFormatEtc * pClipEnum;
|
|||
|
|
|||
|
|
|||
|
*ppIEnum = NULL;
|
|||
|
|
|||
|
pClipEnum = new CGenEnumFormatEtc();
|
|||
|
|
|||
|
assert(pClipEnum);
|
|||
|
|
|||
|
// now allocate memory for the array
|
|||
|
|
|||
|
pClipEnum->m_rgFormats = new FORMATETC[cFormats];
|
|||
|
|
|||
|
assert(pClipEnum->m_rgFormats);
|
|||
|
|
|||
|
pClipEnum->m_cTotal = cFormats;
|
|||
|
|
|||
|
memcpy(pClipEnum->m_rgFormats, prgFormats,
|
|||
|
cFormats * sizeof(FORMATETC));
|
|||
|
|
|||
|
*ppIEnum = pClipEnum;
|
|||
|
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|