Huw Davies : ole32: Store the marshalled IDataObject in a window property of the clipboard window .
Alexandre Julliard
julliard at winehq.org
Thu Apr 16 14:34:50 CDT 2009
Module: wine
Branch: master
Commit: 6d4a39409995c91372c182aa55f791d440ba34a1
URL: http://source.winehq.org/git/wine.git/?a=commit;h=6d4a39409995c91372c182aa55f791d440ba34a1
Author: Huw Davies <huw at codeweavers.com>
Date: Thu Apr 16 12:12:03 2009 +0100
ole32: Store the marshalled IDataObject in a window property of the clipboard window.
This is somewhat different from how Windows behaves. Windows stores
two properties; an IID and an endpoint number.
---
dlls/ole32/clipboard.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 56 insertions(+), 1 deletions(-)
diff --git a/dlls/ole32/clipboard.c b/dlls/ole32/clipboard.c
index 3cfb1a8..9e92abe 100644
--- a/dlls/ole32/clipboard.c
+++ b/dlls/ole32/clipboard.c
@@ -137,6 +137,7 @@ typedef struct ole_clipbrd
HWND window; /* Hidden clipboard window */
IDataObject *src_data; /* Source object passed to OleSetClipboard */
ole_priv_data *cached_enum; /* Cached result from the enumeration of src data object */
+ IStream *marshal_data; /* Stream onto which to marshal src_data */
} ole_clipbrd;
static inline ole_clipbrd *impl_from_IDataObject(IDataObject *iface)
@@ -174,6 +175,8 @@ static inline HRESULT get_ole_clipbrd(ole_clipbrd **clipbrd)
*/
static const WCHAR clipbrd_wndclass[] = {'C','L','I','P','B','R','D','W','N','D','C','L','A','S','S',0};
+static const WCHAR wine_marshal_dataobject[] = {'W','i','n','e',' ','m','a','r','s','h','a','l',' ','d','a','t','a','o','b','j','e','c','t',0};
+
static UINT dataobject_clipboard_format;
static UINT ole_priv_data_clipboard_format;
static UINT embed_source_clipboard_format;
@@ -829,6 +832,7 @@ static void OLEClipbrd_Destroy(ole_clipbrd* This)
if ( This->window ) destroy_clipbrd_window(This->window);
+ IStream_Release(This->marshal_data);
HeapFree(GetProcessHeap(), 0, This);
}
@@ -1119,6 +1123,7 @@ static const IDataObjectVtbl OLEClipbrd_IDataObject_VTable =
static ole_clipbrd* OLEClipbrd_Construct(void)
{
ole_clipbrd* This;
+ HGLOBAL h;
This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
if (!This) return NULL;
@@ -1130,7 +1135,18 @@ static ole_clipbrd* OLEClipbrd_Construct(void)
This->src_data = NULL;
This->cached_enum = NULL;
+ h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 0);
+ if(!h) goto error;
+
+ if(FAILED(CreateStreamOnHGlobal(h, TRUE, &This->marshal_data)))
+ goto error;
+
return This;
+
+error:
+ if(h) GlobalFree(h);
+ HeapFree(GetProcessHeap(), 0, This);
+ return NULL;
}
static void register_clipboard_formats(void)
@@ -1291,17 +1307,45 @@ static inline HRESULT get_clipbrd_window(ole_clipbrd *clipbrd, HWND *wnd)
return *wnd ? S_OK : E_FAIL;
}
+
+/**********************************************************************
+ * release_marshal_data
+ *
+ * Releases the data and sets the stream back to zero size.
+ */
+static inline void release_marshal_data(IStream *stm)
+{
+ LARGE_INTEGER pos;
+ ULARGE_INTEGER size;
+ pos.QuadPart = size.QuadPart = 0;
+
+ IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
+ CoReleaseMarshalData(stm);
+ IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
+ IStream_SetSize(stm, size);
+}
+
/***********************************************************************
* set_src_dataobject
*
* Clears and sets the clipboard's src IDataObject.
+ *
+ * To marshal the source dataobject we do something rather different from Windows.
+ * We set a window prop which contains the marshalled data.
+ * Windows set two props one of which is an IID, the other is an endpoint number.
*/
static HRESULT set_src_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
{
- HRESULT hr = S_OK;
+ HRESULT hr;
+ HWND wnd;
+
+ if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
if(clipbrd->src_data)
{
+ RemovePropW(wnd, wine_marshal_dataobject);
+ release_marshal_data(clipbrd->marshal_data);
+
IDataObject_Release(clipbrd->src_data);
clipbrd->src_data = NULL;
HeapFree(GetProcessHeap(), 0, clipbrd->cached_enum);
@@ -1310,8 +1354,19 @@ static HRESULT set_src_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
if(data)
{
+ HGLOBAL h;
+ IUnknown *unk;
+
IDataObject_AddRef(data);
clipbrd->src_data = data;
+
+ IDataObject_QueryInterface(data, &IID_IUnknown, (void**)&unk);
+ hr = CoMarshalInterface(clipbrd->marshal_data, &IID_IDataObject, unk,
+ MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
+ IUnknown_Release(unk); /* Don't hold a ref on IUnknown, we have one on IDataObject. */
+ if(FAILED(hr)) return hr;
+ GetHGlobalFromStream(clipbrd->marshal_data, &h);
+ SetPropW(wnd, wine_marshal_dataobject, h);
hr = set_clipboard_formats(clipbrd, data);
}
return hr;
More information about the wine-cvs
mailing list