Module: wine Branch: master Commit: e58a9db129f283b3b7e41d79223272cb7057f735 URL: http://source.winehq.org/git/wine.git/?a=commit;h=e58a9db129f283b3b7e41d7922...
Author: Huw Davies huw@codeweavers.com Date: Thu Apr 16 11:49:11 2009 +0100
ole32: Store a cached version of the local data object's enumeration.
---
dlls/ole32/clipboard.c | 100 ++++++++++++++++++++++++++++-------------------- 1 files changed, 58 insertions(+), 42 deletions(-)
diff --git a/dlls/ole32/clipboard.c b/dlls/ole32/clipboard.c index 3926537..bfb9c72 100644 --- a/dlls/ole32/clipboard.c +++ b/dlls/ole32/clipboard.c @@ -84,21 +84,55 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
#define HANDLE_ERROR(err) do { hr = err; TRACE("(HRESULT=%x)\n", (HRESULT)err); goto CLEANUP; } while (0)
+/* Structure of 'Ole Private Data' clipboard format */ +typedef struct +{ + FORMATETC fmtetc; + DWORD first_use; /* Has this cf been added to the list already */ + DWORD unk[2]; +} ole_priv_data_entry; + +typedef struct +{ + DWORD unk1; + DWORD size; /* in bytes of the entire structure */ + DWORD unk2; + DWORD count; /* no. of format entries */ + DWORD unk3[2]; + ole_priv_data_entry entries[1]; /* array of size count */ + /* 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; +} +
/**************************************************************************** * ole_clipbrd */ -struct ole_clipbrd +typedef struct ole_clipbrd { const IDataObjectVtbl* lpvtbl; /* Exposed IDataObject vtable */
LONG ref;
HWND hWndClipboard; /* Hidden clipboard window */ - IDataObject* pIDataObjectSrc; /* Source object passed to OleSetClipboard */ -}; - -typedef struct ole_clipbrd ole_clipbrd; + IDataObject *pIDataObjectSrc; /* Source object passed to OleSetClipboard */ + ole_priv_data *cached_enum; /* Cached result from the enumeration of src data object */ +} ole_clipbrd;
static inline ole_clipbrd *impl_from_IDataObject(IDataObject *iface) { @@ -128,41 +162,6 @@ static UINT dataobject_clipboard_format; static UINT ole_priv_data_clipboard_format; static UINT embed_source_clipboard_format;
-/* Structure of 'Ole Private Data' clipboard format */ -typedef struct -{ - FORMATETC fmtetc; - DWORD first_use; /* Has this cf been added to the list already */ - DWORD unk[2]; -} ole_priv_data_entry; - -typedef struct -{ - DWORD unk1; - DWORD size; /* in bytes of the entire structure */ - DWORD unk2; - DWORD count; /* no. of format entries */ - DWORD unk3[2]; - ole_priv_data_entry entries[1]; /* array of size count */ - /* 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. @@ -690,6 +689,8 @@ static LRESULT CALLBACK OLEClipbrd_WndProc { IDataObject_Release(theOleClipboard->pIDataObjectSrc); theOleClipboard->pIDataObjectSrc = NULL; + HeapFree(GetProcessHeap(), 0, theOleClipboard->cached_enum); + theOleClipboard->cached_enum = NULL; } break; } @@ -1104,6 +1105,7 @@ static ole_clipbrd* OLEClipbrd_Construct(void)
This->hWndClipboard = NULL; This->pIDataObjectSrc = NULL; + This->cached_enum = NULL;
theOleClipboard = This; return This; @@ -1228,7 +1230,7 @@ static inline BOOL is_format_in_list(ole_priv_data_entry *entries, DWORD num, UI * TODO: We need to additionally handle TYMED_IStorage and * TYMED_IStream data by copying into global memory. */ -static HRESULT set_clipboard_formats(IDataObject *data) +static HRESULT set_clipboard_formats(ole_clipbrd *clipbrd, IDataObject *data) { HRESULT hr; FORMATETC fmt; @@ -1301,6 +1303,14 @@ static HRESULT set_clipboard_formats(IDataObject *data)
IEnumFORMATETC_Release(enum_fmt);
+ /* Cache the list and fixup any target device offsets to ptrs */ + clipbrd->cached_enum = HeapAlloc(GetProcessHeap(), 0, needed); + memcpy(clipbrd->cached_enum, priv_data, needed); + for(idx = 0; idx < clipbrd->cached_enum->count; idx++) + if(clipbrd->cached_enum->entries[idx].fmtetc.ptd) + clipbrd->cached_enum->entries[idx].fmtetc.ptd = + (DVTARGETDEVICE *)((char*)clipbrd->cached_enum + (DWORD)clipbrd->cached_enum->entries[idx].fmtetc.ptd); + GlobalUnlock(priv_data_handle); SetClipboardData(ole_priv_data_clipboard_format, priv_data_handle);
@@ -1393,6 +1403,8 @@ HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj) { IDataObject_Release(theOleClipboard->pIDataObjectSrc); theOleClipboard->pIDataObjectSrc = NULL; + HeapFree(GetProcessHeap(), 0, theOleClipboard->cached_enum); + theOleClipboard->cached_enum = NULL; }
/* A NULL value indicates that the clipboard should be emptied. */ @@ -1400,7 +1412,7 @@ HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj) if ( pDataObj ) { IDataObject_AddRef(theOleClipboard->pIDataObjectSrc); - hr = set_clipboard_formats(pDataObj); + hr = set_clipboard_formats(theOleClipboard, pDataObj); if(FAILED(hr)) goto end; }
@@ -1416,6 +1428,8 @@ end: { IDataObject_Release(theOleClipboard->pIDataObjectSrc); theOleClipboard->pIDataObjectSrc = NULL; + HeapFree(GetProcessHeap(), 0, theOleClipboard->cached_enum); + theOleClipboard->cached_enum = NULL; } }
@@ -1506,6 +1520,8 @@ HRESULT WINAPI OleFlushClipboard(void)
IDataObject_Release(theOleClipboard->pIDataObjectSrc); theOleClipboard->pIDataObjectSrc = NULL; + HeapFree(GetProcessHeap(), 0, theOleClipboard->cached_enum); + theOleClipboard->cached_enum = NULL;
end: