Huw Davies : ole32: Reimplement the formatetc enumerator using ' Ole Private Data'.
Alexandre Julliard
julliard at winehq.org
Mon Mar 30 12:08:52 CDT 2009
Module: wine
Branch: master
Commit: 969e5d7ee1e5b486e141be3146bf8781eed49c21
URL: http://source.winehq.org/git/wine.git/?a=commit;h=969e5d7ee1e5b486e141be3146bf8781eed49c21
Author: Huw Davies <huw at codeweavers.com>
Date: Mon Mar 30 12:00:44 2009 +0100
ole32: Reimplement the formatetc enumerator using 'Ole Private Data'.
---
dlls/ole32/clipboard.c | 189 ++++++++++++++++++++----------------------------
1 files changed, 80 insertions(+), 109 deletions(-)
diff --git a/dlls/ole32/clipboard.c b/dlls/ole32/clipboard.c
index 9815749..66f620a 100644
--- a/dlls/ole32/clipboard.c
+++ b/dlls/ole32/clipboard.c
@@ -146,6 +146,22 @@ typedef struct
/* then follows any DVTARGETDEVICE structures referenced in the FORMATETCs */
} ole_priv_data;
+/* Create an empty data structure. The only thing that really matters
+ here is setting count and size members. This is used by the enumerator as a
+ convenience when there's an empty list. */
+static HRESULT create_empty_priv_data(ole_priv_data **data)
+{
+ ole_priv_data *ptr;
+
+ *data = NULL;
+ ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(*ptr));
+ if(!ptr) return E_OUTOFMEMORY;
+ ptr->size = sizeof(*ptr);
+ ptr->count = 0;
+ *data = ptr;
+ return S_OK;
+}
+
/*---------------------------------------------------------------------*
* Implementation of the internal IEnumFORMATETC interface returned by
* the OLE clipboard's IDataObject.
@@ -157,8 +173,7 @@ typedef struct enum_fmtetc
LONG ref;
UINT pos; /* current enumerator position */
- UINT countFmt; /* number of EnumFORMATETC's in array */
- LPFORMATETC pFmt; /* array of EnumFORMATETC's */
+ ole_priv_data *data;
} enum_fmtetc;
static inline enum_fmtetc *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
@@ -225,8 +240,8 @@ static ULONG WINAPI OLEClipbrd_IEnumFORMATETC_Release(LPENUMFORMATETC iface)
if (!ref)
{
TRACE("() - destroying IEnumFORMATETC(%p)\n",This);
- HeapFree(GetProcessHeap(), 0, This->pFmt);
- HeapFree(GetProcessHeap(),0,This);
+ HeapFree(GetProcessHeap(), 0, This->data);
+ HeapFree(GetProcessHeap(), 0, This);
}
return ref;
}
@@ -240,22 +255,31 @@ static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Next
(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
{
enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
- UINT cfetch;
+ UINT cfetch, i;
HRESULT hres = S_FALSE;
TRACE("(%p)->(pos=%u)\n", This, This->pos);
- if (This->pos < This->countFmt)
+ if (This->pos < This->data->count)
{
- cfetch = This->countFmt - This->pos;
+ cfetch = This->data->count - This->pos;
if (cfetch >= celt)
{
cfetch = celt;
hres = S_OK;
}
- memcpy(rgelt, &This->pFmt[This->pos], cfetch * sizeof(FORMATETC));
- This->pos += cfetch;
+ for(i = 0; i < cfetch; i++)
+ {
+ rgelt[i] = This->data->entries[This->pos++].fmtetc;
+ if(rgelt[i].ptd)
+ {
+ DVTARGETDEVICE *target = (DVTARGETDEVICE *)((char *)This->data + (DWORD)rgelt[i].ptd);
+ rgelt[i].ptd = CoTaskMemAlloc(target->tdSize);
+ if(!rgelt[i].ptd) return E_OUTOFMEMORY;
+ memcpy(rgelt[i].ptd, target, target->tdSize);
+ }
+ }
}
else
{
@@ -281,9 +305,9 @@ static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Skip(LPENUMFORMATETC iface, ULON
TRACE("(%p)->(num=%u)\n", This, celt);
This->pos += celt;
- if (This->pos > This->countFmt)
+ if (This->pos > This->data->count)
{
- This->pos = This->countFmt;
+ This->pos = This->data->count;
return S_FALSE;
}
return S_OK;
@@ -303,7 +327,7 @@ static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Reset(LPENUMFORMATETC iface)
return S_OK;
}
-static HRESULT enum_fmtetc_construct(UINT cfmt, const FORMATETC afmt[], IEnumFORMATETC **obj);
+static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj);
/************************************************************************
* OLEClipbrd_IEnumFORMATETC_Clone (IEnumFORMATETC)
@@ -311,19 +335,20 @@ static HRESULT enum_fmtetc_construct(UINT cfmt, const FORMATETC afmt[], IEnumFOR
* Standard enumerator members for IEnumFORMATETC
*/
static HRESULT WINAPI OLEClipbrd_IEnumFORMATETC_Clone
- (LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
+ (LPENUMFORMATETC iface, LPENUMFORMATETC* obj)
{
enum_fmtetc *This = impl_from_IEnumFORMATETC(iface);
- HRESULT hr = S_OK;
+ ole_priv_data *new_data;
- TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
+ TRACE("(%p)->(%p)\n", This, obj);
- if ( !ppenum )
- return E_INVALIDARG;
+ if ( !obj ) return E_INVALIDARG;
+ *obj = NULL;
- hr = enum_fmtetc_construct(This->countFmt, This->pFmt, ppenum);
+ new_data = HeapAlloc(GetProcessHeap(), 0, This->data->size);
+ if(!new_data) return E_OUTOFMEMORY;
- return hr;
+ return enum_fmtetc_construct(new_data, This->pos, obj);
}
static const IEnumFORMATETCVtbl efvt =
@@ -340,13 +365,11 @@ static const IEnumFORMATETCVtbl efvt =
/************************************************************************
* enum_fmtetc_construct
*
- * Creates an IEnumFORMATETC enumerator from an array of FORMATETC
- * Structures.
+ * Creates an IEnumFORMATETC enumerator from ole_priv_data which it then owns.
*/
-static HRESULT enum_fmtetc_construct(UINT cfmt, const FORMATETC afmt[], IEnumFORMATETC **obj)
+static HRESULT enum_fmtetc_construct(ole_priv_data *data, UINT pos, IEnumFORMATETC **obj)
{
enum_fmtetc* ef;
- DWORD size=cfmt * sizeof(FORMATETC);
*obj = NULL;
ef = HeapAlloc(GetProcessHeap(), 0, sizeof(*ef));
@@ -354,19 +377,10 @@ static HRESULT enum_fmtetc_construct(UINT cfmt, const FORMATETC afmt[], IEnumFOR
ef->ref = 1;
ef->lpVtbl = &efvt;
+ ef->data = data;
+ ef->pos = pos;
- ef->pos = 0;
- ef->countFmt = cfmt;
- ef->pFmt = HeapAlloc(GetProcessHeap(), 0, size);
- if (ef->pFmt)
- memcpy(ef->pFmt, afmt, size);
- else
- {
- HeapFree(GetProcessHeap(), 0, ef);
- return E_OUTOFMEMORY;
- }
-
- TRACE("(%p)->()\n",ef);
+ TRACE("(%p)->()\n", ef);
*obj = (IEnumFORMATETC *)ef;
return S_OK;
}
@@ -969,90 +983,47 @@ static HRESULT WINAPI OLEClipbrd_IDataObject_SetData(
static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc(
IDataObject* iface,
DWORD dwDirection,
- IEnumFORMATETC** ppenumFormatEtc)
+ IEnumFORMATETC** enum_fmt)
{
- HRESULT hr = S_OK;
- FORMATETC *afmt = NULL;
- int cfmt, i;
- UINT format;
- BOOL bClipboardOpen;
- ole_clipbrd *This = impl_from_IDataObject(iface);
+ HRESULT hr = S_OK;
+ ole_clipbrd *This = impl_from_IDataObject(iface);
+ HGLOBAL handle;
+ ole_priv_data *data = NULL;
- TRACE("(%p, %x, %p)\n", iface, dwDirection, ppenumFormatEtc);
+ TRACE("(%p, %x, %p)\n", iface, dwDirection, enum_fmt);
- /*
- * 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);
- }
+ *enum_fmt = NULL;
- /*
- * 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 );
+ if ( dwDirection != DATADIR_GET ) return E_NOTIMPL;
+ if ( !OpenClipboard(This->hWndClipboard) ) return 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! */
+ handle = GetClipboardData( ole_priv_data_clipboard_format );
+ if(handle)
{
- ERR("EnumClipboardFormats failed to return format!\n");
- HANDLE_ERROR( E_FAIL );
+ ole_priv_data *src = GlobalLock(handle);
+ if(src)
+ {
+ /* FIXME: sanity check on size */
+ data = HeapAlloc(GetProcessHeap(), 0, src->size);
+ if(!data)
+ {
+ GlobalUnlock(handle);
+ hr = E_OUTOFMEMORY;
+ goto end;
+ }
+ memcpy(data, src, src->size);
+ GlobalUnlock(handle);
+ }
}
- /* 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;
- }
+ if(!data) hr = create_empty_priv_data(&data);
+ if(FAILED(hr)) goto end;
- hr = enum_fmtetc_construct( cfmt, afmt, ppenumFormatEtc );
- if (FAILED(hr))
- HANDLE_ERROR( hr );
+ hr = enum_fmtetc_construct( data, 0, enum_fmt );
-CLEANUP:
- /*
- * Free the array of FORMATETC's
- */
- HeapFree(GetProcessHeap(), 0, afmt);
-
- /*
- * Close Windows clipboard
- */
- if ( bClipboardOpen && !CloseClipboard() )
- hr = CLIPBRD_E_CANT_CLOSE;
-
- return hr;
+end:
+ if ( !CloseClipboard() ) hr = CLIPBRD_E_CANT_CLOSE;
+ return hr;
}
/************************************************************************
More information about the wine-cvs
mailing list