Commit e58a9db1 authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

ole32: Store a cached version of the local data object's enumeration.

parent 999bb6a0
...@@ -84,21 +84,55 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); ...@@ -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) #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 * ole_clipbrd
*/ */
struct ole_clipbrd typedef struct ole_clipbrd
{ {
const IDataObjectVtbl* lpvtbl; /* Exposed IDataObject vtable */ const IDataObjectVtbl* lpvtbl; /* Exposed IDataObject vtable */
LONG ref; LONG ref;
HWND hWndClipboard; /* Hidden clipboard window */ HWND hWndClipboard; /* Hidden clipboard window */
IDataObject* pIDataObjectSrc; /* Source object passed to OleSetClipboard */ IDataObject *pIDataObjectSrc; /* Source object passed to OleSetClipboard */
}; ole_priv_data *cached_enum; /* Cached result from the enumeration of src data object */
} ole_clipbrd;
typedef struct ole_clipbrd ole_clipbrd;
static inline ole_clipbrd *impl_from_IDataObject(IDataObject *iface) static inline ole_clipbrd *impl_from_IDataObject(IDataObject *iface)
{ {
...@@ -128,41 +162,6 @@ static UINT dataobject_clipboard_format; ...@@ -128,41 +162,6 @@ static UINT dataobject_clipboard_format;
static UINT ole_priv_data_clipboard_format; static UINT ole_priv_data_clipboard_format;
static UINT embed_source_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 * Implementation of the internal IEnumFORMATETC interface returned by
* the OLE clipboard's IDataObject. * the OLE clipboard's IDataObject.
...@@ -690,6 +689,8 @@ static LRESULT CALLBACK OLEClipbrd_WndProc ...@@ -690,6 +689,8 @@ static LRESULT CALLBACK OLEClipbrd_WndProc
{ {
IDataObject_Release(theOleClipboard->pIDataObjectSrc); IDataObject_Release(theOleClipboard->pIDataObjectSrc);
theOleClipboard->pIDataObjectSrc = NULL; theOleClipboard->pIDataObjectSrc = NULL;
HeapFree(GetProcessHeap(), 0, theOleClipboard->cached_enum);
theOleClipboard->cached_enum = NULL;
} }
break; break;
} }
...@@ -1104,6 +1105,7 @@ static ole_clipbrd* OLEClipbrd_Construct(void) ...@@ -1104,6 +1105,7 @@ static ole_clipbrd* OLEClipbrd_Construct(void)
This->hWndClipboard = NULL; This->hWndClipboard = NULL;
This->pIDataObjectSrc = NULL; This->pIDataObjectSrc = NULL;
This->cached_enum = NULL;
theOleClipboard = This; theOleClipboard = This;
return This; return This;
...@@ -1228,7 +1230,7 @@ static inline BOOL is_format_in_list(ole_priv_data_entry *entries, DWORD num, UI ...@@ -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 * TODO: We need to additionally handle TYMED_IStorage and
* TYMED_IStream data by copying into global memory. * 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; HRESULT hr;
FORMATETC fmt; FORMATETC fmt;
...@@ -1301,6 +1303,14 @@ static HRESULT set_clipboard_formats(IDataObject *data) ...@@ -1301,6 +1303,14 @@ static HRESULT set_clipboard_formats(IDataObject *data)
IEnumFORMATETC_Release(enum_fmt); 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); GlobalUnlock(priv_data_handle);
SetClipboardData(ole_priv_data_clipboard_format, priv_data_handle); SetClipboardData(ole_priv_data_clipboard_format, priv_data_handle);
...@@ -1393,6 +1403,8 @@ HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj) ...@@ -1393,6 +1403,8 @@ HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
{ {
IDataObject_Release(theOleClipboard->pIDataObjectSrc); IDataObject_Release(theOleClipboard->pIDataObjectSrc);
theOleClipboard->pIDataObjectSrc = NULL; theOleClipboard->pIDataObjectSrc = NULL;
HeapFree(GetProcessHeap(), 0, theOleClipboard->cached_enum);
theOleClipboard->cached_enum = NULL;
} }
/* A NULL value indicates that the clipboard should be emptied. */ /* A NULL value indicates that the clipboard should be emptied. */
...@@ -1400,7 +1412,7 @@ HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj) ...@@ -1400,7 +1412,7 @@ HRESULT WINAPI OleSetClipboard(IDataObject* pDataObj)
if ( pDataObj ) if ( pDataObj )
{ {
IDataObject_AddRef(theOleClipboard->pIDataObjectSrc); IDataObject_AddRef(theOleClipboard->pIDataObjectSrc);
hr = set_clipboard_formats(pDataObj); hr = set_clipboard_formats(theOleClipboard, pDataObj);
if(FAILED(hr)) goto end; if(FAILED(hr)) goto end;
} }
...@@ -1416,6 +1428,8 @@ end: ...@@ -1416,6 +1428,8 @@ end:
{ {
IDataObject_Release(theOleClipboard->pIDataObjectSrc); IDataObject_Release(theOleClipboard->pIDataObjectSrc);
theOleClipboard->pIDataObjectSrc = NULL; theOleClipboard->pIDataObjectSrc = NULL;
HeapFree(GetProcessHeap(), 0, theOleClipboard->cached_enum);
theOleClipboard->cached_enum = NULL;
} }
} }
...@@ -1506,6 +1520,8 @@ HRESULT WINAPI OleFlushClipboard(void) ...@@ -1506,6 +1520,8 @@ HRESULT WINAPI OleFlushClipboard(void)
IDataObject_Release(theOleClipboard->pIDataObjectSrc); IDataObject_Release(theOleClipboard->pIDataObjectSrc);
theOleClipboard->pIDataObjectSrc = NULL; theOleClipboard->pIDataObjectSrc = NULL;
HeapFree(GetProcessHeap(), 0, theOleClipboard->cached_enum);
theOleClipboard->cached_enum = NULL;
end: end:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment