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 ok(0, "unexpected call\n");
126 static HRESULT WINAPI EnumFormatImpl_Clone(IEnumFORMATETC *iface, IEnumFORMATETC **ppenum)
128 ok(0, "unexpected call\n");
132 static const IEnumFORMATETCVtbl VT_EnumFormatImpl = {
133 EnumFormatImpl_QueryInterface,
134 EnumFormatImpl_AddRef,
135 EnumFormatImpl_Release,
138 EnumFormatImpl_Reset,
142 static HRESULT EnumFormatImpl_Create(FORMATETC *fmtetc, UINT fmtetc_cnt, IEnumFORMATETC **lplpformatetc)
146 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumFormatImpl));
147 ret->lpVtbl = &VT_EnumFormatImpl;
150 ret->fmtetc_cnt = fmtetc_cnt;
151 ret->fmtetc = HeapAlloc(GetProcessHeap(), 0, fmtetc_cnt*sizeof(FORMATETC));
152 memcpy(ret->fmtetc, fmtetc, fmtetc_cnt*sizeof(FORMATETC));
153 *lplpformatetc = (LPENUMFORMATETC)ret;
157 static HRESULT WINAPI DataObjectImpl_QueryInterface(IDataObject *iface, REFIID riid, LPVOID *ppvObj)
159 DataObjectImpl *This = (DataObjectImpl*)iface;
161 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDataObject)) {
162 IDataObject_AddRef(iface);
163 *ppvObj = (LPVOID)This;
167 return E_NOINTERFACE;
170 static ULONG WINAPI DataObjectImpl_AddRef(IDataObject* iface)
172 DataObjectImpl *This = (DataObjectImpl*)iface;
173 ULONG ref = InterlockedIncrement(&This->ref);
177 static ULONG WINAPI DataObjectImpl_Release(IDataObject* iface)
179 DataObjectImpl *This = (DataObjectImpl*)iface;
180 ULONG ref = InterlockedDecrement(&This->ref);
183 if(This->text) GlobalFree(This->text);
184 if(This->fmtetc) GlobalFree(This->fmtetc);
185 HeapFree(GetProcessHeap(), 0, This);
191 static HRESULT WINAPI DataObjectImpl_GetData(IDataObject* iface, FORMATETC *pformatetc, STGMEDIUM *pmedium)
193 DataObjectImpl *This = (DataObjectImpl*)iface;
195 if(pformatetc->lindex != -1)
198 if(!(pformatetc->tymed & TYMED_HGLOBAL))
201 if(This->text && pformatetc->cfFormat == CF_TEXT)
202 U(*pmedium).hGlobal = This->text;
204 return DV_E_FORMATETC;
206 pmedium->tymed = TYMED_HGLOBAL;
207 pmedium->pUnkForRelease = (LPUNKNOWN)iface;
208 IUnknown_AddRef(pmedium->pUnkForRelease);
212 static HRESULT WINAPI DataObjectImpl_GetDataHere(IDataObject* iface, FORMATETC *pformatetc, STGMEDIUM *pmedium)
214 ok(0, "unexpected call\n");
218 static HRESULT WINAPI DataObjectImpl_QueryGetData(IDataObject* iface, FORMATETC *pformatetc)
220 DataObjectImpl *This = (DataObjectImpl*)iface;
222 BOOL foundFormat = FALSE;
224 if(pformatetc->lindex != -1)
227 for(i=0; i<This->fmtetc_cnt; i++) {
228 if(This->fmtetc[i].cfFormat == pformatetc->cfFormat) {
230 if(This->fmtetc[i].tymed == pformatetc->tymed)
234 return foundFormat?DV_E_FORMATETC:DV_E_TYMED;
237 static HRESULT WINAPI DataObjectImpl_GetCanonicalFormatEtc(IDataObject* iface, FORMATETC *pformatectIn,
238 FORMATETC *pformatetcOut)
240 ok(0, "unexpected call\n");
244 static HRESULT WINAPI DataObjectImpl_SetData(IDataObject* iface, FORMATETC *pformatetc,
245 STGMEDIUM *pmedium, BOOL fRelease)
247 ok(0, "unexpected call\n");
251 static HRESULT WINAPI DataObjectImpl_EnumFormatEtc(IDataObject* iface, DWORD dwDirection,
252 IEnumFORMATETC **ppenumFormatEtc)
254 DataObjectImpl *This = (DataObjectImpl*)iface;
256 if(dwDirection != DATADIR_GET) {
257 ok(0, "unexpected direction %d\n", dwDirection);
260 return EnumFormatImpl_Create(This->fmtetc, This->fmtetc_cnt, ppenumFormatEtc);
263 static HRESULT WINAPI DataObjectImpl_DAdvise(IDataObject* iface, FORMATETC *pformatetc, DWORD advf,
264 IAdviseSink *pAdvSink, DWORD *pdwConnection)
266 ok(0, "unexpected call\n");
270 static HRESULT WINAPI DataObjectImpl_DUnadvise(IDataObject* iface, DWORD dwConnection)
272 ok(0, "unexpected call\n");
276 static HRESULT WINAPI DataObjectImpl_EnumDAdvise(IDataObject* iface, IEnumSTATDATA **ppenumAdvise)
278 ok(0, "unexpected call\n");
282 static const IDataObjectVtbl VT_DataObjectImpl =
284 DataObjectImpl_QueryInterface,
285 DataObjectImpl_AddRef,
286 DataObjectImpl_Release,
287 DataObjectImpl_GetData,
288 DataObjectImpl_GetDataHere,
289 DataObjectImpl_QueryGetData,
290 DataObjectImpl_GetCanonicalFormatEtc,
291 DataObjectImpl_SetData,
292 DataObjectImpl_EnumFormatEtc,
293 DataObjectImpl_DAdvise,
294 DataObjectImpl_DUnadvise,
295 DataObjectImpl_EnumDAdvise
298 static HRESULT DataObjectImpl_CreateText(LPCSTR text, LPDATAOBJECT *lplpdataobj)
302 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(DataObjectImpl));
303 obj->lpVtbl = &VT_DataObjectImpl;
305 obj->text = GlobalAlloc(GMEM_MOVEABLE, strlen(text) + 1);
306 strcpy(GlobalLock(obj->text), text);
307 GlobalUnlock(obj->text);
310 obj->fmtetc = HeapAlloc(GetProcessHeap(), 0, obj->fmtetc_cnt*sizeof(FORMATETC));
311 InitFormatEtc(obj->fmtetc[0], CF_TEXT, TYMED_HGLOBAL);
313 *lplpdataobj = (LPDATAOBJECT)obj;
317 static void test_set_clipboard(void)
321 LPDATAOBJECT data1, data2;
322 hr = DataObjectImpl_CreateText("data1", &data1);
323 ok(SUCCEEDED(hr), "Failed to create data1 object: %d\n", hr);
326 hr = DataObjectImpl_CreateText("data2", &data2);
327 ok(SUCCEEDED(hr), "Failed to create data2 object: %d\n", hr);
331 ok(OleSetClipboard(data1) == S_OK, "failed to set clipboard to data1\n");
332 ok(OleIsCurrentClipboard(data1) == S_OK, "expected current clipboard to be data1\n");
333 ok(OleIsCurrentClipboard(data2) == S_FALSE, "did not expect current clipboard to be data2\n");
335 ok(OleSetClipboard(data2) == S_OK, "failed to set clipboard to data2\n");
336 ok(OleIsCurrentClipboard(data1) == S_FALSE, "did not expect current clipboard to be data1\n");
337 ok(OleIsCurrentClipboard(data2) == S_OK, "expected current clipboard to be data2\n");
339 ok(OleFlushClipboard() == S_OK, "failed to flush clipboard\n");
340 ok(OleIsCurrentClipboard(data1) == S_FALSE, "did not expect current clipboard to be data1\n");
341 ok(OleIsCurrentClipboard(data2) == S_FALSE, "did not expect current clipboard to be data2\n");
343 ok(OleSetClipboard(NULL) == S_OK, "failed to clear clipboard\n");
345 ref = IDataObject_Release(data1);
346 ok(ref == 0, "expected data1 ref=0, got %d\n", ref);
347 ref = IDataObject_Release(data2);
348 ok(ref == 0, "expected data2 ref=0, got %d\n", ref);
352 START_TEST(clipboard)
354 test_set_clipboard();