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

Alexandre Julliard julliard at winehq.org
Thu Apr 16 14:34:49 CDT 2009


Module: wine
Branch: master
Commit: e58a9db129f283b3b7e41d79223272cb7057f735
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e58a9db129f283b3b7e41d79223272cb7057f735

Author: Huw Davies <huw at 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:
 




More information about the wine-cvs mailing list