Huw Davies : ole32: If there' s a current data object on the ole clipboard GetData should use it.

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


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

Author: Huw Davies <huw at codeweavers.com>
Date:   Thu Apr 16 12:13:39 2009 +0100

ole32: If there's a current data object on the ole clipboard GetData should use it.

---

 dlls/ole32/clipboard.c |  110 +++++++++++++++++++++++++++++++++++++----------
 1 files changed, 86 insertions(+), 24 deletions(-)

diff --git a/dlls/ole32/clipboard.c b/dlls/ole32/clipboard.c
index 9e92abe..83d923e 100644
--- a/dlls/ole32/clipboard.c
+++ b/dlls/ole32/clipboard.c
@@ -859,14 +859,71 @@ static ULONG WINAPI OLEClipbrd_IDataObject_Release(
   return ref;
 }
 
+/************************************************************
+ *              get_current_ole_clip_window
+ *
+ * Return the window that owns the ole clipboard.
+ *
+ * If the clipboard is flushed or not owned by ole this will
+ * return NULL.
+ */
+static HWND get_current_ole_clip_window(void)
+{
+    HGLOBAL h;
+    HWND *ptr, wnd;
+
+    h = GetClipboardData(dataobject_clipboard_format);
+    if(!h) return NULL;
+    ptr = GlobalLock(h);
+    if(!ptr) return NULL;
+    wnd = *ptr;
+    GlobalUnlock(h);
+    return wnd;
+}
+
+/************************************************************
+ *              get_current_dataobject
+ *
+ * Return an unmarshalled IDataObject if there is a current
+ * (ie non-flushed) object on the ole clipboard.
+ */
+static HRESULT get_current_dataobject(IDataObject **data)
+{
+    HRESULT hr = S_FALSE;
+    HWND wnd = get_current_ole_clip_window();
+    HGLOBAL h;
+    void *ptr;
+    IStream *stm;
+    LARGE_INTEGER pos;
+
+    *data = NULL;
+    if(!wnd) return S_FALSE;
+
+    h = GetPropW(wnd, wine_marshal_dataobject);
+    if(!h) return S_FALSE;
+    ptr = GlobalLock(h);
+    if(!ptr) return S_FALSE;
+
+    hr = CreateStreamOnHGlobal(NULL, TRUE, &stm);
+    if(FAILED(hr)) goto end;
+
+    hr = IStream_Write(stm, ptr, GlobalSize(h), NULL);
+    if(SUCCEEDED(hr))
+    {
+        pos.QuadPart = 0;
+        IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
+        hr = CoUnmarshalInterface(stm, &IID_IDataObject, (void**)data);
+    }
+    IStream_Release(stm);
+
+end:
+    GlobalUnlock(h);
+    return hr;
+}
 
 /************************************************************************
  * OLEClipbrd_IDataObject_GetData (IDataObject)
  *
- * The OLE Clipboard's implementation of this method delegates to
- * a data source if there is one or wraps around the windows clipboard
- *
- * See Windows documentation for more details on IDataObject methods.
  */
 static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
 	    IDataObject*     iface,
@@ -874,39 +931,40 @@ static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
 	    STGMEDIUM*       pmedium)
 {
   HANDLE h, hData = 0;
-  ole_clipbrd *This = impl_from_IDataObject(iface);
   HRESULT hr;
+  IDataObject *data;
 
   TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
 
   if ( !pformatetcIn || !pmedium )
     return E_INVALIDARG;
 
-  /*
-   * If we have a data source placed on the clipboard (via OleSetClipboard)
-   * simply delegate to the source object's QueryGetData
-   * NOTE: This code assumes that the IDataObject is in the same address space!
-   * We will need to add marshalling support when Wine handles multiple processes.
-   */
-  if ( This->src_data )
+  if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
+
+  hr = get_current_dataobject(&data);
+  if ( hr == S_OK )
   {
-    return IDataObject_GetData(This->src_data, pformatetcIn, pmedium);
+    hr = IDataObject_GetData(data, pformatetcIn, pmedium);
+    IDataObject_Release(data);
+    CloseClipboard();
+    return hr;
   }
 
-  if ( pformatetcIn->lindex != -1 )
-    return DV_E_FORMATETC;
-
-  if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
-    return DV_E_TYMED;
-/*
-   if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
-     return DV_E_DVASPECT;
-*/
-
   /*
    * Otherwise, get the data from the windows clipboard using GetClipboardData
    */
-  if ( !OpenClipboard(NULL)) return CLIPBRD_E_CANT_OPEN;
+
+  if ( pformatetcIn->lindex != -1 )
+  {
+      hr = DV_E_FORMATETC;
+      goto end;
+  }
+
+  if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
+  {
+      hr = DV_E_TYMED;
+      goto end;
+  }
 
   h = GetClipboardData(pformatetcIn->cfFormat);
   hr = dup_global_mem(h, GMEM_MOVEABLE, &hData);
@@ -918,12 +976,16 @@ static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
   pmedium->u.hGlobal = hData;
   pmedium->pUnkForRelease = NULL;
 
+end:
   if ( !CloseClipboard() ) return CLIPBRD_E_CANT_CLOSE;
 
   if(FAILED(hr)) return hr;
   return (hData == 0) ? DV_E_FORMATETC : S_OK;
 }
 
+/************************************************************************
+ * OLEClipbrd_IDataObject_GetDataHere (IDataObject)
+ */
 static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
 	    IDataObject*     iface,
 	    LPFORMATETC      pformatetc,




More information about the wine-cvs mailing list