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