|
|
//+-------------------------------------------------------------------------
//
// 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; }
|