4 * Copyright 2006 Kevin Koltzau
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.
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.
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
29 #include "wine/test.h"
31 #define InitFormatEtc(fe, cf, med) \
34 (fe).dwAspect=DVASPECT_CONTENT;\
40 typedef struct DataObjectImpl
{
41 const IDataObjectVtbl
*lpVtbl
;
50 typedef struct EnumFormatImpl
{
51 const IEnumFORMATETCVtbl
*lpVtbl
;
60 static HRESULT
EnumFormatImpl_Create(FORMATETC
*fmtetc
, UINT size
, LPENUMFORMATETC
*lplpformatetc
);
62 static HRESULT WINAPI
EnumFormatImpl_QueryInterface(IEnumFORMATETC
*iface
, REFIID riid
, LPVOID
*ppvObj
)
64 EnumFormatImpl
*This
= (EnumFormatImpl
*)iface
;
66 if (IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_IEnumFORMATETC
)) {
67 IEnumFORMATETC_AddRef(iface
);
68 *ppvObj
= (LPVOID
)This
;
75 static ULONG WINAPI
EnumFormatImpl_AddRef(IEnumFORMATETC
*iface
)
77 EnumFormatImpl
*This
= (EnumFormatImpl
*)iface
;
78 LONG ref
= InterlockedIncrement(&This
->ref
);
82 static ULONG WINAPI
EnumFormatImpl_Release(IEnumFORMATETC
*iface
)
84 EnumFormatImpl
*This
= (EnumFormatImpl
*)iface
;
85 ULONG ref
= InterlockedDecrement(&This
->ref
);
88 HeapFree(GetProcessHeap(), 0, This
->fmtetc
);
89 HeapFree(GetProcessHeap(), 0, This
);
95 static HRESULT WINAPI
EnumFormatImpl_Next(IEnumFORMATETC
*iface
, ULONG celt
,
96 FORMATETC
*rgelt
, ULONG
*pceltFetched
)
98 EnumFormatImpl
*This
= (EnumFormatImpl
*)iface
;
104 count
= min(celt
, This
->fmtetc_cnt
-This
->cur
);
106 memcpy(rgelt
, This
->fmtetc
+This
->cur
, count
*sizeof(FORMATETC
));
110 *pceltFetched
= count
;
111 return count
== celt
? S_OK
: S_FALSE
;
114 static HRESULT WINAPI
EnumFormatImpl_Skip(IEnumFORMATETC
*iface
, ULONG celt
)
116 ok(0, "unexpected call\n");
120 static HRESULT WINAPI
EnumFormatImpl_Reset(IEnumFORMATETC
*iface
)
122 EnumFormatImpl
*This
= (EnumFormatImpl
*)iface
;
128 static HRESULT WINAPI
EnumFormatImpl_Clone(IEnumFORMATETC
*iface
, IEnumFORMATETC
**ppenum
)
130 ok(0, "unexpected call\n");
134 static const IEnumFORMATETCVtbl VT_EnumFormatImpl
= {
135 EnumFormatImpl_QueryInterface
,
136 EnumFormatImpl_AddRef
,
137 EnumFormatImpl_Release
,
140 EnumFormatImpl_Reset
,
144 static HRESULT
EnumFormatImpl_Create(FORMATETC
*fmtetc
, UINT fmtetc_cnt
, IEnumFORMATETC
**lplpformatetc
)
148 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(EnumFormatImpl
));
149 ret
->lpVtbl
= &VT_EnumFormatImpl
;
152 ret
->fmtetc_cnt
= fmtetc_cnt
;
153 ret
->fmtetc
= HeapAlloc(GetProcessHeap(), 0, fmtetc_cnt
*sizeof(FORMATETC
));
154 memcpy(ret
->fmtetc
, fmtetc
, fmtetc_cnt
*sizeof(FORMATETC
));
155 *lplpformatetc
= (LPENUMFORMATETC
)ret
;
159 static HRESULT WINAPI
DataObjectImpl_QueryInterface(IDataObject
*iface
, REFIID riid
, LPVOID
*ppvObj
)
161 DataObjectImpl
*This
= (DataObjectImpl
*)iface
;
163 if (IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_IDataObject
)) {
164 IDataObject_AddRef(iface
);
165 *ppvObj
= (LPVOID
)This
;
169 return E_NOINTERFACE
;
172 static ULONG WINAPI
DataObjectImpl_AddRef(IDataObject
* iface
)
174 DataObjectImpl
*This
= (DataObjectImpl
*)iface
;
175 ULONG ref
= InterlockedIncrement(&This
->ref
);
179 static ULONG WINAPI
DataObjectImpl_Release(IDataObject
* iface
)
181 DataObjectImpl
*This
= (DataObjectImpl
*)iface
;
182 ULONG ref
= InterlockedDecrement(&This
->ref
);
185 if(This
->text
) GlobalFree(This
->text
);
186 if(This
->fmtetc
) GlobalFree(This
->fmtetc
);
187 HeapFree(GetProcessHeap(), 0, This
);
193 static HRESULT WINAPI
DataObjectImpl_GetData(IDataObject
* iface
, FORMATETC
*pformatetc
, STGMEDIUM
*pmedium
)
195 DataObjectImpl
*This
= (DataObjectImpl
*)iface
;
197 if(pformatetc
->lindex
!= -1)
200 if(!(pformatetc
->tymed
& TYMED_HGLOBAL
))
203 if(This
->text
&& pformatetc
->cfFormat
== CF_TEXT
)
204 U(*pmedium
).hGlobal
= This
->text
;
206 return DV_E_FORMATETC
;
208 pmedium
->tymed
= TYMED_HGLOBAL
;
209 pmedium
->pUnkForRelease
= (LPUNKNOWN
)iface
;
210 IUnknown_AddRef(pmedium
->pUnkForRelease
);
214 static HRESULT WINAPI
DataObjectImpl_GetDataHere(IDataObject
* iface
, FORMATETC
*pformatetc
, STGMEDIUM
*pmedium
)
216 ok(0, "unexpected call\n");
220 static HRESULT WINAPI
DataObjectImpl_QueryGetData(IDataObject
* iface
, FORMATETC
*pformatetc
)
222 DataObjectImpl
*This
= (DataObjectImpl
*)iface
;
224 BOOL foundFormat
= FALSE
;
226 if(pformatetc
->lindex
!= -1)
229 for(i
=0; i
<This
->fmtetc_cnt
; i
++) {
230 if(This
->fmtetc
[i
].cfFormat
== pformatetc
->cfFormat
) {
232 if(This
->fmtetc
[i
].tymed
== pformatetc
->tymed
)
236 return foundFormat
?DV_E_FORMATETC
:DV_E_TYMED
;
239 static HRESULT WINAPI
DataObjectImpl_GetCanonicalFormatEtc(IDataObject
* iface
, FORMATETC
*pformatectIn
,
240 FORMATETC
*pformatetcOut
)
242 ok(0, "unexpected call\n");
246 static HRESULT WINAPI
DataObjectImpl_SetData(IDataObject
* iface
, FORMATETC
*pformatetc
,
247 STGMEDIUM
*pmedium
, BOOL fRelease
)
249 ok(0, "unexpected call\n");
253 static HRESULT WINAPI
DataObjectImpl_EnumFormatEtc(IDataObject
* iface
, DWORD dwDirection
,
254 IEnumFORMATETC
**ppenumFormatEtc
)
256 DataObjectImpl
*This
= (DataObjectImpl
*)iface
;
258 if(dwDirection
!= DATADIR_GET
) {
259 ok(0, "unexpected direction %d\n", dwDirection
);
262 return EnumFormatImpl_Create(This
->fmtetc
, This
->fmtetc_cnt
, ppenumFormatEtc
);
265 static HRESULT WINAPI
DataObjectImpl_DAdvise(IDataObject
* iface
, FORMATETC
*pformatetc
, DWORD advf
,
266 IAdviseSink
*pAdvSink
, DWORD
*pdwConnection
)
268 ok(0, "unexpected call\n");
272 static HRESULT WINAPI
DataObjectImpl_DUnadvise(IDataObject
* iface
, DWORD dwConnection
)
274 ok(0, "unexpected call\n");
278 static HRESULT WINAPI
DataObjectImpl_EnumDAdvise(IDataObject
* iface
, IEnumSTATDATA
**ppenumAdvise
)
280 ok(0, "unexpected call\n");
284 static const IDataObjectVtbl VT_DataObjectImpl
=
286 DataObjectImpl_QueryInterface
,
287 DataObjectImpl_AddRef
,
288 DataObjectImpl_Release
,
289 DataObjectImpl_GetData
,
290 DataObjectImpl_GetDataHere
,
291 DataObjectImpl_QueryGetData
,
292 DataObjectImpl_GetCanonicalFormatEtc
,
293 DataObjectImpl_SetData
,
294 DataObjectImpl_EnumFormatEtc
,
295 DataObjectImpl_DAdvise
,
296 DataObjectImpl_DUnadvise
,
297 DataObjectImpl_EnumDAdvise
300 static HRESULT
DataObjectImpl_CreateText(LPCSTR text
, LPDATAOBJECT
*lplpdataobj
)
304 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(DataObjectImpl
));
305 obj
->lpVtbl
= &VT_DataObjectImpl
;
307 obj
->text
= GlobalAlloc(GMEM_MOVEABLE
, strlen(text
) + 1);
308 strcpy(GlobalLock(obj
->text
), text
);
309 GlobalUnlock(obj
->text
);
312 obj
->fmtetc
= HeapAlloc(GetProcessHeap(), 0, obj
->fmtetc_cnt
*sizeof(FORMATETC
));
313 InitFormatEtc(obj
->fmtetc
[0], CF_TEXT
, TYMED_HGLOBAL
);
315 *lplpdataobj
= (LPDATAOBJECT
)obj
;
319 static void test_set_clipboard(void)
323 LPDATAOBJECT data1
, data2
;
324 hr
= DataObjectImpl_CreateText("data1", &data1
);
325 ok(SUCCEEDED(hr
), "Failed to create data1 object: 0x%08x\n", hr
);
328 hr
= DataObjectImpl_CreateText("data2", &data2
);
329 ok(SUCCEEDED(hr
), "Failed to create data2 object: 0x%08x\n", hr
);
333 hr
= OleSetClipboard(data1
);
335 ok(hr
== CO_E_NOTINITIALIZED
, "OleSetClipboard should have failed with CO_E_NOTINITIALIZED instead of 0x%08x\n", hr
);
338 hr
= OleSetClipboard(data1
);
340 ok(hr
== CO_E_NOTINITIALIZED
, "OleSetClipboard should have failed with CO_E_NOTINITIALIZED instead of 0x%08x\n", hr
);
343 hr
= OleInitialize(NULL
);
344 ok(hr
== S_OK
, "OleInitialize failed with error 0x%08x\n", hr
);
346 hr
= OleSetClipboard(data1
);
347 ok(hr
== S_OK
, "failed to set clipboard to data1, hr = 0x%08x\n", hr
);
348 hr
= OleIsCurrentClipboard(data1
);
349 ok(hr
== S_OK
, "expected current clipboard to be data1, hr = 0x%08x\n", hr
);
350 hr
= OleIsCurrentClipboard(data2
);
351 ok(hr
== S_FALSE
, "did not expect current clipboard to be data2, hr = 0x%08x\n", hr
);
353 hr
= OleSetClipboard(data2
);
354 ok(hr
== S_OK
, "failed to set clipboard to data2, hr = 0x%08x\n", hr
);
355 hr
= OleIsCurrentClipboard(data1
);
356 ok(hr
== S_FALSE
, "did not expect current clipboard to be data1, hr = 0x%08x\n", hr
);
357 hr
= OleIsCurrentClipboard(data2
);
358 ok(hr
== S_OK
, "expected current clipboard to be data2, hr = 0x%08x\n", hr
);
360 hr
= OleFlushClipboard();
361 ok(hr
== S_OK
, "failed to flush clipboard, hr = 0x%08x\n", hr
);
362 hr
= OleIsCurrentClipboard(data1
);
363 ok(hr
== S_FALSE
, "did not expect current clipboard to be data1, hr = 0x%08x\n", hr
);
364 hr
= OleIsCurrentClipboard(data2
);
365 ok(hr
== S_FALSE
, "did not expect current clipboard to be data2, hr = 0x%08x\n", hr
);
367 ok(OleSetClipboard(NULL
) == S_OK
, "failed to clear clipboard, hr = 0x%08x\n", hr
);
369 ref
= IDataObject_Release(data1
);
370 ok(ref
== 0, "expected data1 ref=0, got %d\n", ref
);
371 ref
= IDataObject_Release(data2
);
372 ok(ref
== 0, "expected data2 ref=0, got %d\n", ref
);
378 START_TEST(clipboard
)
380 test_set_clipboard();