Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

849 lines
21 KiB

/*
* gendatao.cpp - Generic IDataObject implementation.
*/
/* Headers
**********/
#include "project.hpp"
#pragma hdrstop
#include <enumfmte.hpp>
#include "gendatao.hpp"
/***************************** Private Functions *****************************/
#ifdef DEBUG
PRIVATE_CODE BOOL IsValidPCGenDataObject(PCGenDataObject pcgdo)
{
return(IS_VALID_READ_PTR(pcgdo, CGenDataObject) &&
IS_VALID_STRUCT_PTR((PCRefCount)pcgdo, CRefCount) &&
IS_VALID_INTERFACE_PTR((PCIDataObject)pcgdo, IDataObject));
}
#endif
/****************************** Public Functions *****************************/
PUBLIC_CODE HRESULT CloneStgMedium(PCSTGMEDIUM pcstgmedSrc,
PSTGMEDIUM pstgmedDest)
{
HRESULT hr;
ASSERT(IS_VALID_STRUCT_PTR(pcstgmedSrc, CSTGMEDIUM));
ASSERT(IS_VALID_WRITE_PTR(pstgmedDest, STGMEDIUM));
// We only understand how to clone TYMED_HGLOBAL.
ZeroMemory(pstgmedDest, sizeof(*pstgmedDest));
if (pcstgmedSrc->tymed == TYMED_HGLOBAL)
{
PCVOID pcvSrc;
hr = E_OUTOFMEMORY;
pcvSrc = GlobalLock(pcstgmedSrc->hGlobal);
if (pcvSrc)
{
DWORD dwcbLen;
HGLOBAL hGlobalDest;
dwcbLen = GlobalSize(pcstgmedSrc->hGlobal);
hGlobalDest = GlobalAlloc((GMEM_MOVEABLE | GMEM_SHARE), dwcbLen);
if (hGlobalDest)
{
PVOID pvDest;
pvDest = GlobalLock(hGlobalDest);
if (pvDest)
{
CopyMemory(pvDest, pcvSrc, dwcbLen);
pstgmedDest->tymed = TYMED_HGLOBAL;
pstgmedDest->hGlobal = hGlobalDest;
pstgmedDest->pUnkForRelease = pcstgmedSrc->pUnkForRelease;
if (pstgmedDest->pUnkForRelease)
(pstgmedDest->pUnkForRelease)->AddRef();
GlobalUnlock(hGlobalDest);
pvDest = NULL;
hr = S_OK;
}
else
{
EVAL(! GlobalFree(hGlobalDest));
hGlobalDest = NULL;
}
}
GlobalUnlock(pcstgmedSrc->hGlobal);
pcvSrc = NULL;
}
}
else
hr = DV_E_TYMED;
ASSERT(hr == S_OK ||
(FAILED(hr) &&
EVAL(pcstgmedSrc->tymed == TYMED_NULL) &&
EVAL(! pcstgmedSrc->hGlobal) &&
EVAL(! pcstgmedSrc->pUnkForRelease)) &&
IS_VALID_STRUCT_PTR(pstgmedDest, CSTGMEDIUM));
return(hr);
}
PUBLIC_CODE BOOL DVTARGETDEVICEMatchesRequest(PCDVTARGETDEVICE pcdvtdRequest,
PCDVTARGETDEVICE pcdvtdActual)
{
BOOL bMatch;
ASSERT(! pcdvtdRequest ||
IS_VALID_STRUCT_PTR(pcdvtdRequest, CDVTARGETDEVICE));
ASSERT(! pcdvtdActual ||
IS_VALID_STRUCT_PTR(pcdvtdActual, CDVTARGETDEVICE));
/*
* A NULL requested PCDVTARGETDEVICE matches any NULL or non-NULL actual
* PCDVTARGETDEVICE.
*
* Any non-NULL requested PCDVTARGETDEVICE matches any NULL actual
* PCDVTARGETDEVICE.
*
* A non-NULL requested PCDVTARGETDEVICE only matches a non-NULL actual
* PCDVTARGETDEVICE if the actual CDVTARGETDEVICE is an exact binary copy of
* the requested CDVTARGETDEVICE.
*/
if (pcdvtdRequest && pcdvtdActual)
bMatch = (MyMemComp(pcdvtdRequest, pcdvtdActual,
min(pcdvtdRequest->tdSize, pcdvtdActual->tdSize))
== CR_EQUAL);
else
bMatch = TRUE;
return(bMatch);
}
PUBLIC_CODE BOOL TYMEDMatchesRequest(TYMED tymedRequest, TYMED tymedActual)
{
// Don't validate tymedRequest here. MFC apps set tymedRequest to
// 0xffffffff.
ASSERT(FLAGS_ARE_VALID(tymedActual, ALL_TYMED_FLAGS));
// The actual TYMED matches the requested TYMED if they have any flags set
// in common.
return(IS_FLAG_SET(tymedRequest, tymedActual));
}
PUBLIC_CODE BOOL FORMATETCMatchesRequest(PCFORMATETC pcfmtetcRequest,
PCFORMATETC pcfmtetcActual)
{
ASSERT(IS_VALID_STRUCT_PTR(pcfmtetcRequest, CFORMATETC));
ASSERT(IS_VALID_STRUCT_PTR(pcfmtetcActual, CFORMATETC));
return(pcfmtetcRequest->cfFormat == pcfmtetcActual->cfFormat &&
DVTARGETDEVICEMatchesRequest(pcfmtetcRequest->ptd,
pcfmtetcActual->ptd) &&
pcfmtetcRequest->dwAspect == pcfmtetcActual->dwAspect &&
pcfmtetcRequest->lindex == pcfmtetcActual->lindex &&
TYMEDMatchesRequest((TYMED)(pcfmtetcRequest->tymed),
(TYMED)(pcfmtetcActual->tymed)));
}
/********************************** Methods **********************************/
GenDataObject::GenDataObject(ULONG ulcInitialFormats,
ULONG ulcFormatGranularity) : RefCount(NULL)
{
DebugEntry(GenDataObject::GenDataObject);
// Don't validate this until after construction.
// ulcInitialFormats may be any value.
ASSERT(ulcFormatGranularity > 0);
m_ulcFormatGranularity = EVAL(ulcFormatGranularity > 0) ?
ulcFormatGranularity : 1;
m_pfmtetc = NULL;
m_pstgmed = NULL;
m_ulcFormats = 0;
// Ignore return value.
AllocateArrays(ulcInitialFormats);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
DebugExitVOID(GenDataObject::GenDataObject);
return;
}
GenDataObject::~GenDataObject(void)
{
DebugEntry(GenDataObject::~GenDataObject);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
m_ulcFormatGranularity = 0;
if (m_pfmtetc)
{
delete m_pfmtetc;
m_pfmtetc = NULL;
}
if (m_pstgmed)
{
ULONG ul;
for (ul = 0; ul < m_ulcFormats; ul++)
EVAL(MyReleaseStgMedium(&(m_pstgmed[ul])) == S_OK);
delete m_pstgmed;
m_pstgmed = NULL;
}
m_ulcFormats = 0;
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
DebugExitVOID(GenDataObject::~GenDataObject);
return;
}
ULONG STDMETHODCALLTYPE GenDataObject::AddRef(void)
{
ULONG ulcRef;
DebugEntry(GenDataObject::AddRef);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ulcRef = RefCount::AddRef();
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
DebugExitULONG(GenDataObject::AddRef, ulcRef);
return(ulcRef);
}
ULONG STDMETHODCALLTYPE GenDataObject::Release(void)
{
ULONG ulcRef;
DebugEntry(GenDataObject::Release);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ulcRef = RefCount::Release();
DebugExitULONG(GenDataObject::Release, ulcRef);
return(ulcRef);
}
HRESULT STDMETHODCALLTYPE GenDataObject::QueryInterface(REFIID riid,
PVOID *ppvObject)
{
HRESULT hr = S_OK;
DebugEntry(GenDataObject::QueryInterface);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(IsValidREFIID(riid));
ASSERT(IS_VALID_WRITE_PTR(ppvObject, PVOID));
if (riid == IID_IDataObject)
{
*ppvObject = (PIDataObject)this;
ASSERT(IS_VALID_INTERFACE_PTR((PIDataObject)*ppvObject, IDataObject));
TRACE_OUT(("GenDataObject::QueryInterface(): Returning IDataObject."));
}
else if (riid == IID_IUnknown)
{
*ppvObject = (PIUnknown)this;
ASSERT(IS_VALID_INTERFACE_PTR((PIUnknown)*ppvObject, IUnknown));
TRACE_OUT(("GenDataObject::QueryInterface(): Returning IUnknown."));
}
else
{
*ppvObject = NULL;
hr = E_NOINTERFACE;
TRACE_OUT(("GenDataObject::QueryInterface(): Called on unknown interface."));
}
if (hr == S_OK)
AddRef();
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(FAILED(hr) ||
IS_VALID_INTERFACE_PTR(*ppvObject, INTERFACE));
DebugExitHRESULT(GenDataObject::QueryInterface, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE GenDataObject::GetData(PFORMATETC pfmtetc,
PSTGMEDIUM pstgmed)
{
HRESULT hr;
ULONG ulFound;
DebugEntry(GenDataObject::GetData);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(IS_VALID_STRUCT_PTR(pfmtetc, CFORMATETC));
ASSERT(IS_VALID_WRITE_PTR(pstgmed, STGMEDIUM));
ZeroMemory(pstgmed, sizeof(*pstgmed));
hr = FindData(pfmtetc, &ulFound);
if (hr == S_OK)
hr = CloneStgMedium(&(m_pstgmed[ulFound]), pstgmed);
if (hr == S_OK)
TRACE_OUT(("GenDataObject::GetData(): Returning clipboard format %s.",
GetClipboardFormatNameString(pfmtetc->cfFormat)));
else
TRACE_OUT(("GenDataObject::GetData(): Failed to return clipboard format %s.",
GetClipboardFormatNameString(pfmtetc->cfFormat)));
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(FAILED(hr) ||
IS_VALID_STRUCT_PTR(pstgmed, CSTGMEDIUM));
DebugExitHRESULT(GenDataObject::GetData, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE GenDataObject::GetDataHere(PFORMATETC pfmtetc,
PSTGMEDIUM pstgpmed)
{
HRESULT hr;
DebugEntry(GenDataObject::GetDataHere);
ASSERT(IS_VALID_STRUCT_PTR(pfmtetc, CFORMATETC));
ASSERT(IS_VALID_STRUCT_PTR(pstgpmed, CSTGMEDIUM));
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
TRACE_OUT(("GenDataObject::GetDataHere(): Failed to return clipboard format %s.",
GetClipboardFormatNameString(pfmtetc->cfFormat)));
hr = DV_E_FORMATETC;
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(IS_VALID_STRUCT_PTR(pstgpmed, CSTGMEDIUM));
DebugExitHRESULT(GenDataObject::GetDataHere, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE GenDataObject::QueryGetData(PFORMATETC pfmtetc)
{
HRESULT hr;
ULONG ulUnused;
DebugEntry(GenDataObject::QueryGetData);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(IS_VALID_STRUCT_PTR(pfmtetc, CFORMATETC));
TRACE_OUT(("GenDataObject::QueryGetData(): Asked for clipboard format %s.",
GetClipboardFormatNameString(pfmtetc->cfFormat)));
hr = FindData(pfmtetc, &ulUnused);
if (hr == S_OK)
TRACE_OUT(("GenDataObject::QueryGetData(): Clipboard format %s supported.",
GetClipboardFormatNameString(pfmtetc->cfFormat)));
else
TRACE_OUT(("GenDataObject::QueryGetData(): Clipboard format %s not supported.",
GetClipboardFormatNameString(pfmtetc->cfFormat)));
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
DebugExitHRESULT(GenDataObject::QueryGetData, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE GenDataObject::GetCanonicalFormatEtc(
PFORMATETC pfmtetcIn,
PFORMATETC pfmtetcOut)
{
HRESULT hr;
DebugEntry(GenDataObject::GetCanonicalFormatEtc);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(IS_VALID_STRUCT_PTR(pfmtetcIn, CFORMATETC));
ASSERT(IS_VALID_WRITE_PTR(pfmtetcOut, FORMATETC));
hr = QueryGetData(pfmtetcIn);
if (hr == S_OK)
{
*pfmtetcOut = *pfmtetcIn;
if (pfmtetcIn->ptd == NULL)
hr = DATA_S_SAMEFORMATETC;
else
{
pfmtetcIn->ptd = NULL;
ASSERT(hr == S_OK);
}
}
else
ZeroMemory(pfmtetcOut, sizeof(*pfmtetcOut));
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(FAILED(hr) ||
IS_VALID_STRUCT_PTR(pfmtetcOut, CFORMATETC));
DebugExitHRESULT(GenDataObject::GetCanonicalFormatEtc, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE GenDataObject::SetData(PFORMATETC pfmtetc,
PSTGMEDIUM pstgmed,
BOOL bRelease)
{
HRESULT hr;
ULONG ulDup;
STGMEDIUM stgmedClone;
PSTGMEDIUM pstgmedToUse;
DebugEntry(GenDataObject::SetData);
// bRelease may be any value.
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(IS_VALID_STRUCT_PTR(pfmtetc, CFORMATETC));
ASSERT(IS_VALID_STRUCT_PTR(pstgmed, CSTGMEDIUM));
// Can we use the given STGMEDIUM directly?
if (bRelease)
{
// Yes.
pstgmedToUse = pstgmed;
hr = S_OK;
}
else
{
// No. Clone it.
pstgmedToUse = &stgmedClone;
hr = CloneStgMedium(pstgmed, pstgmedToUse);
}
hr = FindData(pfmtetc, &ulDup);
if (hr == S_OK)
hr = ReplaceData(pfmtetc, pstgmedToUse, ulDup);
else
hr = AddData(pfmtetc, pstgmedToUse);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
DebugExitHRESULT(GenDataObject::SetData, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE GenDataObject::EnumFormatEtc(
DWORD dwDirFlags,
PIEnumFORMATETC *ppiefe)
{
HRESULT hr;
DebugEntry(GenDataObject::EnumFormatEtc);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(FLAGS_ARE_VALID(dwDirFlags, ALL_DATADIR_FLAGS));
ASSERT(IS_VALID_WRITE_PTR(ppiefe, PIEnumFORMATETC));
*ppiefe = NULL;
if (dwDirFlags == DATADIR_GET)
{
PEnumFormatEtc pefe;
pefe = new(::EnumFormatEtc(m_pfmtetc, m_ulcFormats));
if (pefe)
{
hr = pefe->Status();
if (hr == S_OK)
*ppiefe = pefe;
else
{
delete pefe;
pefe = NULL;
}
}
else
hr = E_OUTOFMEMORY;
}
else
// No SetData() FORMATETC enumerator.
hr = E_NOTIMPL;
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT((hr == S_OK &&
IS_VALID_INTERFACE_PTR(*ppiefe, IEnumFORMATETC)) ||
(FAILED(hr) &&
! *ppiefe));
DebugExitHRESULT(GenDataObject::EnumFormatEtc, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE GenDataObject::DAdvise(PFORMATETC pfmtetc,
DWORD dwAdviseFlags,
PIAdviseSink piadvsink,
PDWORD pdwConnection)
{
HRESULT hr;
DebugEntry(GenDataObject::DAdvise);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(IS_VALID_STRUCT_PTR(pfmtetc, CFORMATETC));
ASSERT(FLAGS_ARE_VALID(dwAdviseFlags, ALL_ADVISE_FLAGS));
ASSERT(IS_VALID_INTERFACE_PTR(piadvsink, IAdviseSink));
ASSERT(IS_VALID_WRITE_PTR(pdwConnection, DWORD));
*pdwConnection = 0;
hr = OLE_E_ADVISENOTSUPPORTED;
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT((hr == S_OK &&
*pdwConnection) ||
(FAILED(hr) &&
! *pdwConnection));
DebugExitHRESULT(GenDataObject::DAdvise, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE GenDataObject::DUnadvise(DWORD dwConnection)
{
HRESULT hr;
DebugEntry(GenDataObject::DUnadvise);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(dwConnection);
hr = OLE_E_ADVISENOTSUPPORTED;
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
DebugExitHRESULT(GenDataObject::DUnadvise, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE GenDataObject::EnumDAdvise(PIEnumSTATDATA *ppiesd)
{
HRESULT hr;
DebugEntry(GenDataObject::EnumDAdvise);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(IS_VALID_WRITE_PTR(ppiesd, PIEnumSTATDATA));
*ppiesd = NULL;
hr = OLE_E_ADVISENOTSUPPORTED;
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT((hr == S_OK &&
IS_VALID_INTERFACE_PTR(*ppiesd, IEnumSTATDATA)) ||
(FAILED(hr) &&
! *ppiesd));
DebugExitHRESULT(GenDataObject::EnumDAdvise, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE GenDataObject::Status(void)
{
HRESULT hr;
DebugEntry(GenDataObject::Status);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
hr = (m_pfmtetc ? S_OK : E_OUTOFMEMORY);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT((hr == S_OK &&
m_pstgmed) ||
(hr == E_OUTOFMEMORY &&
! m_pstgmed));
DebugExitHRESULT(GenDataObject::Status, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE GenDataObject::AllocateArrays(ULONG ulcElems)
{
HRESULT hr;
DebugEntry(GenDataObject::AllocateArrays);
// ulcElems may be any value.
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(! m_pfmtetc);
ASSERT(! m_pstgmed);
// Create data arrays if necessary.
hr = E_OUTOFMEMORY;
if (AllocateMemory(ulcElems * sizeof(*m_pfmtetc), (PVOID *)&m_pfmtetc))
{
if (AllocateMemory(ulcElems * sizeof(*m_pstgmed), (PVOID *)&m_pstgmed))
hr = S_OK;
else
{
ASSERT(! m_pstgmed);
delete m_pfmtetc;
m_pfmtetc = NULL;
}
}
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT((hr == S_OK &&
m_pfmtetc &&
m_pstgmed) ||
(hr == E_OUTOFMEMORY &&
! m_pfmtetc &&
! m_pstgmed));
DebugExitHRESULT(GenDataObject::AllocateArrays, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE GenDataObject::GrowArrays(ULONG ulcElems)
{
HRESULT hr;
ULONG ulcFormatEtcs;
ULONG ulcStgMediums;
ULONG ulcFormatsAllocated;
DebugEntry(GenDataObject::GrowArrays);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(ulcElems > 0);
// Grow data arrays if necessary.
ulcFormatEtcs = MemorySize(m_pfmtetc) / sizeof(*m_pfmtetc);
ulcStgMediums = MemorySize(m_pstgmed) / sizeof(*m_pstgmed);
ulcFormatsAllocated = min(ulcFormatEtcs, ulcStgMediums);
if (m_ulcFormats < ulcFormatsAllocated)
hr = S_OK;
else
{
PFORMATETC pfmtetcGrown;
ASSERT(m_ulcFormats == ulcFormatsAllocated);
hr = E_OUTOFMEMORY;
if (ReallocateMemory(
m_pfmtetc,
(ulcFormatsAllocated + ulcElems) * sizeof(*m_pfmtetc),
(PVOID *)&pfmtetcGrown))
{
PSTGMEDIUM pstgmedGrown;
m_pfmtetc = pfmtetcGrown;
if (ReallocateMemory(
m_pstgmed,
(ulcFormatsAllocated + ulcElems) * sizeof(*m_pstgmed),
(PVOID *)&pstgmedGrown))
{
m_pstgmed = pstgmedGrown;
hr = S_OK;
}
}
}
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
DebugExitHRESULT(GenDataObject::AllocateArrays, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE GenDataObject::AddData(PCFORMATETC pcfmtetc,
PCSTGMEDIUM pcstgmed)
{
HRESULT hr;
#ifdef DEBUG
ULONG ulUnused;
#endif
DebugEntry(GenDataObject::AddData);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(IS_VALID_STRUCT_PTR(pcfmtetc, CFORMATETC));
ASSERT(IS_VALID_STRUCT_PTR(pcstgmed, CSTGMEDIUM));
ASSERT(FindData(pcfmtetc, &ulUnused) != S_OK);
hr = GrowArrays(m_ulcFormatGranularity);
if (hr == S_OK)
{
m_pfmtetc[m_ulcFormats] = *pcfmtetc;
m_pstgmed[m_ulcFormats] = *pcstgmed;
m_ulcFormats++;
}
if (hr == S_OK)
TRACE_OUT(("GenDataObject::AddData(): Added data of clipboard format %s.",
GetClipboardFormatNameString(pcfmtetc->cfFormat)));
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
DebugExitHRESULT(GenDataObject::AddData, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE GenDataObject::FindData(PCFORMATETC pcfmtetc,
PULONG pulFound)
{
HRESULT hr;
ULONG ul;
DebugEntry(GenDataObject::FindData);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(IS_VALID_STRUCT_PTR(pcfmtetc, CFORMATETC));
ASSERT(IS_VALID_WRITE_PTR(pulFound, ULONG));
hr = DV_E_FORMATETC;
*pulFound = 0;
for (ul = 0; ul < m_ulcFormats; ul++)
{
if (FORMATETCMatchesRequest(pcfmtetc, &(m_pfmtetc[ul])))
{
*pulFound = ul;
hr = S_OK;
break;
}
}
if (hr == S_OK)
TRACE_OUT(("GenDataObject::FindData(): Found data of clipboard format %s.",
GetClipboardFormatNameString(pcfmtetc->cfFormat)));
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT((hr == S_OK &&
*pulFound < m_ulcFormats) ||
(FAILED(hr) &&
! *pulFound));
DebugExitHRESULT(GenDataObject::FindData, hr);
return(hr);
}
HRESULT STDMETHODCALLTYPE GenDataObject::ReplaceData(PCFORMATETC pcfmtetc,
PCSTGMEDIUM pcstgmed,
ULONG ulReplace)
{
HRESULT hr;
DebugEntry(GenDataObject::ReplaceData);
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
ASSERT(IS_VALID_STRUCT_PTR(pcfmtetc, CFORMATETC));
ASSERT(IS_VALID_STRUCT_PTR(pcstgmed, CSTGMEDIUM));
ASSERT(ulReplace < m_ulcFormats);
EVAL(MyReleaseStgMedium(&(m_pstgmed[ulReplace])) == S_OK);
m_pfmtetc[ulReplace] = *pcfmtetc;
m_pstgmed[ulReplace] = *pcstgmed;
hr = S_OK;
if (hr == S_OK)
TRACE_OUT(("GenDataObject::ReplaceData(): Replaced data of clipboard format %s.",
GetClipboardFormatNameString(pcfmtetc->cfFormat)));
ASSERT(IS_VALID_STRUCT_PTR(this, CGenDataObject));
DebugExitHRESULT(GenDataObject::ReplaceData, hr);
return(hr);
}