server: Allow opening the clipboard again with the same owner.
[wine.git] / dlls / user32 / tests / clipboard.c
bloba9aef8429777c7fb025137fab329f2df07642a24
1 /*
2 * Unit test suite for clipboard functions.
4 * Copyright 2002 Dmitry Timoshkov
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
21 #include "wine/test.h"
22 #include "winbase.h"
23 #include "winerror.h"
24 #include "wingdi.h"
25 #include "winuser.h"
27 static void test_ClipboardOwner(void)
29 HWND hWnd1, hWnd2;
30 BOOL ret;
32 SetLastError(0xdeadbeef);
33 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
34 "could not perform clipboard test: clipboard already owned\n");
36 hWnd1 = CreateWindowExA(0, "static", NULL, WS_POPUP,
37 0, 0, 10, 10, 0, 0, 0, NULL);
38 ok(hWnd1 != 0, "CreateWindowExA error %d\n", GetLastError());
39 trace("hWnd1 = %p\n", hWnd1);
41 hWnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP,
42 0, 0, 10, 10, 0, 0, 0, NULL);
43 ok(hWnd2 != 0, "CreateWindowExA error %d\n", GetLastError());
44 trace("hWnd2 = %p\n", hWnd2);
46 SetLastError(0xdeadbeef);
47 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
48 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
49 "wrong error %u\n", GetLastError());
51 ok(OpenClipboard(0), "OpenClipboard failed\n");
52 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
53 ok(!OpenClipboard(hWnd1), "OpenClipboard should fail since clipboard already opened\n");
54 ok(OpenClipboard(0), "OpenClipboard again failed\n");
55 ret = CloseClipboard();
56 ok( ret, "CloseClipboard error %d\n", GetLastError());
58 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
59 ok(OpenClipboard(hWnd1), "OpenClipboard second time in the same hwnd failed\n");
61 SetLastError(0xdeadbeef);
62 ret = OpenClipboard(hWnd2);
63 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
64 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
66 SetLastError(0xdeadbeef);
67 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
68 ret = EmptyClipboard();
69 ok( ret, "EmptyClipboard error %d\n", GetLastError());
70 ok(GetClipboardOwner() == hWnd1, "clipboard should be owned by %p, not by %p\n", hWnd1, GetClipboardOwner());
72 SetLastError(0xdeadbeef);
73 ret = OpenClipboard(hWnd2);
74 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
75 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
77 ret = CloseClipboard();
78 ok( ret, "CloseClipboard error %d\n", GetLastError());
79 ok(GetClipboardOwner() == hWnd1, "clipboard should still be owned\n");
81 ret = DestroyWindow(hWnd1);
82 ok( ret, "DestroyWindow error %d\n", GetLastError());
83 ret = DestroyWindow(hWnd2);
84 ok( ret, "DestroyWindow error %d\n", GetLastError());
85 SetLastError(0xdeadbeef);
86 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
89 static void test_RegisterClipboardFormatA(void)
91 ATOM atom_id;
92 UINT format_id, format_id2;
93 char buf[256];
94 int len;
95 BOOL ret;
97 format_id = RegisterClipboardFormatA("my_cool_clipboard_format");
98 ok(format_id > 0xc000 && format_id < 0xffff, "invalid clipboard format id %04x\n", format_id);
100 format_id2 = RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
101 ok(format_id2 == format_id, "invalid clipboard format id %04x\n", format_id2);
103 len = GetClipboardFormatNameA(format_id, buf, 256);
104 ok(len == lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len);
105 ok(!lstrcmpA(buf, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf);
107 lstrcpyA(buf, "foo");
108 SetLastError(0xdeadbeef);
109 len = GetAtomNameA((ATOM)format_id, buf, 256);
110 ok(len == 0, "GetAtomNameA should fail\n");
111 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
113 todo_wine
115 lstrcpyA(buf, "foo");
116 SetLastError(0xdeadbeef);
117 len = GlobalGetAtomNameA((ATOM)format_id, buf, 256);
118 ok(len == 0, "GlobalGetAtomNameA should fail\n");
119 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
122 SetLastError(0xdeadbeef);
123 atom_id = FindAtomA("my_cool_clipboard_format");
124 ok(atom_id == 0, "FindAtomA should fail\n");
125 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
127 if (0)
129 /* this relies on the clipboard and global atom table being different */
130 SetLastError(0xdeadbeef);
131 atom_id = GlobalFindAtomA("my_cool_clipboard_format");
132 ok(atom_id == 0, "GlobalFindAtomA should fail\n");
133 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
136 for (format_id = 0; format_id < 0xffff; format_id++)
138 SetLastError(0xdeadbeef);
139 len = GetClipboardFormatNameA(format_id, buf, 256);
141 if (format_id < 0xc000)
142 ok(!len, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len, buf);
143 else if (len && winetest_debug > 1)
144 trace("%04x: %s\n", format_id, len ? buf : "");
147 ret = OpenClipboard(0);
148 ok( ret, "OpenClipboard error %d\n", GetLastError());
150 trace("# of formats available: %d\n", CountClipboardFormats());
152 format_id = 0;
153 while ((format_id = EnumClipboardFormats(format_id)))
155 ok(IsClipboardFormatAvailable(format_id), "format %04x was listed as available\n", format_id);
156 len = GetClipboardFormatNameA(format_id, buf, 256);
157 trace("%04x: %s\n", format_id, len ? buf : "");
160 ret = EmptyClipboard();
161 ok( ret, "EmptyClipboard error %d\n", GetLastError());
162 ret =CloseClipboard();
163 ok( ret, "CloseClipboard error %d\n", GetLastError());
165 if (CountClipboardFormats())
167 SetLastError(0xdeadbeef);
168 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
169 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN,
170 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError());
173 SetLastError(0xdeadbeef);
174 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
175 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
176 "Wrong error %u\n", GetLastError());
178 format_id = RegisterClipboardFormatA("#1234");
179 ok(format_id == 1234, "invalid clipboard format id %04x\n", format_id);
182 static HGLOBAL create_text(void)
184 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5);
185 char *p = GlobalLock(h);
186 strcpy(p, "test");
187 GlobalUnlock(h);
188 return h;
191 static HENHMETAFILE create_emf(void)
193 const RECT rect = {0, 0, 100, 100};
194 HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
195 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
196 return CloseEnhMetaFile(hdc);
199 static void test_synthesized(void)
201 HGLOBAL h, htext;
202 HENHMETAFILE emf;
203 BOOL r;
204 UINT cf;
205 HANDLE data;
207 htext = create_text();
208 emf = create_emf();
210 r = OpenClipboard(NULL);
211 ok(r, "gle %d\n", GetLastError());
212 r = EmptyClipboard();
213 ok(r, "gle %d\n", GetLastError());
214 h = SetClipboardData(CF_TEXT, htext);
215 ok(h == htext, "got %p\n", h);
216 h = SetClipboardData(CF_ENHMETAFILE, emf);
217 ok(h == emf, "got %p\n", h);
218 r = CloseClipboard();
219 ok(r, "gle %d\n", GetLastError());
221 r = OpenClipboard(NULL);
222 ok(r, "gle %d\n", GetLastError());
223 cf = EnumClipboardFormats(0);
224 ok(cf == CF_TEXT, "cf %08x\n", cf);
225 data = GetClipboardData(cf);
226 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
228 cf = EnumClipboardFormats(cf);
229 ok(cf == CF_ENHMETAFILE, "cf %08x\n", cf);
230 data = GetClipboardData(cf);
231 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
233 cf = EnumClipboardFormats(cf);
234 todo_wine ok(cf == CF_LOCALE, "cf %08x\n", cf);
235 if(cf == CF_LOCALE)
236 cf = EnumClipboardFormats(cf);
237 ok(cf == CF_OEMTEXT, "cf %08x\n", cf);
238 data = GetClipboardData(cf);
239 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
241 cf = EnumClipboardFormats(cf);
242 ok(cf == CF_UNICODETEXT ||
243 broken(cf == CF_METAFILEPICT), /* win9x and winME has no CF_UNICODETEXT */
244 "cf %08x\n", cf);
246 if(cf == CF_UNICODETEXT)
247 cf = EnumClipboardFormats(cf);
248 ok(cf == CF_METAFILEPICT, "cf %08x\n", cf);
249 data = GetClipboardData(cf);
250 todo_wine ok(data != NULL, "couldn't get data, cf %08x\n", cf);
252 cf = EnumClipboardFormats(cf);
253 ok(cf == 0, "cf %08x\n", cf);
255 r = EmptyClipboard();
256 ok(r, "gle %d\n", GetLastError());
258 r = CloseClipboard();
259 ok(r, "gle %d\n", GetLastError());
262 static CRITICAL_SECTION clipboard_cs;
263 static HWND next_wnd;
264 static LRESULT CALLBACK clipboard_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
266 switch(msg) {
267 case WM_DRAWCLIPBOARD:
268 EnterCriticalSection(&clipboard_cs);
269 LeaveCriticalSection(&clipboard_cs);
270 break;
271 case WM_CHANGECBCHAIN:
272 if (next_wnd == (HWND)wp)
273 next_wnd = (HWND)lp;
274 else if (next_wnd)
275 SendMessageA(next_wnd, msg, wp, lp);
276 break;
277 case WM_USER:
278 ChangeClipboardChain(hwnd, next_wnd);
279 PostQuitMessage(0);
280 break;
283 return DefWindowProcA(hwnd, msg, wp, lp);
286 static DWORD WINAPI clipboard_thread(void *param)
288 HWND win = param;
289 BOOL r;
291 EnterCriticalSection(&clipboard_cs);
292 SetLastError(0xdeadbeef);
293 next_wnd = SetClipboardViewer(win);
294 ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
295 LeaveCriticalSection(&clipboard_cs);
297 r = OpenClipboard(win);
298 ok(r, "OpenClipboard failed: %d\n", GetLastError());
300 r = EmptyClipboard();
301 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
303 EnterCriticalSection(&clipboard_cs);
304 r = CloseClipboard();
305 ok(r, "CloseClipboard failed: %d\n", GetLastError());
306 LeaveCriticalSection(&clipboard_cs);
308 r = PostMessageA(win, WM_USER, 0, 0);
309 ok(r, "PostMessage failed: %d\n", GetLastError());
310 return 0;
313 static void test_messages(void)
315 WNDCLASSA cls;
316 HWND win;
317 MSG msg;
318 HANDLE thread;
319 DWORD tid;
321 InitializeCriticalSection(&clipboard_cs);
323 memset(&cls, 0, sizeof(cls));
324 cls.lpfnWndProc = clipboard_wnd_proc;
325 cls.hInstance = GetModuleHandleA(NULL);
326 cls.lpszClassName = "clipboard_test";
327 RegisterClassA(&cls);
329 win = CreateWindowA("clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0);
330 ok(win != NULL, "CreateWindow failed: %d\n", GetLastError());
332 thread = CreateThread(NULL, 0, clipboard_thread, (void*)win, 0, &tid);
333 ok(thread != NULL, "CreateThread failed: %d\n", GetLastError());
335 while(GetMessageA(&msg, NULL, 0, 0)) {
336 TranslateMessage(&msg);
337 DispatchMessageA(&msg);
340 ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
341 CloseHandle(thread);
343 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL));
344 DeleteCriticalSection(&clipboard_cs);
347 START_TEST(clipboard)
349 test_RegisterClipboardFormatA();
350 test_ClipboardOwner();
351 test_synthesized();
352 test_messages();