mshtml: Pass DispatchEx pointer instead of outer IUnknown to DispatchEx's vtbl functions.
[wine] / dlls / ole32 / tests / clipboard.c
1 /*
2  * Clipboard unit tests
3  *
4  * Copyright 2006 Kevin Koltzau
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define COBJMACROS
22 #define CONST_VTABLE
23 #define NONAMELESSUNION
24
25 #include <stdarg.h>
26 #include <stdio.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "objbase.h"
31
32 #include "wine/test.h"
33
34 #define InitFormatEtc(fe, cf, med) \
35         {\
36         (fe).cfFormat=cf;\
37         (fe).dwAspect=DVASPECT_CONTENT;\
38         (fe).ptd=NULL;\
39         (fe).tymed=med;\
40         (fe).lindex=-1;\
41         };
42
43 static inline char *dump_fmtetc(FORMATETC *fmt)
44 {
45     static char buf[100];
46
47     snprintf(buf, sizeof(buf), "cf %04x ptd %p aspect %x lindex %d tymed %x",
48              fmt->cfFormat, fmt->ptd, fmt->dwAspect, fmt->lindex, fmt->tymed);
49     return buf;
50 }
51
52 typedef struct DataObjectImpl {
53     IDataObject IDataObject_iface;
54     LONG ref;
55
56     FORMATETC *fmtetc;
57     UINT fmtetc_cnt;
58
59     HANDLE text;
60     IStream *stm;
61     IStorage *stg;
62 } DataObjectImpl;
63
64 typedef struct EnumFormatImpl {
65     IEnumFORMATETC IEnumFORMATETC_iface;
66     LONG ref;
67
68     FORMATETC *fmtetc;
69     UINT fmtetc_cnt;
70
71     UINT cur;
72 } EnumFormatImpl;
73
74 static BOOL expect_DataObjectImpl_QueryGetData = TRUE;
75 static ULONG DataObjectImpl_GetData_calls = 0;
76 static ULONG DataObjectImpl_GetDataHere_calls = 0;
77 static ULONG DataObjectImpl_EnumFormatEtc_calls = 0;
78
79 static UINT cf_stream, cf_storage, cf_global, cf_another, cf_onemore;
80
81 static HRESULT EnumFormatImpl_Create(FORMATETC *fmtetc, UINT size, LPENUMFORMATETC *lplpformatetc);
82
83 static inline DataObjectImpl *impl_from_IDataObject(IDataObject *iface)
84 {
85     return CONTAINING_RECORD(iface, DataObjectImpl, IDataObject_iface);
86 }
87
88 static inline EnumFormatImpl *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
89 {
90     return CONTAINING_RECORD(iface, EnumFormatImpl, IEnumFORMATETC_iface);
91 }
92
93 static HRESULT WINAPI EnumFormatImpl_QueryInterface(IEnumFORMATETC *iface, REFIID riid, LPVOID *ppvObj)
94 {
95     EnumFormatImpl *This = impl_from_IEnumFORMATETC(iface);
96
97     if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IEnumFORMATETC)) {
98         IEnumFORMATETC_AddRef(iface);
99         *ppvObj = This;
100         return S_OK;
101     }
102     *ppvObj = NULL;
103     return E_NOINTERFACE;
104 }
105
106 static ULONG WINAPI EnumFormatImpl_AddRef(IEnumFORMATETC *iface)
107 {
108     EnumFormatImpl *This = impl_from_IEnumFORMATETC(iface);
109     LONG ref = InterlockedIncrement(&This->ref);
110     return ref;
111 }
112
113 static ULONG WINAPI EnumFormatImpl_Release(IEnumFORMATETC *iface)
114 {
115     EnumFormatImpl *This = impl_from_IEnumFORMATETC(iface);
116     ULONG ref = InterlockedDecrement(&This->ref);
117
118     if(!ref) {
119         HeapFree(GetProcessHeap(), 0, This->fmtetc);
120         HeapFree(GetProcessHeap(), 0, This);
121     }
122
123     return ref;
124 }
125
126 static HRESULT WINAPI EnumFormatImpl_Next(IEnumFORMATETC *iface, ULONG celt,
127                                           FORMATETC *rgelt, ULONG *pceltFetched)
128 {
129     EnumFormatImpl *This = impl_from_IEnumFORMATETC(iface);
130     ULONG count, i;
131
132     trace("next: count %d cur %d\n", celt, This->cur);
133
134     if(!rgelt)
135         return E_INVALIDARG;
136
137     count = min(celt, This->fmtetc_cnt - This->cur);
138     for(i = 0; i < count; i++, This->cur++, rgelt++)
139     {
140         *rgelt = This->fmtetc[This->cur];
141         if(rgelt->ptd)
142         {
143             DWORD size = This->fmtetc[This->cur].ptd->tdSize;
144             rgelt->ptd = CoTaskMemAlloc(size);
145             memcpy(rgelt->ptd, This->fmtetc[This->cur].ptd, size);
146         }
147     }
148     if(pceltFetched)
149         *pceltFetched = count;
150     return count == celt ? S_OK : S_FALSE;
151 }
152
153 static HRESULT WINAPI EnumFormatImpl_Skip(IEnumFORMATETC *iface, ULONG celt)
154 {
155     ok(0, "unexpected call\n");
156     return E_NOTIMPL;
157 }
158
159 static HRESULT WINAPI EnumFormatImpl_Reset(IEnumFORMATETC *iface)
160 {
161     EnumFormatImpl *This = impl_from_IEnumFORMATETC(iface);
162
163     This->cur = 0;
164     return S_OK;
165 }
166
167 static HRESULT WINAPI EnumFormatImpl_Clone(IEnumFORMATETC *iface, IEnumFORMATETC **ppenum)
168 {
169     ok(0, "unexpected call\n");
170     return E_NOTIMPL;
171 }
172
173 static const IEnumFORMATETCVtbl VT_EnumFormatImpl = {
174     EnumFormatImpl_QueryInterface,
175     EnumFormatImpl_AddRef,
176     EnumFormatImpl_Release,
177     EnumFormatImpl_Next,
178     EnumFormatImpl_Skip,
179     EnumFormatImpl_Reset,
180     EnumFormatImpl_Clone
181 };
182
183 static HRESULT EnumFormatImpl_Create(FORMATETC *fmtetc, UINT fmtetc_cnt, IEnumFORMATETC **lplpformatetc)
184 {
185     EnumFormatImpl *ret;
186
187     ret = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumFormatImpl));
188     ret->IEnumFORMATETC_iface.lpVtbl = &VT_EnumFormatImpl;
189     ret->ref = 1;
190     ret->cur = 0;
191     ret->fmtetc_cnt = fmtetc_cnt;
192     ret->fmtetc = HeapAlloc(GetProcessHeap(), 0, fmtetc_cnt*sizeof(FORMATETC));
193     memcpy(ret->fmtetc, fmtetc, fmtetc_cnt*sizeof(FORMATETC));
194     *lplpformatetc = (LPENUMFORMATETC)ret;
195     return S_OK;
196 }
197
198 static HRESULT WINAPI DataObjectImpl_QueryInterface(IDataObject *iface, REFIID riid, LPVOID *ppvObj)
199 {
200     DataObjectImpl *This = impl_from_IDataObject(iface);
201
202     if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDataObject)) {
203         IDataObject_AddRef(iface);
204         *ppvObj = This;
205         return S_OK;
206     }
207     *ppvObj = NULL;
208     return E_NOINTERFACE;
209 }
210
211 static ULONG WINAPI DataObjectImpl_AddRef(IDataObject* iface)
212 {
213     DataObjectImpl *This = impl_from_IDataObject(iface);
214     ULONG ref = InterlockedIncrement(&This->ref);
215     return ref;
216 }
217
218 static ULONG WINAPI DataObjectImpl_Release(IDataObject* iface)
219 {
220     DataObjectImpl *This = impl_from_IDataObject(iface);
221     ULONG ref = InterlockedDecrement(&This->ref);
222
223     if(!ref)
224     {
225         int i;
226         if(This->text) GlobalFree(This->text);
227         for(i = 0; i < This->fmtetc_cnt; i++)
228             HeapFree(GetProcessHeap(), 0, This->fmtetc[i].ptd);
229         HeapFree(GetProcessHeap(), 0, This->fmtetc);
230         if(This->stm) IStream_Release(This->stm);
231         if(This->stg) IStorage_Release(This->stg);
232         HeapFree(GetProcessHeap(), 0, This);
233     }
234
235     return ref;
236 }
237
238 static HRESULT WINAPI DataObjectImpl_GetData(IDataObject* iface, FORMATETC *pformatetc, STGMEDIUM *pmedium)
239 {
240     DataObjectImpl *This = impl_from_IDataObject(iface);
241     UINT i;
242     BOOL foundFormat = FALSE;
243
244     trace("getdata: %s\n", dump_fmtetc(pformatetc));
245
246     DataObjectImpl_GetData_calls++;
247
248     if(pformatetc->lindex != -1)
249         return DV_E_FORMATETC;
250
251     for(i = 0; i < This->fmtetc_cnt; i++)
252     {
253         if(This->fmtetc[i].cfFormat == pformatetc->cfFormat)
254         {
255             foundFormat = TRUE;
256             if(This->fmtetc[i].tymed & pformatetc->tymed)
257             {
258                 pmedium->pUnkForRelease = (LPUNKNOWN)iface;
259                 IUnknown_AddRef(pmedium->pUnkForRelease);
260
261                 if(pformatetc->cfFormat == CF_TEXT || pformatetc->cfFormat == cf_global)
262                 {
263                     pmedium->tymed = TYMED_HGLOBAL;
264                     U(*pmedium).hGlobal = This->text;
265                 }
266                 else if(pformatetc->cfFormat == cf_stream)
267                 {
268                     pmedium->tymed = TYMED_ISTREAM;
269                     IStream_AddRef(This->stm);
270                     U(*pmedium).pstm = This->stm;
271                 }
272                 else if(pformatetc->cfFormat == cf_storage || pformatetc->cfFormat == cf_another)
273                 {
274                     pmedium->tymed = TYMED_ISTORAGE;
275                     IStorage_AddRef(This->stg);
276                     U(*pmedium).pstg = This->stg;
277                 }
278                 return S_OK;
279             }
280         }
281     }
282
283     return foundFormat ? DV_E_TYMED : DV_E_FORMATETC;
284 }
285
286 static HRESULT WINAPI DataObjectImpl_GetDataHere(IDataObject* iface, FORMATETC *pformatetc, STGMEDIUM *pmedium)
287 {
288     trace("getdatahere: %s\n", dump_fmtetc(pformatetc));
289     DataObjectImpl_GetDataHere_calls++;
290
291     return E_NOTIMPL;
292 }
293
294 static HRESULT WINAPI DataObjectImpl_QueryGetData(IDataObject* iface, FORMATETC *pformatetc)
295 {
296     DataObjectImpl *This = impl_from_IDataObject(iface);
297     UINT i;
298     BOOL foundFormat = FALSE;
299
300     trace("querygetdata: %s\n", dump_fmtetc(pformatetc));
301     if (!expect_DataObjectImpl_QueryGetData)
302         ok(0, "unexpected call to DataObjectImpl_QueryGetData\n");
303
304     if(pformatetc->lindex != -1)
305         return DV_E_LINDEX;
306
307     for(i=0; i<This->fmtetc_cnt; i++) {
308         if(This->fmtetc[i].cfFormat == pformatetc->cfFormat) {
309             foundFormat = TRUE;
310             if(This->fmtetc[i].tymed == pformatetc->tymed)
311                 return S_OK;
312         }
313     }
314     return foundFormat?DV_E_FORMATETC:DV_E_TYMED;
315 }
316
317 static HRESULT WINAPI DataObjectImpl_GetCanonicalFormatEtc(IDataObject* iface, FORMATETC *pformatectIn,
318                                                            FORMATETC *pformatetcOut)
319 {
320     ok(0, "unexpected call\n");
321     return E_NOTIMPL;
322 }
323
324 static HRESULT WINAPI DataObjectImpl_SetData(IDataObject* iface, FORMATETC *pformatetc,
325                                              STGMEDIUM *pmedium, BOOL fRelease)
326 {
327     ok(0, "unexpected call\n");
328     return E_NOTIMPL;
329 }
330
331 static HRESULT WINAPI DataObjectImpl_EnumFormatEtc(IDataObject* iface, DWORD dwDirection,
332                                                    IEnumFORMATETC **ppenumFormatEtc)
333 {
334     DataObjectImpl *This = impl_from_IDataObject(iface);
335
336     DataObjectImpl_EnumFormatEtc_calls++;
337
338     if(dwDirection != DATADIR_GET) {
339         ok(0, "unexpected direction %d\n", dwDirection);
340         return E_NOTIMPL;
341     }
342     return EnumFormatImpl_Create(This->fmtetc, This->fmtetc_cnt, ppenumFormatEtc);
343 }
344
345 static HRESULT WINAPI DataObjectImpl_DAdvise(IDataObject* iface, FORMATETC *pformatetc, DWORD advf,
346                                              IAdviseSink *pAdvSink, DWORD *pdwConnection)
347 {
348     ok(0, "unexpected call\n");
349     return E_NOTIMPL;
350 }
351
352 static HRESULT WINAPI DataObjectImpl_DUnadvise(IDataObject* iface, DWORD dwConnection)
353 {
354     ok(0, "unexpected call\n");
355     return E_NOTIMPL;
356 }
357
358 static HRESULT WINAPI DataObjectImpl_EnumDAdvise(IDataObject* iface, IEnumSTATDATA **ppenumAdvise)
359 {
360     ok(0, "unexpected call\n");
361     return E_NOTIMPL;
362 }
363
364 static const IDataObjectVtbl VT_DataObjectImpl =
365 {
366     DataObjectImpl_QueryInterface,
367     DataObjectImpl_AddRef,
368     DataObjectImpl_Release,
369     DataObjectImpl_GetData,
370     DataObjectImpl_GetDataHere,
371     DataObjectImpl_QueryGetData,
372     DataObjectImpl_GetCanonicalFormatEtc,
373     DataObjectImpl_SetData,
374     DataObjectImpl_EnumFormatEtc,
375     DataObjectImpl_DAdvise,
376     DataObjectImpl_DUnadvise,
377     DataObjectImpl_EnumDAdvise
378 };
379
380 static HRESULT DataObjectImpl_CreateText(LPCSTR text, LPDATAOBJECT *lplpdataobj)
381 {
382     DataObjectImpl *obj;
383
384     obj = HeapAlloc(GetProcessHeap(), 0, sizeof(DataObjectImpl));
385     obj->IDataObject_iface.lpVtbl = &VT_DataObjectImpl;
386     obj->ref = 1;
387     obj->text = GlobalAlloc(GMEM_MOVEABLE, strlen(text) + 1);
388     strcpy(GlobalLock(obj->text), text);
389     GlobalUnlock(obj->text);
390     obj->stm = NULL;
391     obj->stg = NULL;
392
393     obj->fmtetc_cnt = 1;
394     obj->fmtetc = HeapAlloc(GetProcessHeap(), 0, obj->fmtetc_cnt*sizeof(FORMATETC));
395     InitFormatEtc(obj->fmtetc[0], CF_TEXT, TYMED_HGLOBAL);
396
397     *lplpdataobj = (LPDATAOBJECT)obj;
398     return S_OK;
399 }
400
401 static const char *cmpl_stm_data = "complex stream";
402 static const char *cmpl_text_data = "complex text";
403 static const WCHAR device_name[] = {'m','y','d','e','v',0};
404
405 static HRESULT DataObjectImpl_CreateComplex(LPDATAOBJECT *lplpdataobj)
406 {
407     DataObjectImpl *obj;
408     ILockBytes *lbs;
409     DEVMODEW dm;
410
411     obj = HeapAlloc(GetProcessHeap(), 0, sizeof(DataObjectImpl));
412     obj->IDataObject_iface.lpVtbl = &VT_DataObjectImpl;
413     obj->ref = 1;
414     obj->text = GlobalAlloc(GMEM_MOVEABLE, strlen(cmpl_text_data) + 1);
415     strcpy(GlobalLock(obj->text), cmpl_text_data);
416     GlobalUnlock(obj->text);
417     CreateStreamOnHGlobal(NULL, TRUE, &obj->stm);
418     IStream_Write(obj->stm, cmpl_stm_data, strlen(cmpl_stm_data), NULL);
419
420     CreateILockBytesOnHGlobal(NULL, TRUE, &lbs);
421     StgCreateDocfileOnILockBytes(lbs, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &obj->stg);
422     ILockBytes_Release(lbs);
423
424     obj->fmtetc_cnt = 8;
425     /* zeroing here since FORMATETC has a hole in it, and it's confusing to have this uninitialised. */
426     obj->fmtetc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, obj->fmtetc_cnt*sizeof(FORMATETC));
427     InitFormatEtc(obj->fmtetc[0], CF_TEXT, TYMED_HGLOBAL);
428     InitFormatEtc(obj->fmtetc[1], cf_stream, TYMED_ISTREAM);
429     InitFormatEtc(obj->fmtetc[2], cf_storage, TYMED_ISTORAGE);
430     InitFormatEtc(obj->fmtetc[3], cf_another, TYMED_ISTORAGE|TYMED_ISTREAM|TYMED_HGLOBAL);
431     memset(&dm, 0, sizeof(dm));
432     dm.dmSize = sizeof(dm);
433     dm.dmDriverExtra = 0;
434     lstrcpyW(dm.dmDeviceName, device_name);
435     obj->fmtetc[3].ptd = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(DVTARGETDEVICE, tdData) + sizeof(device_name) + dm.dmSize + dm.dmDriverExtra);
436     obj->fmtetc[3].ptd->tdSize = FIELD_OFFSET(DVTARGETDEVICE, tdData) + sizeof(device_name) + dm.dmSize + dm.dmDriverExtra;
437     obj->fmtetc[3].ptd->tdDriverNameOffset = FIELD_OFFSET(DVTARGETDEVICE, tdData);
438     obj->fmtetc[3].ptd->tdDeviceNameOffset = 0;
439     obj->fmtetc[3].ptd->tdPortNameOffset   = 0;
440     obj->fmtetc[3].ptd->tdExtDevmodeOffset = obj->fmtetc[3].ptd->tdDriverNameOffset + sizeof(device_name);
441     lstrcpyW((WCHAR*)obj->fmtetc[3].ptd->tdData, device_name);
442     memcpy(obj->fmtetc[3].ptd->tdData + sizeof(device_name), &dm, dm.dmSize + dm.dmDriverExtra);
443
444     InitFormatEtc(obj->fmtetc[4], cf_global, TYMED_HGLOBAL);
445     InitFormatEtc(obj->fmtetc[5], cf_another, TYMED_HGLOBAL);
446     InitFormatEtc(obj->fmtetc[6], cf_another, 0xfffff);
447     InitFormatEtc(obj->fmtetc[7], cf_another, 0xfffff);
448     obj->fmtetc[7].dwAspect = DVASPECT_ICON;
449
450     *lplpdataobj = (LPDATAOBJECT)obj;
451     return S_OK;
452 }
453
454 static void test_get_clipboard(void)
455 {
456     HRESULT hr;
457     IDataObject *data_obj;
458     FORMATETC fmtetc;
459     STGMEDIUM stgmedium;
460
461     hr = OleGetClipboard(NULL);
462     ok(hr == E_INVALIDARG, "OleGetClipboard(NULL) should return E_INVALIDARG instead of 0x%08x\n", hr);
463
464     hr = OleGetClipboard(&data_obj);
465     ok(hr == S_OK, "OleGetClipboard failed with error 0x%08x\n", hr);
466
467     /* test IDataObject_QueryGetData */
468
469     /* clipboard's IDataObject_QueryGetData shouldn't defer to our IDataObject_QueryGetData */
470     expect_DataObjectImpl_QueryGetData = FALSE;
471
472     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
473     hr = IDataObject_QueryGetData(data_obj, &fmtetc);
474     ok(hr == S_OK, "IDataObject_QueryGetData failed with error 0x%08x\n", hr);
475
476     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
477     fmtetc.dwAspect = 0xdeadbeef;
478     hr = IDataObject_QueryGetData(data_obj, &fmtetc);
479     ok(hr == DV_E_FORMATETC, "IDataObject_QueryGetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
480
481     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
482     fmtetc.dwAspect = DVASPECT_THUMBNAIL;
483     hr = IDataObject_QueryGetData(data_obj, &fmtetc);
484     ok(hr == DV_E_FORMATETC, "IDataObject_QueryGetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
485
486     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
487     fmtetc.lindex = 256;
488     hr = IDataObject_QueryGetData(data_obj, &fmtetc);
489     ok(hr == DV_E_FORMATETC || broken(hr == S_OK),
490         "IDataObject_QueryGetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
491
492     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
493     fmtetc.cfFormat = CF_RIFF;
494     hr = IDataObject_QueryGetData(data_obj, &fmtetc);
495     ok(hr == DV_E_CLIPFORMAT, "IDataObject_QueryGetData should have failed with DV_E_CLIPFORMAT instead of 0x%08x\n", hr);
496
497     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
498     fmtetc.tymed = TYMED_FILE;
499     hr = IDataObject_QueryGetData(data_obj, &fmtetc);
500     ok(hr == S_OK, "IDataObject_QueryGetData failed with error 0x%08x\n", hr);
501
502     expect_DataObjectImpl_QueryGetData = TRUE;
503
504     /* test IDataObject_GetData */
505
506     DataObjectImpl_GetData_calls = 0;
507
508     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
509     hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
510     ok(hr == S_OK, "IDataObject_GetData failed with error 0x%08x\n", hr);
511     if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
512
513     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
514     fmtetc.dwAspect = 0xdeadbeef;
515     hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
516     ok(hr == S_OK, "IDataObject_GetData failed with error 0x%08x\n", hr);
517     if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
518
519     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
520     fmtetc.dwAspect = DVASPECT_THUMBNAIL;
521     hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
522     ok(hr == S_OK, "IDataObject_GetData failed with error 0x%08x\n", hr);
523     if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
524
525     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
526     fmtetc.lindex = 256;
527     hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
528     ok(hr == DV_E_FORMATETC || broken(hr == S_OK), "IDataObject_GetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
529     if (hr == S_OK)
530     {
531         /* undo the unexpected success */
532         DataObjectImpl_GetData_calls--;
533         ReleaseStgMedium(&stgmedium);
534     }
535
536     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
537     fmtetc.cfFormat = CF_RIFF;
538     hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
539     ok(hr == DV_E_FORMATETC, "IDataObject_GetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
540     if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
541
542     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
543     fmtetc.tymed = TYMED_FILE;
544     hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
545     ok(hr == DV_E_TYMED, "IDataObject_GetData should have failed with DV_E_TYMED instead of 0x%08x\n", hr);
546     if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
547
548     ok(DataObjectImpl_GetData_calls == 6, "DataObjectImpl_GetData should have been called 6 times instead of %d times\n", DataObjectImpl_GetData_calls);
549
550     IDataObject_Release(data_obj);
551 }
552
553 static void test_enum_fmtetc(IDataObject *src)
554 {
555     HRESULT hr;
556     IDataObject *data;
557     IEnumFORMATETC *enum_fmt, *src_enum;
558     FORMATETC fmt, src_fmt;
559     DWORD count = 0;
560
561     hr = OleGetClipboard(&data);
562     ok(hr == S_OK, "OleGetClipboard failed with error 0x%08x\n", hr);
563
564     hr = IDataObject_EnumFormatEtc(data, DATADIR_SET, &enum_fmt);
565     ok(hr == E_NOTIMPL ||
566        broken(hr == E_INVALIDARG), /* win98 (not win98SE) */
567        "got %08x\n", hr);
568
569     DataObjectImpl_EnumFormatEtc_calls = 0;
570     hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
571     ok(hr == S_OK, "got %08x\n", hr);
572     ok(DataObjectImpl_EnumFormatEtc_calls == 0, "EnumFormatEtc was called\n");
573
574     if(src) IDataObject_EnumFormatEtc(src, DATADIR_GET, &src_enum);
575
576     while((hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL)) == S_OK)
577     {
578         ok(src != NULL, "shouldn't be here\n");
579         hr = IEnumFORMATETC_Next(src_enum, 1, &src_fmt, NULL);
580         ok(hr == S_OK, "%d: got %08x\n", count, hr);
581         trace("%d: %s\n", count, dump_fmtetc(&fmt));
582         ok(fmt.cfFormat == src_fmt.cfFormat, "%d: %04x %04x\n", count, fmt.cfFormat, src_fmt.cfFormat);
583         ok(fmt.dwAspect == src_fmt.dwAspect, "%d: %08x %08x\n", count, fmt.dwAspect, src_fmt.dwAspect);
584         ok(fmt.lindex == src_fmt.lindex, "%d: %08x %08x\n", count, fmt.lindex, src_fmt.lindex);
585         ok(fmt.tymed == src_fmt.tymed, "%d: %08x %08x\n", count, fmt.tymed, src_fmt.tymed);
586         if(fmt.ptd)
587         {
588             ok(src_fmt.ptd != NULL, "%d: expected non-NULL\n", count);
589             CoTaskMemFree(fmt.ptd);
590             CoTaskMemFree(src_fmt.ptd);
591         }
592         count++;
593     }
594
595     ok(hr == S_FALSE, "%d: got %08x\n", count, hr);
596
597     if(src)
598     {
599         hr = IEnumFORMATETC_Next(src_enum, 1, &src_fmt, NULL);
600         ok(hr == S_FALSE ||
601            broken(hr == S_OK && count == 5), /* win9x and winme don't enumerate duplicated cf's */
602            "%d: got %08x\n", count, hr);
603         IEnumFORMATETC_Release(src_enum);
604     }
605
606     hr = IEnumFORMATETC_Reset(enum_fmt);
607     ok(hr == S_OK, "got %08x\n", hr);
608
609     if(src) /* Exercise the enumerator a bit */
610     {
611         IEnumFORMATETC *clone;
612         FORMATETC third_fmt;
613
614         hr = IEnumFORMATETC_Next(enum_fmt, 1, &third_fmt, NULL);
615         ok(hr == S_OK, "got %08x\n", hr);
616         hr = IEnumFORMATETC_Next(enum_fmt, 1, &third_fmt, NULL);
617         ok(hr == S_OK, "got %08x\n", hr);
618         hr = IEnumFORMATETC_Next(enum_fmt, 1, &third_fmt, NULL);
619         ok(hr == S_OK, "got %08x\n", hr);
620
621         hr = IEnumFORMATETC_Reset(enum_fmt);
622         ok(hr == S_OK, "got %08x\n", hr);
623         hr = IEnumFORMATETC_Skip(enum_fmt, 2);
624         ok(hr == S_OK, "got %08x\n", hr);
625
626         hr = IEnumFORMATETC_Clone(enum_fmt, &clone);
627         ok(hr == S_OK, "got %08x\n", hr);
628         hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
629         ok(hr == S_OK, "got %08x\n", hr);
630         ok(fmt.cfFormat == third_fmt.cfFormat, "formats don't match\n");
631         hr = IEnumFORMATETC_Next(clone, 1, &fmt, NULL);
632         ok(hr == S_OK, "got %08x\n", hr);
633         ok(fmt.cfFormat == third_fmt.cfFormat, "formats don't match\n");
634         IEnumFORMATETC_Release(clone);
635     }
636
637     IEnumFORMATETC_Release(enum_fmt);
638     IDataObject_Release(data);
639 }
640
641 static void test_no_cf_dataobject(void)
642 {
643     UINT cf_dataobject = RegisterClipboardFormatA("DataObject");
644     UINT cf_ole_priv_data = RegisterClipboardFormatA("Ole Private Data");
645     HANDLE h;
646     OpenClipboard(NULL);
647
648     h = GetClipboardData(cf_dataobject);
649     ok(!h, "got %p\n", h);
650     h = GetClipboardData(cf_ole_priv_data);
651     ok(!h, "got %p\n", h);
652
653     CloseClipboard();
654 }
655
656 static void test_cf_dataobject(IDataObject *data)
657 {
658     UINT cf = 0;
659     UINT cf_dataobject = RegisterClipboardFormatA("DataObject");
660     UINT cf_ole_priv_data = RegisterClipboardFormatA("Ole Private Data");
661     BOOL found_dataobject = FALSE, found_priv_data = FALSE;
662
663     OpenClipboard(NULL);
664     do
665     {
666         cf = EnumClipboardFormats(cf);
667         if(cf == cf_dataobject)
668         {
669             HGLOBAL h = GetClipboardData(cf);
670             HWND *ptr = GlobalLock(h);
671             DWORD size = GlobalSize(h);
672             HWND clip_owner = GetClipboardOwner();
673
674             found_dataobject = TRUE;
675             ok(size >= sizeof(*ptr), "size %d\n", size);
676             if(data)
677                 ok(*ptr == clip_owner, "hwnd %p clip_owner %p\n", *ptr, clip_owner);
678             else /* ole clipboard flushed */
679                 ok(*ptr == NULL, "hwnd %p\n", *ptr);
680             GlobalUnlock(h);
681         }
682         else if(cf == cf_ole_priv_data)
683         {
684             found_priv_data = TRUE;
685             if(data)
686             {
687                 HGLOBAL h = GetClipboardData(cf);
688                 DWORD *ptr = GlobalLock(h);
689                 DWORD size = GlobalSize(h);
690
691                 if(size != ptr[1])
692                     win_skip("Ole Private Data in win9x format\n");
693                 else
694                 {
695                     HRESULT hr;
696                     IEnumFORMATETC *enum_fmt;
697                     DWORD count = 0;
698                     FORMATETC fmt;
699                     struct formatetcetc
700                     {
701                         FORMATETC fmt;
702                         BOOL first_use_of_cf;
703                         DWORD res[2];
704                     } *fmt_ptr;
705                     struct priv_data
706                     {
707                         DWORD res1;
708                         DWORD size;
709                         DWORD res2;
710                         DWORD count;
711                         DWORD res3[2];
712                         struct formatetcetc fmts[1];
713                     } *priv = (struct priv_data*)ptr;
714                     CLIPFORMAT cfs_seen[10];
715
716                     hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
717                     ok(hr == S_OK, "got %08x\n", hr);
718                     fmt_ptr = priv->fmts;
719
720                     while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
721                     {
722                         int i;
723                         BOOL seen_cf = FALSE;
724
725                         ok(fmt_ptr->fmt.cfFormat == fmt.cfFormat,
726                            "got %08x expected %08x\n", fmt_ptr->fmt.cfFormat, fmt.cfFormat);
727                         ok(fmt_ptr->fmt.dwAspect == fmt.dwAspect, "got %08x expected %08x\n",
728                            fmt_ptr->fmt.dwAspect, fmt.dwAspect);
729                         ok(fmt_ptr->fmt.lindex == fmt.lindex, "got %08x expected %08x\n",
730                            fmt_ptr->fmt.lindex, fmt.lindex);
731                         ok(fmt_ptr->fmt.tymed == fmt.tymed, "got %08x expected %08x\n",
732                            fmt_ptr->fmt.tymed, fmt.tymed);
733                         for(i = 0; i < count; i++)
734                             if(fmt_ptr->fmt.cfFormat == cfs_seen[i])
735                             {
736                                 seen_cf = TRUE;
737                                 break;
738                             }
739                         cfs_seen[count] = fmt.cfFormat;
740                         ok(fmt_ptr->first_use_of_cf == seen_cf ? FALSE : TRUE, "got %08x expected %08x\n",
741                            fmt_ptr->first_use_of_cf, !seen_cf);
742                         ok(fmt_ptr->res[0] == 0, "got %08x\n", fmt_ptr->res[1]);
743                         ok(fmt_ptr->res[1] == 0, "got %08x\n", fmt_ptr->res[2]);
744                         if(fmt.ptd)
745                         {
746                             DVTARGETDEVICE *target;
747
748                             ok(fmt_ptr->fmt.ptd != NULL, "target device offset zero\n");
749                             target = (DVTARGETDEVICE*)((char*)priv + (DWORD_PTR)fmt_ptr->fmt.ptd);
750                             ok(!memcmp(target, fmt.ptd, fmt.ptd->tdSize), "target devices differ\n");
751                             CoTaskMemFree(fmt.ptd);
752                         }
753                         fmt_ptr++;
754                         count++;
755                     }
756                     ok(priv->res1 == 0, "got %08x\n", priv->res1);
757                     ok(priv->res2 == 1, "got %08x\n", priv->res2);
758                     ok(priv->count == count, "got %08x expected %08x\n", priv->count, count);
759                     ok(priv->res3[0] == 0, "got %08x\n", priv->res3[0]);
760
761                     /* win64 sets the lsb */
762                     if(sizeof(fmt_ptr->fmt.ptd) == 8)
763                         todo_wine ok(priv->res3[1] == 1, "got %08x\n", priv->res3[1]);
764                     else
765                         ok(priv->res3[1] == 0, "got %08x\n", priv->res3[1]);
766
767                     GlobalUnlock(h);
768                     IEnumFORMATETC_Release(enum_fmt);
769                 }
770             }
771         }
772         else if(cf == cf_stream)
773         {
774             HGLOBAL h;
775             void *ptr;
776             DWORD size;
777
778             DataObjectImpl_GetDataHere_calls = 0;
779             h = GetClipboardData(cf);
780             ok(DataObjectImpl_GetDataHere_calls == 1, "got %d\n", DataObjectImpl_GetDataHere_calls);
781             ptr = GlobalLock(h);
782             size = GlobalSize(h);
783             ok(size == strlen(cmpl_stm_data) ||
784                broken(size > strlen(cmpl_stm_data)), /* win9x, winme */
785                "expected %d got %d\n", lstrlenA(cmpl_stm_data), size);
786             ok(!memcmp(ptr, cmpl_stm_data, strlen(cmpl_stm_data)), "mismatch\n");
787             GlobalUnlock(h);
788         }
789         else if(cf == cf_global)
790         {
791             HGLOBAL h;
792             void *ptr;
793             DWORD size;
794
795             DataObjectImpl_GetDataHere_calls = 0;
796             h = GetClipboardData(cf);
797             ok(DataObjectImpl_GetDataHere_calls == 0, "got %d\n", DataObjectImpl_GetDataHere_calls);
798             ptr = GlobalLock(h);
799             size = GlobalSize(h);
800             ok(size == strlen(cmpl_text_data) + 1 ||
801                broken(size > strlen(cmpl_text_data) + 1), /* win9x, winme */
802                "expected %d got %d\n", lstrlenA(cmpl_text_data) + 1, size);
803             ok(!memcmp(ptr, cmpl_text_data, strlen(cmpl_text_data) + 1), "mismatch\n");
804             GlobalUnlock(h);
805         }
806     } while(cf);
807     CloseClipboard();
808     ok(found_dataobject, "didn't find cf_dataobject\n");
809     ok(found_priv_data, "didn't find cf_ole_priv_data\n");
810 }
811
812 static void test_set_clipboard(void)
813 {
814     HRESULT hr;
815     ULONG ref;
816     LPDATAOBJECT data1, data2, data_cmpl;
817     HGLOBAL hblob, h;
818
819     cf_stream = RegisterClipboardFormatA("stream format");
820     cf_storage = RegisterClipboardFormatA("storage format");
821     cf_global = RegisterClipboardFormatA("global format");
822     cf_another = RegisterClipboardFormatA("another format");
823     cf_onemore = RegisterClipboardFormatA("one more format");
824
825     hr = DataObjectImpl_CreateText("data1", &data1);
826     ok(SUCCEEDED(hr), "Failed to create data1 object: 0x%08x\n", hr);
827     if(FAILED(hr))
828         return;
829     hr = DataObjectImpl_CreateText("data2", &data2);
830     ok(SUCCEEDED(hr), "Failed to create data2 object: 0x%08x\n", hr);
831     if(FAILED(hr))
832         return;
833     hr = DataObjectImpl_CreateComplex(&data_cmpl);
834     ok(SUCCEEDED(hr), "Failed to create complex data object: 0x%08x\n", hr);
835     if(FAILED(hr))
836         return;
837
838     hr = OleSetClipboard(data1);
839     ok(hr == CO_E_NOTINITIALIZED, "OleSetClipboard should have failed with CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
840
841     CoInitialize(NULL);
842     hr = OleSetClipboard(data1);
843     ok(hr == CO_E_NOTINITIALIZED ||
844        hr == CLIPBRD_E_CANT_SET, /* win9x */
845        "OleSetClipboard should have failed with "
846        "CO_E_NOTINITIALIZED or CLIPBRD_E_CANT_SET instead of 0x%08x\n", hr);
847     CoUninitialize();
848
849     hr = OleInitialize(NULL);
850     ok(hr == S_OK, "OleInitialize failed with error 0x%08x\n", hr);
851
852     hr = OleSetClipboard(data1);
853     ok(hr == S_OK, "failed to set clipboard to data1, hr = 0x%08x\n", hr);
854
855     test_cf_dataobject(data1);
856
857     hr = OleIsCurrentClipboard(data1);
858     ok(hr == S_OK, "expected current clipboard to be data1, hr = 0x%08x\n", hr);
859     hr = OleIsCurrentClipboard(data2);
860     ok(hr == S_FALSE, "did not expect current clipboard to be data2, hr = 0x%08x\n", hr);
861     hr = OleIsCurrentClipboard(NULL);
862     ok(hr == S_FALSE, "expect S_FALSE, hr = 0x%08x\n", hr);
863
864     test_get_clipboard();
865
866     hr = OleSetClipboard(data2);
867     ok(hr == S_OK, "failed to set clipboard to data2, hr = 0x%08x\n", hr);
868     hr = OleIsCurrentClipboard(data1);
869     ok(hr == S_FALSE, "did not expect current clipboard to be data1, hr = 0x%08x\n", hr);
870     hr = OleIsCurrentClipboard(data2);
871     ok(hr == S_OK, "expected current clipboard to be data2, hr = 0x%08x\n", hr);
872     hr = OleIsCurrentClipboard(NULL);
873     ok(hr == S_FALSE, "expect S_FALSE, hr = 0x%08x\n", hr);
874
875     /* put a format directly onto the clipboard to show
876        OleFlushClipboard doesn't empty the clipboard */
877     hblob = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT, 10);
878     OpenClipboard(NULL);
879     h = SetClipboardData(cf_onemore, hblob);
880     ok(h == hblob, "got %p\n", h);
881     h = GetClipboardData(cf_onemore);
882     ok(h == hblob ||
883        broken(h != NULL), /* win9x */
884        "got %p\n", h);
885     CloseClipboard();
886
887     hr = OleFlushClipboard();
888     ok(hr == S_OK, "failed to flush clipboard, hr = 0x%08x\n", hr);
889     hr = OleIsCurrentClipboard(data1);
890     ok(hr == S_FALSE, "did not expect current clipboard to be data1, hr = 0x%08x\n", hr);
891     hr = OleIsCurrentClipboard(data2);
892     ok(hr == S_FALSE, "did not expect current clipboard to be data2, hr = 0x%08x\n", hr);
893     hr = OleIsCurrentClipboard(NULL);
894     ok(hr == S_FALSE, "expect S_FALSE, hr = 0x%08x\n", hr);
895
896     /* format should survive the flush */
897     OpenClipboard(NULL);
898     h = GetClipboardData(cf_onemore);
899     ok(h == hblob ||
900        broken(h != NULL), /* win9x */
901        "got %p\n", h);
902     CloseClipboard();
903
904     test_cf_dataobject(NULL);
905
906     ok(OleSetClipboard(NULL) == S_OK, "failed to clear clipboard, hr = 0x%08x\n", hr);
907
908     OpenClipboard(NULL);
909     h = GetClipboardData(cf_onemore);
910     ok(h == NULL, "got %p\n", h);
911     CloseClipboard();
912
913     trace("setting complex\n");
914     hr = OleSetClipboard(data_cmpl);
915     ok(hr == S_OK, "failed to set clipboard to complex data, hr = 0x%08x\n", hr);
916     test_cf_dataobject(data_cmpl);
917     test_enum_fmtetc(data_cmpl);
918
919     ok(OleSetClipboard(NULL) == S_OK, "failed to clear clipboard, hr = 0x%08x\n", hr);
920
921     test_no_cf_dataobject();
922     test_enum_fmtetc(NULL);
923
924     ref = IDataObject_Release(data1);
925     ok(ref == 0, "expected data1 ref=0, got %d\n", ref);
926     ref = IDataObject_Release(data2);
927     ok(ref == 0, "expected data2 ref=0, got %d\n", ref);
928     ref = IDataObject_Release(data_cmpl);
929     ok(ref == 0, "expected data_cmpl ref=0, got %d\n", ref);
930
931     OleUninitialize();
932 }
933
934 static inline ULONG count_refs(IDataObject *d)
935 {
936     IDataObject_AddRef(d);
937     return IDataObject_Release(d);
938 }
939
940 static void test_consumer_refs(void)
941 {
942     HRESULT hr;
943     IDataObject *src, *src2, *get1, *get2, *get3;
944     ULONG refs, old_refs;
945     FORMATETC fmt;
946     STGMEDIUM med;
947
948     InitFormatEtc(fmt, CF_TEXT, TYMED_HGLOBAL);
949
950     OleInitialize(NULL);
951
952     /* First show that each clipboard state results in
953        a different data object */
954
955     hr = DataObjectImpl_CreateText("data1", &src);
956     ok(hr == S_OK, "got %08x\n", hr);
957     hr = DataObjectImpl_CreateText("data2", &src2);
958     ok(hr == S_OK, "got %08x\n", hr);
959
960     hr = OleSetClipboard(src);
961     ok(hr == S_OK, "got %08x\n", hr);
962
963     hr = OleGetClipboard(&get1);
964     ok(hr == S_OK, "got %08x\n", hr);
965
966     hr = OleGetClipboard(&get2);
967     ok(hr == S_OK, "got %08x\n", hr);
968
969     ok(get1 == get2 ||
970        broken(get1 != get2), /* win9x, winme & nt4 */
971        "data objects differ\n");
972     refs = IDataObject_Release(get2);
973     ok(refs == (get1 == get2 ? 1 : 0), "got %d\n", refs);
974
975     OleFlushClipboard();
976
977     DataObjectImpl_GetData_calls = 0;
978     hr = IDataObject_GetData(get1, &fmt, &med);
979     ok(hr == S_OK, "got %08x\n", hr);
980     ok(DataObjectImpl_GetData_calls == 0, "GetData called\n");
981     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
982
983     hr = OleGetClipboard(&get2);
984     ok(hr == S_OK, "got %08x\n", hr);
985
986     ok(get1 != get2, "data objects match\n");
987
988     OleSetClipboard(NULL);
989
990     hr = OleGetClipboard(&get3);
991     ok(hr == S_OK, "got %08x\n", hr);
992
993     ok(get1 != get3, "data objects match\n");
994     ok(get2 != get3, "data objects match\n");
995
996     IDataObject_Release(get3);
997     IDataObject_Release(get2);
998     IDataObject_Release(get1);
999
1000     /* Now call GetData before the flush and show that this
1001        takes a ref on our src data obj. */
1002
1003     hr = OleSetClipboard(src);
1004     ok(hr == S_OK, "got %08x\n", hr);
1005
1006     old_refs = count_refs(src);
1007
1008     hr = OleGetClipboard(&get1);
1009     ok(hr == S_OK, "got %08x\n", hr);
1010
1011     refs = count_refs(src);
1012     ok(refs == old_refs, "%d %d\n", refs, old_refs);
1013
1014     DataObjectImpl_GetData_calls = 0;
1015     hr = IDataObject_GetData(get1, &fmt, &med);
1016     ok(hr == S_OK, "got %08x\n", hr);
1017     ok(DataObjectImpl_GetData_calls == 1, "GetData not called\n");
1018     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1019     refs = count_refs(src);
1020     ok(refs == old_refs + 1, "%d %d\n", refs, old_refs);
1021
1022     OleFlushClipboard();
1023
1024     DataObjectImpl_GetData_calls = 0;
1025     hr = IDataObject_GetData(get1, &fmt, &med);
1026     ok(hr == S_OK, "got %08x\n", hr);
1027     ok(DataObjectImpl_GetData_calls == 1, "GetData not called\n");
1028     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1029
1030     refs = count_refs(src);
1031     ok(refs == 2, "%d\n", refs);
1032
1033     IDataObject_Release(get1);
1034
1035     refs = count_refs(src);
1036     ok(refs == 1, "%d\n", refs);
1037
1038     /* Now set a second src object before the call to GetData
1039        and show that GetData calls that second src. */
1040
1041     hr = OleSetClipboard(src);
1042     ok(hr == S_OK, "got %08x\n", hr);
1043
1044     old_refs = count_refs(src);
1045
1046     hr = OleGetClipboard(&get1);
1047     ok(hr == S_OK, "got %08x\n", hr);
1048
1049     refs = count_refs(src);
1050     ok(refs == old_refs, "%d %d\n", refs, old_refs);
1051
1052     hr = OleSetClipboard(src2);
1053     ok(hr == S_OK, "got %08x\n", hr);
1054
1055     old_refs = count_refs(src2);
1056
1057     DataObjectImpl_GetData_calls = 0;
1058     hr = IDataObject_GetData(get1, &fmt, &med);
1059     ok(hr == S_OK, "got %08x\n", hr);
1060     ok(DataObjectImpl_GetData_calls == 1, "GetData not called\n");
1061     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1062
1063     refs = count_refs(src);
1064     ok(refs == 1, "%d\n", refs);
1065     refs = count_refs(src2);
1066     ok(refs == old_refs + 1, "%d %d\n", refs, old_refs);
1067
1068     OleSetClipboard(NULL);
1069
1070     refs = count_refs(src2);
1071     ok(refs == 2, "%d\n", refs);
1072
1073     IDataObject_Release(get1);
1074
1075     IDataObject_Release(src2);
1076     IDataObject_Release(src);
1077
1078     OleUninitialize();
1079 }
1080
1081 static void test_flushed_getdata(void)
1082 {
1083     HRESULT hr;
1084     IDataObject *src, *get;
1085     FORMATETC fmt;
1086     STGMEDIUM med;
1087     STATSTG stat;
1088     DEVMODEW dm;
1089
1090     OleInitialize(NULL);
1091
1092     hr = DataObjectImpl_CreateComplex(&src);
1093     ok(hr == S_OK, "got %08x\n", hr);
1094
1095     hr = OleSetClipboard(src);
1096     ok(hr == S_OK, "got %08x\n", hr);
1097
1098     hr = OleFlushClipboard();
1099     ok(hr == S_OK, "got %08x\n", hr);
1100
1101     hr = OleGetClipboard(&get);
1102     ok(hr == S_OK, "got %08x\n", hr);
1103
1104     /* global format -> global & stream */
1105
1106     InitFormatEtc(fmt, CF_TEXT, TYMED_HGLOBAL);
1107     hr = IDataObject_GetData(get, &fmt, &med);
1108     ok(hr == S_OK, "got %08x\n", hr);
1109     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1110     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1111
1112     InitFormatEtc(fmt, CF_TEXT, TYMED_ISTREAM);
1113     hr = IDataObject_GetData(get, &fmt, &med);
1114     ok(hr == S_OK, "got %08x\n", hr);
1115     ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1116     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1117
1118     InitFormatEtc(fmt, CF_TEXT, TYMED_ISTORAGE);
1119     hr = IDataObject_GetData(get, &fmt, &med);
1120     ok(hr == E_FAIL, "got %08x\n", hr);
1121     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1122
1123     InitFormatEtc(fmt, CF_TEXT, 0xffff);
1124     hr = IDataObject_GetData(get, &fmt, &med);
1125     ok(hr == S_OK, "got %08x\n", hr);
1126     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1127     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1128
1129     /* stream format -> global & stream */
1130
1131     InitFormatEtc(fmt, cf_stream, TYMED_ISTREAM);
1132     hr = IDataObject_GetData(get, &fmt, &med);
1133     ok(hr == S_OK, "got %08x\n", hr);
1134     ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1135     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1136
1137     InitFormatEtc(fmt, cf_stream, TYMED_ISTORAGE);
1138     hr = IDataObject_GetData(get, &fmt, &med);
1139     ok(hr == E_FAIL, "got %08x\n", hr);
1140     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1141
1142     InitFormatEtc(fmt, cf_stream, TYMED_HGLOBAL);
1143     hr = IDataObject_GetData(get, &fmt, &med);
1144     ok(hr == S_OK, "got %08x\n", hr);
1145     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1146     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1147
1148     InitFormatEtc(fmt, cf_stream, 0xffff);
1149     hr = IDataObject_GetData(get, &fmt, &med);
1150     ok(hr == S_OK, "got %08x\n", hr);
1151     ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1152     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1153
1154     /* storage format -> global, stream & storage */
1155
1156     InitFormatEtc(fmt, cf_storage, TYMED_ISTORAGE);
1157     hr = IDataObject_GetData(get, &fmt, &med);
1158     ok(hr == S_OK, "got %08x\n", hr);
1159     ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1160     if(SUCCEEDED(hr)) {
1161         hr = IStorage_Stat(med.u.pstg, &stat, STATFLAG_NONAME);
1162         ok(hr == S_OK, "got %08x\n", hr);
1163         ok(stat.grfMode == (STGM_SHARE_EXCLUSIVE | STGM_READWRITE), "got %08x\n", stat.grfMode);
1164         ReleaseStgMedium(&med);
1165     }
1166
1167     InitFormatEtc(fmt, cf_storage, TYMED_ISTREAM);
1168     hr = IDataObject_GetData(get, &fmt, &med);
1169     ok(hr == S_OK, "got %08x\n", hr);
1170     ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1171     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1172
1173     InitFormatEtc(fmt, cf_storage, TYMED_HGLOBAL);
1174     hr = IDataObject_GetData(get, &fmt, &med);
1175     ok(hr == S_OK, "got %08x\n", hr);
1176     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1177     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1178
1179     InitFormatEtc(fmt, cf_storage, TYMED_HGLOBAL | TYMED_ISTREAM);
1180     hr = IDataObject_GetData(get, &fmt, &med);
1181     ok(hr == S_OK, "got %08x\n", hr);
1182     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1183     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1184
1185     InitFormatEtc(fmt, cf_storage, 0xffff);
1186     hr = IDataObject_GetData(get, &fmt, &med);
1187     ok(hr == S_OK, "got %08x\n", hr);
1188     ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1189     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1190
1191     /* complex format with target device */
1192
1193     InitFormatEtc(fmt, cf_another, 0xffff);
1194     hr = IDataObject_GetData(get, &fmt, &med);
1195     ok(hr == DV_E_FORMATETC ||
1196        broken(hr == S_OK), /* win9x, winme & nt4 */
1197        "got %08x\n", hr);
1198     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1199
1200     InitFormatEtc(fmt, cf_another, 0xffff);
1201     memset(&dm, 0, sizeof(dm));
1202     dm.dmSize = sizeof(dm);
1203     dm.dmDriverExtra = 0;
1204     lstrcpyW(dm.dmDeviceName, device_name);
1205     fmt.ptd = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(DVTARGETDEVICE, tdData) + sizeof(device_name) + dm.dmSize + dm.dmDriverExtra);
1206     fmt.ptd->tdSize = FIELD_OFFSET(DVTARGETDEVICE, tdData) + sizeof(device_name) + dm.dmSize + dm.dmDriverExtra;
1207     fmt.ptd->tdDriverNameOffset = FIELD_OFFSET(DVTARGETDEVICE, tdData);
1208     fmt.ptd->tdDeviceNameOffset = 0;
1209     fmt.ptd->tdPortNameOffset   = 0;
1210     fmt.ptd->tdExtDevmodeOffset = fmt.ptd->tdDriverNameOffset + sizeof(device_name);
1211     lstrcpyW((WCHAR*)fmt.ptd->tdData, device_name);
1212     memcpy(fmt.ptd->tdData + sizeof(device_name), &dm, dm.dmSize + dm.dmDriverExtra);
1213
1214     hr = IDataObject_GetData(get, &fmt, &med);
1215     ok(hr == S_OK, "got %08x\n", hr);
1216     ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1217     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1218
1219     HeapFree(GetProcessHeap(), 0, fmt.ptd);
1220
1221
1222     IDataObject_Release(get);
1223     IDataObject_Release(src);
1224     OleUninitialize();
1225 }
1226
1227 static HGLOBAL create_text(void)
1228 {
1229     HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5);
1230     char *p = GlobalLock(h);
1231     strcpy(p, "test");
1232     GlobalUnlock(h);
1233     return h;
1234 }
1235
1236 static HENHMETAFILE create_emf(void)
1237 {
1238     const RECT rect = {0, 0, 100, 100};
1239     HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
1240     ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
1241     return CloseEnhMetaFile(hdc);
1242 }
1243
1244 static void test_nonole_clipboard(void)
1245 {
1246     HRESULT hr;
1247     BOOL r;
1248     IDataObject *get;
1249     IEnumFORMATETC *enum_fmt;
1250     FORMATETC fmt;
1251     HGLOBAL h, hblob, htext;
1252     HENHMETAFILE emf;
1253     STGMEDIUM med;
1254     DWORD obj_type;
1255
1256     r = OpenClipboard(NULL);
1257     ok(r, "gle %d\n", GetLastError());
1258     r = EmptyClipboard();
1259     ok(r, "gle %d\n", GetLastError());
1260     r = CloseClipboard();
1261     ok(r, "gle %d\n", GetLastError());
1262
1263     OleInitialize(NULL);
1264
1265     /* empty clipboard */
1266     hr = OleGetClipboard(&get);
1267     ok(hr == S_OK, "got %08x\n", hr);
1268     hr = IDataObject_EnumFormatEtc(get, DATADIR_GET, &enum_fmt);
1269     ok(hr == S_OK, "got %08x\n", hr);
1270
1271     hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1272     ok(hr == S_FALSE, "got %08x\n", hr);
1273     IEnumFORMATETC_Release(enum_fmt);
1274
1275     IDataObject_Release(get);
1276
1277     /* set a user defined clipboard type */
1278
1279     htext = create_text();
1280     hblob = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT, 10);
1281     emf = create_emf();
1282
1283     r = OpenClipboard(NULL);
1284     ok(r, "gle %d\n", GetLastError());
1285     h = SetClipboardData(CF_TEXT, htext);
1286     ok(h == htext, "got %p\n", h);
1287     h = SetClipboardData(cf_onemore, hblob);
1288     ok(h == hblob, "got %p\n", h);
1289     h = SetClipboardData(CF_ENHMETAFILE, emf);
1290     ok(h == emf, "got %p\n", h);
1291     r = CloseClipboard();
1292     ok(r, "gle %d\n", GetLastError());
1293
1294     hr = OleGetClipboard(&get);
1295     ok(hr == S_OK, "got %08x\n", hr);
1296     hr = IDataObject_EnumFormatEtc(get, DATADIR_GET, &enum_fmt);
1297     ok(hr == S_OK, "got %08x\n", hr);
1298
1299     hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1300     ok(hr == S_OK, "got %08x\n", hr);
1301     ok(fmt.cfFormat == CF_TEXT, "cf %04x\n", fmt.cfFormat);
1302     ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1303     ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1304     ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1305     ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
1306
1307     hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1308     ok(hr == S_OK, "got %08x\n", hr);
1309     ok(fmt.cfFormat == cf_onemore, "cf %04x\n", fmt.cfFormat);
1310     ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1311     ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1312     ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1313     ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
1314
1315     hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1316     ok(hr == S_OK, "got %08x\n", hr);
1317     ok(fmt.cfFormat == CF_ENHMETAFILE, "cf %04x\n", fmt.cfFormat);
1318     ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1319     ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1320     ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1321     ok(fmt.tymed == TYMED_ENHMF, "tymed %x\n", fmt.tymed);
1322
1323     hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1324     ok(hr == S_OK, "got %08x\n", hr); /* User32 adds some synthesised formats */
1325
1326     todo_wine ok(fmt.cfFormat == CF_LOCALE, "cf %04x\n", fmt.cfFormat);
1327     if(fmt.cfFormat == CF_LOCALE)
1328     {
1329         ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1330         ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1331         ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1332         ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
1333
1334         hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1335         ok(hr == S_OK, "got %08x\n", hr);
1336     }
1337
1338     ok(fmt.cfFormat == CF_OEMTEXT, "cf %04x\n", fmt.cfFormat);
1339     ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1340     ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1341     ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1342     ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
1343
1344     hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1345     ok(hr == S_OK, "got %08x\n", hr);
1346     ok(fmt.cfFormat == CF_UNICODETEXT ||
1347        broken(fmt.cfFormat == CF_METAFILEPICT), /* win9x and winme don't have CF_UNICODETEXT */
1348        "cf %04x\n", fmt.cfFormat);
1349     if(fmt.cfFormat == CF_UNICODETEXT)
1350     {
1351         ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1352         ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1353         ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1354         ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
1355
1356         hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1357         ok(hr == S_OK, "got %08x\n", hr);
1358     }
1359     ok(fmt.cfFormat == CF_METAFILEPICT, "cf %04x\n", fmt.cfFormat);
1360     ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1361     ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1362     ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1363     ok(fmt.tymed == TYMED_MFPICT, "tymed %x\n", fmt.tymed);
1364
1365     hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1366     ok(hr == S_FALSE, "got %08x\n", hr);
1367     IEnumFORMATETC_Release(enum_fmt);
1368
1369     InitFormatEtc(fmt, CF_ENHMETAFILE, TYMED_ENHMF);
1370     hr = IDataObject_GetData(get, &fmt, &med);
1371     ok(hr == S_OK, "got %08x\n", hr);
1372     obj_type = GetObjectType(U(med).hEnhMetaFile);
1373     ok(obj_type == OBJ_ENHMETAFILE, "got %d\n", obj_type);
1374     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1375
1376     IDataObject_Release(get);
1377
1378     r = OpenClipboard(NULL);
1379     ok(r, "gle %d\n", GetLastError());
1380     r = EmptyClipboard();
1381     ok(r, "gle %d\n", GetLastError());
1382     r = CloseClipboard();
1383     ok(r, "gle %d\n", GetLastError());
1384
1385     OleUninitialize();
1386 }
1387
1388 static void test_getdatahere(void)
1389 {
1390     HRESULT hr;
1391     IDataObject *src, *get;
1392     FORMATETC fmt;
1393     STGMEDIUM med;
1394
1395     OleInitialize(NULL);
1396
1397     hr = DataObjectImpl_CreateComplex(&src);
1398     ok(hr == S_OK, "got %08x\n", hr);
1399
1400     hr = OleSetClipboard(src);
1401     ok(hr == S_OK, "got %08x\n", hr);
1402
1403     hr = OleGetClipboard(&get);
1404     ok(hr == S_OK, "got %08x\n", hr);
1405
1406     /* global format -> global & stream */
1407
1408     DataObjectImpl_GetData_calls = 0;
1409     DataObjectImpl_GetDataHere_calls = 0;
1410
1411     InitFormatEtc(fmt, CF_TEXT, TYMED_HGLOBAL);
1412
1413     med.pUnkForRelease = NULL;
1414     med.tymed = TYMED_HGLOBAL;
1415     U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 100);
1416     hr = IDataObject_GetDataHere(get, &fmt, &med);
1417     ok(hr == S_OK, "got %08x\n", hr);
1418     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1419     ReleaseStgMedium(&med);
1420     ok(DataObjectImpl_GetDataHere_calls == 1, "called %d\n", DataObjectImpl_GetDataHere_calls);
1421     ok(DataObjectImpl_GetData_calls == 1, "called %d\n", DataObjectImpl_GetData_calls);
1422
1423     InitFormatEtc(fmt, CF_TEXT, 0);
1424
1425     med.pUnkForRelease = NULL;
1426     med.tymed = TYMED_HGLOBAL;
1427     U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 100);
1428     hr = IDataObject_GetDataHere(get, &fmt, &med);
1429     ok(hr == S_OK, "got %08x\n", hr);
1430     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1431     ReleaseStgMedium(&med);
1432     ok(DataObjectImpl_GetDataHere_calls == 2, "called %d\n", DataObjectImpl_GetDataHere_calls);
1433     ok(DataObjectImpl_GetData_calls == 1, "called %d\n", DataObjectImpl_GetData_calls);
1434
1435     med.pUnkForRelease = NULL;
1436     med.tymed = TYMED_HGLOBAL;
1437     U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 1);
1438     hr = IDataObject_GetDataHere(get, &fmt, &med);
1439     ok(hr == E_FAIL, "got %08x\n", hr);
1440     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1441     ReleaseStgMedium(&med);
1442     ok(DataObjectImpl_GetDataHere_calls == 3, "called %d\n", DataObjectImpl_GetDataHere_calls);
1443     ok(DataObjectImpl_GetData_calls == 1, "called %d\n", DataObjectImpl_GetData_calls);
1444
1445     med.pUnkForRelease = NULL;
1446     med.tymed = TYMED_ISTREAM;
1447     CreateStreamOnHGlobal(NULL, TRUE, &U(med).pstm);
1448     hr = IDataObject_GetDataHere(get, &fmt, &med);
1449     ok(hr == S_OK, "got %08x\n", hr);
1450     ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1451     ReleaseStgMedium(&med);
1452     ok(DataObjectImpl_GetDataHere_calls == 4, "called %d\n", DataObjectImpl_GetDataHere_calls);
1453     ok(DataObjectImpl_GetData_calls == 1, "called %d\n", DataObjectImpl_GetData_calls);
1454
1455     med.pUnkForRelease = NULL;
1456     med.tymed = TYMED_ISTORAGE;
1457     StgCreateDocfile(NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &U(med).pstg);
1458     hr = IDataObject_GetDataHere(get, &fmt, &med);
1459     ok(hr == E_FAIL, "got %08x\n", hr);
1460     ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1461     ReleaseStgMedium(&med);
1462     ok(DataObjectImpl_GetDataHere_calls == 5, "called %d\n", DataObjectImpl_GetDataHere_calls);
1463     ok(DataObjectImpl_GetData_calls == 1, "called %d\n", DataObjectImpl_GetData_calls);
1464
1465     InitFormatEtc(fmt, cf_stream, 0);
1466
1467     med.pUnkForRelease = NULL;
1468     med.tymed = TYMED_HGLOBAL;
1469     U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 100);
1470     hr = IDataObject_GetDataHere(get, &fmt, &med);
1471     ok(hr == S_OK, "got %08x\n", hr);
1472     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1473     ReleaseStgMedium(&med);
1474     ok(DataObjectImpl_GetDataHere_calls == 7, "called %d\n", DataObjectImpl_GetDataHere_calls);
1475     ok(DataObjectImpl_GetData_calls == 2, "called %d\n", DataObjectImpl_GetData_calls);
1476
1477     med.pUnkForRelease = NULL;
1478     med.tymed = TYMED_ISTREAM;
1479     CreateStreamOnHGlobal(NULL, TRUE, &U(med).pstm);
1480     hr = IDataObject_GetDataHere(get, &fmt, &med);
1481     ok(hr == S_OK, "got %08x\n", hr);
1482     ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1483     ReleaseStgMedium(&med);
1484     ok(DataObjectImpl_GetDataHere_calls == 8, "called %d\n", DataObjectImpl_GetDataHere_calls);
1485     ok(DataObjectImpl_GetData_calls == 2, "called %d\n", DataObjectImpl_GetData_calls);
1486
1487     med.pUnkForRelease = NULL;
1488     med.tymed = TYMED_ISTORAGE;
1489     StgCreateDocfile(NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &U(med).pstg);
1490     hr = IDataObject_GetDataHere(get, &fmt, &med);
1491     ok(hr == E_FAIL, "got %08x\n", hr);
1492     ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1493     ReleaseStgMedium(&med);
1494     ok(DataObjectImpl_GetDataHere_calls == 9, "called %d\n", DataObjectImpl_GetDataHere_calls);
1495     ok(DataObjectImpl_GetData_calls == 2, "called %d\n", DataObjectImpl_GetData_calls);
1496
1497     InitFormatEtc(fmt, cf_storage, 0);
1498
1499     med.pUnkForRelease = NULL;
1500     med.tymed = TYMED_HGLOBAL;
1501     U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 3000);
1502     hr = IDataObject_GetDataHere(get, &fmt, &med);
1503     ok(hr == S_OK, "got %08x\n", hr);
1504     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1505     ReleaseStgMedium(&med);
1506     ok(DataObjectImpl_GetDataHere_calls == 11, "called %d\n", DataObjectImpl_GetDataHere_calls);
1507     ok(DataObjectImpl_GetData_calls == 3, "called %d\n", DataObjectImpl_GetData_calls);
1508
1509     med.pUnkForRelease = NULL;
1510     med.tymed = TYMED_ISTREAM;
1511     CreateStreamOnHGlobal(NULL, TRUE, &U(med).pstm);
1512     hr = IDataObject_GetDataHere(get, &fmt, &med);
1513     ok(hr == S_OK, "got %08x\n", hr);
1514     ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1515     ReleaseStgMedium(&med);
1516     ok(DataObjectImpl_GetDataHere_calls == 12, "called %d\n", DataObjectImpl_GetDataHere_calls);
1517     ok(DataObjectImpl_GetData_calls == 3, "called %d\n", DataObjectImpl_GetData_calls);
1518
1519     med.pUnkForRelease = NULL;
1520     med.tymed = TYMED_ISTORAGE;
1521     StgCreateDocfile(NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &U(med).pstg);
1522     hr = IDataObject_GetDataHere(get, &fmt, &med);
1523     ok(hr == S_OK, "got %08x\n", hr);
1524     ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1525     ReleaseStgMedium(&med);
1526     ok(DataObjectImpl_GetDataHere_calls == 13, "called %d\n", DataObjectImpl_GetDataHere_calls);
1527     ok(DataObjectImpl_GetData_calls == 3, "called %d\n", DataObjectImpl_GetData_calls);
1528
1529
1530     IDataObject_Release(get);
1531     IDataObject_Release(src);
1532
1533     OleUninitialize();
1534
1535 }
1536
1537 START_TEST(clipboard)
1538 {
1539     test_set_clipboard();
1540     test_consumer_refs();
1541     test_flushed_getdata();
1542     test_nonole_clipboard();
1543     test_getdatahere();
1544 }