wineps.drv: Default page dimensions are part of DEVMODE, remove an old hack.
[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     if (0)  /* Causes crashes on both Wine and Windows */
432     {
433         memset(&dm, 0, sizeof(dm));
434         dm.dmSize = sizeof(dm);
435         dm.dmDriverExtra = 0;
436         lstrcpyW(dm.dmDeviceName, device_name);
437         obj->fmtetc[3].ptd = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(DVTARGETDEVICE, tdData) + sizeof(device_name) + dm.dmSize + dm.dmDriverExtra);
438         obj->fmtetc[3].ptd->tdSize = FIELD_OFFSET(DVTARGETDEVICE, tdData) + sizeof(device_name) + dm.dmSize + dm.dmDriverExtra;
439         obj->fmtetc[3].ptd->tdDriverNameOffset = FIELD_OFFSET(DVTARGETDEVICE, tdData);
440         obj->fmtetc[3].ptd->tdDeviceNameOffset = 0;
441         obj->fmtetc[3].ptd->tdPortNameOffset   = 0;
442         obj->fmtetc[3].ptd->tdExtDevmodeOffset = obj->fmtetc[3].ptd->tdDriverNameOffset + sizeof(device_name);
443         lstrcpyW((WCHAR*)obj->fmtetc[3].ptd->tdData, device_name);
444         memcpy(obj->fmtetc[3].ptd->tdData + sizeof(device_name), &dm, dm.dmSize + dm.dmDriverExtra);
445     }
446
447     InitFormatEtc(obj->fmtetc[4], cf_global, TYMED_HGLOBAL);
448     InitFormatEtc(obj->fmtetc[5], cf_another, TYMED_HGLOBAL);
449     InitFormatEtc(obj->fmtetc[6], cf_another, 0xfffff);
450     InitFormatEtc(obj->fmtetc[7], cf_another, 0xfffff);
451     obj->fmtetc[7].dwAspect = DVASPECT_ICON;
452
453     *lplpdataobj = (LPDATAOBJECT)obj;
454     return S_OK;
455 }
456
457 static void test_get_clipboard(void)
458 {
459     HRESULT hr;
460     IDataObject *data_obj;
461     FORMATETC fmtetc;
462     STGMEDIUM stgmedium;
463
464     hr = OleGetClipboard(NULL);
465     ok(hr == E_INVALIDARG, "OleGetClipboard(NULL) should return E_INVALIDARG instead of 0x%08x\n", hr);
466
467     hr = OleGetClipboard(&data_obj);
468     ok(hr == S_OK, "OleGetClipboard failed with error 0x%08x\n", hr);
469
470     /* test IDataObject_QueryGetData */
471
472     /* clipboard's IDataObject_QueryGetData shouldn't defer to our IDataObject_QueryGetData */
473     expect_DataObjectImpl_QueryGetData = FALSE;
474
475     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
476     hr = IDataObject_QueryGetData(data_obj, &fmtetc);
477     ok(hr == S_OK, "IDataObject_QueryGetData failed with error 0x%08x\n", hr);
478
479     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
480     fmtetc.dwAspect = 0xdeadbeef;
481     hr = IDataObject_QueryGetData(data_obj, &fmtetc);
482     ok(hr == DV_E_FORMATETC, "IDataObject_QueryGetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
483
484     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
485     fmtetc.dwAspect = DVASPECT_THUMBNAIL;
486     hr = IDataObject_QueryGetData(data_obj, &fmtetc);
487     ok(hr == DV_E_FORMATETC, "IDataObject_QueryGetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
488
489     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
490     fmtetc.lindex = 256;
491     hr = IDataObject_QueryGetData(data_obj, &fmtetc);
492     ok(hr == DV_E_FORMATETC || broken(hr == S_OK),
493         "IDataObject_QueryGetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
494
495     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
496     fmtetc.cfFormat = CF_RIFF;
497     hr = IDataObject_QueryGetData(data_obj, &fmtetc);
498     ok(hr == DV_E_CLIPFORMAT, "IDataObject_QueryGetData should have failed with DV_E_CLIPFORMAT instead of 0x%08x\n", hr);
499
500     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
501     fmtetc.tymed = TYMED_FILE;
502     hr = IDataObject_QueryGetData(data_obj, &fmtetc);
503     ok(hr == S_OK, "IDataObject_QueryGetData failed with error 0x%08x\n", hr);
504
505     expect_DataObjectImpl_QueryGetData = TRUE;
506
507     /* test IDataObject_GetData */
508
509     DataObjectImpl_GetData_calls = 0;
510
511     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
512     hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
513     ok(hr == S_OK, "IDataObject_GetData failed with error 0x%08x\n", hr);
514     if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
515
516     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
517     fmtetc.dwAspect = 0xdeadbeef;
518     hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
519     ok(hr == S_OK, "IDataObject_GetData failed with error 0x%08x\n", hr);
520     if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
521
522     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
523     fmtetc.dwAspect = DVASPECT_THUMBNAIL;
524     hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
525     ok(hr == S_OK, "IDataObject_GetData failed with error 0x%08x\n", hr);
526     if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
527
528     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
529     fmtetc.lindex = 256;
530     hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
531     ok(hr == DV_E_FORMATETC || broken(hr == S_OK), "IDataObject_GetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
532     if (hr == S_OK)
533     {
534         /* undo the unexpected success */
535         DataObjectImpl_GetData_calls--;
536         ReleaseStgMedium(&stgmedium);
537     }
538
539     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
540     fmtetc.cfFormat = CF_RIFF;
541     hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
542     ok(hr == DV_E_FORMATETC, "IDataObject_GetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
543     if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
544
545     InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
546     fmtetc.tymed = TYMED_FILE;
547     hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
548     ok(hr == DV_E_TYMED, "IDataObject_GetData should have failed with DV_E_TYMED instead of 0x%08x\n", hr);
549     if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
550
551     ok(DataObjectImpl_GetData_calls == 6, "DataObjectImpl_GetData should have been called 6 times instead of %d times\n", DataObjectImpl_GetData_calls);
552
553     IDataObject_Release(data_obj);
554 }
555
556 static void test_enum_fmtetc(IDataObject *src)
557 {
558     HRESULT hr;
559     IDataObject *data;
560     IEnumFORMATETC *enum_fmt, *src_enum;
561     FORMATETC fmt, src_fmt;
562     DWORD count = 0;
563
564     hr = OleGetClipboard(&data);
565     ok(hr == S_OK, "OleGetClipboard failed with error 0x%08x\n", hr);
566
567     hr = IDataObject_EnumFormatEtc(data, DATADIR_SET, &enum_fmt);
568     ok(hr == E_NOTIMPL ||
569        broken(hr == E_INVALIDARG), /* win98 (not win98SE) */
570        "got %08x\n", hr);
571
572     DataObjectImpl_EnumFormatEtc_calls = 0;
573     hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
574     ok(hr == S_OK, "got %08x\n", hr);
575     ok(DataObjectImpl_EnumFormatEtc_calls == 0, "EnumFormatEtc was called\n");
576
577     if(src) IDataObject_EnumFormatEtc(src, DATADIR_GET, &src_enum);
578
579     while((hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL)) == S_OK)
580     {
581         ok(src != NULL, "shouldn't be here\n");
582         hr = IEnumFORMATETC_Next(src_enum, 1, &src_fmt, NULL);
583         ok(hr == S_OK, "%d: got %08x\n", count, hr);
584         trace("%d: %s\n", count, dump_fmtetc(&fmt));
585         ok(fmt.cfFormat == src_fmt.cfFormat, "%d: %04x %04x\n", count, fmt.cfFormat, src_fmt.cfFormat);
586         ok(fmt.dwAspect == src_fmt.dwAspect, "%d: %08x %08x\n", count, fmt.dwAspect, src_fmt.dwAspect);
587         ok(fmt.lindex == src_fmt.lindex, "%d: %08x %08x\n", count, fmt.lindex, src_fmt.lindex);
588         ok(fmt.tymed == src_fmt.tymed, "%d: %08x %08x\n", count, fmt.tymed, src_fmt.tymed);
589         if(fmt.ptd)
590         {
591             ok(src_fmt.ptd != NULL, "%d: expected non-NULL\n", count);
592             CoTaskMemFree(fmt.ptd);
593             CoTaskMemFree(src_fmt.ptd);
594         }
595         count++;
596     }
597
598     ok(hr == S_FALSE, "%d: got %08x\n", count, hr);
599
600     if(src)
601     {
602         hr = IEnumFORMATETC_Next(src_enum, 1, &src_fmt, NULL);
603         ok(hr == S_FALSE ||
604            broken(hr == S_OK && count == 5), /* win9x and winme don't enumerate duplicated cf's */
605            "%d: got %08x\n", count, hr);
606         IEnumFORMATETC_Release(src_enum);
607     }
608
609     hr = IEnumFORMATETC_Reset(enum_fmt);
610     ok(hr == S_OK, "got %08x\n", hr);
611
612     if(src) /* Exercise the enumerator a bit */
613     {
614         IEnumFORMATETC *clone;
615         FORMATETC third_fmt;
616
617         hr = IEnumFORMATETC_Next(enum_fmt, 1, &third_fmt, NULL);
618         ok(hr == S_OK, "got %08x\n", hr);
619         hr = IEnumFORMATETC_Next(enum_fmt, 1, &third_fmt, NULL);
620         ok(hr == S_OK, "got %08x\n", hr);
621         hr = IEnumFORMATETC_Next(enum_fmt, 1, &third_fmt, NULL);
622         ok(hr == S_OK, "got %08x\n", hr);
623
624         hr = IEnumFORMATETC_Reset(enum_fmt);
625         ok(hr == S_OK, "got %08x\n", hr);
626         hr = IEnumFORMATETC_Skip(enum_fmt, 2);
627         ok(hr == S_OK, "got %08x\n", hr);
628
629         hr = IEnumFORMATETC_Clone(enum_fmt, &clone);
630         ok(hr == S_OK, "got %08x\n", hr);
631         hr = IEnumFORMATETC_Next(enum_fmt, 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         hr = IEnumFORMATETC_Next(clone, 1, &fmt, NULL);
635         ok(hr == S_OK, "got %08x\n", hr);
636         ok(fmt.cfFormat == third_fmt.cfFormat, "formats don't match\n");
637         IEnumFORMATETC_Release(clone);
638     }
639
640     IEnumFORMATETC_Release(enum_fmt);
641     IDataObject_Release(data);
642 }
643
644 static void test_no_cf_dataobject(void)
645 {
646     UINT cf_dataobject = RegisterClipboardFormatA("DataObject");
647     UINT cf_ole_priv_data = RegisterClipboardFormatA("Ole Private Data");
648     HANDLE h;
649     OpenClipboard(NULL);
650
651     h = GetClipboardData(cf_dataobject);
652     ok(!h, "got %p\n", h);
653     h = GetClipboardData(cf_ole_priv_data);
654     ok(!h, "got %p\n", h);
655
656     CloseClipboard();
657 }
658
659 static void test_cf_dataobject(IDataObject *data)
660 {
661     UINT cf = 0;
662     UINT cf_dataobject = RegisterClipboardFormatA("DataObject");
663     UINT cf_ole_priv_data = RegisterClipboardFormatA("Ole Private Data");
664     BOOL found_dataobject = FALSE, found_priv_data = FALSE;
665
666     OpenClipboard(NULL);
667     do
668     {
669         cf = EnumClipboardFormats(cf);
670         if(cf == cf_dataobject)
671         {
672             HGLOBAL h = GetClipboardData(cf);
673             HWND *ptr = GlobalLock(h);
674             DWORD size = GlobalSize(h);
675             HWND clip_owner = GetClipboardOwner();
676
677             found_dataobject = TRUE;
678             ok(size >= sizeof(*ptr), "size %d\n", size);
679             if(data)
680                 ok(*ptr == clip_owner, "hwnd %p clip_owner %p\n", *ptr, clip_owner);
681             else /* ole clipboard flushed */
682                 ok(*ptr == NULL, "hwnd %p\n", *ptr);
683             GlobalUnlock(h);
684         }
685         else if(cf == cf_ole_priv_data)
686         {
687             found_priv_data = TRUE;
688             if(data)
689             {
690                 HGLOBAL h = GetClipboardData(cf);
691                 DWORD *ptr = GlobalLock(h);
692                 DWORD size = GlobalSize(h);
693
694                 if(size != ptr[1])
695                     win_skip("Ole Private Data in win9x format\n");
696                 else
697                 {
698                     HRESULT hr;
699                     IEnumFORMATETC *enum_fmt;
700                     DWORD count = 0;
701                     FORMATETC fmt;
702                     struct formatetcetc
703                     {
704                         FORMATETC fmt;
705                         BOOL first_use_of_cf;
706                         DWORD res[2];
707                     } *fmt_ptr;
708                     struct priv_data
709                     {
710                         DWORD res1;
711                         DWORD size;
712                         DWORD res2;
713                         DWORD count;
714                         DWORD res3[2];
715                         struct formatetcetc fmts[1];
716                     } *priv = (struct priv_data*)ptr;
717                     CLIPFORMAT cfs_seen[10];
718
719                     hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
720                     ok(hr == S_OK, "got %08x\n", hr);
721                     fmt_ptr = priv->fmts;
722
723                     while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
724                     {
725                         int i;
726                         BOOL seen_cf = FALSE;
727
728                         ok(fmt_ptr->fmt.cfFormat == fmt.cfFormat,
729                            "got %08x expected %08x\n", fmt_ptr->fmt.cfFormat, fmt.cfFormat);
730                         ok(fmt_ptr->fmt.dwAspect == fmt.dwAspect, "got %08x expected %08x\n",
731                            fmt_ptr->fmt.dwAspect, fmt.dwAspect);
732                         ok(fmt_ptr->fmt.lindex == fmt.lindex, "got %08x expected %08x\n",
733                            fmt_ptr->fmt.lindex, fmt.lindex);
734                         ok(fmt_ptr->fmt.tymed == fmt.tymed, "got %08x expected %08x\n",
735                            fmt_ptr->fmt.tymed, fmt.tymed);
736                         for(i = 0; i < count; i++)
737                             if(fmt_ptr->fmt.cfFormat == cfs_seen[i])
738                             {
739                                 seen_cf = TRUE;
740                                 break;
741                             }
742                         cfs_seen[count] = fmt.cfFormat;
743                         ok(fmt_ptr->first_use_of_cf != seen_cf, "got %08x expected %08x\n",
744                            fmt_ptr->first_use_of_cf, !seen_cf);
745                         ok(fmt_ptr->res[0] == 0, "got %08x\n", fmt_ptr->res[1]);
746                         ok(fmt_ptr->res[1] == 0, "got %08x\n", fmt_ptr->res[2]);
747                         if(fmt.ptd)
748                         {
749                             DVTARGETDEVICE *target;
750
751                             ok(fmt_ptr->fmt.ptd != NULL, "target device offset zero\n");
752                             target = (DVTARGETDEVICE*)((char*)priv + (DWORD_PTR)fmt_ptr->fmt.ptd);
753                             ok(!memcmp(target, fmt.ptd, fmt.ptd->tdSize), "target devices differ\n");
754                             CoTaskMemFree(fmt.ptd);
755                         }
756                         fmt_ptr++;
757                         count++;
758                     }
759                     ok(priv->res1 == 0, "got %08x\n", priv->res1);
760                     ok(priv->res2 == 1, "got %08x\n", priv->res2);
761                     ok(priv->count == count, "got %08x expected %08x\n", priv->count, count);
762                     ok(priv->res3[0] == 0, "got %08x\n", priv->res3[0]);
763
764                     /* win64 sets the lsb */
765                     if(sizeof(fmt_ptr->fmt.ptd) == 8)
766                         todo_wine ok(priv->res3[1] == 1, "got %08x\n", priv->res3[1]);
767                     else
768                         ok(priv->res3[1] == 0, "got %08x\n", priv->res3[1]);
769
770                     GlobalUnlock(h);
771                     IEnumFORMATETC_Release(enum_fmt);
772                 }
773             }
774         }
775         else if(cf == cf_stream)
776         {
777             HGLOBAL h;
778             void *ptr;
779             DWORD size;
780
781             DataObjectImpl_GetDataHere_calls = 0;
782             h = GetClipboardData(cf);
783             ok(DataObjectImpl_GetDataHere_calls == 1, "got %d\n", DataObjectImpl_GetDataHere_calls);
784             ptr = GlobalLock(h);
785             size = GlobalSize(h);
786             ok(size == strlen(cmpl_stm_data) ||
787                broken(size > strlen(cmpl_stm_data)), /* win9x, winme */
788                "expected %d got %d\n", lstrlenA(cmpl_stm_data), size);
789             ok(!memcmp(ptr, cmpl_stm_data, strlen(cmpl_stm_data)), "mismatch\n");
790             GlobalUnlock(h);
791         }
792         else if(cf == cf_global)
793         {
794             HGLOBAL h;
795             void *ptr;
796             DWORD size;
797
798             DataObjectImpl_GetDataHere_calls = 0;
799             h = GetClipboardData(cf);
800             ok(DataObjectImpl_GetDataHere_calls == 0, "got %d\n", DataObjectImpl_GetDataHere_calls);
801             ptr = GlobalLock(h);
802             size = GlobalSize(h);
803             ok(size == strlen(cmpl_text_data) + 1 ||
804                broken(size > strlen(cmpl_text_data) + 1), /* win9x, winme */
805                "expected %d got %d\n", lstrlenA(cmpl_text_data) + 1, size);
806             ok(!memcmp(ptr, cmpl_text_data, strlen(cmpl_text_data) + 1), "mismatch\n");
807             GlobalUnlock(h);
808         }
809     } while(cf);
810     CloseClipboard();
811     ok(found_dataobject, "didn't find cf_dataobject\n");
812     ok(found_priv_data, "didn't find cf_ole_priv_data\n");
813 }
814
815 static void test_set_clipboard(void)
816 {
817     HRESULT hr;
818     ULONG ref;
819     LPDATAOBJECT data1, data2, data_cmpl;
820     HGLOBAL hblob, h;
821
822     cf_stream = RegisterClipboardFormatA("stream format");
823     cf_storage = RegisterClipboardFormatA("storage format");
824     cf_global = RegisterClipboardFormatA("global format");
825     cf_another = RegisterClipboardFormatA("another format");
826     cf_onemore = RegisterClipboardFormatA("one more format");
827
828     hr = DataObjectImpl_CreateText("data1", &data1);
829     ok(hr == S_OK, "Failed to create data1 object: 0x%08x\n", hr);
830     if(FAILED(hr))
831         return;
832     hr = DataObjectImpl_CreateText("data2", &data2);
833     ok(hr == S_OK, "Failed to create data2 object: 0x%08x\n", hr);
834     if(FAILED(hr))
835         return;
836     hr = DataObjectImpl_CreateComplex(&data_cmpl);
837     ok(hr == S_OK, "Failed to create complex data object: 0x%08x\n", hr);
838     if(FAILED(hr))
839         return;
840
841     hr = OleSetClipboard(data1);
842     ok(hr == CO_E_NOTINITIALIZED, "OleSetClipboard should have failed with CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
843
844     CoInitialize(NULL);
845     hr = OleSetClipboard(data1);
846     ok(hr == CO_E_NOTINITIALIZED ||
847        hr == CLIPBRD_E_CANT_SET, /* win9x */
848        "OleSetClipboard should have failed with "
849        "CO_E_NOTINITIALIZED or CLIPBRD_E_CANT_SET instead of 0x%08x\n", hr);
850     CoUninitialize();
851
852     hr = OleInitialize(NULL);
853     ok(hr == S_OK, "OleInitialize failed with error 0x%08x\n", hr);
854
855     hr = OleSetClipboard(data1);
856     ok(hr == S_OK, "failed to set clipboard to data1, hr = 0x%08x\n", hr);
857
858     test_cf_dataobject(data1);
859
860     hr = OleIsCurrentClipboard(data1);
861     ok(hr == S_OK, "expected current clipboard to be data1, hr = 0x%08x\n", hr);
862     hr = OleIsCurrentClipboard(data2);
863     ok(hr == S_FALSE, "did not expect current clipboard to be data2, hr = 0x%08x\n", hr);
864     hr = OleIsCurrentClipboard(NULL);
865     ok(hr == S_FALSE, "expect S_FALSE, hr = 0x%08x\n", hr);
866
867     test_get_clipboard();
868
869     hr = OleSetClipboard(data2);
870     ok(hr == S_OK, "failed to set clipboard to data2, hr = 0x%08x\n", hr);
871     hr = OleIsCurrentClipboard(data1);
872     ok(hr == S_FALSE, "did not expect current clipboard to be data1, hr = 0x%08x\n", hr);
873     hr = OleIsCurrentClipboard(data2);
874     ok(hr == S_OK, "expected current clipboard to be data2, hr = 0x%08x\n", hr);
875     hr = OleIsCurrentClipboard(NULL);
876     ok(hr == S_FALSE, "expect S_FALSE, hr = 0x%08x\n", hr);
877
878     /* put a format directly onto the clipboard to show
879        OleFlushClipboard doesn't empty the clipboard */
880     hblob = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT, 10);
881     OpenClipboard(NULL);
882     h = SetClipboardData(cf_onemore, hblob);
883     ok(h == hblob, "got %p\n", h);
884     h = GetClipboardData(cf_onemore);
885     ok(h == hblob ||
886        broken(h != NULL), /* win9x */
887        "got %p\n", h);
888     CloseClipboard();
889
890     hr = OleFlushClipboard();
891     ok(hr == S_OK, "failed to flush clipboard, hr = 0x%08x\n", hr);
892     hr = OleIsCurrentClipboard(data1);
893     ok(hr == S_FALSE, "did not expect current clipboard to be data1, hr = 0x%08x\n", hr);
894     hr = OleIsCurrentClipboard(data2);
895     ok(hr == S_FALSE, "did not expect current clipboard to be data2, hr = 0x%08x\n", hr);
896     hr = OleIsCurrentClipboard(NULL);
897     ok(hr == S_FALSE, "expect S_FALSE, hr = 0x%08x\n", hr);
898
899     /* format should survive the flush */
900     OpenClipboard(NULL);
901     h = GetClipboardData(cf_onemore);
902     ok(h == hblob ||
903        broken(h != NULL), /* win9x */
904        "got %p\n", h);
905     CloseClipboard();
906
907     test_cf_dataobject(NULL);
908
909     ok(OleSetClipboard(NULL) == S_OK, "failed to clear clipboard, hr = 0x%08x\n", hr);
910
911     OpenClipboard(NULL);
912     h = GetClipboardData(cf_onemore);
913     ok(h == NULL, "got %p\n", h);
914     CloseClipboard();
915
916     trace("setting complex\n");
917     hr = OleSetClipboard(data_cmpl);
918     ok(hr == S_OK, "failed to set clipboard to complex data, hr = 0x%08x\n", hr);
919     test_cf_dataobject(data_cmpl);
920     test_enum_fmtetc(data_cmpl);
921
922     ok(OleSetClipboard(NULL) == S_OK, "failed to clear clipboard, hr = 0x%08x\n", hr);
923
924     test_no_cf_dataobject();
925     test_enum_fmtetc(NULL);
926
927     ref = IDataObject_Release(data1);
928     ok(ref == 0, "expected data1 ref=0, got %d\n", ref);
929     ref = IDataObject_Release(data2);
930     ok(ref == 0, "expected data2 ref=0, got %d\n", ref);
931     ref = IDataObject_Release(data_cmpl);
932     ok(ref == 0, "expected data_cmpl ref=0, got %d\n", ref);
933
934     OleUninitialize();
935 }
936
937 static inline ULONG count_refs(IDataObject *d)
938 {
939     IDataObject_AddRef(d);
940     return IDataObject_Release(d);
941 }
942
943 static void test_consumer_refs(void)
944 {
945     HRESULT hr;
946     IDataObject *src, *src2, *get1, *get2, *get3;
947     ULONG refs, old_refs;
948     FORMATETC fmt;
949     STGMEDIUM med;
950
951     InitFormatEtc(fmt, CF_TEXT, TYMED_HGLOBAL);
952
953     OleInitialize(NULL);
954
955     /* First show that each clipboard state results in
956        a different data object */
957
958     hr = DataObjectImpl_CreateText("data1", &src);
959     ok(hr == S_OK, "got %08x\n", hr);
960     hr = DataObjectImpl_CreateText("data2", &src2);
961     ok(hr == S_OK, "got %08x\n", hr);
962
963     hr = OleSetClipboard(src);
964     ok(hr == S_OK, "got %08x\n", hr);
965
966     hr = OleGetClipboard(&get1);
967     ok(hr == S_OK, "got %08x\n", hr);
968
969     hr = OleGetClipboard(&get2);
970     ok(hr == S_OK, "got %08x\n", hr);
971
972     ok(get1 == get2 ||
973        broken(get1 != get2), /* win9x, winme & nt4 */
974        "data objects differ\n");
975     refs = IDataObject_Release(get2);
976     ok(refs == (get1 == get2 ? 1 : 0), "got %d\n", refs);
977
978     OleFlushClipboard();
979
980     DataObjectImpl_GetData_calls = 0;
981     hr = IDataObject_GetData(get1, &fmt, &med);
982     ok(hr == S_OK, "got %08x\n", hr);
983     ok(DataObjectImpl_GetData_calls == 0, "GetData called\n");
984     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
985
986     hr = OleGetClipboard(&get2);
987     ok(hr == S_OK, "got %08x\n", hr);
988
989     ok(get1 != get2, "data objects match\n");
990
991     OleSetClipboard(NULL);
992
993     hr = OleGetClipboard(&get3);
994     ok(hr == S_OK, "got %08x\n", hr);
995
996     ok(get1 != get3, "data objects match\n");
997     ok(get2 != get3, "data objects match\n");
998
999     IDataObject_Release(get3);
1000     IDataObject_Release(get2);
1001     IDataObject_Release(get1);
1002
1003     /* Now call GetData before the flush and show that this
1004        takes a ref on our src data obj. */
1005
1006     hr = OleSetClipboard(src);
1007     ok(hr == S_OK, "got %08x\n", hr);
1008
1009     old_refs = count_refs(src);
1010
1011     hr = OleGetClipboard(&get1);
1012     ok(hr == S_OK, "got %08x\n", hr);
1013
1014     refs = count_refs(src);
1015     ok(refs == old_refs, "%d %d\n", refs, old_refs);
1016
1017     DataObjectImpl_GetData_calls = 0;
1018     hr = IDataObject_GetData(get1, &fmt, &med);
1019     ok(hr == S_OK, "got %08x\n", hr);
1020     ok(DataObjectImpl_GetData_calls == 1, "GetData not called\n");
1021     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1022     refs = count_refs(src);
1023     ok(refs == old_refs + 1, "%d %d\n", refs, old_refs);
1024
1025     OleFlushClipboard();
1026
1027     DataObjectImpl_GetData_calls = 0;
1028     hr = IDataObject_GetData(get1, &fmt, &med);
1029     ok(hr == S_OK, "got %08x\n", hr);
1030     ok(DataObjectImpl_GetData_calls == 1, "GetData not called\n");
1031     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1032
1033     refs = count_refs(src);
1034     ok(refs == 2, "%d\n", refs);
1035
1036     IDataObject_Release(get1);
1037
1038     refs = count_refs(src);
1039     ok(refs == 1, "%d\n", refs);
1040
1041     /* Now set a second src object before the call to GetData
1042        and show that GetData calls that second src. */
1043
1044     hr = OleSetClipboard(src);
1045     ok(hr == S_OK, "got %08x\n", hr);
1046
1047     old_refs = count_refs(src);
1048
1049     hr = OleGetClipboard(&get1);
1050     ok(hr == S_OK, "got %08x\n", hr);
1051
1052     refs = count_refs(src);
1053     ok(refs == old_refs, "%d %d\n", refs, old_refs);
1054
1055     hr = OleSetClipboard(src2);
1056     ok(hr == S_OK, "got %08x\n", hr);
1057
1058     old_refs = count_refs(src2);
1059
1060     DataObjectImpl_GetData_calls = 0;
1061     hr = IDataObject_GetData(get1, &fmt, &med);
1062     ok(hr == S_OK, "got %08x\n", hr);
1063     ok(DataObjectImpl_GetData_calls == 1, "GetData not called\n");
1064     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1065
1066     refs = count_refs(src);
1067     ok(refs == 1, "%d\n", refs);
1068     refs = count_refs(src2);
1069     ok(refs == old_refs + 1, "%d %d\n", refs, old_refs);
1070
1071     OleSetClipboard(NULL);
1072
1073     refs = count_refs(src2);
1074     ok(refs == 2, "%d\n", refs);
1075
1076     IDataObject_Release(get1);
1077
1078     IDataObject_Release(src2);
1079     IDataObject_Release(src);
1080
1081     OleUninitialize();
1082 }
1083
1084 static void test_flushed_getdata(void)
1085 {
1086     HRESULT hr;
1087     IDataObject *src, *get;
1088     FORMATETC fmt;
1089     STGMEDIUM med;
1090     STATSTG stat;
1091     DEVMODEW dm;
1092
1093     OleInitialize(NULL);
1094
1095     hr = DataObjectImpl_CreateComplex(&src);
1096     ok(hr == S_OK, "got %08x\n", hr);
1097
1098     hr = OleSetClipboard(src);
1099     ok(hr == S_OK, "got %08x\n", hr);
1100
1101     hr = OleFlushClipboard();
1102     ok(hr == S_OK, "got %08x\n", hr);
1103
1104     hr = OleGetClipboard(&get);
1105     ok(hr == S_OK, "got %08x\n", hr);
1106
1107     /* global format -> global & stream */
1108
1109     InitFormatEtc(fmt, CF_TEXT, TYMED_HGLOBAL);
1110     hr = IDataObject_GetData(get, &fmt, &med);
1111     ok(hr == S_OK, "got %08x\n", hr);
1112     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1113     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1114
1115     InitFormatEtc(fmt, CF_TEXT, TYMED_ISTREAM);
1116     hr = IDataObject_GetData(get, &fmt, &med);
1117     ok(hr == S_OK, "got %08x\n", hr);
1118     ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1119     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1120
1121     InitFormatEtc(fmt, CF_TEXT, TYMED_ISTORAGE);
1122     hr = IDataObject_GetData(get, &fmt, &med);
1123     ok(hr == E_FAIL, "got %08x\n", hr);
1124     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1125
1126     InitFormatEtc(fmt, CF_TEXT, 0xffff);
1127     hr = IDataObject_GetData(get, &fmt, &med);
1128     ok(hr == S_OK, "got %08x\n", hr);
1129     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1130     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1131
1132     /* stream format -> global & stream */
1133
1134     InitFormatEtc(fmt, cf_stream, TYMED_ISTREAM);
1135     hr = IDataObject_GetData(get, &fmt, &med);
1136     ok(hr == S_OK, "got %08x\n", hr);
1137     ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1138     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1139
1140     InitFormatEtc(fmt, cf_stream, TYMED_ISTORAGE);
1141     hr = IDataObject_GetData(get, &fmt, &med);
1142     ok(hr == E_FAIL, "got %08x\n", hr);
1143     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1144
1145     InitFormatEtc(fmt, cf_stream, TYMED_HGLOBAL);
1146     hr = IDataObject_GetData(get, &fmt, &med);
1147     ok(hr == S_OK, "got %08x\n", hr);
1148     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1149     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1150
1151     InitFormatEtc(fmt, cf_stream, 0xffff);
1152     hr = IDataObject_GetData(get, &fmt, &med);
1153     ok(hr == S_OK, "got %08x\n", hr);
1154     ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1155     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1156
1157     /* storage format -> global, stream & storage */
1158
1159     InitFormatEtc(fmt, cf_storage, TYMED_ISTORAGE);
1160     hr = IDataObject_GetData(get, &fmt, &med);
1161     ok(hr == S_OK, "got %08x\n", hr);
1162     ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1163     if(SUCCEEDED(hr)) {
1164         hr = IStorage_Stat(med.u.pstg, &stat, STATFLAG_NONAME);
1165         ok(hr == S_OK, "got %08x\n", hr);
1166         ok(stat.grfMode == (STGM_SHARE_EXCLUSIVE | STGM_READWRITE), "got %08x\n", stat.grfMode);
1167         ReleaseStgMedium(&med);
1168     }
1169
1170     InitFormatEtc(fmt, cf_storage, TYMED_ISTREAM);
1171     hr = IDataObject_GetData(get, &fmt, &med);
1172     ok(hr == S_OK, "got %08x\n", hr);
1173     ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1174     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1175
1176     InitFormatEtc(fmt, cf_storage, TYMED_HGLOBAL);
1177     hr = IDataObject_GetData(get, &fmt, &med);
1178     ok(hr == S_OK, "got %08x\n", hr);
1179     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1180     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1181
1182     InitFormatEtc(fmt, cf_storage, TYMED_HGLOBAL | TYMED_ISTREAM);
1183     hr = IDataObject_GetData(get, &fmt, &med);
1184     ok(hr == S_OK, "got %08x\n", hr);
1185     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1186     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1187
1188     InitFormatEtc(fmt, cf_storage, 0xffff);
1189     hr = IDataObject_GetData(get, &fmt, &med);
1190     ok(hr == S_OK, "got %08x\n", hr);
1191     ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1192     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1193
1194     /* complex format with target device */
1195
1196     InitFormatEtc(fmt, cf_another, 0xffff);
1197     hr = IDataObject_GetData(get, &fmt, &med);
1198     ok(hr == S_OK, "got %08x\n", hr);
1199     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1200
1201     if (0)  /* Causes crashes on both Wine and Windows */
1202     {
1203         InitFormatEtc(fmt, cf_another, 0xffff);
1204         memset(&dm, 0, sizeof(dm));
1205         dm.dmSize = sizeof(dm);
1206         dm.dmDriverExtra = 0;
1207         lstrcpyW(dm.dmDeviceName, device_name);
1208         fmt.ptd = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(DVTARGETDEVICE, tdData) + sizeof(device_name) + dm.dmSize + dm.dmDriverExtra);
1209         fmt.ptd->tdSize = FIELD_OFFSET(DVTARGETDEVICE, tdData) + sizeof(device_name) + dm.dmSize + dm.dmDriverExtra;
1210         fmt.ptd->tdDriverNameOffset = FIELD_OFFSET(DVTARGETDEVICE, tdData);
1211         fmt.ptd->tdDeviceNameOffset = 0;
1212         fmt.ptd->tdPortNameOffset   = 0;
1213         fmt.ptd->tdExtDevmodeOffset = fmt.ptd->tdDriverNameOffset + sizeof(device_name);
1214         lstrcpyW((WCHAR*)fmt.ptd->tdData, device_name);
1215         memcpy(fmt.ptd->tdData + sizeof(device_name), &dm, dm.dmSize + dm.dmDriverExtra);
1216
1217         hr = IDataObject_GetData(get, &fmt, &med);
1218         ok(hr == S_OK, "got %08x\n", hr);
1219         ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1220         if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1221
1222         HeapFree(GetProcessHeap(), 0, fmt.ptd);
1223     }
1224
1225
1226     IDataObject_Release(get);
1227     IDataObject_Release(src);
1228     OleUninitialize();
1229 }
1230
1231 static HGLOBAL create_text(void)
1232 {
1233     HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5);
1234     char *p = GlobalLock(h);
1235     strcpy(p, "test");
1236     GlobalUnlock(h);
1237     return h;
1238 }
1239
1240 static HENHMETAFILE create_emf(void)
1241 {
1242     const RECT rect = {0, 0, 100, 100};
1243     HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
1244     ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
1245     return CloseEnhMetaFile(hdc);
1246 }
1247
1248 static void test_nonole_clipboard(void)
1249 {
1250     HRESULT hr;
1251     BOOL r;
1252     IDataObject *get;
1253     IEnumFORMATETC *enum_fmt;
1254     FORMATETC fmt;
1255     HGLOBAL h, hblob, htext;
1256     HENHMETAFILE emf;
1257     STGMEDIUM med;
1258     DWORD obj_type;
1259
1260     r = OpenClipboard(NULL);
1261     ok(r, "gle %d\n", GetLastError());
1262     r = EmptyClipboard();
1263     ok(r, "gle %d\n", GetLastError());
1264     r = CloseClipboard();
1265     ok(r, "gle %d\n", GetLastError());
1266
1267     OleInitialize(NULL);
1268
1269     /* empty clipboard */
1270     hr = OleGetClipboard(&get);
1271     ok(hr == S_OK, "got %08x\n", hr);
1272     hr = IDataObject_EnumFormatEtc(get, DATADIR_GET, &enum_fmt);
1273     ok(hr == S_OK, "got %08x\n", hr);
1274
1275     hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1276     ok(hr == S_FALSE, "got %08x\n", hr);
1277     IEnumFORMATETC_Release(enum_fmt);
1278
1279     IDataObject_Release(get);
1280
1281     /* set a user defined clipboard type */
1282
1283     htext = create_text();
1284     hblob = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT, 10);
1285     emf = create_emf();
1286
1287     r = OpenClipboard(NULL);
1288     ok(r, "gle %d\n", GetLastError());
1289     h = SetClipboardData(CF_TEXT, htext);
1290     ok(h == htext, "got %p\n", h);
1291     h = SetClipboardData(cf_onemore, hblob);
1292     ok(h == hblob, "got %p\n", h);
1293     h = SetClipboardData(CF_ENHMETAFILE, emf);
1294     ok(h == emf, "got %p\n", h);
1295     r = CloseClipboard();
1296     ok(r, "gle %d\n", GetLastError());
1297
1298     hr = OleGetClipboard(&get);
1299     ok(hr == S_OK, "got %08x\n", hr);
1300     hr = IDataObject_EnumFormatEtc(get, DATADIR_GET, &enum_fmt);
1301     ok(hr == S_OK, "got %08x\n", hr);
1302
1303     hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1304     ok(hr == S_OK, "got %08x\n", hr);
1305     ok(fmt.cfFormat == CF_TEXT, "cf %04x\n", fmt.cfFormat);
1306     ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1307     ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1308     ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1309     ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
1310
1311     hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1312     ok(hr == S_OK, "got %08x\n", hr);
1313     ok(fmt.cfFormat == cf_onemore, "cf %04x\n", fmt.cfFormat);
1314     ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1315     ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1316     ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1317     ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
1318
1319     hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1320     ok(hr == S_OK, "got %08x\n", hr);
1321     ok(fmt.cfFormat == CF_ENHMETAFILE, "cf %04x\n", fmt.cfFormat);
1322     ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1323     ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1324     ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1325     ok(fmt.tymed == TYMED_ENHMF, "tymed %x\n", fmt.tymed);
1326
1327     hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1328     ok(hr == S_OK, "got %08x\n", hr); /* User32 adds some synthesised formats */
1329
1330     todo_wine ok(fmt.cfFormat == CF_LOCALE, "cf %04x\n", fmt.cfFormat);
1331     if(fmt.cfFormat == CF_LOCALE)
1332     {
1333         ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1334         ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1335         ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1336         ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
1337
1338         hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1339         ok(hr == S_OK, "got %08x\n", hr);
1340     }
1341
1342     ok(fmt.cfFormat == CF_OEMTEXT, "cf %04x\n", fmt.cfFormat);
1343     ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1344     ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1345     ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1346     ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
1347
1348     hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1349     ok(hr == S_OK, "got %08x\n", hr);
1350     ok(fmt.cfFormat == CF_UNICODETEXT ||
1351        broken(fmt.cfFormat == CF_METAFILEPICT), /* win9x and winme don't have CF_UNICODETEXT */
1352        "cf %04x\n", fmt.cfFormat);
1353     if(fmt.cfFormat == CF_UNICODETEXT)
1354     {
1355         ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1356         ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1357         ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1358         ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
1359
1360         hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1361         ok(hr == S_OK, "got %08x\n", hr);
1362     }
1363     ok(fmt.cfFormat == CF_METAFILEPICT, "cf %04x\n", fmt.cfFormat);
1364     ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1365     ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1366     ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1367     ok(fmt.tymed == TYMED_MFPICT, "tymed %x\n", fmt.tymed);
1368
1369     hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1370     ok(hr == S_FALSE, "got %08x\n", hr);
1371     IEnumFORMATETC_Release(enum_fmt);
1372
1373     InitFormatEtc(fmt, CF_ENHMETAFILE, TYMED_ENHMF);
1374     hr = IDataObject_GetData(get, &fmt, &med);
1375     ok(hr == S_OK, "got %08x\n", hr);
1376     obj_type = GetObjectType(U(med).hEnhMetaFile);
1377     ok(obj_type == OBJ_ENHMETAFILE, "got %d\n", obj_type);
1378     if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1379
1380     IDataObject_Release(get);
1381
1382     r = OpenClipboard(NULL);
1383     ok(r, "gle %d\n", GetLastError());
1384     r = EmptyClipboard();
1385     ok(r, "gle %d\n", GetLastError());
1386     r = CloseClipboard();
1387     ok(r, "gle %d\n", GetLastError());
1388
1389     OleUninitialize();
1390 }
1391
1392 static void test_getdatahere(void)
1393 {
1394     HRESULT hr;
1395     IDataObject *src, *get;
1396     FORMATETC fmt;
1397     STGMEDIUM med;
1398
1399     OleInitialize(NULL);
1400
1401     hr = DataObjectImpl_CreateComplex(&src);
1402     ok(hr == S_OK, "got %08x\n", hr);
1403
1404     hr = OleSetClipboard(src);
1405     ok(hr == S_OK, "got %08x\n", hr);
1406
1407     hr = OleGetClipboard(&get);
1408     ok(hr == S_OK, "got %08x\n", hr);
1409
1410     /* global format -> global & stream */
1411
1412     DataObjectImpl_GetData_calls = 0;
1413     DataObjectImpl_GetDataHere_calls = 0;
1414
1415     InitFormatEtc(fmt, CF_TEXT, TYMED_HGLOBAL);
1416
1417     med.pUnkForRelease = NULL;
1418     med.tymed = TYMED_HGLOBAL;
1419     U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 100);
1420     hr = IDataObject_GetDataHere(get, &fmt, &med);
1421     ok(hr == S_OK, "got %08x\n", hr);
1422     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1423     ReleaseStgMedium(&med);
1424     ok(DataObjectImpl_GetDataHere_calls == 1, "called %d\n", DataObjectImpl_GetDataHere_calls);
1425     ok(DataObjectImpl_GetData_calls == 1, "called %d\n", DataObjectImpl_GetData_calls);
1426
1427     InitFormatEtc(fmt, CF_TEXT, 0);
1428
1429     med.pUnkForRelease = NULL;
1430     med.tymed = TYMED_HGLOBAL;
1431     U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 100);
1432     hr = IDataObject_GetDataHere(get, &fmt, &med);
1433     ok(hr == S_OK, "got %08x\n", hr);
1434     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1435     ReleaseStgMedium(&med);
1436     ok(DataObjectImpl_GetDataHere_calls == 2, "called %d\n", DataObjectImpl_GetDataHere_calls);
1437     ok(DataObjectImpl_GetData_calls == 1, "called %d\n", DataObjectImpl_GetData_calls);
1438
1439     med.pUnkForRelease = NULL;
1440     med.tymed = TYMED_HGLOBAL;
1441     U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 1);
1442     hr = IDataObject_GetDataHere(get, &fmt, &med);
1443     ok(hr == E_FAIL, "got %08x\n", hr);
1444     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1445     ReleaseStgMedium(&med);
1446     ok(DataObjectImpl_GetDataHere_calls == 3, "called %d\n", DataObjectImpl_GetDataHere_calls);
1447     ok(DataObjectImpl_GetData_calls == 1, "called %d\n", DataObjectImpl_GetData_calls);
1448
1449     med.pUnkForRelease = NULL;
1450     med.tymed = TYMED_ISTREAM;
1451     CreateStreamOnHGlobal(NULL, TRUE, &U(med).pstm);
1452     hr = IDataObject_GetDataHere(get, &fmt, &med);
1453     ok(hr == S_OK, "got %08x\n", hr);
1454     ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1455     ReleaseStgMedium(&med);
1456     ok(DataObjectImpl_GetDataHere_calls == 4, "called %d\n", DataObjectImpl_GetDataHere_calls);
1457     ok(DataObjectImpl_GetData_calls == 1, "called %d\n", DataObjectImpl_GetData_calls);
1458
1459     med.pUnkForRelease = NULL;
1460     med.tymed = TYMED_ISTORAGE;
1461     StgCreateDocfile(NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &U(med).pstg);
1462     hr = IDataObject_GetDataHere(get, &fmt, &med);
1463     ok(hr == E_FAIL, "got %08x\n", hr);
1464     ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1465     ReleaseStgMedium(&med);
1466     ok(DataObjectImpl_GetDataHere_calls == 5, "called %d\n", DataObjectImpl_GetDataHere_calls);
1467     ok(DataObjectImpl_GetData_calls == 1, "called %d\n", DataObjectImpl_GetData_calls);
1468
1469     InitFormatEtc(fmt, cf_stream, 0);
1470
1471     med.pUnkForRelease = NULL;
1472     med.tymed = TYMED_HGLOBAL;
1473     U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 100);
1474     hr = IDataObject_GetDataHere(get, &fmt, &med);
1475     ok(hr == S_OK, "got %08x\n", hr);
1476     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1477     ReleaseStgMedium(&med);
1478     ok(DataObjectImpl_GetDataHere_calls == 7, "called %d\n", DataObjectImpl_GetDataHere_calls);
1479     ok(DataObjectImpl_GetData_calls == 2, "called %d\n", DataObjectImpl_GetData_calls);
1480
1481     med.pUnkForRelease = NULL;
1482     med.tymed = TYMED_ISTREAM;
1483     CreateStreamOnHGlobal(NULL, TRUE, &U(med).pstm);
1484     hr = IDataObject_GetDataHere(get, &fmt, &med);
1485     ok(hr == S_OK, "got %08x\n", hr);
1486     ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1487     ReleaseStgMedium(&med);
1488     ok(DataObjectImpl_GetDataHere_calls == 8, "called %d\n", DataObjectImpl_GetDataHere_calls);
1489     ok(DataObjectImpl_GetData_calls == 2, "called %d\n", DataObjectImpl_GetData_calls);
1490
1491     med.pUnkForRelease = NULL;
1492     med.tymed = TYMED_ISTORAGE;
1493     StgCreateDocfile(NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &U(med).pstg);
1494     hr = IDataObject_GetDataHere(get, &fmt, &med);
1495     ok(hr == E_FAIL, "got %08x\n", hr);
1496     ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1497     ReleaseStgMedium(&med);
1498     ok(DataObjectImpl_GetDataHere_calls == 9, "called %d\n", DataObjectImpl_GetDataHere_calls);
1499     ok(DataObjectImpl_GetData_calls == 2, "called %d\n", DataObjectImpl_GetData_calls);
1500
1501     InitFormatEtc(fmt, cf_storage, 0);
1502
1503     med.pUnkForRelease = NULL;
1504     med.tymed = TYMED_HGLOBAL;
1505     U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 3000);
1506     hr = IDataObject_GetDataHere(get, &fmt, &med);
1507     ok(hr == S_OK, "got %08x\n", hr);
1508     ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1509     ReleaseStgMedium(&med);
1510     ok(DataObjectImpl_GetDataHere_calls == 11, "called %d\n", DataObjectImpl_GetDataHere_calls);
1511     ok(DataObjectImpl_GetData_calls == 3, "called %d\n", DataObjectImpl_GetData_calls);
1512
1513     med.pUnkForRelease = NULL;
1514     med.tymed = TYMED_ISTREAM;
1515     CreateStreamOnHGlobal(NULL, TRUE, &U(med).pstm);
1516     hr = IDataObject_GetDataHere(get, &fmt, &med);
1517     ok(hr == S_OK, "got %08x\n", hr);
1518     ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1519     ReleaseStgMedium(&med);
1520     ok(DataObjectImpl_GetDataHere_calls == 12, "called %d\n", DataObjectImpl_GetDataHere_calls);
1521     ok(DataObjectImpl_GetData_calls == 3, "called %d\n", DataObjectImpl_GetData_calls);
1522
1523     med.pUnkForRelease = NULL;
1524     med.tymed = TYMED_ISTORAGE;
1525     StgCreateDocfile(NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &U(med).pstg);
1526     hr = IDataObject_GetDataHere(get, &fmt, &med);
1527     ok(hr == S_OK, "got %08x\n", hr);
1528     ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1529     ReleaseStgMedium(&med);
1530     ok(DataObjectImpl_GetDataHere_calls == 13, "called %d\n", DataObjectImpl_GetDataHere_calls);
1531     ok(DataObjectImpl_GetData_calls == 3, "called %d\n", DataObjectImpl_GetData_calls);
1532
1533
1534     IDataObject_Release(get);
1535     IDataObject_Release(src);
1536
1537     OleUninitialize();
1538
1539 }
1540
1541 START_TEST(clipboard)
1542 {
1543     test_set_clipboard();
1544     test_consumer_refs();
1545     test_flushed_getdata();
1546     test_nonole_clipboard();
1547     test_getdatahere();
1548 }