📄 clipboard.c
字号:
*/
if ( pformatetc->lindex != -1 )
return DV_E_LINDEX;
/* TODO: Handle TYMED_IStorage media which were put on the clipboard
* by copying the storage into global memory. We must convert this
* TYMED_HGLOBAL back to TYMED_IStorage.
*/
if ( pformatetc->tymed != TYMED_HGLOBAL )
return DV_E_TYMED;
/*
* Delegate to the Windows clipboard function IsClipboardFormatAvailable
*/
return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_FORMATETC;
}
/************************************************************************
* OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject)
*
* See Windows documentation for more details on IDataObject methods.
*/
static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc(
IDataObject* iface,
LPFORMATETC pformatectIn,
LPFORMATETC pformatetcOut)
{
TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
if ( !pformatectIn || !pformatetcOut )
return E_INVALIDARG;
memcpy(pformatetcOut, pformatectIn, sizeof(FORMATETC));
return DATA_S_SAMEFORMATETC;
}
/************************************************************************
* OLEClipbrd_IDataObject_SetData (IDataObject)
*
* The OLE Clipboard's does not implement this method
*
* See Windows documentation for more details on IDataObject methods.
*/
static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
IDataObject* iface,
LPFORMATETC pformatetc,
STGMEDIUM* pmedium,
BOOL fRelease)
{
TRACE("\n");
return E_NOTIMPL;
}
/************************************************************************
* OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject)
*
* See Windows documentation for more details on IDataObject methods.
*/
static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
IDataObject* iface,
DWORD dwDirection,
IEnumFORMATETC** ppenumFormatEtc)
{
HRESULT hr = S_OK;
FORMATETC *afmt = NULL;
int cfmt, i;
UINT format;
BOOL bClipboardOpen;
/*
* Declare "This" pointer
*/
OLEClipbrd *This = (OLEClipbrd *)iface;
TRACE("(%p, %x, %p)\n", iface, dwDirection, ppenumFormatEtc);
/*
* If we have a data source placed on the clipboard (via OleSetClipboard)
* simply delegate to the source object's EnumFormatEtc
*/
if ( This->pIDataObjectSrc )
{
return IDataObject_EnumFormatEtc(This->pIDataObjectSrc,
dwDirection, ppenumFormatEtc);
}
/*
* Otherwise we must provide our own enumerator which wraps around the
* Windows clipboard function EnumClipboardFormats
*/
if ( !ppenumFormatEtc )
return E_INVALIDARG;
if ( dwDirection != DATADIR_GET ) /* IDataObject_SetData not implemented */
return E_NOTIMPL;
/*
* Store all current clipboard formats in an array of FORMATETC's,
* and create an IEnumFORMATETC enumerator from this list.
*/
cfmt = CountClipboardFormats();
afmt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(FORMATETC) * cfmt);
/*
* Open the Windows clipboard, associating it with our hidden window
*/
if ( !(bClipboardOpen = OpenClipboard(This->hWndClipboard)) )
HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
/*
* Store all current clipboard formats in an array of FORMATETC's
* TODO: Handle TYMED_IStorage media which were put on the clipboard
* by copying the storage into global memory. We must convert this
* TYMED_HGLOBAL back to TYMED_IStorage.
*/
for (i = 0, format = 0; i < cfmt; i++)
{
format = EnumClipboardFormats(format);
if (!format) /* Failed! */
{
ERR("EnumClipboardFormats failed to return format!\n");
HANDLE_ERROR( E_FAIL );
}
/* Init the FORMATETC struct */
afmt[i].cfFormat = format;
afmt[i].ptd = NULL;
afmt[i].dwAspect = DVASPECT_CONTENT;
afmt[i].lindex = -1;
afmt[i].tymed = TYMED_HGLOBAL;
}
/*
* Create an EnumFORMATETC enumerator and return an
* EnumFORMATETC after bumping up its ref count
*/
*ppenumFormatEtc = OLEClipbrd_IEnumFORMATETC_Construct( cfmt, afmt, (LPUNKNOWN)iface);
if (!(*ppenumFormatEtc))
HANDLE_ERROR( E_OUTOFMEMORY );
if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenumFormatEtc)))
HANDLE_ERROR( hr );
hr = S_OK;
CLEANUP:
/*
* Free the array of FORMATETC's
*/
HeapFree(GetProcessHeap(), 0, afmt);
/*
* Close Windows clipboard
*/
if ( bClipboardOpen && !CloseClipboard() )
hr = CLIPBRD_E_CANT_CLOSE;
return hr;
}
/************************************************************************
* OLEClipbrd_IDataObject_DAdvise (IDataObject)
*
* The OLE Clipboard's does not implement this method
*
* See Windows documentation for more details on IDataObject methods.
*/
static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise(
IDataObject* iface,
FORMATETC* pformatetc,
DWORD advf,
IAdviseSink* pAdvSink,
DWORD* pdwConnection)
{
TRACE("\n");
return E_NOTIMPL;
}
/************************************************************************
* OLEClipbrd_IDataObject_DUnadvise (IDataObject)
*
* The OLE Clipboard's does not implement this method
*
* See Windows documentation for more details on IDataObject methods.
*/
static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise(
IDataObject* iface,
DWORD dwConnection)
{
TRACE("\n");
return E_NOTIMPL;
}
/************************************************************************
* OLEClipbrd_IDataObject_EnumDAdvise (IDataObject)
*
* The OLE Clipboard does not implement this method
*
* See Windows documentation for more details on IDataObject methods.
*/
static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise(
IDataObject* iface,
IEnumSTATDATA** ppenumAdvise)
{
TRACE("\n");
return E_NOTIMPL;
}
/*---------------------------------------------------------------------*
* Implementation of the internal IEnumFORMATETC interface returned by
* the OLE clipboard's IDataObject.
*---------------------------------------------------------------------*/
/************************************************************************
* OLEClipbrd_IEnumFORMATETC_Construct (UINT, const FORMATETC, LPUNKNOWN)
*
* Creates an IEnumFORMATETC enumerator from an array of FORMATETC
* Structures. pUnkOuter is the outer unknown for reference counting only.
* NOTE: this does not AddRef the interface.
*/
static LPENUMFORMATETC OLEClipbrd_IEnumFORMATETC_Construct(UINT cfmt, const FORMATETC afmt[],
LPUNKNOWN pUnkDataObj)
{
IEnumFORMATETCImpl* ef;
DWORD size=cfmt * sizeof(FORMATETC);
LPMALLOC pIMalloc;
ef = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl));
if (!ef)
return NULL;
ef->ref = 0;
ef->lpVtbl = &efvt;
ef->pUnkDataObj = pUnkDataObj;
ef->posFmt = 0;
ef->countFmt = cfmt;
if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc))) {
HeapFree(GetProcessHeap(), 0, ef);
return NULL;
}
ef->pFmt = (LPFORMATETC)IMalloc_Alloc(pIMalloc, size);
IMalloc_Release(pIMalloc);
if (ef->pFmt)
memcpy(ef->pFmt, afmt, size);
TRACE("(%p)->()\n",ef);
return (LPENUMFORMATETC)ef;
}
/************************************************************************
* OLEClipbrd_IEnumFORMATETC_QueryInterface (IUnknown)
*
* See Windows documentation for more details on IUnknown methods.
*/
static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_QueryInterface
(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
{
IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
/*
* Since enumerators are separate objects from the parent data object
* we only need to support the IUnknown and IEnumFORMATETC interfaces
*/
*ppvObj = NULL;
if(IsEqualIID(riid, &IID_IUnknown))
{
*ppvObj = This;
}
else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
{
*ppvObj = (IDataObject*)This;
}
if(*ppvObj)
{
IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
return S_OK;
}
TRACE("-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
/************************************************************************
* OLEClipbrd_IEnumFORMATETC_AddRef (IUnknown)
*
* Since enumerating formats only makes sense when our data object is around,
* we insure that it stays as long as we stay by calling our parents IUnknown
* for AddRef and Release. But since we are not controlled by the lifetime of
* the outer object, we still keep our own reference count in order to
* free ourselves.
*/
static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_AddRef(LPENUMFORMATETC iface)
{
IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
TRACE("(%p)->(count=%u)\n",This, This->ref);
if (This->pUnkDataObj)
IUnknown_AddRef(This->pUnkDataObj);
return InterlockedIncrement(&This->ref);
}
/************************************************************************
* OLEClipbrd_IEnumFORMATETC_Release (IUnknown)
*
* See Windows documentation for more details on IUnknown methods.
*/
static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
{
IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
LPMALLOC pIMalloc;
ULONG ref;
TRACE("(%p)->(count=%u)\n",This, This->ref);
if (This->pUnkDataObj)
IUnknown_Release(This->pUnkDataObj); /* Release parent data object */
ref = InterlockedDecrement(&This->ref);
if (!ref)
{
TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
{
IMalloc_Free(pIMalloc, This->pFmt);
IMalloc_Release(pIMalloc);
}
HeapFree(GetProcessHeap(),0,This);
}
return ref;
}
/************************************************************************
* OLEClipbrd_IEnumFORMATETC_Next (IEnumFORMATETC)
*
* Standard enumerator members for IEnumFORMATETC
*/
static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
{
IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
UINT cfetch;
HRESULT hres = S_FALSE;
TRACE("(%p)->(pos=%u)\n", This, This->posFmt);
if (This->posFmt < This->countFmt)
{
cfetch = This->countFmt - This->posFmt;
if (cfetch >= celt)
{
cfetch = celt;
hres = S_OK;
}
memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
This->posFmt += cfetch;
}
else
{
cfetch = 0;
}
if (pceltFethed)
{
*pceltFethed = cfetch;
}
return hres;
}
/************************************************************************
* OLEClipbrd_IEnumFORMATETC_Skip (IEnumFORMATETC)
*
* Standard enumerator members for IEnumFORMATETC
*/
static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULONG celt)
{
IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
TRACE("(%p)->(num=%u)\n", This, celt);
This->posFmt += celt;
if (This->posFmt > This->countFmt)
{
This->posFmt = This->countFmt;
return S_FALSE;
}
return S_OK;
}
/************************************************************************
* OLEClipbrd_IEnumFORMATETC_Reset (IEnumFORMATETC)
*
* Standard enumerator members for IEnumFORMATETC
*/
static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
{
IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
TRACE("(%p)->()\n", This);
This->posFmt = 0;
return S_OK;
}
/************************************************************************
* OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
*
* Standard enumerator members for IEnumFORMATETC
*/
static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
{
IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
HRESULT hr = S_OK;
TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
if ( !ppenum )
return E_INVALIDARG;
*ppenum = OLEClipbrd_IEnumFORMATETC_Construct(This->countFmt,
This->pFmt,
This->pUnkDataObj);
if (FAILED( hr = IEnumFORMATETC_AddRef(*ppenum)))
return ( hr );
return (*ppenum) ? S_OK : E_OUTOFMEMORY;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -