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

ole32: The consumer data object is not a singleton, but reflects the state of…

ole32: The consumer data object is not a singleton, but reflects the state of the clipboard when it was acquired.
parent f8a1b7e5
...@@ -124,15 +124,24 @@ static HRESULT create_empty_priv_data(ole_priv_data **data) ...@@ -124,15 +124,24 @@ static HRESULT create_empty_priv_data(ole_priv_data **data)
return S_OK; return S_OK;
} }
/****************************************************************************
* Consumer snapshot. Represents the state of the ole clipboard
* returned by OleGetClipboard().
*/
typedef struct snapshot
{
const IDataObjectVtbl* lpVtbl;
LONG ref;
DWORD seq_no; /* Clipboard sequence number corresponding to this snapshot */
} snapshot;
/**************************************************************************** /****************************************************************************
* ole_clipbrd * ole_clipbrd
*/ */
typedef struct ole_clipbrd typedef struct ole_clipbrd
{ {
const IDataObjectVtbl* lpvtbl; /* Exposed IDataObject vtable */ snapshot *latest_snapshot; /* Latest consumer snapshot */
LONG ref;
HWND window; /* Hidden clipboard window */ HWND window; /* Hidden clipboard window */
IDataObject *src_data; /* Source object passed to OleSetClipboard */ IDataObject *src_data; /* Source object passed to OleSetClipboard */
...@@ -140,9 +149,9 @@ typedef struct ole_clipbrd ...@@ -140,9 +149,9 @@ typedef struct ole_clipbrd
IStream *marshal_data; /* Stream onto which to marshal src_data */ IStream *marshal_data; /* Stream onto which to marshal src_data */
} ole_clipbrd; } ole_clipbrd;
static inline ole_clipbrd *impl_from_IDataObject(IDataObject *iface) static inline snapshot *impl_from_IDataObject(IDataObject *iface)
{ {
return (ole_clipbrd*)((char*)iface - FIELD_OFFSET(ole_clipbrd, lpvtbl)); return (snapshot*)((char*)iface - FIELD_OFFSET(snapshot, lpVtbl));
} }
typedef struct PresentationDataHeader typedef struct PresentationDataHeader
...@@ -763,16 +772,12 @@ static HRESULT render_format(IDataObject *data, LPFORMATETC fmt) ...@@ -763,16 +772,12 @@ static HRESULT render_format(IDataObject *data, LPFORMATETC fmt)
/************************************************************************ /************************************************************************
* OLEClipbrd_IDataObject_QueryInterface (IUnknown) * snapshot_QueryInterface
*
* See Windows documentation for more details on IUnknown methods.
*/ */
static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface( static HRESULT WINAPI snapshot_QueryInterface(IDataObject *iface,
IDataObject* iface, REFIID riid, void **ppvObject)
REFIID riid,
void** ppvObject)
{ {
ole_clipbrd *This = impl_from_IDataObject(iface); snapshot *This = impl_from_IDataObject(iface);
TRACE("(%p)->(IID:%s, %p)\n", This, debugstr_guid(riid), ppvObject); TRACE("(%p)->(IID:%s, %p)\n", This, debugstr_guid(riid), ppvObject);
if ( (This==0) || (ppvObject==0) ) if ( (This==0) || (ppvObject==0) )
...@@ -797,16 +802,13 @@ static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface( ...@@ -797,16 +802,13 @@ static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
} }
/************************************************************************ /************************************************************************
* OLEClipbrd_IDataObject_AddRef (IUnknown) * snapshot_AddRef
*
* See Windows documentation for more details on IUnknown methods.
*/ */
static ULONG WINAPI OLEClipbrd_IDataObject_AddRef( static ULONG WINAPI snapshot_AddRef(IDataObject *iface)
IDataObject* iface)
{ {
ole_clipbrd *This = impl_from_IDataObject(iface); snapshot *This = impl_from_IDataObject(iface);
TRACE("(%p)->(count=%u)\n",This, This->ref); TRACE("(%p)->(count=%u)\n", This, This->ref);
return InterlockedIncrement(&This->ref); return InterlockedIncrement(&This->ref);
} }
...@@ -837,23 +839,25 @@ static void OLEClipbrd_Destroy(ole_clipbrd* This) ...@@ -837,23 +839,25 @@ static void OLEClipbrd_Destroy(ole_clipbrd* This)
} }
/************************************************************************ /************************************************************************
* OLEClipbrd_IDataObject_Release (IUnknown) * snapshot_Release
*
* See Windows documentation for more details on IUnknown methods.
*/ */
static ULONG WINAPI OLEClipbrd_IDataObject_Release( static ULONG WINAPI snapshot_Release(IDataObject *iface)
IDataObject* iface)
{ {
ole_clipbrd *This = impl_from_IDataObject(iface); snapshot *This = impl_from_IDataObject(iface);
ULONG ref; ULONG ref;
TRACE("(%p)->(count=%u)\n",This, This->ref); TRACE("(%p)->(count=%u)\n", This, This->ref);
ref = InterlockedDecrement(&This->ref); ref = InterlockedDecrement(&This->ref);
if (ref == 0) if (ref == 0)
{ {
OLEClipbrd_Destroy(This); ole_clipbrd *clipbrd;
HRESULT hr = get_ole_clipbrd(&clipbrd);
if(SUCCEEDED(hr) && clipbrd->latest_snapshot == This)
clipbrd->latest_snapshot = NULL;
HeapFree(GetProcessHeap(), 0, This);
} }
return ref; return ref;
...@@ -922,13 +926,11 @@ end: ...@@ -922,13 +926,11 @@ end:
} }
/************************************************************************ /************************************************************************
* OLEClipbrd_IDataObject_GetData (IDataObject) * snapshot_GetData
*
*/ */
static HRESULT WINAPI OLEClipbrd_IDataObject_GetData( static HRESULT WINAPI snapshot_GetData(IDataObject *iface,
IDataObject* iface, FORMATETC *pformatetcIn,
LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
STGMEDIUM* pmedium)
{ {
HANDLE h, hData = 0; HANDLE h, hData = 0;
HRESULT hr; HRESULT hr;
...@@ -984,102 +986,78 @@ end: ...@@ -984,102 +986,78 @@ end:
} }
/************************************************************************ /************************************************************************
* OLEClipbrd_IDataObject_GetDataHere (IDataObject) * snapshot_GetDataHere
*/ */
static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere( static HRESULT WINAPI snapshot_GetDataHere(IDataObject *iface, FORMATETC *fmt,
IDataObject* iface, STGMEDIUM *med)
LPFORMATETC pformatetc,
STGMEDIUM* pmedium)
{ {
FIXME(": Stub\n"); FIXME("(%p, %p, %p): stub\n", iface, fmt, med);
return E_NOTIMPL; return E_NOTIMPL;
} }
/************************************************************************ /************************************************************************
* OLEClipbrd_IDataObject_QueryGetData (IDataObject) * snapshot_QueryGetData
* *
* The OLE Clipboard's implementation of this method delegates to * The OLE Clipboard's implementation of this method delegates to
* a data source if there is one or wraps around the windows clipboard * a data source if there is one or wraps around the windows clipboard
* function IsClipboardFormatAvailable() otherwise. * function IsClipboardFormatAvailable() otherwise.
* *
* See Windows documentation for more details on IDataObject methods.
*/ */
static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData( static HRESULT WINAPI snapshot_QueryGetData(IDataObject *iface, FORMATETC *fmt)
IDataObject* iface,
LPFORMATETC pformatetc)
{ {
TRACE("(%p, %p)\n", iface, pformatetc); FIXME("(%p, %p)\n", iface, fmt);
if (!pformatetc) if (!fmt) return E_INVALIDARG;
return E_INVALIDARG;
if ( pformatetc->dwAspect != DVASPECT_CONTENT ) if ( fmt->dwAspect != DVASPECT_CONTENT ) return DV_E_FORMATETC;
return DV_E_FORMATETC;
if ( pformatetc->lindex != -1 ) if ( fmt->lindex != -1 ) return DV_E_FORMATETC;
return DV_E_FORMATETC;
/* return (IsClipboardFormatAvailable(fmt->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
* Delegate to the Windows clipboard function IsClipboardFormatAvailable
*/
return (IsClipboardFormatAvailable(pformatetc->cfFormat)) ? S_OK : DV_E_CLIPFORMAT;
} }
/************************************************************************ /************************************************************************
* OLEClipbrd_IDataObject_GetCanonicalFormatEtc (IDataObject) * snapshot_GetCanonicalFormatEtc
*
* See Windows documentation for more details on IDataObject methods.
*/ */
static HRESULT WINAPI OLEClipbrd_IDataObject_GetCanonicalFormatEtc( static HRESULT WINAPI snapshot_GetCanonicalFormatEtc(IDataObject *iface, FORMATETC *fmt_in,
IDataObject* iface, FORMATETC *fmt_out)
LPFORMATETC pformatectIn,
LPFORMATETC pformatetcOut)
{ {
TRACE("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut); TRACE("(%p, %p, %p)\n", iface, fmt_in, fmt_out);
if ( !pformatectIn || !pformatetcOut ) if ( !fmt_in || !fmt_out ) return E_INVALIDARG;
return E_INVALIDARG;
*pformatetcOut = *pformatectIn; *fmt_out = *fmt_in;
return DATA_S_SAMEFORMATETC; return DATA_S_SAMEFORMATETC;
} }
/************************************************************************ /************************************************************************
* OLEClipbrd_IDataObject_SetData (IDataObject) * snapshot_SetData
* *
* The OLE Clipboard's does not implement this method * The OLE Clipboard does not implement this method
*
* See Windows documentation for more details on IDataObject methods.
*/ */
static HRESULT WINAPI OLEClipbrd_IDataObject_SetData( static HRESULT WINAPI snapshot_SetData(IDataObject *iface, FORMATETC *fmt,
IDataObject* iface, STGMEDIUM *med, BOOL release)
LPFORMATETC pformatetc,
STGMEDIUM* pmedium,
BOOL fRelease)
{ {
TRACE("\n"); TRACE("(%p, %p, %p, %d): not implemented\n", iface, fmt, med, release);
return E_NOTIMPL; return E_NOTIMPL;
} }
/************************************************************************ /************************************************************************
* OLEClipbrd_IDataObject_EnumFormatEtc (IDataObject) * snapshot_EnumFormatEtc
* *
* See Windows documentation for more details on IDataObject methods.
*/ */
static HRESULT WINAPI OLEClipbrd_IDataObject_EnumFormatEtc( static HRESULT WINAPI snapshot_EnumFormatEtc(IDataObject *iface, DWORD dir,
IDataObject* iface, IEnumFORMATETC **enum_fmt)
DWORD dwDirection,
IEnumFORMATETC** enum_fmt)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
HGLOBAL handle; HGLOBAL handle;
ole_priv_data *data = NULL; ole_priv_data *data = NULL;
TRACE("(%p, %x, %p)\n", iface, dwDirection, enum_fmt); TRACE("(%p, %x, %p)\n", iface, dir, enum_fmt);
*enum_fmt = NULL; *enum_fmt = NULL;
if ( dwDirection != DATADIR_GET ) return E_NOTIMPL; if ( dir != DATADIR_GET ) return E_NOTIMPL;
if ( !OpenClipboard(NULL) ) return CLIPBRD_E_CANT_OPEN; if ( !OpenClipboard(NULL) ) return CLIPBRD_E_CANT_OPEN;
handle = GetClipboardData( ole_priv_data_clipboard_format ); handle = GetClipboardData( ole_priv_data_clipboard_format );
...@@ -1112,73 +1090,75 @@ end: ...@@ -1112,73 +1090,75 @@ end:
} }
/************************************************************************ /************************************************************************
* OLEClipbrd_IDataObject_DAdvise (IDataObject) * snapshot_DAdvise
* *
* The OLE Clipboard's does not implement this method * The OLE Clipboard does not implement this method
*
* See Windows documentation for more details on IDataObject methods.
*/ */
static HRESULT WINAPI OLEClipbrd_IDataObject_DAdvise( static HRESULT WINAPI snapshot_DAdvise(IDataObject *iface, FORMATETC *fmt,
IDataObject* iface, DWORD flags, IAdviseSink *sink,
FORMATETC* pformatetc, DWORD *conn)
DWORD advf,
IAdviseSink* pAdvSink,
DWORD* pdwConnection)
{ {
TRACE("\n"); TRACE("(%p, %p, %x, %p, %p): not implemented\n", iface, fmt, flags, sink, conn);
return E_NOTIMPL; return E_NOTIMPL;
} }
/************************************************************************ /************************************************************************
* OLEClipbrd_IDataObject_DUnadvise (IDataObject) * snapshot_DUnadvise
*
* The OLE Clipboard's does not implement this method
* *
* See Windows documentation for more details on IDataObject methods. * The OLE Clipboard does not implement this method
*/ */
static HRESULT WINAPI OLEClipbrd_IDataObject_DUnadvise( static HRESULT WINAPI snapshot_DUnadvise(IDataObject* iface, DWORD conn)
IDataObject* iface,
DWORD dwConnection)
{ {
TRACE("\n"); TRACE("(%p, %d): not implemented\n", iface, conn);
return E_NOTIMPL; return E_NOTIMPL;
} }
/************************************************************************ /************************************************************************
* OLEClipbrd_IDataObject_EnumDAdvise (IDataObject) * snapshot_EnumDAdvise
* *
* The OLE Clipboard does not implement this method * The OLE Clipboard does not implement this method
*
* See Windows documentation for more details on IDataObject methods.
*/ */
static HRESULT WINAPI OLEClipbrd_IDataObject_EnumDAdvise( static HRESULT WINAPI snapshot_EnumDAdvise(IDataObject* iface,
IDataObject* iface, IEnumSTATDATA** enum_advise)
IEnumSTATDATA** ppenumAdvise)
{ {
TRACE("\n"); TRACE("(%p, %p): not implemented\n", iface, enum_advise);
return E_NOTIMPL; return E_NOTIMPL;
} }
static const IDataObjectVtbl OLEClipbrd_IDataObject_VTable = static const IDataObjectVtbl snapshot_vtable =
{ {
OLEClipbrd_IDataObject_QueryInterface, snapshot_QueryInterface,
OLEClipbrd_IDataObject_AddRef, snapshot_AddRef,
OLEClipbrd_IDataObject_Release, snapshot_Release,
OLEClipbrd_IDataObject_GetData, snapshot_GetData,
OLEClipbrd_IDataObject_GetDataHere, snapshot_GetDataHere,
OLEClipbrd_IDataObject_QueryGetData, snapshot_QueryGetData,
OLEClipbrd_IDataObject_GetCanonicalFormatEtc, snapshot_GetCanonicalFormatEtc,
OLEClipbrd_IDataObject_SetData, snapshot_SetData,
OLEClipbrd_IDataObject_EnumFormatEtc, snapshot_EnumFormatEtc,
OLEClipbrd_IDataObject_DAdvise, snapshot_DAdvise,
OLEClipbrd_IDataObject_DUnadvise, snapshot_DUnadvise,
OLEClipbrd_IDataObject_EnumDAdvise snapshot_EnumDAdvise
}; };
/*---------------------------------------------------------------------* /*---------------------------------------------------------------------*
* Internal implementation methods for the OLE clipboard * Internal implementation methods for the OLE clipboard
*---------------------------------------------------------------------*/ *---------------------------------------------------------------------*/
static snapshot *snapshot_construct(DWORD seq_no)
{
snapshot *This;
This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
if (!This) return NULL;
This->lpVtbl = &snapshot_vtable;
This->ref = 0;
This->seq_no = seq_no;
return This;
}
/********************************************************* /*********************************************************
* Construct the OLEClipbrd class. * Construct the OLEClipbrd class.
*/ */
...@@ -1190,9 +1170,7 @@ static ole_clipbrd* OLEClipbrd_Construct(void) ...@@ -1190,9 +1170,7 @@ static ole_clipbrd* OLEClipbrd_Construct(void)
This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) ); This = HeapAlloc( GetProcessHeap(), 0, sizeof(*This) );
if (!This) return NULL; if (!This) return NULL;
This->lpvtbl = &OLEClipbrd_IDataObject_VTable; This->latest_snapshot = NULL;
This->ref = 1;
This->window = NULL; This->window = NULL;
This->src_data = NULL; This->src_data = NULL;
This->cached_enum = NULL; This->cached_enum = NULL;
...@@ -1248,19 +1226,12 @@ void OLEClipbrd_Initialize(void) ...@@ -1248,19 +1226,12 @@ void OLEClipbrd_Initialize(void)
void OLEClipbrd_UnInitialize(void) void OLEClipbrd_UnInitialize(void)
{ {
TRACE("()\n"); TRACE("()\n");
/*
* Destroy the clipboard if no one holds a reference to us. if ( theOleClipboard )
* Note that the clipboard was created with a reference count of 1.
*/
if ( theOleClipboard && (theOleClipboard->ref <= 1) )
{ {
OLEClipbrd_Destroy( theOleClipboard ); OLEClipbrd_Destroy( theOleClipboard );
theOleClipboard = NULL; theOleClipboard = NULL;
} }
else
{
WARN( "() : OLEClipbrd_UnInitialize called while client holds an IDataObject reference!\n");
}
} }
/********************************************************************* /*********************************************************************
...@@ -1608,17 +1579,32 @@ end: ...@@ -1608,17 +1579,32 @@ end:
* state of the Windows clipboard. If the current clipboard already contains * state of the Windows clipboard. If the current clipboard already contains
* an IDataObject, our internal IDataObject will delegate to this object. * an IDataObject, our internal IDataObject will delegate to this object.
*/ */
HRESULT WINAPI OleGetClipboard(IDataObject** ppDataObj) HRESULT WINAPI OleGetClipboard(IDataObject **obj)
{ {
HRESULT hr; HRESULT hr;
ole_clipbrd *clipbrd; ole_clipbrd *clipbrd;
TRACE("()\n"); DWORD seq_no;
TRACE("(%p)\n", obj);
if(!obj) return E_INVALIDARG;
if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr; if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
hr = IDataObject_QueryInterface( (IDataObject*)&(clipbrd->lpvtbl), seq_no = GetClipboardSequenceNumber();
&IID_IDataObject, (void**)ppDataObj); if(clipbrd->latest_snapshot && clipbrd->latest_snapshot->seq_no != seq_no)
return hr; clipbrd->latest_snapshot = NULL;
if(!clipbrd->latest_snapshot)
{
clipbrd->latest_snapshot = snapshot_construct(seq_no);
if(!clipbrd->latest_snapshot) return E_OUTOFMEMORY;
}
*obj = (IDataObject*)&clipbrd->latest_snapshot->lpVtbl;
IDataObject_AddRef(*obj);
return S_OK;
} }
/****************************************************************************** /******************************************************************************
......
...@@ -884,7 +884,6 @@ static void test_consumer_refs(void) ...@@ -884,7 +884,6 @@ static void test_consumer_refs(void)
ok(get1 == get2, "data objects differ\n"); ok(get1 == get2, "data objects differ\n");
refs = IDataObject_Release(get2); refs = IDataObject_Release(get2);
todo_wine
ok(refs == 1, "got %d\n", refs); ok(refs == 1, "got %d\n", refs);
OleFlushClipboard(); OleFlushClipboard();
...@@ -892,7 +891,6 @@ todo_wine ...@@ -892,7 +891,6 @@ todo_wine
hr = OleGetClipboard(&get2); hr = OleGetClipboard(&get2);
ok(hr == S_OK, "got %08x\n", hr); ok(hr == S_OK, "got %08x\n", hr);
todo_wine
ok(get1 != get2, "data objects match\n"); ok(get1 != get2, "data objects match\n");
OleSetClipboard(NULL); OleSetClipboard(NULL);
...@@ -900,10 +898,8 @@ todo_wine ...@@ -900,10 +898,8 @@ todo_wine
hr = OleGetClipboard(&get3); hr = OleGetClipboard(&get3);
ok(hr == S_OK, "got %08x\n", hr); ok(hr == S_OK, "got %08x\n", hr);
todo_wine {
ok(get1 != get3, "data objects match\n"); ok(get1 != get3, "data objects match\n");
ok(get2 != get3, "data objects match\n"); ok(get2 != get3, "data objects match\n");
}
IDataObject_Release(get3); IDataObject_Release(get3);
IDataObject_Release(get2); IDataObject_Release(get2);
......
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