ReactOS 0.4.16-dev-197-g92996da
clipboard.c
Go to the documentation of this file.
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#ifndef __REACTOS__
24#define NONAMELESSUNION
25#endif
26
27#include <stdarg.h>
28#include <stdio.h>
29
30#include "windef.h"
31#include "winbase.h"
32#include "objbase.h"
33
34#include "wine/test.h"
35
36#define InitFormatEtc(fe, cf, med) \
37 {\
38 (fe).cfFormat=cf;\
39 (fe).dwAspect=DVASPECT_CONTENT;\
40 (fe).ptd=NULL;\
41 (fe).tymed=med;\
42 (fe).lindex=-1;\
43 };
44
45static inline char *dump_fmtetc(FORMATETC *fmt)
46{
47 static char buf[100];
48
49 sprintf(buf, "cf %04x ptd %p aspect %x lindex %d tymed %x",
50 fmt->cfFormat, fmt->ptd, fmt->dwAspect, fmt->lindex, fmt->tymed);
51 return buf;
52}
53
54typedef struct DataObjectImpl {
56 LONG ref;
57
58 FORMATETC *fmtetc;
60
64 HMETAFILEPICT hmfp;
66
67typedef struct EnumFormatImpl {
69 LONG ref;
70
71 FORMATETC *fmtetc;
73
74 UINT cur;
76
81
83
84static HRESULT EnumFormatImpl_Create(FORMATETC *fmtetc, UINT size, LPENUMFORMATETC *lplpformatetc);
85
86static HMETAFILE create_mf(void)
87{
88 RECT rect = {0, 0, 100, 100};
90 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
91 return CloseMetaFile(hdc);
92}
93
94static HMETAFILEPICT create_metafilepict(void)
95{
98 mf->mm = MM_ANISOTROPIC;
99 mf->xExt = 100;
100 mf->yExt = 200;
101 mf->hMF = create_mf();
103 return ret;
104}
105
107{
108 return CONTAINING_RECORD(iface, DataObjectImpl, IDataObject_iface);
109}
110
112{
113 return CONTAINING_RECORD(iface, EnumFormatImpl, IEnumFORMATETC_iface);
114}
115
117{
119
121 IEnumFORMATETC_AddRef(iface);
122 *ppvObj = &This->IEnumFORMATETC_iface;
123 return S_OK;
124 }
125 *ppvObj = NULL;
126 return E_NOINTERFACE;
127}
128
130{
133 return ref;
134}
135
137{
140
141 if(!ref) {
142 HeapFree(GetProcessHeap(), 0, This->fmtetc);
144 }
145
146 return ref;
147}
148
150 FORMATETC *rgelt, ULONG *pceltFetched)
151{
153 ULONG count, i;
154
155 if (winetest_debug > 1)
156 trace("next: count %d cur %d\n", celt, This->cur);
157
158 if(!rgelt)
159 return E_INVALIDARG;
160
161 count = min(celt, This->fmtetc_cnt - This->cur);
162 for(i = 0; i < count; i++, This->cur++, rgelt++)
163 {
164 *rgelt = This->fmtetc[This->cur];
165 if(rgelt->ptd)
166 {
167 DWORD size = This->fmtetc[This->cur].ptd->tdSize;
168 rgelt->ptd = CoTaskMemAlloc(size);
169 memcpy(rgelt->ptd, This->fmtetc[This->cur].ptd, size);
170 }
171 }
172 if(pceltFetched)
173 *pceltFetched = count;
174 return count == celt ? S_OK : S_FALSE;
175}
176
178{
179 ok(0, "unexpected call\n");
180 return E_NOTIMPL;
181}
182
184{
186
187 This->cur = 0;
188 return S_OK;
189}
190
192{
193 ok(0, "unexpected call\n");
194 return E_NOTIMPL;
195}
196
197static const IEnumFORMATETCVtbl VT_EnumFormatImpl = {
205};
206
207static HRESULT EnumFormatImpl_Create(FORMATETC *fmtetc, UINT fmtetc_cnt, IEnumFORMATETC **lplpformatetc)
208{
210
212 ret->IEnumFORMATETC_iface.lpVtbl = &VT_EnumFormatImpl;
213 ret->ref = 1;
214 ret->cur = 0;
215 ret->fmtetc_cnt = fmtetc_cnt;
216 ret->fmtetc = HeapAlloc(GetProcessHeap(), 0, fmtetc_cnt*sizeof(FORMATETC));
217 memcpy(ret->fmtetc, fmtetc, fmtetc_cnt*sizeof(FORMATETC));
218 *lplpformatetc = &ret->IEnumFORMATETC_iface;
219 return S_OK;
220}
221
223{
225
227 IDataObject_AddRef(iface);
228 *ppvObj = &This->IDataObject_iface;
229 return S_OK;
230 }
231 *ppvObj = NULL;
232 return E_NOINTERFACE;
233}
234
236{
239 return ref;
240}
241
243{
246
247 if(!ref)
248 {
249 int i;
250 if(This->text) GlobalFree(This->text);
251 for(i = 0; i < This->fmtetc_cnt; i++)
252 HeapFree(GetProcessHeap(), 0, This->fmtetc[i].ptd);
253 HeapFree(GetProcessHeap(), 0, This->fmtetc);
254 if(This->stm) IStream_Release(This->stm);
255 if(This->stg) IStorage_Release(This->stg);
256 if(This->hmfp) {
257 METAFILEPICT *mfp = GlobalLock(This->hmfp);
258 DeleteMetaFile(mfp->hMF);
259 GlobalUnlock(This->hmfp);
260 GlobalFree(This->hmfp);
261 }
263 }
264
265 return ref;
266}
267
268static HRESULT WINAPI DataObjectImpl_GetData(IDataObject* iface, FORMATETC *pformatetc, STGMEDIUM *pmedium)
269{
271 UINT i;
272
273 trace("getdata: %s\n", dump_fmtetc(pformatetc));
274
276
277 ok(pmedium->tymed == 0, "pmedium->tymed = %u\n", pmedium->tymed);
278 ok(U(*pmedium).hGlobal == NULL, "pmedium->hGlobal = %p\n", U(*pmedium).hGlobal);
279 ok(pmedium->pUnkForRelease == NULL, "pmedium->pUnkForRelease = %p\n", pmedium->pUnkForRelease);
280
281 if(pformatetc->lindex != -1)
282 return DV_E_FORMATETC;
283
284 for(i = 0; i < This->fmtetc_cnt; i++)
285 {
286 if(This->fmtetc[i].cfFormat == pformatetc->cfFormat)
287 {
288 if(This->fmtetc[i].tymed & pformatetc->tymed)
289 {
290 pmedium->pUnkForRelease = (LPUNKNOWN)iface;
291 IUnknown_AddRef(pmedium->pUnkForRelease);
292
293 if(pformatetc->cfFormat == CF_TEXT || pformatetc->cfFormat == cf_global)
294 {
295 pmedium->tymed = TYMED_HGLOBAL;
296 U(*pmedium).hGlobal = This->text;
297 }
298 else if(pformatetc->cfFormat == cf_stream)
299 {
300 pmedium->tymed = TYMED_ISTREAM;
301 IStream_AddRef(This->stm);
302 U(*pmedium).pstm = This->stm;
303 }
304 else if(pformatetc->cfFormat == cf_storage || pformatetc->cfFormat == cf_another)
305 {
306 pmedium->tymed = TYMED_ISTORAGE;
307 IStorage_AddRef(This->stg);
308 U(*pmedium).pstg = This->stg;
309 }
310 else if(pformatetc->cfFormat == CF_METAFILEPICT)
311 {
312 pmedium->tymed = TYMED_MFPICT;
313 U(*pmedium).hMetaFilePict = This->hmfp;
314 }
315 return S_OK;
316 }
317 }
318 }
319
320 return E_FAIL;
321}
322
323static HRESULT WINAPI DataObjectImpl_GetDataHere(IDataObject* iface, FORMATETC *pformatetc, STGMEDIUM *pmedium)
324{
325 trace("getdatahere: %s\n", dump_fmtetc(pformatetc));
327
328 return E_NOTIMPL;
329}
330
331static HRESULT WINAPI DataObjectImpl_QueryGetData(IDataObject* iface, FORMATETC *pformatetc)
332{
334 UINT i;
335 BOOL foundFormat = FALSE;
336
337 trace("querygetdata: %s\n", dump_fmtetc(pformatetc));
339 ok(0, "unexpected call to DataObjectImpl_QueryGetData\n");
340
341 if(pformatetc->lindex != -1)
342 return DV_E_LINDEX;
343
344 for(i=0; i<This->fmtetc_cnt; i++) {
345 if(This->fmtetc[i].cfFormat == pformatetc->cfFormat) {
346 foundFormat = TRUE;
347 if(This->fmtetc[i].tymed == pformatetc->tymed)
348 return S_OK;
349 }
350 }
351 return foundFormat?DV_E_FORMATETC:DV_E_TYMED;
352}
353
354static HRESULT WINAPI DataObjectImpl_GetCanonicalFormatEtc(IDataObject* iface, FORMATETC *pformatectIn,
355 FORMATETC *pformatetcOut)
356{
357 ok(0, "unexpected call\n");
358 return E_NOTIMPL;
359}
360
361static HRESULT WINAPI DataObjectImpl_SetData(IDataObject* iface, FORMATETC *pformatetc,
362 STGMEDIUM *pmedium, BOOL fRelease)
363{
364 ok(0, "unexpected call\n");
365 return E_NOTIMPL;
366}
367
369 IEnumFORMATETC **ppenumFormatEtc)
370{
372
374
375 if(dwDirection != DATADIR_GET) {
376 ok(0, "unexpected direction %d\n", dwDirection);
377 return E_NOTIMPL;
378 }
379 return EnumFormatImpl_Create(This->fmtetc, This->fmtetc_cnt, ppenumFormatEtc);
380}
381
382static HRESULT WINAPI DataObjectImpl_DAdvise(IDataObject* iface, FORMATETC *pformatetc, DWORD advf,
383 IAdviseSink *pAdvSink, DWORD *pdwConnection)
384{
385 ok(0, "unexpected call\n");
386 return E_NOTIMPL;
387}
388
390{
391 ok(0, "unexpected call\n");
392 return E_NOTIMPL;
393}
394
396{
397 ok(0, "unexpected call\n");
398 return E_NOTIMPL;
399}
400
401static const IDataObjectVtbl VT_DataObjectImpl =
402{
415};
416
418{
420
423 obj->ref = 1;
424 obj->text = text;
425 obj->stm = NULL;
426 obj->stg = NULL;
427 obj->hmfp = NULL;
428
429 obj->fmtetc_cnt = 1;
430 obj->fmtetc = HeapAlloc(GetProcessHeap(), 0, obj->fmtetc_cnt*sizeof(FORMATETC));
431 InitFormatEtc(obj->fmtetc[0], CF_TEXT, TYMED_HGLOBAL);
432
433 *dataobj = &obj->IDataObject_iface;
434 return S_OK;
435}
436
438{
442 return DataObjectImpl_CreateFromHGlobal(h, lplpdataobj);
443}
444
445static const char *cmpl_stm_data = "complex stream";
446static const char *cmpl_text_data = "complex text";
447static const WCHAR device_name[] = {'m','y','d','e','v',0};
448
450{
452 ILockBytes *lbs;
453 DEVMODEW dm;
454
457 obj->ref = 1;
460 GlobalUnlock(obj->text);
462 IStream_Write(obj->stm, cmpl_stm_data, strlen(cmpl_stm_data), NULL);
463
466 ILockBytes_Release(lbs);
467
468 obj->hmfp = create_metafilepict();
469
470 obj->fmtetc_cnt = 9;
471 /* zeroing here since FORMATETC has a hole in it, and it's confusing to have this uninitialised. */
472 obj->fmtetc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, obj->fmtetc_cnt*sizeof(FORMATETC));
473 InitFormatEtc(obj->fmtetc[0], CF_TEXT, TYMED_HGLOBAL);
474 InitFormatEtc(obj->fmtetc[1], cf_stream, TYMED_ISTREAM);
475 InitFormatEtc(obj->fmtetc[2], cf_storage, TYMED_ISTORAGE);
476 InitFormatEtc(obj->fmtetc[3], cf_another, TYMED_ISTORAGE|TYMED_ISTREAM|TYMED_HGLOBAL);
477 if (0) /* Causes crashes on both Wine and Windows */
478 {
479 memset(&dm, 0, sizeof(dm));
480 dm.dmSize = sizeof(dm);
481 dm.dmDriverExtra = 0;
483 obj->fmtetc[3].ptd = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(DVTARGETDEVICE, tdData) + sizeof(device_name) + dm.dmSize + dm.dmDriverExtra);
484 obj->fmtetc[3].ptd->tdSize = FIELD_OFFSET(DVTARGETDEVICE, tdData) + sizeof(device_name) + dm.dmSize + dm.dmDriverExtra;
485 obj->fmtetc[3].ptd->tdDriverNameOffset = FIELD_OFFSET(DVTARGETDEVICE, tdData);
486 obj->fmtetc[3].ptd->tdDeviceNameOffset = 0;
487 obj->fmtetc[3].ptd->tdPortNameOffset = 0;
488 obj->fmtetc[3].ptd->tdExtDevmodeOffset = obj->fmtetc[3].ptd->tdDriverNameOffset + sizeof(device_name);
489 lstrcpyW((WCHAR*)obj->fmtetc[3].ptd->tdData, device_name);
490 memcpy(obj->fmtetc[3].ptd->tdData + sizeof(device_name), &dm, dm.dmSize + dm.dmDriverExtra);
491 }
492
493 InitFormatEtc(obj->fmtetc[4], cf_global, TYMED_HGLOBAL);
494 InitFormatEtc(obj->fmtetc[5], cf_another, TYMED_HGLOBAL);
495 InitFormatEtc(obj->fmtetc[6], cf_another, 0xfffff);
496 InitFormatEtc(obj->fmtetc[7], cf_another, 0xfffff);
497 obj->fmtetc[7].dwAspect = DVASPECT_ICON;
498 InitFormatEtc(obj->fmtetc[8], CF_METAFILEPICT, TYMED_MFPICT);
499
500 *lplpdataobj = &obj->IDataObject_iface;
501 return S_OK;
502}
503
505{
506 HRESULT hr;
507 IDataObject *pDObj;
508
509 pDObj = (IDataObject *)0xdeadbeef;
510 hr = OleGetClipboard(&pDObj);
511 todo_wine ok(hr == S_OK, "OleGetClipboard() got 0x%08x instead of 0x%08x\n", hr, S_OK);
512 if (pDObj && pDObj != (IDataObject *)0xdeadbeef) IDataObject_Release(pDObj);
513}
514
515static void test_get_clipboard(void)
516{
517 HRESULT hr;
518 IDataObject *data_obj;
519 FORMATETC fmtetc;
520 STGMEDIUM stgmedium;
521
523 ok(hr == E_INVALIDARG, "OleGetClipboard(NULL) should return E_INVALIDARG instead of 0x%08x\n", hr);
524
525 hr = OleGetClipboard(&data_obj);
526 ok(hr == S_OK, "OleGetClipboard failed with error 0x%08x\n", hr);
527
528 /* test IDataObject_QueryGetData */
529
530 /* clipboard's IDataObject_QueryGetData shouldn't defer to our IDataObject_QueryGetData */
532
533 InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
534 hr = IDataObject_QueryGetData(data_obj, &fmtetc);
535 ok(hr == S_OK, "IDataObject_QueryGetData failed with error 0x%08x\n", hr);
536
537 InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
538 fmtetc.dwAspect = 0xdeadbeef;
539 hr = IDataObject_QueryGetData(data_obj, &fmtetc);
540 ok(hr == DV_E_FORMATETC, "IDataObject_QueryGetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
541
542 InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
543 fmtetc.dwAspect = DVASPECT_THUMBNAIL;
544 hr = IDataObject_QueryGetData(data_obj, &fmtetc);
545 ok(hr == DV_E_FORMATETC, "IDataObject_QueryGetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
546
547 InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
548 fmtetc.lindex = 256;
549 hr = IDataObject_QueryGetData(data_obj, &fmtetc);
550 ok(hr == DV_E_FORMATETC || broken(hr == S_OK),
551 "IDataObject_QueryGetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
552
553 InitFormatEtc(fmtetc, CF_RIFF, TYMED_HGLOBAL);
554 hr = IDataObject_QueryGetData(data_obj, &fmtetc);
555 ok(hr == DV_E_CLIPFORMAT, "IDataObject_QueryGetData should have failed with DV_E_CLIPFORMAT instead of 0x%08x\n", hr);
556
557 InitFormatEtc(fmtetc, CF_TEXT, TYMED_FILE);
558 hr = IDataObject_QueryGetData(data_obj, &fmtetc);
559 ok(hr == S_OK, "IDataObject_QueryGetData failed with error 0x%08x\n", hr);
560
562
563 /* test IDataObject_GetData */
564
566
567 InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
568 hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
569 ok(hr == S_OK, "IDataObject_GetData failed with error 0x%08x\n", hr);
570 if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
571
572 InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
573 fmtetc.dwAspect = 0xdeadbeef;
574 hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
575 ok(hr == S_OK, "IDataObject_GetData failed with error 0x%08x\n", hr);
576 if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
577
578 InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
579 fmtetc.dwAspect = DVASPECT_THUMBNAIL;
580 hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
581 ok(hr == S_OK, "IDataObject_GetData failed with error 0x%08x\n", hr);
582 if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
583
584 InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
585 fmtetc.lindex = 256;
586 hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
587 ok(hr == DV_E_FORMATETC || broken(hr == S_OK), "IDataObject_GetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
588 if (hr == S_OK)
589 {
590 /* undo the unexpected success */
592 ReleaseStgMedium(&stgmedium);
593 }
594
595 InitFormatEtc(fmtetc, CF_RIFF, TYMED_HGLOBAL);
596 hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
597 ok(hr == DV_E_FORMATETC, "IDataObject_GetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
598 if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
599
600 InitFormatEtc(fmtetc, CF_TEXT, TYMED_FILE);
601 hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
602 ok(hr == DV_E_TYMED, "IDataObject_GetData should have failed with DV_E_TYMED instead of 0x%08x\n", hr);
603 if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
604
605 ok(DataObjectImpl_GetData_calls == 6, "DataObjectImpl_GetData should have been called 6 times instead of %d times\n", DataObjectImpl_GetData_calls);
606
607 IDataObject_Release(data_obj);
608}
609
611{
612 HRESULT hr;
614 IEnumFORMATETC *enum_fmt, *src_enum;
615 FORMATETC fmt, src_fmt;
616 DWORD count = 0;
617
619 ok(hr == S_OK, "OleGetClipboard failed with error 0x%08x\n", hr);
620
621 hr = IDataObject_EnumFormatEtc(data, DATADIR_SET, &enum_fmt);
622 ok(hr == E_NOTIMPL ||
623 broken(hr == E_INVALIDARG), /* win98 (not win98SE) */
624 "got %08x\n", hr);
625
627 hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
628 ok(hr == S_OK, "got %08x\n", hr);
629 ok(DataObjectImpl_EnumFormatEtc_calls == 0, "EnumFormatEtc was called\n");
630 if (FAILED(hr))
631 {
632 skip("EnumFormatEtc failed, skipping tests.\n");
633 return;
634 }
635
636 if(src) IDataObject_EnumFormatEtc(src, DATADIR_GET, &src_enum);
637
638 while((hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL)) == S_OK)
639 {
640 ok(src != NULL, "shouldn't be here\n");
641 hr = IEnumFORMATETC_Next(src_enum, 1, &src_fmt, NULL);
642 ok(hr == S_OK, "%d: got %08x\n", count, hr);
643 trace("%d: %s\n", count, dump_fmtetc(&fmt));
644 ok(fmt.cfFormat == src_fmt.cfFormat, "%d: %04x %04x\n", count, fmt.cfFormat, src_fmt.cfFormat);
645 ok(fmt.dwAspect == src_fmt.dwAspect, "%d: %08x %08x\n", count, fmt.dwAspect, src_fmt.dwAspect);
646 ok(fmt.lindex == src_fmt.lindex, "%d: %08x %08x\n", count, fmt.lindex, src_fmt.lindex);
647 ok(fmt.tymed == src_fmt.tymed, "%d: %08x %08x\n", count, fmt.tymed, src_fmt.tymed);
648 if(fmt.ptd)
649 {
650 ok(src_fmt.ptd != NULL, "%d: expected non-NULL\n", count);
651 CoTaskMemFree(fmt.ptd);
652 CoTaskMemFree(src_fmt.ptd);
653 }
654 count++;
655 }
656
657 ok(hr == S_FALSE, "%d: got %08x\n", count, hr);
658
659 if(src)
660 {
661 hr = IEnumFORMATETC_Next(src_enum, 1, &src_fmt, NULL);
662 ok(hr == S_FALSE, "%d: got %08x\n", count, hr);
663 IEnumFORMATETC_Release(src_enum);
664 }
665
666 hr = IEnumFORMATETC_Reset(enum_fmt);
667 ok(hr == S_OK, "got %08x\n", hr);
668
669 if(src) /* Exercise the enumerator a bit */
670 {
671 IEnumFORMATETC *clone;
672 FORMATETC third_fmt;
673
674 hr = IEnumFORMATETC_Next(enum_fmt, 1, &third_fmt, NULL);
675 ok(hr == S_OK, "got %08x\n", hr);
676 hr = IEnumFORMATETC_Next(enum_fmt, 1, &third_fmt, NULL);
677 ok(hr == S_OK, "got %08x\n", hr);
678 hr = IEnumFORMATETC_Next(enum_fmt, 1, &third_fmt, NULL);
679 ok(hr == S_OK, "got %08x\n", hr);
680
681 hr = IEnumFORMATETC_Reset(enum_fmt);
682 ok(hr == S_OK, "got %08x\n", hr);
683 hr = IEnumFORMATETC_Skip(enum_fmt, 2);
684 ok(hr == S_OK, "got %08x\n", hr);
685
686 hr = IEnumFORMATETC_Clone(enum_fmt, &clone);
687 ok(hr == S_OK, "got %08x\n", hr);
688 hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
689 ok(hr == S_OK, "got %08x\n", hr);
690 ok(fmt.cfFormat == third_fmt.cfFormat, "formats don't match\n");
691 hr = IEnumFORMATETC_Next(clone, 1, &fmt, NULL);
692 ok(hr == S_OK, "got %08x\n", hr);
693 ok(fmt.cfFormat == third_fmt.cfFormat, "formats don't match\n");
694 IEnumFORMATETC_Release(clone);
695 }
696
697 IEnumFORMATETC_Release(enum_fmt);
698 IDataObject_Release(data);
699}
700
701static void test_no_cf_dataobject(void)
702{
703 UINT cf_dataobject = RegisterClipboardFormatA("DataObject");
704 UINT cf_ole_priv_data = RegisterClipboardFormatA("Ole Private Data");
705 HANDLE h;
707
708 h = GetClipboardData(cf_dataobject);
709 ok(!h, "got %p\n", h);
710 h = GetClipboardData(cf_ole_priv_data);
711 ok(!h, "got %p\n", h);
712
714}
715
717{
718 UINT cf = 0;
719 UINT cf_dataobject = RegisterClipboardFormatA("DataObject");
720 UINT cf_ole_priv_data = RegisterClipboardFormatA("Ole Private Data");
721 BOOL found_dataobject = FALSE, found_priv_data = FALSE;
722
724 do
725 {
727 if(cf == cf_dataobject)
728 {
730 HWND *ptr = GlobalLock(h);
732 HWND clip_owner = GetClipboardOwner();
733
734 found_dataobject = TRUE;
735 ok(size >= sizeof(*ptr), "size %d\n", size);
736 if(data)
737 ok(*ptr == clip_owner, "hwnd %p clip_owner %p\n", *ptr, clip_owner);
738 else /* ole clipboard flushed */
739 ok(*ptr == NULL, "hwnd %p\n", *ptr);
741 }
742 else if(cf == cf_ole_priv_data)
743 {
744 found_priv_data = TRUE;
745 if(data)
746 {
748 DWORD *ptr = GlobalLock(h);
750
751 if(size != ptr[1])
752 win_skip("Ole Private Data in win9x format\n");
753 else
754 {
755 HRESULT hr;
756 IEnumFORMATETC *enum_fmt;
757 DWORD count = 0;
758 FORMATETC fmt;
759 struct formatetcetc
760 {
761 FORMATETC fmt;
762 BOOL first_use_of_cf;
763 DWORD res[2];
764 } *fmt_ptr;
765 struct priv_data
766 {
767 DWORD res1;
768 DWORD size;
769 DWORD res2;
770 DWORD count;
771 DWORD res3[2];
772 struct formatetcetc fmts[1];
773 } *priv = (struct priv_data*)ptr;
774 CLIPFORMAT cfs_seen[10];
775
776 hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
777 ok(hr == S_OK, "got %08x\n", hr);
778 fmt_ptr = priv->fmts;
779
780 while(IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL) == S_OK)
781 {
782 int i;
783 BOOL seen_cf = FALSE;
784
785 ok(fmt_ptr->fmt.cfFormat == fmt.cfFormat,
786 "got %08x expected %08x\n", fmt_ptr->fmt.cfFormat, fmt.cfFormat);
787 ok(fmt_ptr->fmt.dwAspect == fmt.dwAspect, "got %08x expected %08x\n",
788 fmt_ptr->fmt.dwAspect, fmt.dwAspect);
789 ok(fmt_ptr->fmt.lindex == fmt.lindex, "got %08x expected %08x\n",
790 fmt_ptr->fmt.lindex, fmt.lindex);
791 ok(fmt_ptr->fmt.tymed == fmt.tymed, "got %08x expected %08x\n",
792 fmt_ptr->fmt.tymed, fmt.tymed);
793 for(i = 0; i < count; i++)
794 if(fmt_ptr->fmt.cfFormat == cfs_seen[i])
795 {
796 seen_cf = TRUE;
797 break;
798 }
799 cfs_seen[count] = fmt.cfFormat;
800 ok(fmt_ptr->first_use_of_cf != seen_cf, "got %08x expected %08x\n",
801 fmt_ptr->first_use_of_cf, !seen_cf);
802 ok(fmt_ptr->res[0] == 0, "got %08x\n", fmt_ptr->res[0]);
803 ok(fmt_ptr->res[1] == 0, "got %08x\n", fmt_ptr->res[1]);
804 if(fmt.ptd)
805 {
806 DVTARGETDEVICE *target;
807
808 ok(fmt_ptr->fmt.ptd != NULL, "target device offset zero\n");
809 target = (DVTARGETDEVICE*)((char*)priv + (DWORD_PTR)fmt_ptr->fmt.ptd);
810 ok(!memcmp(target, fmt.ptd, fmt.ptd->tdSize), "target devices differ\n");
811 CoTaskMemFree(fmt.ptd);
812 }
813 fmt_ptr++;
814 count++;
815 }
816 ok(priv->res1 == 0, "got %08x\n", priv->res1);
817 ok(priv->res2 == 1, "got %08x\n", priv->res2);
818 ok(priv->count == count, "got %08x expected %08x\n", priv->count, count);
819 ok(priv->res3[0] == 0, "got %08x\n", priv->res3[0]);
820
821 /* win64 sets the lsb */
822 if(sizeof(fmt_ptr->fmt.ptd) == 8)
823 todo_wine ok(priv->res3[1] == 1, "got %08x\n", priv->res3[1]);
824 else
825 ok(priv->res3[1] == 0, "got %08x\n", priv->res3[1]);
826
828 IEnumFORMATETC_Release(enum_fmt);
829 }
830 }
831 }
832 else if(cf == cf_stream)
833 {
834 HGLOBAL h;
835 void *ptr;
836 DWORD size;
837
841 ptr = GlobalLock(h);
842 size = GlobalSize(h);
844 "expected %d got %d\n", lstrlenA(cmpl_stm_data), size);
845 ok(!memcmp(ptr, cmpl_stm_data, strlen(cmpl_stm_data)), "mismatch\n");
847 }
848 else if(cf == cf_global)
849 {
850 HGLOBAL h;
851 void *ptr;
852 DWORD size;
853
857 ptr = GlobalLock(h);
858 size = GlobalSize(h);
860 "expected %d got %d\n", lstrlenA(cmpl_text_data) + 1, size);
861 ok(!memcmp(ptr, cmpl_text_data, strlen(cmpl_text_data) + 1), "mismatch\n");
863 }
864 } while(cf);
866 ok(found_dataobject, "didn't find cf_dataobject\n");
867 ok(found_priv_data, "didn't find cf_ole_priv_data\n");
868}
869
871{
872 HRESULT hr;
873 IDataObject *data_obj;
874 FORMATETC fmtetc;
875 STGMEDIUM stgmedium;
876
877 hr = OleGetClipboard(&data_obj);
878 ok(hr == S_OK, "OleGetClipboard failed with error 0x%08x\n", hr);
879
881
882 InitFormatEtc(fmtetc, CF_METAFILEPICT, TYMED_MFPICT);
883 hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
884 ok(hr == S_OK, "IDataObject_GetData failed with error 0x%08x\n", hr);
885 if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
886
887 InitFormatEtc(fmtetc, CF_METAFILEPICT, TYMED_HGLOBAL);
888 hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
889 ok(hr == DV_E_TYMED, "IDataObject_GetData failed with error 0x%08x\n", hr);
890 if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
891
892 InitFormatEtc(fmtetc, CF_ENHMETAFILE, TYMED_HGLOBAL);
893 hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
894 ok(hr == DV_E_TYMED, "IDataObject_GetData failed with error 0x%08x\n", hr);
895 if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
896
897 InitFormatEtc(fmtetc, CF_ENHMETAFILE, TYMED_ENHMF);
898 hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
899 ok(hr == S_OK, "IDataObject_GetData failed with error 0x%08x\n", hr);
900 if(SUCCEEDED(hr)) ReleaseStgMedium(&stgmedium);
901
903 "DataObjectImpl_GetData called 5 times instead of %d times\n",
905 IDataObject_Release(data_obj);
906}
907
908static void test_set_clipboard(void)
909{
910 HRESULT hr;
911 ULONG ref;
912 LPDATAOBJECT data1, data2, data_cmpl;
913 HGLOBAL hblob, h;
914 void *ptr;
915
916 cf_stream = RegisterClipboardFormatA("stream format");
917 cf_storage = RegisterClipboardFormatA("storage format");
918 cf_global = RegisterClipboardFormatA("global format");
919 cf_another = RegisterClipboardFormatA("another format");
920 cf_onemore = RegisterClipboardFormatA("one more format");
921
923 ok(hr == S_OK, "Failed to create data1 object: 0x%08x\n", hr);
924 if(FAILED(hr))
925 return;
927 ok(hr == S_OK, "Failed to create data2 object: 0x%08x\n", hr);
928 if(FAILED(hr))
929 return;
930 hr = DataObjectImpl_CreateComplex(&data_cmpl);
931 ok(hr == S_OK, "Failed to create complex data object: 0x%08x\n", hr);
932 if(FAILED(hr))
933 return;
934
936 ok(hr == CO_E_NOTINITIALIZED, "OleSetClipboard should have failed with CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
937
940 ok(hr == CO_E_NOTINITIALIZED, "OleSetClipboard failed with 0x%08x\n", hr);
942
944 ok(hr == S_OK, "OleInitialize failed with error 0x%08x\n", hr);
945
947 ok(hr == S_OK, "failed to set clipboard to data1, hr = 0x%08x\n", hr);
948
950
952 ok(hr == S_OK, "expected current clipboard to be data1, hr = 0x%08x\n", hr);
954 ok(hr == S_FALSE, "did not expect current clipboard to be data2, hr = 0x%08x\n", hr);
956 ok(hr == S_FALSE, "expect S_FALSE, hr = 0x%08x\n", hr);
957
959
961 ok(hr == S_OK, "failed to set clipboard to data2, hr = 0x%08x\n", hr);
963 ok(hr == S_FALSE, "did not expect current clipboard to be data1, hr = 0x%08x\n", hr);
965 ok(hr == S_OK, "expected current clipboard to be data2, hr = 0x%08x\n", hr);
967 ok(hr == S_FALSE, "expect S_FALSE, hr = 0x%08x\n", hr);
968
969 /* put a format directly onto the clipboard to show
970 OleFlushClipboard doesn't empty the clipboard */
972 ptr = GlobalLock( hblob );
973 ok( ptr && ptr != hblob, "got fixed block %p / %p\n", ptr, hblob );
974 GlobalUnlock( hblob );
975 ok( OpenClipboard(NULL), "OpenClipboard failed\n" );
976 h = SetClipboardData(cf_onemore, hblob);
977 ok(h == hblob, "got %p\n", h);
979 ok(h == hblob, "got %p / %p\n", h, hblob);
980 ptr = GlobalLock( h );
981 ok( ptr && ptr != h, "got fixed block %p / %p\n", ptr, h );
982 GlobalUnlock( hblob );
983 ok( CloseClipboard(), "CloseClipboard failed\n" );
984
986 ok(hr == S_OK, "failed to flush clipboard, hr = 0x%08x\n", hr);
988 ok(hr == S_FALSE, "did not expect current clipboard to be data1, hr = 0x%08x\n", hr);
990 ok(hr == S_FALSE, "did not expect current clipboard to be data2, hr = 0x%08x\n", hr);
992 ok(hr == S_FALSE, "expect S_FALSE, hr = 0x%08x\n", hr);
993
994 /* format should survive the flush */
995 ok( OpenClipboard(NULL), "OpenClipboard failed\n" );
997 ok(h == hblob, "got %p\n", h);
998 ptr = GlobalLock( h );
999 ok( ptr && ptr != h, "got fixed block %p / %p\n", ptr, h );
1000 GlobalUnlock( hblob );
1001 ok( CloseClipboard(), "CloseClipboard failed\n" );
1002
1004
1005 ok(OleSetClipboard(NULL) == S_OK, "failed to clear clipboard, hr = 0x%08x\n", hr);
1006
1009 ok(h == NULL, "got %p\n", h);
1011
1012 trace("setting complex\n");
1013 hr = OleSetClipboard(data_cmpl);
1014 ok(hr == S_OK, "failed to set clipboard to complex data, hr = 0x%08x\n", hr);
1016 test_cf_dataobject(data_cmpl);
1017 test_enum_fmtetc(data_cmpl);
1018
1019 ok(OleSetClipboard(NULL) == S_OK, "failed to clear clipboard, hr = 0x%08x\n", hr);
1020
1023
1024 ref = IDataObject_Release(data1);
1025 ok(ref == 0, "expected data1 ref=0, got %d\n", ref);
1026 ref = IDataObject_Release(data2);
1027 ok(ref == 0, "expected data2 ref=0, got %d\n", ref);
1028 ref = IDataObject_Release(data_cmpl);
1029 ok(ref == 0, "expected data_cmpl ref=0, got %d\n", ref);
1030
1032}
1033
1037
1039{
1040 LRESULT ret;
1041
1042 switch (msg)
1043 {
1044 case WM_DRAWCLIPBOARD:
1046 if (clip_data)
1047 {
1048 /* if this is the WM_DRAWCLIPBOARD of a previous change, the data isn't current yet */
1049 /* this demonstrates an issue in Qt where it will free the data while it's being set */
1051 ok( hr == (wm_drawclipboard > 1) ? S_OK : S_FALSE,
1052 "OleIsCurrentClipboard returned %x\n", hr );
1053 }
1054 break;
1055 case WM_CHANGECBCHAIN:
1056 if (next_wnd == (HWND)wp) next_wnd = (HWND)lp;
1057 else if (next_wnd) SendMessageA( next_wnd, msg, wp, lp );
1058 break;
1059 case WM_USER:
1061 wm_drawclipboard = 0;
1062 return ret;
1063 }
1064
1065 return DefWindowProcA(hwnd, msg, wp, lp);
1066}
1067
1069{
1074 return 0;
1075}
1076
1077/* test that WM_DRAWCLIPBOARD can be delivered for a previous change during OleSetClipboard */
1079{
1081 HRESULT hr;
1082 WNDCLASSA cls;
1083 HWND viewer;
1084 int ret;
1085 HANDLE thread;
1086
1087 hr = DataObjectImpl_CreateText("data", &data);
1088 ok(hr == S_OK, "Failed to create data object: 0x%08x\n", hr);
1089
1090 memset(&cls, 0, sizeof(cls));
1093 cls.lpszClassName = "clipboard_test";
1094 RegisterClassA(&cls);
1095
1096 viewer = CreateWindowA("clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0);
1097 ok(viewer != NULL, "CreateWindow failed: %d\n", GetLastError());
1098 next_wnd = SetClipboardViewer( viewer );
1099
1100 ret = SendMessageA( viewer, WM_USER, 0, 0 );
1101 ok( ret == 1, "%u WM_DRAWCLIPBOARD received\n", ret );
1102
1104 ok(hr == S_OK, "OleInitialize failed with error 0x%08x\n", hr);
1105
1106 ret = SendMessageA( viewer, WM_USER, 0, 0 );
1107 ok( !ret, "%u WM_DRAWCLIPBOARD received\n", ret );
1108
1110 ok(thread != NULL, "CreateThread failed (%d)\n", GetLastError());
1112 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", ret);
1113
1114 clip_data = data;
1116 ok(hr == S_OK, "failed to set clipboard to data, hr = 0x%08x\n", hr);
1117
1118 ret = SendMessageA( viewer, WM_USER, 0, 0 );
1119 ok( ret == 2, "%u WM_DRAWCLIPBOARD received\n", ret );
1120
1121 clip_data = NULL;
1123 ok(hr == S_OK, "failed to flush clipboard, hr = 0x%08x\n", hr);
1124 ret = IDataObject_Release(data);
1125 ok(ret == 0, "got %d\n", ret);
1126
1128 ChangeClipboardChain( viewer, next_wnd );
1129 DestroyWindow( viewer );
1130}
1131
1133{
1134 IDataObject_AddRef(d);
1135 return IDataObject_Release(d);
1136}
1137
1138static void test_consumer_refs(void)
1139{
1140 HRESULT hr;
1141 IDataObject *src, *src2, *get1, *get2, *get3;
1142 ULONG refs, old_refs;
1143 FORMATETC fmt;
1144 STGMEDIUM med;
1145
1146 InitFormatEtc(fmt, CF_TEXT, TYMED_HGLOBAL);
1147
1149
1150 /* First show that each clipboard state results in
1151 a different data object */
1152
1153 hr = DataObjectImpl_CreateText("data1", &src);
1154 ok(hr == S_OK, "got %08x\n", hr);
1155 hr = DataObjectImpl_CreateText("data2", &src2);
1156 ok(hr == S_OK, "got %08x\n", hr);
1157
1159 ok(hr == S_OK, "got %08x\n", hr);
1160
1161 hr = OleGetClipboard(&get1);
1162 ok(hr == S_OK, "got %08x\n", hr);
1163
1164 hr = OleGetClipboard(&get2);
1165 ok(hr == S_OK, "got %08x\n", hr);
1166
1167 ok(get1 == get2, "data objects differ\n");
1168 refs = IDataObject_Release(get2);
1169 ok(refs == (get1 == get2 ? 1 : 0), "got %d\n", refs);
1170
1172
1174 hr = IDataObject_GetData(get1, &fmt, &med);
1175 ok(hr == S_OK, "got %08x\n", hr);
1176 ok(DataObjectImpl_GetData_calls == 0, "GetData called\n");
1177 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1178
1179 hr = OleGetClipboard(&get2);
1180 ok(hr == S_OK, "got %08x\n", hr);
1181
1182 ok(get1 != get2, "data objects match\n");
1183
1185
1186 hr = OleGetClipboard(&get3);
1187 ok(hr == S_OK, "got %08x\n", hr);
1188
1189 ok(get1 != get3, "data objects match\n");
1190 ok(get2 != get3, "data objects match\n");
1191
1192 IDataObject_Release(get3);
1193 IDataObject_Release(get2);
1194 IDataObject_Release(get1);
1195
1196 /* Now call GetData before the flush and show that this
1197 takes a ref on our src data obj. */
1198
1200 ok(hr == S_OK, "got %08x\n", hr);
1201
1202 old_refs = count_refs(src);
1203
1204 hr = OleGetClipboard(&get1);
1205 ok(hr == S_OK, "got %08x\n", hr);
1206
1207 refs = count_refs(src);
1208 ok(refs == old_refs, "%d %d\n", refs, old_refs);
1209
1211 hr = IDataObject_GetData(get1, &fmt, &med);
1212 ok(hr == S_OK, "got %08x\n", hr);
1213 ok(DataObjectImpl_GetData_calls == 1, "GetData not called\n");
1214 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1215 refs = count_refs(src);
1216 ok(refs == old_refs + 1, "%d %d\n", refs, old_refs);
1217
1219
1221 hr = IDataObject_GetData(get1, &fmt, &med);
1222 ok(hr == S_OK, "got %08x\n", hr);
1223 ok(DataObjectImpl_GetData_calls == 1, "GetData not called\n");
1224 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1225
1226 refs = count_refs(src);
1227 ok(refs == 2, "%d\n", refs);
1228
1229 IDataObject_Release(get1);
1230
1231 refs = count_refs(src);
1232 ok(refs == 1, "%d\n", refs);
1233
1234 /* Now set a second src object before the call to GetData
1235 and show that GetData calls that second src. */
1236
1238 ok(hr == S_OK, "got %08x\n", hr);
1239
1240 old_refs = count_refs(src);
1241
1242 hr = OleGetClipboard(&get1);
1243 ok(hr == S_OK, "got %08x\n", hr);
1244
1245 refs = count_refs(src);
1246 ok(refs == old_refs, "%d %d\n", refs, old_refs);
1247
1248 hr = OleSetClipboard(src2);
1249 ok(hr == S_OK, "got %08x\n", hr);
1250
1251 old_refs = count_refs(src2);
1252
1254 hr = IDataObject_GetData(get1, &fmt, &med);
1255 ok(hr == S_OK, "got %08x\n", hr);
1256 ok(DataObjectImpl_GetData_calls == 1, "GetData not called\n");
1257 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1258
1259 refs = count_refs(src);
1260 ok(refs == 1, "%d\n", refs);
1261 refs = count_refs(src2);
1262 ok(refs == old_refs + 1, "%d %d\n", refs, old_refs);
1263
1265
1266 refs = count_refs(src2);
1267 ok(refs == 2, "%d\n", refs);
1268
1269 IDataObject_Release(get1);
1270
1271 IDataObject_Release(src2);
1272
1273 /* Show that OleUninitialize() doesn't release the
1274 dataobject's ref, and thus the object is leaked. */
1275 old_refs = count_refs(src);
1276 ok(old_refs == 1, "%d\n", old_refs);
1277
1279 refs = count_refs(src);
1280 ok(refs > old_refs, "%d %d\n", refs, old_refs);
1281
1283 refs = count_refs(src);
1284 ok(refs == 2, "%d\n", refs);
1285
1286 IDataObject_Release(src);
1287}
1288
1290{
1291 ILockBytes *ilb;
1292 IStorage *stg;
1293 HGLOBAL hg;
1294 HRESULT hr;
1295
1297 ok(hr == S_OK, "got %08x\n", hr);
1299 ok(hr == S_OK, "got %08x\n", hr);
1300 IStorage_Release(stg);
1302 ok(hr == S_OK, "got %08x\n", hr);
1303 ILockBytes_Release(ilb);
1304 return hg;
1305}
1306
1307static void test_flushed_getdata(void)
1308{
1309 HRESULT hr;
1310 IDataObject *src, *get;
1311 FORMATETC fmt;
1312 STGMEDIUM med;
1313 STATSTG stat;
1314 DEVMODEW dm;
1315
1317
1319 ok(hr == S_OK, "got %08x\n", hr);
1320
1322 ok(hr == S_OK, "got %08x\n", hr);
1323
1325 ok(hr == S_OK, "got %08x\n", hr);
1326
1328 ok(hr == S_OK, "got %08x\n", hr);
1329
1330 /* global format -> global & stream */
1331
1332 InitFormatEtc(fmt, CF_TEXT, TYMED_HGLOBAL);
1333 hr = IDataObject_GetData(get, &fmt, &med);
1334 ok(hr == S_OK, "got %08x\n", hr);
1335 ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1336 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1337
1338 InitFormatEtc(fmt, CF_TEXT, TYMED_ISTREAM);
1339 hr = IDataObject_GetData(get, &fmt, &med);
1340 ok(hr == S_OK, "got %08x\n", hr);
1341 ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1342 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1343
1344 InitFormatEtc(fmt, CF_TEXT, TYMED_ISTORAGE);
1345 hr = IDataObject_GetData(get, &fmt, &med);
1346 ok(hr == E_FAIL, "got %08x\n", hr);
1347 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1348
1349 InitFormatEtc(fmt, CF_TEXT, 0xffff);
1350 hr = IDataObject_GetData(get, &fmt, &med);
1351 ok(hr == S_OK, "got %08x\n", hr);
1352 ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1353 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1354
1355 /* stream format -> global & stream */
1356
1357 InitFormatEtc(fmt, cf_stream, TYMED_ISTREAM);
1358 hr = IDataObject_GetData(get, &fmt, &med);
1359 ok(hr == S_OK, "got %08x\n", hr);
1360 ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1361 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1362
1363 InitFormatEtc(fmt, cf_stream, TYMED_ISTORAGE);
1364 hr = IDataObject_GetData(get, &fmt, &med);
1365 ok(hr == E_FAIL, "got %08x\n", hr);
1366 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1367
1368 InitFormatEtc(fmt, cf_stream, TYMED_HGLOBAL);
1369 hr = IDataObject_GetData(get, &fmt, &med);
1370 ok(hr == S_OK, "got %08x\n", hr);
1371 ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1372 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1373
1374 InitFormatEtc(fmt, cf_stream, 0xffff);
1375 hr = IDataObject_GetData(get, &fmt, &med);
1376 ok(hr == S_OK, "got %08x\n", hr);
1377 ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1378 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1379
1380 /* storage format -> global, stream & storage */
1381
1382 InitFormatEtc(fmt, cf_storage, TYMED_ISTORAGE);
1383 hr = IDataObject_GetData(get, &fmt, &med);
1384 ok(hr == S_OK, "got %08x\n", hr);
1385 ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1386 if(SUCCEEDED(hr)) {
1387 hr = IStorage_Stat(med.pstg, &stat, STATFLAG_NONAME);
1388 ok(hr == S_OK, "got %08x\n", hr);
1389 ok(stat.grfMode == (STGM_SHARE_EXCLUSIVE | STGM_READWRITE), "got %08x\n", stat.grfMode);
1390 ReleaseStgMedium(&med);
1391 }
1392
1393 InitFormatEtc(fmt, cf_storage, TYMED_ISTREAM);
1394 hr = IDataObject_GetData(get, &fmt, &med);
1395 ok(hr == S_OK, "got %08x\n", hr);
1396 ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1397 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1398
1399 InitFormatEtc(fmt, cf_storage, TYMED_HGLOBAL);
1400 hr = IDataObject_GetData(get, &fmt, &med);
1401 ok(hr == S_OK, "got %08x\n", hr);
1402 ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1403 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1404
1405 InitFormatEtc(fmt, cf_storage, TYMED_HGLOBAL | TYMED_ISTREAM);
1406 hr = IDataObject_GetData(get, &fmt, &med);
1407 ok(hr == S_OK, "got %08x\n", hr);
1408 ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1409 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1410
1411 InitFormatEtc(fmt, cf_storage, 0xffff);
1412 hr = IDataObject_GetData(get, &fmt, &med);
1413 ok(hr == S_OK, "got %08x\n", hr);
1414 ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1415 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1416
1417 /* complex format with target device */
1418
1419 InitFormatEtc(fmt, cf_another, 0xffff);
1420 hr = IDataObject_GetData(get, &fmt, &med);
1421 ok(hr == S_OK, "got %08x\n", hr);
1422 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1423
1424 if (0) /* Causes crashes on both Wine and Windows */
1425 {
1426 InitFormatEtc(fmt, cf_another, 0xffff);
1427 memset(&dm, 0, sizeof(dm));
1428 dm.dmSize = sizeof(dm);
1429 dm.dmDriverExtra = 0;
1431 fmt.ptd = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(DVTARGETDEVICE, tdData) + sizeof(device_name) + dm.dmSize + dm.dmDriverExtra);
1432 fmt.ptd->tdSize = FIELD_OFFSET(DVTARGETDEVICE, tdData) + sizeof(device_name) + dm.dmSize + dm.dmDriverExtra;
1433 fmt.ptd->tdDriverNameOffset = FIELD_OFFSET(DVTARGETDEVICE, tdData);
1434 fmt.ptd->tdDeviceNameOffset = 0;
1435 fmt.ptd->tdPortNameOffset = 0;
1436 fmt.ptd->tdExtDevmodeOffset = fmt.ptd->tdDriverNameOffset + sizeof(device_name);
1437 lstrcpyW((WCHAR*)fmt.ptd->tdData, device_name);
1438 memcpy(fmt.ptd->tdData + sizeof(device_name), &dm, dm.dmSize + dm.dmDriverExtra);
1439
1440 hr = IDataObject_GetData(get, &fmt, &med);
1441 ok(hr == S_OK, "got %08x\n", hr);
1442 ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1443 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1444
1445 HeapFree(GetProcessHeap(), 0, fmt.ptd);
1446 }
1447
1448 /* CF_ENHMETAFILE format */
1449 InitFormatEtc(fmt, CF_ENHMETAFILE, TYMED_ENHMF);
1450 hr = IDataObject_GetData(get, &fmt, &med);
1451 ok(hr == S_OK, "got %08x\n", hr);
1452 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1453
1454 IDataObject_Release(get);
1455 IDataObject_Release(src);
1456
1458 ok(hr == S_OK, "got %08x\n", hr);
1459
1461 ok(hr == S_OK, "got %08x\n", hr);
1462
1464 ok(hr == S_OK, "got %08x\n", hr);
1465 InitFormatEtc(fmt, CF_TEXT, TYMED_ISTORAGE);
1466 hr = IDataObject_GetData(get, &fmt, &med);
1467 ok(hr == S_OK, "got %08x\n", hr);
1468 ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1469 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1470 IDataObject_Release(get);
1471
1473 ok(hr == S_OK, "got %08x\n", hr);
1474
1476 ok(hr == S_OK, "got %08x\n", hr);
1477
1478 InitFormatEtc(fmt, CF_TEXT, TYMED_ISTORAGE);
1479 hr = IDataObject_GetData(get, &fmt, &med);
1480 ok(hr == S_OK, "got %08x\n", hr);
1481 ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1482 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1483
1484 InitFormatEtc(fmt, CF_TEXT, 0xffff);
1485 hr = IDataObject_GetData(get, &fmt, &med);
1486 ok(hr == S_OK, "got %08x\n", hr);
1487 ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1488 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1489
1490 IDataObject_Release(get);
1491 IDataObject_Release(src);
1492
1494}
1495
1497{
1499 char *p = GlobalLock(h);
1500 strcpy(p, "test");
1501 GlobalUnlock(h);
1502 return h;
1503}
1504
1505static HENHMETAFILE create_emf(void)
1506{
1507 const RECT rect = {0, 0, 100, 100};
1508 HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
1509 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
1510 return CloseEnhMetaFile(hdc);
1511}
1512
1513static void test_nonole_clipboard(void)
1514{
1515 HRESULT hr;
1516 BOOL r;
1518 IEnumFORMATETC *enum_fmt;
1519 FORMATETC fmt;
1520 HGLOBAL h, hblob, htext, hstorage;
1521 HENHMETAFILE emf;
1522 STGMEDIUM med;
1523 DWORD obj_type;
1524
1525 r = OpenClipboard(NULL);
1526 ok(r, "gle %d\n", GetLastError());
1527 r = EmptyClipboard();
1528 ok(r, "gle %d\n", GetLastError());
1529 r = CloseClipboard();
1530 ok(r, "gle %d\n", GetLastError());
1531
1533
1534 /* empty clipboard */
1536 ok(hr == S_OK, "got %08x\n", hr);
1537 hr = IDataObject_EnumFormatEtc(get, DATADIR_GET, &enum_fmt);
1538 ok(hr == S_OK, "got %08x\n", hr);
1539
1540 hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1541 ok(hr == S_FALSE, "got %08x\n", hr);
1542 IEnumFORMATETC_Release(enum_fmt);
1543
1544 IDataObject_Release(get);
1545
1546 /* set a user defined clipboard type */
1547
1548 htext = create_text();
1550 emf = create_emf();
1551 hstorage = create_storage();
1552
1553 r = OpenClipboard(NULL);
1554 ok(r, "gle %d\n", GetLastError());
1555 h = SetClipboardData(CF_TEXT, htext);
1556 ok(h == htext, "got %p\n", h);
1557 h = SetClipboardData(cf_onemore, hblob);
1558 ok(h == hblob, "got %p\n", h);
1560 ok(h == emf, "got %p\n", h);
1561 h = SetClipboardData(cf_storage, hstorage);
1562 ok(h == hstorage, "got %p\n", h);
1563 r = CloseClipboard();
1564 ok(r, "gle %d\n", GetLastError());
1565
1567 ok(hr == S_OK, "got %08x\n", hr);
1568 hr = IDataObject_EnumFormatEtc(get, DATADIR_GET, &enum_fmt);
1569 ok(hr == S_OK, "got %08x\n", hr);
1570 if (FAILED(hr))
1571 {
1572 skip("EnumFormatEtc failed, skipping tests.\n");
1573 return;
1574 }
1575
1576 hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1577 ok(hr == S_OK, "got %08x\n", hr);
1578 ok(fmt.cfFormat == CF_TEXT, "cf %04x\n", fmt.cfFormat);
1579 ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1580 ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1581 ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1582 ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
1583
1584 hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1585 ok(hr == S_OK, "got %08x\n", hr);
1586 ok(fmt.cfFormat == cf_onemore, "cf %04x\n", fmt.cfFormat);
1587 ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1588 ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1589 ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1590 ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
1591
1592 hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1593 ok(hr == S_OK, "got %08x\n", hr);
1594 ok(fmt.cfFormat == CF_ENHMETAFILE, "cf %04x\n", fmt.cfFormat);
1595 ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1596 ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1597 ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1598 ok(fmt.tymed == TYMED_ENHMF, "tymed %x\n", fmt.tymed);
1599
1600 hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1601 ok(hr == S_OK, "got %08x\n", hr);
1602 ok(fmt.cfFormat == cf_storage, "cf %04x\n", fmt.cfFormat);
1603 ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1604 ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1605 ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1606 ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
1607
1608 hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1609 ok(hr == S_OK, "got %08x\n", hr); /* User32 adds some synthesised formats */
1610
1611 ok(fmt.cfFormat == CF_LOCALE, "cf %04x\n", fmt.cfFormat);
1612 ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1613 ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1614 ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1615 todo_wine ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
1616
1617 hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1618 ok(hr == S_OK, "got %08x\n", hr);
1619
1620 ok(fmt.cfFormat == CF_OEMTEXT, "cf %04x\n", fmt.cfFormat);
1621 ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1622 ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1623 ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1624 ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
1625
1626 hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1627 ok(hr == S_OK, "got %08x\n", hr);
1628 ok(fmt.cfFormat == CF_UNICODETEXT, "cf %04x\n", fmt.cfFormat);
1629 ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1630 ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1631 ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1632 ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
1633
1634 hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1635 ok(hr == S_OK, "got %08x\n", hr);
1636 ok(fmt.cfFormat == CF_METAFILEPICT, "cf %04x\n", fmt.cfFormat);
1637 ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
1638 ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
1639 ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
1640 ok(fmt.tymed == TYMED_MFPICT, "tymed %x\n", fmt.tymed);
1641
1642 hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
1643 ok(hr == S_FALSE, "got %08x\n", hr);
1644 IEnumFORMATETC_Release(enum_fmt);
1645
1646 InitFormatEtc(fmt, CF_ENHMETAFILE, TYMED_ENHMF);
1647 hr = IDataObject_GetData(get, &fmt, &med);
1648 ok(hr == S_OK, "got %08x\n", hr);
1649 obj_type = GetObjectType(U(med).hEnhMetaFile);
1650 ok(obj_type == OBJ_ENHMETAFILE, "got %d\n", obj_type);
1651 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1652
1653 InitFormatEtc(fmt, cf_storage, TYMED_ISTORAGE);
1654 hr = IDataObject_GetData(get, &fmt, &med);
1655 ok(hr == S_OK, "got %08x\n", hr);
1656 ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1657 if(SUCCEEDED(hr)) ReleaseStgMedium(&med);
1658
1659 IDataObject_Release(get);
1660
1661 r = OpenClipboard(NULL);
1662 ok(r, "gle %d\n", GetLastError());
1663 r = EmptyClipboard();
1664 ok(r, "gle %d\n", GetLastError());
1665 r = CloseClipboard();
1666 ok(r, "gle %d\n", GetLastError());
1667
1669}
1670
1671static void test_getdatahere(void)
1672{
1673 HRESULT hr;
1674 IDataObject *src, *get;
1675 FORMATETC fmt;
1676 STGMEDIUM med;
1677
1679
1681 ok(hr == S_OK, "got %08x\n", hr);
1682
1684 ok(hr == S_OK, "got %08x\n", hr);
1685
1687 ok(hr == S_OK, "got %08x\n", hr);
1688
1689 /* global format -> global & stream */
1690
1693
1694 InitFormatEtc(fmt, CF_TEXT, TYMED_HGLOBAL);
1695
1696 med.pUnkForRelease = NULL;
1697 med.tymed = TYMED_HGLOBAL;
1698 U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 100);
1699 hr = IDataObject_GetDataHere(get, &fmt, &med);
1700 ok(hr == S_OK, "got %08x\n", hr);
1701 ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1702 ReleaseStgMedium(&med);
1705
1707
1708 med.pUnkForRelease = NULL;
1709 med.tymed = TYMED_HGLOBAL;
1710 U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 100);
1711 hr = IDataObject_GetDataHere(get, &fmt, &med);
1712 ok(hr == S_OK, "got %08x\n", hr);
1713 ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1714 ReleaseStgMedium(&med);
1717
1718 med.pUnkForRelease = NULL;
1719 med.tymed = TYMED_HGLOBAL;
1720 U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 1);
1721 hr = IDataObject_GetDataHere(get, &fmt, &med);
1722 ok(hr == E_FAIL, "got %08x\n", hr);
1723 ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1724 ReleaseStgMedium(&med);
1727
1728 med.pUnkForRelease = NULL;
1729 med.tymed = TYMED_ISTREAM;
1730 CreateStreamOnHGlobal(NULL, TRUE, &U(med).pstm);
1731 hr = IDataObject_GetDataHere(get, &fmt, &med);
1732 ok(hr == S_OK, "got %08x\n", hr);
1733 ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1734 ReleaseStgMedium(&med);
1737
1738 med.pUnkForRelease = NULL;
1739 med.tymed = TYMED_ISTORAGE;
1741 hr = IDataObject_GetDataHere(get, &fmt, &med);
1742 ok(hr == E_FAIL, "got %08x\n", hr);
1743 ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1744 ReleaseStgMedium(&med);
1747
1749
1750 med.pUnkForRelease = NULL;
1751 med.tymed = TYMED_HGLOBAL;
1752 U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 100);
1753 hr = IDataObject_GetDataHere(get, &fmt, &med);
1754 ok(hr == S_OK, "got %08x\n", hr);
1755 ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1756 ReleaseStgMedium(&med);
1759
1760 med.pUnkForRelease = NULL;
1761 med.tymed = TYMED_ISTREAM;
1762 CreateStreamOnHGlobal(NULL, TRUE, &U(med).pstm);
1763 hr = IDataObject_GetDataHere(get, &fmt, &med);
1764 ok(hr == S_OK, "got %08x\n", hr);
1765 ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1766 ReleaseStgMedium(&med);
1769
1770 med.pUnkForRelease = NULL;
1771 med.tymed = TYMED_ISTORAGE;
1773 hr = IDataObject_GetDataHere(get, &fmt, &med);
1774 ok(hr == E_FAIL, "got %08x\n", hr);
1775 ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1776 ReleaseStgMedium(&med);
1779
1781
1782 med.pUnkForRelease = NULL;
1783 med.tymed = TYMED_HGLOBAL;
1784 U(med).hGlobal = GlobalAlloc(GMEM_MOVEABLE, 3000);
1785 hr = IDataObject_GetDataHere(get, &fmt, &med);
1786 ok(hr == S_OK, "got %08x\n", hr);
1787 ok(med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed);
1788 ReleaseStgMedium(&med);
1791
1792 med.pUnkForRelease = NULL;
1793 med.tymed = TYMED_ISTREAM;
1794 CreateStreamOnHGlobal(NULL, TRUE, &U(med).pstm);
1795 hr = IDataObject_GetDataHere(get, &fmt, &med);
1796 ok(hr == S_OK, "got %08x\n", hr);
1797 ok(med.tymed == TYMED_ISTREAM, "got %x\n", med.tymed);
1798 ReleaseStgMedium(&med);
1801
1802 med.pUnkForRelease = NULL;
1803 med.tymed = TYMED_ISTORAGE;
1805 hr = IDataObject_GetDataHere(get, &fmt, &med);
1806 ok(hr == S_OK, "got %08x\n", hr);
1807 ok(med.tymed == TYMED_ISTORAGE, "got %x\n", med.tymed);
1808 ReleaseStgMedium(&med);
1811
1812
1813 IDataObject_Release(get);
1814 IDataObject_Release(src);
1815
1817
1818}
1819
1821{
1822 IDataObject *data_obj = arg;
1823
1824 IDataObject_Release(data_obj);
1825 return 0;
1826}
1827
1829{
1830 IDataObject *data_obj;
1831 HANDLE thread;
1832 HRESULT hr;
1833 DWORD ret;
1834
1836
1837 hr = OleGetClipboard(&data_obj);
1838 ok(hr == S_OK, "OleGetClipboard returned %x\n", hr);
1839
1840 thread = CreateThread(NULL, 0, test_data_obj, data_obj, 0, NULL);
1841 ok(thread != NULL, "CreateThread failed (%d)\n", GetLastError());
1843 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", ret);
1844
1845 hr = OleGetClipboard(&data_obj);
1846 ok(hr == S_OK, "OleGetClipboard returned %x\n", hr);
1847 IDataObject_Release(data_obj);
1848
1850}
1851
1853{
1854 HRESULT hr;
1855 IDataObject *pDObj;
1856
1858
1859 pDObj = (IDataObject *)0xdeadbeef;
1860 /* lock clipboard */
1862 hr = OleGetClipboard(&pDObj);
1863 todo_wine ok(hr == CLIPBRD_E_CANT_OPEN, "OleGetClipboard() got 0x%08x instead of 0x%08x\n", hr, CLIPBRD_E_CANT_OPEN);
1864 todo_wine ok(pDObj == NULL, "OleGetClipboard() got 0x%p instead of NULL\n",pDObj);
1865 if (pDObj) IDataObject_Release(pDObj);
1867
1869}
1870
1871START_TEST(clipboard)
1872{
1882}
#define CO_E_NOTINITIALIZED
static POBJECT_TYPE GetObjectType(IN PCWSTR TypeName)
Definition: ObTypes.c:15
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define stat
Definition: acwin.h:99
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
#define msg(x)
Definition: auth_time.c:54
#define CF_UNICODETEXT
Definition: constants.h:408
#define CF_METAFILEPICT
Definition: constants.h:398
#define CF_WAVE
Definition: constants.h:407
#define CF_LOCALE
Definition: constants.h:411
#define CF_ENHMETAFILE
Definition: constants.h:409
#define CF_TEXT
Definition: constants.h:396
#define CF_RIFF
Definition: constants.h:406
#define CF_OEMTEXT
Definition: constants.h:402
void get(int argc, const char *argv[])
Definition: cmds.c:480
#define U(x)
Definition: wordpad.c:45
static HANDLE thread
Definition: service.c:33
const GUID IID_IUnknown
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define GetProcessHeap()
Definition: compat.h:736
HANDLE HWND
Definition: compat.h:19
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CALLBACK
Definition: compat.h:35
#define lstrcpyW
Definition: compat.h:749
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
const WCHAR * text
Definition: package.c:1794
HRESULT WINAPI OleIsCurrentClipboard(IDataObject *data)
Definition: clipboard.c:2328
HRESULT WINAPI OleSetClipboard(IDataObject *data)
Definition: clipboard.c:2199
static snapshot * impl_from_IDataObject(IDataObject *iface)
Definition: clipboard.c:159
static const char * dump_fmtetc(FORMATETC *fmt)
Definition: clipboard.c:217
static enum_fmtetc * impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
Definition: clipboard.c:238
HRESULT WINAPI OleFlushClipboard(void)
Definition: clipboard.c:2293
HRESULT WINAPI OleGetClipboard(IDataObject **obj)
Definition: clipboard.c:2249
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1964
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
HRESULT WINAPI CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm)
HRESULT WINAPI DECLSPEC_HOTPATCH OleInitialize(LPVOID reserved)
Definition: ole2.c:169
void WINAPI ReleaseStgMedium(STGMEDIUM *pmedium)
Definition: ole2.c:2033
void WINAPI DECLSPEC_HOTPATCH OleUninitialize(void)
Definition: ole2.c:230
HRESULT WINAPI StgCreateDocfileOnILockBytes(ILockBytes *plkbyt, DWORD grfMode, DWORD reserved, IStorage **ppstgOpen)
Definition: storage32.c:8946
HRESULT WINAPI StgCreateDocfile(LPCOLESTR pwcsName, DWORD grfMode, DWORD reserved, IStorage **ppstgOpen)
Definition: storage32.c:8636
struct EnumFormatImpl EnumFormatImpl
static ULONG WINAPI EnumFormatImpl_AddRef(IEnumFORMATETC *iface)
Definition: clipboard.c:76
static HRESULT WINAPI DataObjectImpl_GetDataHere(IDataObject *iface, FORMATETC *pformatetc, STGMEDIUM *pmedium)
Definition: clipboard.c:241
static ULONG WINAPI DataObjectImpl_AddRef(IDataObject *iface)
Definition: clipboard.c:193
static HRESULT WINAPI EnumFormatImpl_Skip(IEnumFORMATETC *iface, ULONG celt)
Definition: clipboard.c:118
static HRESULT EnumFormatImpl_Create(const FORMATETC *fmtetc, UINT size, LPENUMFORMATETC *lplpformatetc)
static ULONG WINAPI EnumFormatImpl_Release(IEnumFORMATETC *iface)
Definition: clipboard.c:84
static const IDataObjectVtbl VT_DataObjectImpl
Definition: clipboard.c:326
static HRESULT WINAPI DataObjectImpl_QueryGetData(IDataObject *iface, FORMATETC *pformatetc)
Definition: clipboard.c:248
static HRESULT WINAPI EnumFormatImpl_Next(IEnumFORMATETC *iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched)
Definition: clipboard.c:98
static HRESULT WINAPI DataObjectImpl_DAdvise(IDataObject *iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
Definition: clipboard.c:304
static HRESULT WINAPI DataObjectImpl_QueryInterface(IDataObject *iface, REFIID riid, LPVOID *ppvObj)
Definition: clipboard.c:179
static HRESULT WINAPI DataObjectImpl_DUnadvise(IDataObject *iface, DWORD dwConnection)
Definition: clipboard.c:312
static HRESULT WINAPI DataObjectImpl_EnumFormatEtc(IDataObject *iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
Definition: clipboard.c:289
static ULONG WINAPI DataObjectImpl_Release(IDataObject *iface)
Definition: clipboard.c:201
static HRESULT WINAPI DataObjectImpl_GetData(IDataObject *iface, FORMATETC *pformatetc, STGMEDIUM *pmedium)
Definition: clipboard.c:217
static HRESULT WINAPI DataObjectImpl_GetCanonicalFormatEtc(IDataObject *iface, FORMATETC *pformatetcIn, FORMATETC *pformatetcOut)
Definition: clipboard.c:268
static HRESULT WINAPI EnumFormatImpl_Clone(IEnumFORMATETC *iface, IEnumFORMATETC **ppenum)
Definition: clipboard.c:138
static HRESULT WINAPI DataObjectImpl_EnumDAdvise(IDataObject *iface, IEnumSTATDATA **ppenumAdvise)
Definition: clipboard.c:319
static HRESULT WINAPI EnumFormatImpl_QueryInterface(IEnumFORMATETC *iface, REFIID riid, LPVOID *ppvObj)
Definition: clipboard.c:62
static HRESULT WINAPI DataObjectImpl_SetData(IDataObject *iface, FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
Definition: clipboard.c:281
static HRESULT WINAPI EnumFormatImpl_Reset(IEnumFORMATETC *iface)
Definition: clipboard.c:129
struct DataObjectImpl DataObjectImpl
static const IEnumFORMATETCVtbl VT_EnumFormatImpl
Definition: clipboard.c:152
#define InitFormatEtc(fe, cf, med)
Definition: editor.h:32
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLfloat GLfloat p
Definition: glext.h:8902
GLenum target
Definition: glext.h:7315
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
SIZE_T NTAPI GlobalSize(HGLOBAL hMem)
Definition: heapmem.c:1090
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define d
Definition: ke_i.h:81
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
HRESULT WINAPI GetHGlobalFromILockBytes(ILockBytes *iface, HGLOBAL *phglobal)
Definition: memlockbytes.c:145
HRESULT WINAPI CreateILockBytesOnHGlobal(HGLOBAL global, BOOL delete_on_release, ILockBytes **ret)
Definition: memlockbytes.c:98
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static PVOID ptr
Definition: dispmode.c:27
#define sprintf(buf, format,...)
Definition: sprintf.c:55
HDC hdc
Definition: main.c:9
static HDC
Definition: imagelist.c:88
static struct fmt fmts[]
#define todo_wine
Definition: custom.c:89
static LPDATAOBJECT clip_data
Definition: clipboard.c:1034
static HRESULT DataObjectImpl_CreateText(LPCSTR text, LPDATAOBJECT *lplpdataobj)
Definition: clipboard.c:437
static UINT wm_drawclipboard
Definition: clipboard.c:1036
static HGLOBAL create_text(void)
Definition: clipboard.c:1496
static ULONG DataObjectImpl_GetData_calls
Definition: clipboard.c:78
static const char * cmpl_stm_data
Definition: clipboard.c:445
static void test_nonole_clipboard(void)
Definition: clipboard.c:1513
static HMETAFILE create_mf(void)
Definition: clipboard.c:86
static UINT cf_onemore
Definition: clipboard.c:82
static void test_cf_dataobject(IDataObject *data)
Definition: clipboard.c:716
static HGLOBAL create_storage(void)
Definition: clipboard.c:1289
static HENHMETAFILE create_emf(void)
Definition: clipboard.c:1505
static ULONG DataObjectImpl_EnumFormatEtc_calls
Definition: clipboard.c:80
static void test_enum_fmtetc(IDataObject *src)
Definition: clipboard.c:610
static void test_consumer_refs(void)
Definition: clipboard.c:1138
static const WCHAR device_name[]
Definition: clipboard.c:447
static HRESULT DataObjectImpl_CreateFromHGlobal(HGLOBAL text, LPDATAOBJECT *dataobj)
Definition: clipboard.c:417
static BOOL expect_DataObjectImpl_QueryGetData
Definition: clipboard.c:77
static DWORD CALLBACK test_data_obj(void *arg)
Definition: clipboard.c:1820
static const char * cmpl_text_data
Definition: clipboard.c:446
static HRESULT DataObjectImpl_CreateComplex(LPDATAOBJECT *lplpdataobj)
Definition: clipboard.c:449
static UINT cf_storage
Definition: clipboard.c:82
static void test_no_cf_dataobject(void)
Definition: clipboard.c:701
static UINT cf_another
Definition: clipboard.c:82
static void test_getdatahere(void)
Definition: clipboard.c:1671
static void test_get_clipboard_locked(void)
Definition: clipboard.c:1852
static void test_complex_get_clipboard(void)
Definition: clipboard.c:870
static UINT cf_stream
Definition: clipboard.c:82
static void test_multithreaded_clipboard(void)
Definition: clipboard.c:1828
static void test_get_clipboard(void)
Definition: clipboard.c:515
static UINT cf_global
Definition: clipboard.c:82
static ULONG count_refs(IDataObject *d)
Definition: clipboard.c:1132
static void test_set_clipboard_DRAWCLIPBOARD(void)
Definition: clipboard.c:1078
static void test_flushed_getdata(void)
Definition: clipboard.c:1307
static void test_set_clipboard(void)
Definition: clipboard.c:908
static LRESULT CALLBACK clipboard_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
Definition: clipboard.c:1038
static DWORD CALLBACK set_clipboard_thread(void *arg)
Definition: clipboard.c:1068
static void test_get_clipboard_uninitialized(void)
Definition: clipboard.c:504
static HWND next_wnd
Definition: clipboard.c:1035
static ULONG DataObjectImpl_GetDataHere_calls
Definition: clipboard.c:79
static HMETAFILEPICT create_metafilepict(void)
Definition: clipboard.c:94
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
static LPUNKNOWN
Definition: ndr_ole.c:49
#define STGM_CREATE
Definition: objbase.h:926
#define STGM_READWRITE
Definition: objbase.h:919
#define STGM_SHARE_EXCLUSIVE
Definition: objbase.h:923
#define STGM_DELETEONRELEASE
Definition: objbase.h:925
interface IEnumFORMATETC * LPENUMFORMATETC
Definition: objfwd.h:24
interface IDataObject * LPDATAOBJECT
Definition: objfwd.h:21
#define OBJ_ENHMETAFILE
Definition: objidl.idl:1421
const GUID IID_IEnumFORMATETC
const GUID IID_IDataObject
long LONG
Definition: pedump.c:60
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define REFIID
Definition: guiddef.h:118
int winetest_debug
#define win_skip
Definition: test.h:163
#define memset(x, y, z)
Definition: compat.h:39
HRESULT hr
Definition: shlfolder.c:183
& rect
Definition: startmenu.cpp:1413
HMETAFILEPICT hmfp
Definition: clipboard.c:64
IStorage * stg
Definition: clipboard.c:63
HANDLE text
Definition: clipboard.c:61
IStream * stm
Definition: clipboard.c:62
FORMATETC * fmtetc
Definition: clipboard.c:33
IDataObject IDataObject_iface
Definition: clipboard.c:30
UINT fmtetc_cnt
Definition: clipboard.c:34
IEnumFORMATETC IEnumFORMATETC_iface
Definition: clipboard.c:41
FORMATETC * fmtetc
Definition: clipboard.c:44
UINT fmtetc_cnt
Definition: clipboard.c:45
HINSTANCE hInstance
Definition: winuser.h:3170
LPCSTR lpszClassName
Definition: winuser.h:3175
WNDPROC lpfnWndProc
Definition: winuser.h:3167
WCHAR dmDeviceName[CCHDEVICENAME]
Definition: wingdi.h:1617
WORD dmDriverExtra
Definition: wingdi.h:1621
WORD dmSize
Definition: wingdi.h:1620
Definition: tftpd.h:126
Definition: tftpd.h:138
Definition: emfdc.c:45
Definition: dsound.c:943
IDataObject IDataObject_iface
Definition: usrmarshal.c:1273
Definition: send.c:48
Definition: stat.h:55
HMETAFILE hMF
Definition: wingdi.h:2608
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define DWORD_PTR
Definition: treelist.c:76
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
int ret
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define GMEM_ZEROINIT
Definition: winbase.h:331
#define WAIT_OBJECT_0
Definition: winbase.h:431
#define GMEM_MOVEABLE
Definition: winbase.h:319
#define GMEM_DDESHARE
Definition: winbase.h:323
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
_In_ FONTOBJ _In_ ULONG _In_ HGLYPH hg
Definition: winddi.h:3871
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
void * arg
Definition: msvc.h:10
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define E_NOINTERFACE
Definition: winerror.h:2364
#define DV_E_TYMED
Definition: winerror.h:2638
#define DV_E_CLIPFORMAT
Definition: winerror.h:2639
#define CLIPBRD_E_CANT_OPEN
Definition: winerror.h:2766
#define DV_E_FORMATETC
Definition: winerror.h:2633
#define DV_E_LINDEX
Definition: winerror.h:2637
BOOL WINAPI DeleteMetaFile(_In_ HMETAFILE)
HDC WINAPI CreateMetaFileA(_In_opt_ LPCSTR)
#define MM_ANISOTROPIC
Definition: wingdi.h:867
HMETAFILE WINAPI CloseMetaFile(_In_ HDC hdc)
BOOL WINAPI ExtTextOutA(_In_ HDC hdc, _In_ int x, _In_ int y, _In_ UINT options, _In_opt_ const RECT *lprect, _In_reads_opt_(c) LPCSTR lpString, _In_ UINT c, _In_reads_opt_(c) const INT *lpDx)
HDC WINAPI CreateEnhMetaFileA(_In_opt_ HDC, _In_opt_ LPCSTR, _In_opt_ LPCRECT, _In_opt_ LPCSTR)
#define ETO_OPAQUE
Definition: wingdi.h:647
HENHMETAFILE WINAPI CloseEnhMetaFile(_In_ HDC hdc)
LRESULT WINAPI DefWindowProcA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define CreateWindowA(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4318
#define WM_DRAWCLIPBOARD
Definition: winuser.h:1872
HANDLE WINAPI SetClipboardData(_In_ UINT, _In_opt_ HANDLE)
BOOL WINAPI CloseClipboard(void)
Definition: ntwrapper.h:178
HWND WINAPI GetClipboardOwner(void)
Definition: ntwrapper.h:196
LRESULT WINAPI SendMessageA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
BOOL WINAPI OpenClipboard(_In_opt_ HWND)
UINT WINAPI EnumClipboardFormats(_In_ UINT)
#define WM_CHANGECBCHAIN
Definition: winuser.h:1877
HANDLE WINAPI GetClipboardData(_In_ UINT)
HWND WINAPI SetClipboardViewer(_In_ HWND)
HWND WINAPI GetDesktopWindow(void)
Definition: window.c:628
ATOM WINAPI RegisterClassA(_In_ CONST WNDCLASSA *)
BOOL WINAPI ChangeClipboardChain(_In_ HWND, _In_ HWND)
BOOL WINAPI EmptyClipboard(void)
Definition: ntwrapper.h:190
#define WM_USER
Definition: winuser.h:1898
UINT WINAPI RegisterClipboardFormatA(_In_ LPCSTR)
BOOL WINAPI DestroyWindow(_In_ HWND)
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180