You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
513 lines
12 KiB
513 lines
12 KiB
/**************************************************************************
|
|
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 1998 Microsoft Corporation. All Rights Reserved.
|
|
**************************************************************************/
|
|
|
|
/**************************************************************************
|
|
|
|
File: DataObj.cpp
|
|
|
|
Description: CDataObject implementation.
|
|
|
|
**************************************************************************/
|
|
|
|
/**************************************************************************
|
|
#include statements
|
|
**************************************************************************/
|
|
|
|
#include "DataObj.h"
|
|
|
|
/**************************************************************************
|
|
global variables
|
|
**************************************************************************/
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::CDataObject()
|
|
|
|
**************************************************************************/
|
|
|
|
CDataObject::CDataObject(CShellFolder *psfParent, LPCITEMIDLIST *aPidls, UINT uItemCount)
|
|
{
|
|
g_DllRefCount++;
|
|
|
|
m_uItemCount = 0;
|
|
|
|
m_psfParent = psfParent;
|
|
if(m_psfParent)
|
|
m_psfParent->AddRef();
|
|
|
|
m_ObjRefCount = 1;
|
|
|
|
m_aPidls = NULL;
|
|
SHGetMalloc(&m_pMalloc);
|
|
if(!m_pMalloc)
|
|
{
|
|
delete this;
|
|
return;
|
|
}
|
|
|
|
m_pPidlMgr = new CPidlMgr();
|
|
|
|
m_uItemCount = uItemCount;
|
|
|
|
AllocPidlTable(uItemCount);
|
|
if(m_aPidls)
|
|
{
|
|
FillPidlTable(aPidls, uItemCount);
|
|
}
|
|
|
|
m_cfPrivateData = RegisterClipboardFormat(CFSTR_SAMPVIEWDATA);
|
|
m_cfShellIDList = RegisterClipboardFormat(CFSTR_SHELLIDLIST);
|
|
|
|
m_cFormatEtc = 2;
|
|
m_pFormatEtc = new FORMATETC[m_cFormatEtc];
|
|
SETDefFormatEtc(m_pFormatEtc[0], m_cfPrivateData, TYMED_HGLOBAL);
|
|
SETDefFormatEtc(m_pFormatEtc[1], m_cfShellIDList, TYMED_HGLOBAL);
|
|
|
|
m_iCurrent = 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::~CDataObject()
|
|
|
|
**************************************************************************/
|
|
|
|
CDataObject::~CDataObject()
|
|
{
|
|
if(m_psfParent)
|
|
m_psfParent->Release();
|
|
|
|
g_DllRefCount--;
|
|
|
|
//make sure the pidls are freed
|
|
if(m_aPidls && m_pMalloc)
|
|
{
|
|
FreePidlTable();
|
|
}
|
|
|
|
if(m_pPidlMgr)
|
|
delete m_pPidlMgr;
|
|
|
|
if(m_pMalloc)
|
|
m_pMalloc->Release();
|
|
|
|
//delete [] m_pFormatEtc;
|
|
delete m_pFormatEtc;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IUnknown Implementation
|
|
//
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::QueryInterface
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CDataObject::QueryInterface( REFIID riid,
|
|
LPVOID *ppReturn)
|
|
{
|
|
*ppReturn = NULL;
|
|
|
|
if(IsEqualIID(riid, IID_IUnknown))
|
|
{
|
|
*ppReturn = (LPUNKNOWN)(LPCONTEXTMENU)this;
|
|
}
|
|
else if(IsEqualIID(riid, IID_IDataObject))
|
|
{
|
|
*ppReturn = (LPDATAOBJECT)this;
|
|
}
|
|
else if(IsEqualIID(riid, IID_IEnumFORMATETC))
|
|
{
|
|
*ppReturn = (LPENUMFORMATETC)this;
|
|
}
|
|
|
|
if(*ppReturn)
|
|
{
|
|
(*(LPUNKNOWN*)ppReturn)->AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::AddRef
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP_(DWORD) CDataObject::AddRef()
|
|
{
|
|
return ++m_ObjRefCount;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::Release
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP_(DWORD) CDataObject::Release()
|
|
{
|
|
if(--m_ObjRefCount == 0)
|
|
delete this;
|
|
|
|
return m_ObjRefCount;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IDataObject Implementation
|
|
//
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::GetData()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CDataObject::GetData(LPFORMATETC pFE, LPSTGMEDIUM pStgMedium)
|
|
{
|
|
if(pFE->cfFormat == m_cfPrivateData)
|
|
{
|
|
LPITEMIDLIST pidlParent;
|
|
|
|
pidlParent = m_psfParent->CreateFQPidl(NULL);
|
|
|
|
if(pidlParent)
|
|
{
|
|
pStgMedium->hGlobal = CreatePrivateClipboardData(pidlParent, m_aPidls, m_uItemCount, FALSE);
|
|
|
|
m_pPidlMgr->Delete(pidlParent);
|
|
|
|
if(pStgMedium->hGlobal)
|
|
{
|
|
pStgMedium->tymed = TYMED_HGLOBAL;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
else if(pFE->cfFormat == m_cfShellIDList)
|
|
{
|
|
LPITEMIDLIST pidlParent;
|
|
|
|
pidlParent = m_psfParent->CreateFQPidl(NULL);
|
|
|
|
if(pidlParent)
|
|
{
|
|
pStgMedium->hGlobal = CreateShellIDList(pidlParent, m_aPidls, m_uItemCount);
|
|
|
|
m_pPidlMgr->Delete(pidlParent);
|
|
|
|
if(pStgMedium->hGlobal)
|
|
{
|
|
pStgMedium->tymed = TYMED_HGLOBAL;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::GetDataHere()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CDataObject::GetDataHere (LPFORMATETC pFE, LPSTGMEDIUM pStgMedium)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::QueryGetData()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CDataObject::QueryGetData(LPFORMATETC pFE)
|
|
{
|
|
BOOL fReturn = FALSE;
|
|
|
|
/*
|
|
Check the aspects we support. Implementations of this object will only
|
|
support DVASPECT_CONTENT.
|
|
*/
|
|
if(!(DVASPECT_CONTENT & pFE->dwAspect))
|
|
return DV_E_DVASPECT;
|
|
|
|
if(pFE->cfFormat == m_cfPrivateData)
|
|
{
|
|
//
|
|
// Now check for an appropriate TYMED.
|
|
//
|
|
for(UINT i = 0; i < m_cFormatEtc; i++)
|
|
{
|
|
fReturn |= m_pFormatEtc[i].tymed & pFE->tymed;
|
|
}
|
|
}
|
|
|
|
if(pFE->cfFormat == m_cfShellIDList)
|
|
{
|
|
//
|
|
// Now check for an appropriate TYMED.
|
|
//
|
|
for(UINT i = 0; i < m_cFormatEtc; i++)
|
|
{
|
|
fReturn |= m_pFormatEtc[i].tymed & pFE->tymed;
|
|
}
|
|
}
|
|
|
|
return (fReturn ? S_OK : DV_E_TYMED);
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::GetCanonicalFormatEtc()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CDataObject::GetCanonicalFormatEtc(LPFORMATETC pFEIn, LPFORMATETC pFEOut)
|
|
{
|
|
if(NULL == pFEOut)
|
|
return E_INVALIDARG;
|
|
|
|
pFEOut->ptd = NULL;
|
|
|
|
return DATA_S_SAMEFORMATETC;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::EnumFormatEtc()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CDataObject::EnumFormatEtc( DWORD dwDirection,
|
|
IEnumFORMATETC** ppEFE)
|
|
{
|
|
*ppEFE = NULL;
|
|
|
|
if(DATADIR_GET == dwDirection)
|
|
{
|
|
return this->QueryInterface(IID_IEnumFORMATETC, (LPVOID*)ppEFE);
|
|
}
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::SetData()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CDataObject::SetData( LPFORMATETC pFE,
|
|
LPSTGMEDIUM pStgMedium,
|
|
BOOL fRelease)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::DAdvise()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CDataObject::DAdvise( LPFORMATETC pFE,
|
|
DWORD advf,
|
|
IAdviseSink *ppAdviseSink,
|
|
LPDWORD pdwConnection)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::DUnadvise()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CDataObject::DUnadvise(DWORD dwConnection)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::EnumDAdvise()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CDataObject::EnumDAdvise(IEnumSTATDATA** ppEnumAdvise)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IEnumFORMATETC Implementation
|
|
//
|
|
|
|
STDMETHODIMP CDataObject::Next(ULONG uRequested, LPFORMATETC pFormatEtc, ULONG* pulFetched)
|
|
{
|
|
if(NULL == m_pFormatEtc)
|
|
return S_FALSE;
|
|
|
|
if(NULL != pulFetched)
|
|
*pulFetched = 0L;
|
|
|
|
if(NULL == pFormatEtc)
|
|
return E_INVALIDARG;
|
|
|
|
ULONG uFetched;
|
|
for(uFetched = 0; m_iCurrent < m_cFormatEtc && uRequested > uFetched; uFetched++)
|
|
{
|
|
*pFormatEtc++ = m_pFormatEtc[m_iCurrent++];
|
|
}
|
|
|
|
if(NULL != pulFetched)
|
|
*pulFetched = uFetched;
|
|
|
|
return ((uFetched == uRequested) ? S_OK : S_FALSE);
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::Skip()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CDataObject::Skip(ULONG cSkip)
|
|
{
|
|
if((m_iCurrent + cSkip) >= m_cFormatEtc)
|
|
return S_FALSE;
|
|
|
|
m_iCurrent += cSkip;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::Reset()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CDataObject::Reset(void)
|
|
{
|
|
m_iCurrent = 0;
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::Clone()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CDataObject::Clone(LPENUMFORMATETC* ppEnum)
|
|
{
|
|
CDataObject* pNew;
|
|
|
|
*ppEnum = NULL;
|
|
|
|
// Create the clone.
|
|
pNew = new CDataObject(m_psfParent, (LPCITEMIDLIST*)m_aPidls, m_uItemCount);
|
|
if (NULL == pNew)
|
|
return E_OUTOFMEMORY;
|
|
|
|
pNew->m_iCurrent = m_iCurrent;
|
|
|
|
*ppEnum = pNew;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// private and utility methods
|
|
//
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::AllocPidlTable()
|
|
|
|
**************************************************************************/
|
|
|
|
BOOL CDataObject::AllocPidlTable(DWORD dwEntries)
|
|
{
|
|
m_aPidls = (LPITEMIDLIST*)m_pMalloc->Alloc(dwEntries * sizeof(LPITEMIDLIST));
|
|
|
|
if(m_aPidls)
|
|
{
|
|
//set all of the entries to NULL
|
|
ZeroMemory(m_aPidls, dwEntries * sizeof(LPITEMIDLIST));
|
|
}
|
|
|
|
return (m_aPidls != NULL);
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::FreePidlTable()
|
|
|
|
**************************************************************************/
|
|
|
|
VOID CDataObject::FreePidlTable(VOID)
|
|
{
|
|
if(m_aPidls && m_pPidlMgr)
|
|
{
|
|
UINT i;
|
|
for(i = 0; i < m_uItemCount; i++)
|
|
m_pPidlMgr->Delete(m_aPidls[i]);
|
|
|
|
m_pMalloc->Free(m_aPidls);
|
|
|
|
m_aPidls = NULL;
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CDataObject::FillPidlTable()
|
|
|
|
**************************************************************************/
|
|
|
|
BOOL CDataObject::FillPidlTable(LPCITEMIDLIST *aPidls, UINT uItemCount)
|
|
{
|
|
if(m_aPidls)
|
|
{
|
|
if(m_pPidlMgr)
|
|
{
|
|
UINT i;
|
|
for(i = 0; i < uItemCount; i++)
|
|
{
|
|
m_aPidls[i] = m_pPidlMgr->Copy(aPidls[i]);
|
|
}
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|